Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Array1D.hh>
54 : #include <ObjexxFCL/Fmath.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Construction.hh>
58 : #include <EnergyPlus/DXFEarClipping.hh>
59 : #include <EnergyPlus/Data/EnergyPlusData.hh>
60 : #include <EnergyPlus/DataErrorTracking.hh>
61 : #include <EnergyPlus/DataHeatBalance.hh>
62 : #include <EnergyPlus/DataStringGlobals.hh>
63 : #include <EnergyPlus/DataSurfaceColors.hh>
64 : #include <EnergyPlus/DataSurfaces.hh>
65 : #include <EnergyPlus/DaylightingManager.hh>
66 : #include <EnergyPlus/General.hh>
67 : #include <EnergyPlus/OutputReports.hh>
68 : #include <EnergyPlus/ScheduleManager.hh>
69 : #include <EnergyPlus/UtilityRoutines.hh>
70 :
71 : namespace EnergyPlus {
72 :
73 73 : void ReportSurfaces(EnergyPlusData &state)
74 : {
75 :
76 : // SUBROUTINE INFORMATION:
77 : // AUTHOR Linda K. Lawrie
78 : // DATE WRITTEN February 1999
79 : // MODIFIED na
80 : // RE-ENGINEERED na
81 :
82 : // PURPOSE OF THIS SUBROUTINE:
83 : // This subroutine calls several optional routines to report
84 : // the surfaces to output formats that can render the data
85 : // into a descriptive picture.
86 :
87 : // METHODOLOGY EMPLOYED:
88 : // Use a REPORT command to determine if there should be
89 : // a file created.
90 :
91 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
92 :
93 73 : state.dataErrTracking->AskForSurfacesReport = false;
94 :
95 73 : int SurfDetails = 0;
96 73 : bool SurfVert = false;
97 73 : bool SurfDet = false;
98 73 : bool DXFDone = false;
99 73 : bool VRMLDone = false;
100 73 : std::string Option1;
101 73 : std::string Option2;
102 : bool DoReport;
103 :
104 219 : General::ScanForReports(state, "Surfaces", DoReport, "Lines", Option1);
105 73 : if (DoReport) {
106 0 : LinesOut(state, Option1);
107 : }
108 :
109 219 : General::ScanForReports(state, "Surfaces", DoReport, "Vertices");
110 73 : if (DoReport) {
111 0 : if (!SurfVert) {
112 0 : ++SurfDetails;
113 0 : SurfVert = true;
114 : }
115 : }
116 :
117 219 : General::ScanForReports(state, "Surfaces", DoReport, "Details");
118 73 : if (DoReport) {
119 0 : if (!SurfDet) {
120 0 : SurfDetails += 10;
121 0 : SurfDet = true;
122 : }
123 : }
124 :
125 219 : General::ScanForReports(state, "Surfaces", DoReport, "DetailsWithVertices");
126 73 : if (DoReport) {
127 0 : if (!SurfDet) {
128 0 : SurfDetails += 10;
129 0 : SurfDet = true;
130 : }
131 0 : if (!SurfVert) {
132 0 : ++SurfDetails;
133 0 : SurfVert = true;
134 : }
135 : }
136 :
137 219 : General::ScanForReports(state, "Surfaces", DoReport, "DXF", Option1, Option2);
138 73 : if (DoReport) {
139 0 : if (!DXFDone) {
140 0 : if (!Option2.empty()) {
141 0 : DataSurfaceColors::SetUpSchemeColors(state, Option2, "DXF");
142 : }
143 0 : DXFOut(state, Option1, Option2);
144 0 : DXFDone = true;
145 : } else {
146 0 : ShowWarningError(state, format("ReportSurfaces: DXF output already generated. DXF with option=[{}] will not be generated.", Option1));
147 : }
148 : }
149 :
150 219 : General::ScanForReports(state, "Surfaces", DoReport, "DXF:WireFrame", Option1, Option2);
151 73 : if (DoReport) {
152 23 : if (!DXFDone) {
153 23 : if (!Option2.empty()) {
154 0 : DataSurfaceColors::SetUpSchemeColors(state, Option2, "DXF");
155 : }
156 23 : DXFOutWireFrame(state, Option2);
157 23 : DXFDone = true;
158 : } else {
159 0 : ShowWarningError(state, "ReportSurfaces: DXF output already generated. DXF:WireFrame will not be generated.");
160 : }
161 : }
162 :
163 219 : General::ScanForReports(state, "Surfaces", DoReport, "VRML", Option1, Option2);
164 73 : if (DoReport) {
165 0 : if (!VRMLDone) {
166 0 : VRMLOut(state, Option1, Option2);
167 0 : VRMLDone = true;
168 : } else {
169 0 : ShowWarningError(state, format("ReportSurfaces: VRML output already generated. VRML with option=[{}] will not be generated.", Option1));
170 : }
171 : }
172 :
173 219 : General::ScanForReports(state, "Surfaces", DoReport, "CostInfo");
174 73 : if (DoReport) {
175 0 : CostInfoOut(state);
176 : }
177 :
178 73 : if (SurfDet || SurfVert) {
179 0 : DetailsForSurfaces(state, SurfDetails);
180 : }
181 73 : }
182 :
183 0 : void LinesOut(EnergyPlusData &state, std::string const &option)
184 : {
185 : // SUBROUTINE INFORMATION:
186 : // AUTHOR Linda K. Lawrie
187 : // DATE WRITTEN March 1999
188 : // MODIFIED March 2006 -- add option for "IDF segments out"
189 : // RE-ENGINEERED na
190 :
191 : // PURPOSE OF THIS SUBROUTINE:
192 : // This subroutine produces a file of lines in the surfaces.
193 :
194 : // METHODOLOGY EMPLOYED:
195 : // Use the surface absolute coordinate information to produce
196 : // lines.
197 :
198 : static constexpr std::string_view vertexstring("X,Y,Z ==> Vertex");
199 :
200 0 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
201 : // no error needed, probably in end processing, just return
202 0 : return;
203 : }
204 :
205 0 : if (state.dataOutputReports->optiondone) {
206 0 : ShowWarningError(state,
207 0 : format("Report of Surfaces/Lines Option has already been completed with option={}", state.dataOutputReports->lastoption));
208 0 : ShowContinueError(state, format("..option=\"{}\" will not be done this time.", option));
209 0 : return;
210 : }
211 :
212 0 : state.dataOutputReports->lastoption = option;
213 0 : state.dataOutputReports->optiondone = true;
214 :
215 0 : auto slnfile = state.files.sln.open(state, "LinesOut", state.files.outputControl.sln);
216 :
217 0 : if (option != "IDF") {
218 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
219 0 : auto &thisSurface = state.dataSurface->Surface(surf);
220 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
221 0 : continue;
222 : }
223 0 : if (thisSurface.Sides == 0) {
224 0 : continue;
225 : }
226 0 : print<FormatSyntax::FMT>(slnfile, "{}:{}\n", thisSurface.ZoneName, thisSurface.Name);
227 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
228 : static constexpr std::string_view fmt700("{:10.2F},{:10.2F},{:10.2F},{:10.2F},{:10.2F},{:10.2F}\n");
229 :
230 0 : if (vert != thisSurface.Sides) {
231 0 : print<check_syntax(fmt700)>(slnfile,
232 : fmt700,
233 0 : thisSurface.Vertex(vert).x,
234 0 : thisSurface.Vertex(vert).y,
235 0 : thisSurface.Vertex(vert).z,
236 0 : thisSurface.Vertex(vert + 1).x,
237 0 : thisSurface.Vertex(vert + 1).y,
238 0 : thisSurface.Vertex(vert + 1).z);
239 : } else {
240 0 : print<check_syntax(fmt700)>(slnfile,
241 : fmt700,
242 0 : thisSurface.Vertex(vert).x,
243 0 : thisSurface.Vertex(vert).y,
244 0 : thisSurface.Vertex(vert).z,
245 0 : thisSurface.Vertex(1).x,
246 0 : thisSurface.Vertex(1).y,
247 0 : thisSurface.Vertex(1).z);
248 : }
249 : }
250 0 : }
251 : } else {
252 0 : print<FormatSyntax::FMT>(slnfile, "{}\n", " Building North Axis = 0");
253 0 : print<FormatSyntax::FMT>(slnfile, "{}\n", "GlobalGeometryRules,UpperLeftCorner,CounterClockwise,WorldCoordinates;");
254 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
255 0 : auto &thisSurface = state.dataSurface->Surface(surf);
256 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
257 0 : continue;
258 : }
259 0 : if (thisSurface.Sides == 0) {
260 0 : continue;
261 : }
262 : // process heat transfer surfaces
263 0 : print(slnfile, " Surface={}, Name={}, Azimuth={:.1R}\n", cSurfaceClass(thisSurface.Class), thisSurface.Name, thisSurface.Azimuth);
264 0 : print<FormatSyntax::FMT>(slnfile, " {}, !- Number of (X,Y,Z) groups in this surface\n", thisSurface.Sides);
265 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
266 0 : std::string optcommasemi = ",";
267 0 : if (vert == thisSurface.Sides) {
268 0 : optcommasemi = ";";
269 : }
270 : static constexpr std::string_view fmtcoord(" {:10.2F},{:10.2F},{:10.2F}{} !- {} {}\n");
271 0 : print<check_syntax(fmtcoord)>(slnfile,
272 : fmtcoord,
273 0 : thisSurface.Vertex(vert).x,
274 0 : thisSurface.Vertex(vert).y,
275 0 : thisSurface.Vertex(vert).z,
276 : optcommasemi,
277 : vertexstring,
278 : vert);
279 0 : }
280 0 : }
281 : }
282 0 : }
283 :
284 46 : static std::string normalizeName(std::string name)
285 : {
286 92 : std::replace(begin(name), end(name), ' ', '_');
287 92 : std::replace(begin(name), end(name), ':', '_');
288 46 : return name;
289 : }
290 :
291 23 : static void WriteDXFCommon(EnergyPlusData &state, InputOutputFile &of, const std::string &ColorScheme)
292 : {
293 : static constexpr std::string_view Format_800(
294 : " 0\nTEXT\n 8\n1\n 6\nContinuous\n 62\n{:3}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n 40\n .25\n "
295 : "1\nTrue North\n 41\n 0.0\n 7\nMONOTXT\n210\n0.0\n220\n0.0\n230\n1.0\n");
296 : static constexpr std::string_view Format_801(
297 : " 0\nTEXT\n 8\n1\n 6\nContinuous\n 62\n{:3}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n 40\n .4\n "
298 : "1\n{}\n 41\n 0.0\n 7\nMONOTXT\n210\n0.0\n220\n0.0\n230\n1.0\n");
299 :
300 : static constexpr std::string_view Format_703_0(" 0\n3DFACE\n 8\n1\n 62\n{:3}\n");
301 : static constexpr std::string_view Format_703_1(" 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
302 : static constexpr std::string_view Format_703_2(" 11\n{:15.5F}\n 21\n{:15.5F}\n 31\n{:15.5F}\n");
303 : static constexpr std::string_view Format_703_3(" 12\n{:15.5F}\n 22\n{:15.5F}\n 32\n{:15.5F}\n");
304 : static constexpr std::string_view Format_703_4(" 13\n{:15.5F}\n 23\n{:15.5F}\n 33\n{:15.5F}\n");
305 :
306 : static constexpr std::string_view Format_708{"999\n{}{}{}\n"};
307 : static constexpr std::string_view Format_710{"999\n{}\n"};
308 :
309 23 : constexpr int lenArr = 4;
310 23 : std::array<Real64, lenArr> StemX = {-10.0, -10.0, -10.0, -10.0};
311 23 : std::array<Real64, lenArr> StemY = {3.0, 3.0, 0.0, 0.0};
312 23 : std::array<Real64, lenArr> StemZ = {0.1, 0.0, 0.0, 0.1};
313 23 : std::array<Real64, lenArr> Head1X = {-10.0, -10.0, -10.5, -10.5};
314 23 : std::array<Real64, lenArr> Head1Y = {3.0, 3.0, 2.133975, 2.133975};
315 23 : std::array<Real64, lenArr> Head1Z = {0.1, 0.0, 0.0, 0.1};
316 23 : std::array<Real64, lenArr> Head2X = {-10.0, -10.0, -9.5, -9.5};
317 23 : std::array<Real64, lenArr> Head2Y = {3.0, 3.0, 2.133975, 2.133975};
318 23 : std::array<Real64, lenArr> Head2Z = {0.1, 0.0, 0.0, 0.1};
319 23 : std::array<Real64, lenArr> NSide1X = {-10.5, -10.5, -10.5, -10.5};
320 23 : std::array<Real64, lenArr> NSide1Y = {4.5, 4.5, 3.5, 3.5};
321 23 : std::array<Real64, lenArr> NSide1Z = {0.1, 0.0, 0.0, 0.1};
322 23 : std::array<Real64, lenArr> NSide2X = {-10.5, -10.5, -9.5, -9.5};
323 23 : std::array<Real64, lenArr> NSide2Y = {4.5, 4.5, 3.5, 3.5};
324 23 : std::array<Real64, lenArr> NSide2Z = {0.1, 0.0, 0.0, 0.1};
325 23 : std::array<Real64, lenArr> NSide3X = {-9.5, -9.5, -9.5, -9.5};
326 23 : std::array<Real64, lenArr> NSide3Y = {4.5, 4.5, 3.5, 3.5};
327 23 : std::array<Real64, lenArr> NSide3Z = {0.1, 0.0, 0.0, 0.1};
328 :
329 23 : if (ColorScheme.empty()) {
330 23 : print(of, Format_708, "Color Scheme", ",", "Default");
331 : } else {
332 0 : print(of, Format_708, "Color Scheme", ",", ColorScheme);
333 : }
334 :
335 23 : Real64 minx = 99999.0;
336 23 : Real64 miny = 99999.0;
337 161 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
338 138 : auto &thisSurface = state.dataSurface->Surface(surf);
339 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
340 0 : continue;
341 : }
342 690 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
343 552 : minx = min(minx, thisSurface.Vertex(vert).x);
344 552 : miny = min(miny, thisSurface.Vertex(vert).y);
345 : }
346 23 : }
347 :
348 115 : for (int vert = 0; vert < lenArr; ++vert) {
349 92 : StemX[vert] += minx;
350 92 : StemY[vert] += miny;
351 92 : Head1X[vert] += minx;
352 92 : Head1Y[vert] += miny;
353 92 : Head2X[vert] += minx;
354 92 : Head2Y[vert] += miny;
355 92 : NSide1X[vert] += minx;
356 92 : NSide1Y[vert] += miny;
357 92 : NSide2X[vert] += minx;
358 92 : NSide2Y[vert] += miny;
359 92 : NSide3X[vert] += minx;
360 92 : NSide3Y[vert] += miny;
361 : }
362 :
363 23 : auto &DXFcolorno = state.dataSurfColor->DXFcolorno;
364 :
365 : // This writes "True North" above the Arrow Head
366 23 : print(of, Format_710, "Text - True North");
367 23 : print<check_syntax(Format_800)>(
368 23 : of, Format_800, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)], StemX[0] - 1.0, StemY[0], StemZ[0]);
369 :
370 23 : print(of, Format_710, "Text - Building Title");
371 23 : print<check_syntax(Format_801)>(of,
372 : Format_801,
373 23 : DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)],
374 23 : StemX[0] - 4.0,
375 23 : StemY[0] - 4.0,
376 23 : StemZ[0],
377 46 : "Building - " + state.dataHeatBal->BuildingName);
378 :
379 : // We want to point the north arrow to true north
380 23 : print(of, Format_710, "North Arrow Stem");
381 23 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
382 23 : print(of, Format_703_1, StemX[0], StemY[0], StemZ[0]);
383 23 : print(of, Format_703_2, StemX[1], StemY[1], StemZ[1]);
384 23 : print(of, Format_703_3, StemX[2], StemY[2], StemZ[2]);
385 23 : print(of, Format_703_4, StemX[3], StemY[3], StemZ[3]);
386 :
387 23 : print(of, Format_710, "North Arrow Head 1");
388 23 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
389 23 : print(of, Format_703_1, Head1X[0], Head1Y[0], Head1Z[0]);
390 23 : print(of, Format_703_2, Head1X[1], Head1Y[1], Head1Z[1]);
391 23 : print(of, Format_703_3, Head1X[2], Head1Y[2], Head1Z[2]);
392 23 : print(of, Format_703_4, Head1X[3], Head1Y[3], Head1Z[3]);
393 :
394 23 : print(of, Format_710, "North Arrow Head 2");
395 23 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
396 23 : print(of, Format_703_1, Head2X[0], Head2Y[0], Head2Z[0]);
397 23 : print(of, Format_703_2, Head2X[1], Head2Y[1], Head2Z[1]);
398 23 : print(of, Format_703_3, Head2X[2], Head2Y[2], Head2Z[2]);
399 23 : print(of, Format_703_4, Head2X[3], Head2Y[3], Head2Z[3]);
400 :
401 23 : print(of, Format_710, "North Arrow Side 1");
402 23 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
403 23 : print(of, Format_703_1, NSide1X[0], NSide1Y[0], NSide1Z[0]);
404 23 : print(of, Format_703_2, NSide1X[1], NSide1Y[1], NSide1Z[1]);
405 23 : print(of, Format_703_3, NSide1X[2], NSide1Y[2], NSide1Z[2]);
406 23 : print(of, Format_703_4, NSide1X[3], NSide1Y[3], NSide1Z[3]);
407 :
408 23 : print(of, Format_710, "North Arrow Side 2");
409 23 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
410 23 : print(of, Format_703_1, NSide2X[0], NSide2Y[0], NSide2Z[0]);
411 23 : print(of, Format_703_2, NSide2X[1], NSide2Y[1], NSide2Z[1]);
412 23 : print(of, Format_703_3, NSide2X[2], NSide2Y[2], NSide2Z[2]);
413 23 : print(of, Format_703_4, NSide2X[3], NSide2Y[3], NSide2Z[3]);
414 :
415 23 : print(of, Format_710, "North Arrow Side 3");
416 23 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
417 23 : print(of, Format_703_1, NSide3X[0], NSide3Y[0], NSide3Z[0]);
418 23 : print(of, Format_703_2, NSide3X[1], NSide3Y[1], NSide3Z[1]);
419 23 : print(of, Format_703_3, NSide3X[2], NSide3Y[2], NSide3Z[2]);
420 23 : print(of, Format_703_4, NSide3X[3], NSide3Y[3], NSide3Z[3]);
421 :
422 23 : print(of, Format_710, "Zone Names");
423 :
424 46 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
425 46 : print<check_syntax(Format_710)>(of, Format_710, fmt::format("Zone={}:{}", zones, normalizeName(state.dataHeatBal->Zone(zones).Name)));
426 : }
427 23 : }
428 :
429 23 : static void DXFDaylightingReferencePoints(EnergyPlusData &state, InputOutputFile &of)
430 : {
431 :
432 : static constexpr std::string_view Format_709(" 0\nCIRCLE\n 8\n{}\n 62\n{:3}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n 40\n{:15.5F}\n");
433 :
434 : // Do any daylighting reference points on layer for zone
435 23 : if ((int)state.dataDayltg->DaylRefPt.size() > 0) {
436 0 : for (int daylightCtrlNum = 1; daylightCtrlNum <= (int)state.dataDayltg->daylightControl.size(); ++daylightCtrlNum) {
437 0 : auto &thisDaylightControl = state.dataDayltg->daylightControl(daylightCtrlNum);
438 0 : DataSurfaceColors::ColorNo curcolorno = DataSurfaceColors::ColorNo::DaylSensor1;
439 0 : std::string refPtType;
440 0 : if (thisDaylightControl.DaylightMethod == Dayltg::DaylightingMethod::DElight) {
441 0 : refPtType = "DEDayRefPt";
442 0 : } else if (thisDaylightControl.DaylightMethod == Dayltg::DaylightingMethod::SplitFlux) {
443 0 : refPtType = "DayRefPt";
444 : }
445 :
446 0 : for (auto const &refPt : thisDaylightControl.refPts) {
447 0 : print<FormatSyntax::FMT>(of, "999\n{}:{}:{}\n", thisDaylightControl.ZoneName, refPtType, state.dataDayltg->DaylRefPt(refPt.num).Name);
448 0 : print<check_syntax(Format_709)>(of,
449 : Format_709,
450 0 : normalizeName(thisDaylightControl.ZoneName),
451 0 : state.dataSurfColor->DXFcolorno[static_cast<int>(curcolorno)],
452 0 : refPt.absCoords.x,
453 0 : refPt.absCoords.y,
454 0 : refPt.absCoords.z,
455 0 : 0.2);
456 0 : curcolorno = DataSurfaceColors::ColorNo::DaylSensor2; // ref pts 2 and later are this color
457 : }
458 0 : }
459 : }
460 23 : }
461 :
462 0 : void DXFOut(EnergyPlusData &state,
463 : std::string const &PolygonAction,
464 : std::string const &ColorScheme // Name from user for color scheme or blank
465 : )
466 : {
467 :
468 : // SUBROUTINE INFORMATION:
469 : // AUTHOR Linda K. Lawrie
470 : // DATE WRITTEN March 1999
471 : // MODIFIED na
472 : // RE-ENGINEERED na
473 :
474 : // PURPOSE OF THIS SUBROUTINE:
475 : // This subroutine produces a file of DXF objects for the surfaces.
476 :
477 : // METHODOLOGY EMPLOYED:
478 : // Use the surface absolute coordinate information to produce
479 : // lines.
480 :
481 0 : bool ThickPolyline(false);
482 0 : bool RegularPolyline(false);
483 0 : std::string PolylineWidth(" 0.55");
484 0 : bool TriangulateFace(false);
485 :
486 : // Formats
487 0 : constexpr std::string_view Format_702(" 0\nSECTION\n 2\nENTITIES\n");
488 0 : constexpr std::string_view Format_707("999\nDXF created from EnergyPlus\n");
489 0 : constexpr std::string_view Format_708("999\n{}{}{}\n");
490 :
491 0 : constexpr std::string_view Format_715(
492 : " 0\nPOLYLINE\n 8\n{}\n 62\n{:3}\n 66\n 1\n 10\n 0.0\n 20\n 0.0\n 30\n{:15.5F}\n 70\n 9\n 40\n{}\n 41\n{}\n");
493 0 : constexpr std::string_view Format_716(" 0\nVERTEX\n 8\n{}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
494 0 : constexpr std::string_view Format_717(" 0\nSEQEND\n 8\n{}\n");
495 0 : constexpr std::string_view Format_704(
496 : " 0\n3DFACE\n 8\n{}\n 62\n{:3}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n 11\n{:15.5F}\n 21\n{:15.5F}\n "
497 : "31\n{:15.5F}\n 12\n{:15.5F}\n 22\n{:15.5F}\n 32\n{:15.5F}\n");
498 0 : constexpr std::string_view Format_704_0(" 0\n3DFACE\n 8\n{}\n 62\n{:3}\n");
499 0 : constexpr std::string_view Format_704_1(" 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
500 0 : constexpr std::string_view Format_704_2(" 11\n{:15.5F}\n 21\n{:15.5F}\n 31\n{:15.5F}\n");
501 0 : constexpr std::string_view Format_704_3(" 12\n{:15.5F}\n 22\n{:15.5F}\n 32\n{:15.5F}\n");
502 0 : constexpr std::string_view Format_705(" 13\n{:15.5F}\n 23\n{:15.5F}\n 33\n{:15.5F}\n");
503 0 : constexpr std::string_view Format_706(" 0\nENDSEC\n 0\nEOF\n");
504 0 : constexpr std::string_view Format_709(" 0\nCIRCLE\n 8\n{}\n 62\n{:3}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n 40\n{:15.5F}\n");
505 0 : constexpr std::string_view Format_710("999\n{}\n");
506 :
507 0 : if (PolygonAction == "TRIANGULATE3DFACE" || PolygonAction == "TRIANGULATE" || PolygonAction.empty()) {
508 0 : TriangulateFace = true;
509 0 : RegularPolyline = false;
510 0 : ThickPolyline = false;
511 0 : } else if (PolygonAction == "THICKPOLYLINE") {
512 0 : ThickPolyline = true;
513 0 : RegularPolyline = false;
514 0 : TriangulateFace = false;
515 0 : } else if (PolygonAction == "REGULARPOLYLINE") {
516 0 : RegularPolyline = true;
517 0 : TriangulateFace = false;
518 0 : ThickPolyline = false;
519 0 : PolylineWidth = " 0";
520 : } else {
521 0 : ShowWarningError(state, format("DXFOut: Illegal key specified for Surfaces with > 4 sides={}", PolygonAction));
522 0 : ShowContinueError(state, R"(...Valid keys are: "ThickPolyline", "RegularPolyline", "Triangulate3DFace".)");
523 0 : ShowContinueError(state, "\"Triangulate3DFace\" will be used for any surfaces with > 4 sides.");
524 0 : TriangulateFace = true;
525 0 : RegularPolyline = false;
526 0 : ThickPolyline = false;
527 : }
528 :
529 0 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
530 : // no error needed, probably in end processing, just return
531 0 : return;
532 : }
533 :
534 0 : auto dxffile = state.files.dxf.open(state, "DXFOut", state.files.outputControl.dxf);
535 :
536 0 : print(dxffile, Format_702); // Start of Entities section
537 :
538 0 : print(dxffile, Format_707); // Comment
539 :
540 0 : print(dxffile, Format_708, "Program Version", ",", state.dataStrGlobals->VerStringVar);
541 :
542 0 : if (PolygonAction.empty()) {
543 0 : print(dxffile, Format_708, "Polygon Action", ",", "Triangulate3DFace");
544 : } else {
545 0 : print(dxffile, Format_708, "Polygon Action", ",", PolygonAction);
546 : }
547 :
548 0 : WriteDXFCommon(state, dxffile, ColorScheme);
549 0 : auto &DXFcolorno = state.dataSurfColor->DXFcolorno;
550 0 : DataSurfaceColors::ColorNo colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
551 : // Do all detached shading surfaces first
552 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
553 0 : std::string ShadeType;
554 0 : auto &thisSurface = state.dataSurface->Surface(surf);
555 :
556 0 : if (thisSurface.HeatTransSurf) {
557 0 : continue;
558 : }
559 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) {
560 0 : continue;
561 : }
562 0 : if (thisSurface.Sides == 0) {
563 0 : continue;
564 : }
565 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
566 0 : colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
567 : }
568 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
569 0 : colorindex = DataSurfaceColors::ColorNo::ShdDetBldg;
570 : }
571 0 : if (state.dataSurface->SurfIsPV(surf)) {
572 0 : colorindex = DataSurfaceColors::ColorNo::PV;
573 : }
574 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
575 0 : ShadeType = "Fixed Shading";
576 0 : print(dxffile, Format_710, "Fixed Shading:" + thisSurface.Name);
577 0 : } else if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
578 0 : ShadeType = "Building Shading";
579 0 : print(dxffile, Format_710, "Building Shading:" + thisSurface.Name);
580 : }
581 0 : if (thisSurface.Sides <= 4) {
582 0 : print(dxffile, Format_704_0, ShadeType, DXFcolorno[static_cast<int>(colorindex)]);
583 0 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
584 0 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
585 0 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
586 0 : if (thisSurface.Sides == 3) {
587 0 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
588 : } else {
589 0 : print(dxffile, Format_705, thisSurface.Vertex(4).x, thisSurface.Vertex(4).y, thisSurface.Vertex(4).z);
590 : }
591 : } else { // polygon
592 0 : if (!TriangulateFace) {
593 0 : Real64 minz = 99999.0;
594 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
595 0 : minz = min(minz, thisSurface.Vertex(vert).z);
596 : }
597 0 : print(dxffile, Format_715, ShadeType, DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
598 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
599 0 : print(dxffile, Format_716, ShadeType, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
600 : }
601 0 : print(dxffile, Format_717, ShadeType);
602 : } else {
603 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
604 :
605 0 : const int ntri = DXFEarClipping::Triangulate(state,
606 : thisSurface.Sides,
607 0 : thisSurface.Vertex,
608 : mytriangles,
609 : thisSurface.Azimuth,
610 : thisSurface.Tilt,
611 0 : thisSurface.Name,
612 : thisSurface.Class);
613 0 : for (int svert = 1; svert <= ntri; ++svert) {
614 0 : const int vv0 = mytriangles(svert).vv0;
615 0 : const int vv1 = mytriangles(svert).vv1;
616 0 : const int vv2 = mytriangles(svert).vv2;
617 0 : print(dxffile,
618 : Format_704,
619 : ShadeType,
620 0 : DXFcolorno[static_cast<int>(colorindex)],
621 0 : thisSurface.Vertex(vv0).x,
622 0 : thisSurface.Vertex(vv0).y,
623 0 : thisSurface.Vertex(vv0).z,
624 0 : thisSurface.Vertex(vv1).x,
625 0 : thisSurface.Vertex(vv1).y,
626 0 : thisSurface.Vertex(vv1).z,
627 0 : thisSurface.Vertex(vv2).x,
628 0 : thisSurface.Vertex(vv2).y,
629 0 : thisSurface.Vertex(vv2).z);
630 0 : print(dxffile, Format_705, thisSurface.Vertex(vv2).x, thisSurface.Vertex(vv2).y, thisSurface.Vertex(vv2).z);
631 : }
632 0 : mytriangles.deallocate();
633 0 : }
634 : }
635 0 : }
636 :
637 : // now do zone surfaces, by zone
638 0 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
639 0 : const std::string TempZoneName = normalizeName(state.dataHeatBal->Zone(zones).Name);
640 :
641 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
642 0 : auto &thisSurface = state.dataSurface->Surface(surf);
643 0 : if (thisSurface.Zone != zones) {
644 0 : continue;
645 : }
646 0 : if (thisSurface.Sides == 0) {
647 0 : continue;
648 : }
649 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
650 0 : continue;
651 : }
652 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) {
653 0 : colorindex = DataSurfaceColors::ColorNo::Wall;
654 : }
655 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) {
656 0 : colorindex = DataSurfaceColors::ColorNo::Roof;
657 : }
658 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) {
659 0 : colorindex = DataSurfaceColors::ColorNo::Floor;
660 : }
661 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) {
662 0 : colorindex = DataSurfaceColors::ColorNo::Door;
663 : }
664 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
665 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::Window) {
666 0 : colorindex = DataSurfaceColors::ColorNo::Window;
667 : }
668 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::GlassDoor) {
669 0 : colorindex = DataSurfaceColors::ColorNo::GlassDoor;
670 : }
671 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Dome) {
672 0 : colorindex = DataSurfaceColors::ColorNo::TDDDome;
673 : }
674 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Diffuser) {
675 0 : colorindex = DataSurfaceColors::ColorNo::TDDDiffuser;
676 : }
677 : }
678 0 : if (state.dataSurface->SurfIsPV(surf)) {
679 0 : colorindex = DataSurfaceColors::ColorNo::PV;
680 : }
681 :
682 0 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
683 0 : if (thisSurface.Sides <= 4) {
684 0 : print(dxffile, Format_704_0, TempZoneName, DXFcolorno[static_cast<int>(colorindex)]);
685 0 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
686 0 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
687 0 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
688 0 : if (thisSurface.Sides == 3) {
689 0 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
690 : } else {
691 0 : print(dxffile, Format_705, thisSurface.Vertex(4).x, thisSurface.Vertex(4).y, thisSurface.Vertex(4).z);
692 : }
693 : } else { // polygon surface
694 0 : if (!TriangulateFace) {
695 0 : Real64 minz = 99999.0;
696 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
697 0 : minz = min(minz, thisSurface.Vertex(vert).z);
698 : }
699 0 : print(dxffile, Format_715, TempZoneName, DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
700 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
701 0 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
702 : }
703 0 : print(dxffile, Format_717, TempZoneName);
704 : } else {
705 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
706 :
707 0 : const int ntri = DXFEarClipping::Triangulate(state,
708 : thisSurface.Sides,
709 0 : thisSurface.Vertex,
710 : mytriangles,
711 : thisSurface.Azimuth,
712 : thisSurface.Tilt,
713 0 : thisSurface.Name,
714 : thisSurface.Class);
715 0 : for (int svert = 1; svert <= ntri; ++svert) {
716 0 : const int vv0 = mytriangles(svert).vv0;
717 0 : const int vv1 = mytriangles(svert).vv1;
718 0 : const int vv2 = mytriangles(svert).vv2;
719 0 : print(dxffile,
720 : Format_704,
721 : TempZoneName,
722 0 : DXFcolorno[static_cast<int>(colorindex)],
723 0 : thisSurface.Vertex(vv0).x,
724 0 : thisSurface.Vertex(vv0).y,
725 0 : thisSurface.Vertex(vv0).z,
726 0 : thisSurface.Vertex(vv1).x,
727 0 : thisSurface.Vertex(vv1).y,
728 0 : thisSurface.Vertex(vv1).z,
729 0 : thisSurface.Vertex(vv2).x,
730 0 : thisSurface.Vertex(vv2).y,
731 0 : thisSurface.Vertex(vv2).z);
732 0 : print(dxffile, Format_705, thisSurface.Vertex(vv2).x, thisSurface.Vertex(vv2).y, thisSurface.Vertex(vv2).z);
733 : }
734 0 : mytriangles.deallocate();
735 0 : }
736 : }
737 0 : }
738 : // still have to do shading surfaces for zone
739 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
740 0 : auto &thisSurface = state.dataSurface->Surface(surf);
741 : // if (surface(surf)%heattranssurf) CYCLE ! Shading with a construction is allowed to be HT surf for daylighting shelves
742 0 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) {
743 0 : continue;
744 : }
745 0 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zones).Name) {
746 0 : continue;
747 : }
748 0 : if (thisSurface.Sides == 0) {
749 0 : continue;
750 : }
751 0 : colorindex = DataSurfaceColors::ColorNo::ShdAtt;
752 0 : if (state.dataSurface->SurfIsPV(surf)) {
753 0 : colorindex = DataSurfaceColors::ColorNo::PV;
754 : }
755 0 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
756 0 : if (thisSurface.Sides <= 4) {
757 0 : print(dxffile, Format_704_0, TempZoneName, DXFcolorno[static_cast<int>(colorindex)]);
758 0 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
759 0 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
760 0 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
761 0 : if (thisSurface.Sides == 3) {
762 0 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
763 : } else {
764 0 : print(dxffile, Format_705, thisSurface.Vertex(4).x, thisSurface.Vertex(4).y, thisSurface.Vertex(4).z);
765 : }
766 : } else { // polygon attached shading
767 0 : if (!TriangulateFace) {
768 0 : Real64 minz = 99999.0;
769 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
770 0 : minz = min(minz, thisSurface.Vertex(vert).z);
771 : }
772 0 : print(dxffile, Format_715, TempZoneName, DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
773 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
774 0 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
775 : }
776 0 : print(dxffile, Format_717, TempZoneName);
777 : } else {
778 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
779 0 : int ntri = 0;
780 0 : if (thisSurface.Shape == DataSurfaces::SurfaceShape::RectangularOverhang) {
781 0 : ntri = DXFEarClipping::Triangulate(state,
782 : thisSurface.Sides,
783 0 : thisSurface.Vertex,
784 : mytriangles,
785 : thisSurface.Azimuth,
786 : thisSurface.Tilt,
787 0 : thisSurface.Name,
788 : DataSurfaces::SurfaceClass::Overhang);
789 : } else {
790 0 : ntri = DXFEarClipping::Triangulate(state,
791 : thisSurface.Sides,
792 0 : thisSurface.Vertex,
793 : mytriangles,
794 : thisSurface.Azimuth,
795 : thisSurface.Tilt,
796 0 : thisSurface.Name,
797 : DataSurfaces::SurfaceClass::Fin);
798 : }
799 0 : for (int svert = 1; svert <= ntri; ++svert) {
800 0 : const int vv0 = mytriangles(svert).vv0;
801 0 : const int vv1 = mytriangles(svert).vv1;
802 0 : const int vv2 = mytriangles(svert).vv2;
803 0 : print(dxffile,
804 : Format_704,
805 : TempZoneName,
806 0 : DXFcolorno[static_cast<int>(colorindex)],
807 0 : thisSurface.Vertex(vv0).x,
808 0 : thisSurface.Vertex(vv0).y,
809 0 : thisSurface.Vertex(vv0).z,
810 0 : thisSurface.Vertex(vv1).x,
811 0 : thisSurface.Vertex(vv1).y,
812 0 : thisSurface.Vertex(vv1).z,
813 0 : thisSurface.Vertex(vv2).x,
814 0 : thisSurface.Vertex(vv2).y,
815 0 : thisSurface.Vertex(vv2).z);
816 0 : print(dxffile, Format_705, thisSurface.Vertex(vv2).x, thisSurface.Vertex(vv2).y, thisSurface.Vertex(vv2).z);
817 : }
818 0 : mytriangles.deallocate();
819 0 : }
820 : }
821 0 : }
822 0 : }
823 :
824 0 : DXFDaylightingReferencePoints(state, dxffile);
825 :
826 0 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
827 0 : const DataSurfaceColors::ColorNo curcolorno = DataSurfaceColors::ColorNo::DaylSensor1;
828 :
829 0 : for (auto const &illumMap : state.dataDayltg->illumMaps) {
830 0 : if (illumMap.zoneIndex != zones) {
831 0 : continue;
832 : }
833 0 : int numRefPt = 0;
834 0 : for (auto const &refPt : illumMap.refPts) {
835 0 : print(dxffile, Format_710, format("{}:MapRefPt:{}", state.dataHeatBal->Zone(zones).Name, ++numRefPt));
836 0 : print(dxffile,
837 : Format_709,
838 0 : normalizeName(state.dataHeatBal->Zone(zones).Name),
839 0 : DXFcolorno[static_cast<int>(curcolorno)],
840 0 : refPt.absCoords.x,
841 0 : refPt.absCoords.y,
842 0 : refPt.absCoords.z,
843 0 : 0.05);
844 : }
845 : }
846 : }
847 :
848 0 : print(dxffile, Format_706);
849 0 : }
850 :
851 23 : void DXFOutWireFrame(EnergyPlusData &state, std::string const &ColorScheme)
852 : {
853 :
854 : // SUBROUTINE INFORMATION:
855 : // AUTHOR Linda K. Lawrie
856 : // DATE WRITTEN August 2005
857 : // MODIFIED na
858 : // RE-ENGINEERED na
859 :
860 : // PURPOSE OF THIS SUBROUTINE:
861 : // This subroutine produces a file of DXF objects for the surfaces (all lines -- wireframe).
862 :
863 : // METHODOLOGY EMPLOYED:
864 : // Use the surface absolute coordinate information to produce
865 : // lines.
866 :
867 23 : constexpr std::string_view PolylineWidth = " 0.55";
868 :
869 23 : constexpr std::string_view Format_702(" 0\nSECTION\n 2\nENTITIES\n");
870 23 : constexpr std::string_view Format_707("999\nDXF created from EnergyPlus\n");
871 23 : constexpr std::string_view Format_708("999\n{}{}{}\n");
872 :
873 23 : constexpr std::string_view Format_715(
874 : " 0\nPOLYLINE\n 8\n{}\n 62\n{:3}\n 66\n 1\n 10\n 0.0\n 20\n 0.0\n 30\n{:15.5F}\n 70\n 9\n 40\n{}\n 41\n{}\n");
875 23 : constexpr std::string_view Format_716(" 0\nVERTEX\n 8\n{}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
876 23 : constexpr std::string_view Format_717(" 0\nSEQEND\n 8\n{}\n");
877 23 : constexpr std::string_view Format_706(" 0\nENDSEC\n 0\nEOF\n");
878 23 : constexpr std::string_view Format_710("999\n{}\n");
879 :
880 23 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
881 : // no error needed, probably in end processing, just return
882 0 : return;
883 : }
884 :
885 46 : auto dxffile = state.files.dxf.open(state, "DXFOutWireFrame", state.files.outputControl.dxf);
886 :
887 23 : print(dxffile, Format_702); // Start of Entities section
888 :
889 23 : print(dxffile, Format_707); // Comment
890 :
891 23 : print(dxffile, Format_708, "Program Version", ",", state.dataStrGlobals->VerStringVar);
892 23 : print(dxffile, Format_708, "DXF using Wireframe", ' ', ' ');
893 :
894 23 : WriteDXFCommon(state, dxffile, ColorScheme);
895 :
896 : // Do all detached shading surfaces first
897 23 : int surfcount = 0;
898 23 : DataSurfaceColors::ColorNo colorindex = DataSurfaceColors::ColorNo::Invalid;
899 161 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
900 138 : std::string ShadeType;
901 138 : auto &thisSurface = state.dataSurface->Surface(surf);
902 138 : if (thisSurface.HeatTransSurf) {
903 138 : continue;
904 : }
905 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) {
906 0 : continue;
907 : }
908 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
909 0 : colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
910 : }
911 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
912 0 : colorindex = DataSurfaceColors::ColorNo::ShdDetBldg;
913 : }
914 0 : if (state.dataSurface->SurfIsPV(surf)) {
915 0 : colorindex = DataSurfaceColors::ColorNo::PV;
916 : }
917 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
918 0 : ShadeType = "Fixed Shading";
919 0 : print(dxffile, Format_710, "Fixed Shading:" + thisSurface.Name);
920 0 : } else if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
921 0 : ShadeType = "Building Shading";
922 0 : print(dxffile, Format_710, "Building Shading:" + thisSurface.Name);
923 : }
924 0 : ++surfcount;
925 0 : ShadeType += format("_{}", surfcount);
926 0 : Real64 minz = 99999.0;
927 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
928 0 : minz = min(minz, thisSurface.Vertex(vert).z);
929 : }
930 :
931 0 : print(dxffile, Format_715, ShadeType, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
932 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
933 0 : print(dxffile, Format_716, ShadeType, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
934 : }
935 0 : print(dxffile, Format_717, ShadeType);
936 161 : }
937 :
938 : // now do zone surfaces, by zone
939 46 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
940 23 : std::string const SaveZoneName = normalizeName(state.dataHeatBal->Zone(zones).Name);
941 :
942 23 : surfcount = 0;
943 161 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
944 138 : auto &thisSurface = state.dataSurface->Surface(surf);
945 138 : if (thisSurface.Zone != zones) {
946 0 : continue;
947 : }
948 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
949 0 : continue;
950 : }
951 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) {
952 92 : colorindex = DataSurfaceColors::ColorNo::Wall;
953 : }
954 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) {
955 23 : colorindex = DataSurfaceColors::ColorNo::Roof;
956 : }
957 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) {
958 23 : colorindex = DataSurfaceColors::ColorNo::Floor;
959 : }
960 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) {
961 0 : colorindex = DataSurfaceColors::ColorNo::Door;
962 : }
963 138 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
964 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::Window) {
965 0 : colorindex = DataSurfaceColors::ColorNo::Window;
966 : }
967 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::GlassDoor) {
968 0 : colorindex = DataSurfaceColors::ColorNo::GlassDoor;
969 : }
970 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Dome) {
971 0 : colorindex = DataSurfaceColors::ColorNo::TDDDome;
972 : }
973 0 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Diffuser) {
974 0 : colorindex = DataSurfaceColors::ColorNo::TDDDiffuser;
975 : }
976 : }
977 138 : if (state.dataSurface->SurfIsPV(surf)) {
978 0 : colorindex = DataSurfaceColors::ColorNo::PV;
979 : }
980 138 : ++surfcount;
981 :
982 138 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
983 138 : std::string const TempZoneName = format("{}_{}", SaveZoneName, surfcount);
984 138 : Real64 minz = 99999.0;
985 690 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
986 552 : minz = min(minz, thisSurface.Vertex(vert).z);
987 : }
988 :
989 138 : print(
990 138 : dxffile, Format_715, TempZoneName, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
991 690 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
992 552 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
993 : }
994 138 : print(dxffile, Format_717, TempZoneName);
995 161 : }
996 : // still have to do shading surfaces for zone
997 23 : surfcount = 0;
998 161 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
999 138 : auto &thisSurface = state.dataSurface->Surface(surf);
1000 138 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) {
1001 138 : continue;
1002 : }
1003 0 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zones).Name) {
1004 0 : continue;
1005 : }
1006 0 : colorindex = DataSurfaceColors::ColorNo::ShdAtt;
1007 0 : if (state.dataSurface->SurfIsPV(surf)) {
1008 0 : colorindex = DataSurfaceColors::ColorNo::PV;
1009 : }
1010 0 : ++surfcount;
1011 :
1012 0 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
1013 0 : std::string const TempZoneName = format("{}_{}", SaveZoneName, surfcount);
1014 0 : Real64 minz = 99999.0;
1015 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1016 0 : minz = min(minz, thisSurface.Vertex(vert).z);
1017 : }
1018 :
1019 0 : print(
1020 0 : dxffile, Format_715, TempZoneName, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
1021 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1022 0 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1023 : }
1024 0 : print(dxffile, Format_717, TempZoneName);
1025 23 : }
1026 23 : }
1027 :
1028 23 : DXFDaylightingReferencePoints(state, dxffile);
1029 :
1030 23 : print(dxffile, Format_706);
1031 23 : }
1032 :
1033 1 : void DetailsForSurfaces(EnergyPlusData &state, int const RptType) // (1=Vertices only, 10=Details only, 11=Details with vertices)
1034 : {
1035 :
1036 : // SUBROUTINE INFORMATION:
1037 : // AUTHOR Linda Lawrie
1038 : // DATE WRITTEN February 2002
1039 : // MODIFIED na
1040 : // RE-ENGINEERED na
1041 :
1042 : // PURPOSE OF THIS SUBROUTINE:
1043 : // This subroutine provides an optional detailed surface report
1044 : // for each surface in the input file.
1045 :
1046 : // SUBROUTINE PARAMETER DEFINITIONS:
1047 : constexpr static std::array<std::string_view, 9> ConvCoeffCalcs = {
1048 : "ASHRAESimple", "ASHRAETARP", "CeilingDiffuser", "TrombeWall", "TARP", "MoWitt", "DOE-2", "BLAST", "AdaptiveConvectionAlgorithm"};
1049 :
1050 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1051 1 : std::string BaseSurfName;
1052 1 : std::string ConstructionName;
1053 1 : std::string IntConvCoeffCalc;
1054 1 : std::string ExtConvCoeffCalc;
1055 : Real64 NominalUwithConvCoeffs;
1056 1 : std::string cNominalU;
1057 1 : std::string cNominalUwithConvCoeffs;
1058 1 : std::string SolarDiffusing;
1059 1 : std::string AlgoName;
1060 :
1061 1 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
1062 : // no error needed, probably in end processing, just return
1063 0 : return;
1064 : }
1065 :
1066 1 : std::stringstream ss;
1067 1 : auto *eiostream = &ss;
1068 : //!!! Write Header lines for report
1069 1 : if (RptType == 10) { // Details only
1070 1 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces\n"; // Format_700
1071 1 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces\n"; // Format_700b
1072 1 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
1073 : *eiostream << ",Construction,Nominal U (w/o film coefs) {W/m2-K},Nominal U (with film coefs) {W/m2-K},Solar Diffusing,Area (Net) {m2},Area "
1074 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
1075 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
1076 1 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides\n"; // Format_7011
1077 1 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
1078 : *eiostream << ",Transmittance Schedule,Min Schedule Value,Max Schedule Value,Solar Diffusing,Area (Net) {m2},Area (Gross) {m2},Area (Sunlit "
1079 : "Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
1080 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
1081 1 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides\n"; // Format_7011b
1082 1 : *eiostream << "! <Frame/Divider Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701c
1083 : *eiostream << ",Construction,Nominal U (w/o film coefs) {W/m2-K},Nominal U (with film coefs) {W/m2-K},Solar Diffusing,Area (Net) {m2},Area "
1084 1 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal {m}\n"; // Format_7011c
1085 0 : } else if (RptType == 11) { // Details with Vertices
1086 0 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces"; // Format_700
1087 0 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1088 0 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces"; // Format_700b
1089 0 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1090 0 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
1091 : *eiostream << ",Construction,Nominal U (w/o film coefs) {W/m2-K},Nominal U (with film coefs) {W/m2-K},Solar Diffusing,Area (Net) {m2},Area "
1092 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
1093 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
1094 0 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides"; // Format_7011
1095 : *eiostream << ",Vertex 1 X {m},Vertex 1 Y {m},Vertex 1 Z {m},Vertex 2 X {m},Vertex 2 Y {m},Vertex 2 Z {m},Vertex 3 X {m},Vertex 3 Y "
1096 0 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1097 0 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
1098 : *eiostream << ",Transmittance Schedule,Min Schedule Value,Max Schedule Value,Solar Diffusing,Area (Net) {m2},Area (Gross) {m2},Area (Sunlit "
1099 : "Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
1100 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
1101 0 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides"; // Format_7011b
1102 : *eiostream << ",Vertex 1 X {m},Vertex 1 Y {m},Vertex 1 Z {m},Vertex 2 X {m},Vertex 2 Y {m},Vertex 2 Z {m},Vertex 3 X {m},Vertex 3 Y "
1103 0 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1104 0 : *eiostream << "! <Frame/Divider Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701c
1105 : // Vertices are not applicable for window frame and divider, so skip 707
1106 : *eiostream << ",Construction,Nominal U (w/o film coefs) {W/m2-K},Nominal U (with film coefs) {W/m2-K},Solar Diffusing,Area (Net) {m2},Area "
1107 0 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal {m}\n"; // Format_7011c
1108 : } else { // Vertices only
1109 0 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces"; // Format_700
1110 0 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1111 0 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces"; // Format_700b
1112 0 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1113 0 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
1114 0 : *eiostream << ",#Sides"; // Format_7012
1115 : *eiostream << ",Vertex 1 X {m},Vertex 1 Y {m},Vertex 1 Z {m},Vertex 2 X {m},Vertex 2 Y {m},Vertex 2 Z {m},Vertex 3 X {m},Vertex 3 Y "
1116 0 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1117 0 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
1118 0 : *eiostream << ",#Sides"; // Format_7012
1119 : *eiostream << ",Vertex 1 X {m},Vertex 1 Y {m},Vertex 1 Z {m},Vertex 2 X {m},Vertex 2 Y {m},Vertex 2 Z {m},Vertex 3 X {m},Vertex 3 Y "
1120 0 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1121 : // Vertices are not applicable for window frame and divider, so skip 701c here
1122 : }
1123 :
1124 : // Do just "detached" shading first
1125 1 : int surf2 = 0;
1126 1 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1127 1 : surf2 = surf;
1128 1 : auto const &thisSurface = state.dataSurface->Surface(surf);
1129 1 : if (thisSurface.Zone != 0) {
1130 1 : break;
1131 : }
1132 1 : }
1133 1 : if ((surf2 - 1) > 0) {
1134 0 : std::string ScheduleName;
1135 0 : std::string cSchedMin;
1136 0 : std::string cSchedMax;
1137 0 : *eiostream << "Shading Surfaces," << "Number of Shading Surfaces," << surf2 - 1 << '\n';
1138 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1139 0 : auto &thisSurface = state.dataSurface->Surface(surf);
1140 0 : if (thisSurface.Zone != 0) {
1141 0 : break;
1142 : }
1143 0 : AlgoName = "None";
1144 0 : *eiostream << "Shading Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << thisSurface.BaseSurfName << ","
1145 0 : << AlgoName << ",";
1146 0 : if (RptType == 10) {
1147 0 : if (thisSurface.shadowSurfSched != nullptr) {
1148 0 : ScheduleName = thisSurface.shadowSurfSched->Name;
1149 0 : cSchedMin = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1150 0 : cSchedMax = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1151 : } else {
1152 0 : ScheduleName = "";
1153 0 : cSchedMin = "0.0";
1154 0 : cSchedMax = "0.0";
1155 : }
1156 0 : *eiostream << ScheduleName << "," << cSchedMin << "," << cSchedMax << "," << ' ' << "," << format("{:.2R}", thisSurface.Area) << ","
1157 0 : << format("{:.2R}", thisSurface.GrossArea) << "," << format("{:.2R}", thisSurface.NetAreaShadowCalc) << ","
1158 0 : << format("{:.2R}", thisSurface.Azimuth) << "," << format("{:.2R}", thisSurface.Tilt) << ","
1159 0 : << format("{:.2R}", thisSurface.Width) << "," << format("{:.2R}", thisSurface.Height) << ",";
1160 0 : *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << '\n';
1161 0 : } else if (RptType == 1) {
1162 0 : *eiostream << fmt::to_string(thisSurface.Sides) << ",";
1163 : } else {
1164 0 : if (thisSurface.shadowSurfSched != nullptr) {
1165 0 : ScheduleName = thisSurface.shadowSurfSched->Name;
1166 0 : cSchedMin = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1167 0 : cSchedMax = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1168 : } else {
1169 0 : ScheduleName = "";
1170 0 : cSchedMin = "0.0";
1171 0 : cSchedMax = "0.0";
1172 : }
1173 0 : *eiostream << ScheduleName << "," << cSchedMin << "," << cSchedMax << "," << ' ' << "," << format("{:.2R}", thisSurface.Area) << ","
1174 0 : << format("{:.2R}", thisSurface.GrossArea) << "," << format("{:.2R}", thisSurface.NetAreaShadowCalc) << ","
1175 0 : << format("{:.2R}", thisSurface.Azimuth) << "," << format("{:.2R}", thisSurface.Tilt) << ","
1176 0 : << format("{:.2R}", thisSurface.Width) << "," << format("{:.2R}", thisSurface.Height) << ",";
1177 0 : *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << ",";
1178 : }
1179 0 : if (RptType == 10) {
1180 0 : continue;
1181 : }
1182 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1183 0 : if (vert != thisSurface.Sides) {
1184 0 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1185 0 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1186 : } else {
1187 0 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1188 0 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1189 : }
1190 : }
1191 : // This shouldn't happen with shading surface -- always have vertices
1192 0 : if (thisSurface.Sides == 0) {
1193 0 : *eiostream << '\n';
1194 : }
1195 0 : }
1196 0 : }
1197 :
1198 2 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1199 1 : *eiostream << "Zone Surfaces," << state.dataHeatBal->Zone(ZoneNum).Name << ","
1200 1 : << (state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast - state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst + 1) << '\n';
1201 2 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1202 1 : auto &thisSurface = state.dataSurface->Surface(surf);
1203 1 : if (thisSurface.Zone != ZoneNum) {
1204 0 : continue;
1205 : }
1206 1 : SolarDiffusing = "";
1207 1 : if (RptType == 10 || RptType == 11) { // Details and Details with Vertices
1208 1 : if (thisSurface.BaseSurf == surf) {
1209 1 : BaseSurfName = "";
1210 : } else {
1211 0 : BaseSurfName = thisSurface.BaseSurfName;
1212 : }
1213 :
1214 1 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1215 :
1216 : // Default Convection Coefficient Calculation Algorithms
1217 : // This doulbe lookup is a screwed up way to do this, but ...
1218 1 : IntConvCoeffCalc = ConvCoeffCalcs[Convect::HcIntReportVals[static_cast<int>(state.dataHeatBal->Zone(ZoneNum).IntConvAlgo)] - 1];
1219 1 : ExtConvCoeffCalc = ConvCoeffCalcs[Convect::HcExtReportVals[static_cast<int>(state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo)] - 1];
1220 :
1221 1 : *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << ","
1222 1 : << AlgoName << ",";
1223 :
1224 : // NOTE - THIS CODE IS REPEATED IN SurfaceGeometry.cc IN SetupZoneGeometry
1225 : // Calculate Nominal U-value with convection/film coefficients for reporting by adding on
1226 : // prescribed R-values for interior and exterior convection coefficients as found in ASHRAE 90.1-2004, Appendix A
1227 1 : if (thisSurface.Construction > 0 && thisSurface.Construction <= state.dataHeatBal->TotConstructs) {
1228 1 : cNominalUwithConvCoeffs = "";
1229 1 : ConstructionName = state.dataConstruction->Construct(thisSurface.Construction).Name;
1230 1 : switch (thisSurface.Class) {
1231 1 : case DataSurfaces::SurfaceClass::Wall: {
1232 : // Interior: vertical, still air, Rcin = 0.68 ft2-F-hr/BTU
1233 : // Exterior: vertical, exterior wind exposure, Rcout = 0.17 ft2-F-hr/BTU
1234 1 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1235 1 : NominalUwithConvCoeffs = 1.0 / (0.1197548 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0299387);
1236 : } else {
1237 0 : cNominalUwithConvCoeffs = "[invalid]";
1238 : }
1239 1 : } break;
1240 0 : case DataSurfaces::SurfaceClass::Floor: {
1241 : // Interior: horizontal, still air, heat flow downward, Rcin = 0.92 ft2-F-hr/BTU
1242 : // Exterior: horizontal, semi-exterior (crawlspace), Rcout = 0.46 ft2-F-hr/BTU
1243 0 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1244 0 : NominalUwithConvCoeffs = 1.0 / (0.1620212 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0810106);
1245 : } else {
1246 0 : cNominalUwithConvCoeffs = "[invalid]";
1247 : }
1248 0 : } break;
1249 0 : case DataSurfaces::SurfaceClass::Roof: {
1250 : // Interior: horizontal, still air, heat flow upward, Rcin = 0.61 ft2-F-hr/BTU
1251 : // Exterior: horizontal, semi-exterior (attic), Rcout = 0.46 ft2-F-hr/BTU
1252 0 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1253 0 : NominalUwithConvCoeffs = 1.0 / (0.1074271 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0810106);
1254 : } else {
1255 0 : cNominalUwithConvCoeffs = "[invalid]";
1256 : }
1257 0 : } break;
1258 0 : default: {
1259 0 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1260 0 : NominalUwithConvCoeffs = state.dataHeatBal->NominalU(thisSurface.Construction);
1261 : } else {
1262 0 : cNominalUwithConvCoeffs = "[invalid]";
1263 : }
1264 0 : } break;
1265 : }
1266 1 : if (cNominalUwithConvCoeffs.empty()) {
1267 1 : cNominalUwithConvCoeffs = format("{:.3R}", NominalUwithConvCoeffs);
1268 : } else {
1269 0 : cNominalUwithConvCoeffs = "[invalid]";
1270 : }
1271 1 : if ((thisSurface.Class == DataSurfaces::SurfaceClass::Window) || (thisSurface.Class == DataSurfaces::SurfaceClass::TDD_Dome)) {
1272 : // DataSurfaces::SurfaceClass::Window also covers glass doors and TDD:Diffusers
1273 0 : cNominalU = "N/A";
1274 0 : if (state.dataSurface->SurfWinSolarDiffusing(surf)) {
1275 0 : SolarDiffusing = "Yes";
1276 : } else {
1277 0 : SolarDiffusing = "No";
1278 : }
1279 : } else {
1280 1 : cNominalU = format("{:.3R}", state.dataHeatBal->NominalU(thisSurface.Construction));
1281 : }
1282 : } else {
1283 0 : cNominalUwithConvCoeffs = "**";
1284 0 : cNominalU = "**";
1285 0 : ConstructionName = "**invalid**";
1286 : }
1287 :
1288 : *eiostream << ConstructionName << "," << cNominalU << "," << cNominalUwithConvCoeffs << "," << SolarDiffusing << ","
1289 3 : << format("{:.2R}", thisSurface.Area) << "," << format("{:.2R}", thisSurface.GrossArea) << ","
1290 3 : << format("{:.2R}", thisSurface.NetAreaShadowCalc) << "," << format("{:.2R}", thisSurface.Azimuth) << ","
1291 3 : << format("{:.2R}", thisSurface.Tilt) << "," << format("{:.2R}", thisSurface.Width) << ","
1292 7 : << format("{:.2R}", thisSurface.Height) << "," << format("{:.2R}", thisSurface.Reveal) << ",";
1293 :
1294 : static constexpr std::array<std::string_view, (int)Convect::OverrideType::Num> overrideTypeStrs = {
1295 : "User Supplied Value", "User Supplied Schedule", "User Supplied Curve", "User Specified Model"};
1296 :
1297 1 : auto const &surfIntConv = state.dataSurface->surfIntConv(surf);
1298 1 : auto const &surfExtConv = state.dataSurface->surfExtConv(surf);
1299 1 : if (surfIntConv.userModelNum != 0) {
1300 0 : IntConvCoeffCalc = overrideTypeStrs[(int)state.dataSurface->userIntConvModels(surfIntConv.userModelNum).overrideType];
1301 : } else {
1302 1 : Convect::HcInt hcInt = surfIntConv.model;
1303 1 : if (hcInt == Convect::HcInt::SetByZone) {
1304 1 : hcInt = state.dataHeatBal->Zone(ZoneNum).IntConvAlgo;
1305 : }
1306 1 : IntConvCoeffCalc = ConvCoeffCalcs[Convect::HcIntReportVals[(int)hcInt] - 1];
1307 : }
1308 1 : if (surfExtConv.userModelNum != 0) {
1309 0 : ExtConvCoeffCalc = overrideTypeStrs[(int)state.dataSurface->userExtConvModels(surfExtConv.userModelNum).overrideType];
1310 : } else {
1311 1 : Convect::HcExt hcExt = surfExtConv.model;
1312 1 : if (hcExt == Convect::HcExt::SetByZone) {
1313 1 : hcExt = state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo;
1314 : }
1315 1 : ExtConvCoeffCalc = ConvCoeffCalcs[Convect::HcExtReportVals[static_cast<int>(hcExt)] - 1];
1316 : }
1317 1 : if (thisSurface.ExtBoundCond == DataSurfaces::ExternalEnvironment) {
1318 1 : *eiostream << "ExternalEnvironment" << "," << ExtConvCoeffCalc << "," << IntConvCoeffCalc << ",";
1319 0 : } else if (thisSurface.ExtBoundCond == DataSurfaces::Ground) {
1320 0 : *eiostream << "Ground" << "," << "N/A-Ground" << "," << IntConvCoeffCalc << ",";
1321 0 : } else if (thisSurface.ExtBoundCond == DataSurfaces::GroundFCfactorMethod) {
1322 0 : *eiostream << "FCGround" << "," << "N/A-FCGround" << "," << IntConvCoeffCalc << ",";
1323 0 : } else if (thisSurface.ExtBoundCond == DataSurfaces::KivaFoundation) {
1324 0 : *eiostream << "Foundation" << "," << "N/A-Foundation" << "," << IntConvCoeffCalc << ",";
1325 0 : } else if (thisSurface.ExtBoundCond == DataSurfaces::OtherSideCoefNoCalcExt ||
1326 0 : thisSurface.ExtBoundCond == DataSurfaces::OtherSideCoefCalcExt) {
1327 0 : *eiostream << state.dataSurface->OSC(thisSurface.OSCPtr).Name << "," << "N/A-OSC" << "," << IntConvCoeffCalc << ",";
1328 0 : } else if (thisSurface.ExtBoundCond == DataSurfaces::OtherSideCondModeledExt) {
1329 0 : *eiostream << state.dataSurface->OSCM(thisSurface.OSCMPtr).Name << "," << "N/A-OSCM" << "," << IntConvCoeffCalc << ",";
1330 : } else {
1331 0 : *eiostream << thisSurface.ExtBoundCondName << "," << "Other/Same Surface Int Conv" << "," << IntConvCoeffCalc << ",";
1332 : }
1333 1 : if (thisSurface.ExtSolar) {
1334 1 : *eiostream << "SunExposed" << ",";
1335 : } else {
1336 0 : *eiostream << "NoSun" << ",";
1337 : }
1338 1 : if (thisSurface.ExtWind) {
1339 1 : *eiostream << "WindExposed" << ",";
1340 : } else {
1341 0 : *eiostream << "NoWind" << ",";
1342 : }
1343 1 : if (RptType == 10) {
1344 3 : *eiostream << format("{:.2R}", thisSurface.ViewFactorGround) << "," << format("{:.2R}", thisSurface.ViewFactorSky) << ","
1345 3 : << format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," << format("{:.2R}", thisSurface.ViewFactorSkyIR) << ","
1346 5 : << fmt::to_string(thisSurface.Sides) << '\n';
1347 : } else {
1348 0 : *eiostream << format("{:.2R}", thisSurface.ViewFactorGround) << "," << format("{:.2R}", thisSurface.ViewFactorSky) << ","
1349 0 : << format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," << format("{:.2R}", thisSurface.ViewFactorSkyIR) << ","
1350 0 : << fmt::to_string(thisSurface.Sides) << ",";
1351 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1352 0 : if (vert != thisSurface.Sides) {
1353 0 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1354 0 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1355 : } else {
1356 0 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1357 0 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1358 : }
1359 : }
1360 0 : if (thisSurface.Sides == 0) {
1361 0 : *eiostream << '\n';
1362 : }
1363 : }
1364 : // if window, report frame/divider as appropriate
1365 1 : if (thisSurface.FrameDivider > 0) {
1366 0 : int fd = thisSurface.FrameDivider;
1367 0 : if (state.dataSurface->FrameDivider(fd).FrameWidth > 0.0) {
1368 0 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1369 0 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << "," << "Frame," << thisSurface.Name
1370 0 : << "," << AlgoName << ",";
1371 0 : *eiostream << ",N/A,N/A,," << format("{:.2R}", state.dataSurface->SurfWinFrameArea(surf)) << ","
1372 0 : << format("{:.2R}", state.dataSurface->SurfWinFrameArea(surf) / thisSurface.Multiplier) << ",*" << ",N/A"
1373 0 : << ",N/A," << format("{:.2R}", state.dataSurface->FrameDivider(fd).FrameWidth) << ",N/A" << '\n';
1374 : }
1375 0 : if (state.dataSurface->FrameDivider(fd).DividerWidth > 0.0) {
1376 0 : if (state.dataSurface->FrameDivider(fd).DividerType == DataSurfaces::FrameDividerType::DividedLite) {
1377 0 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << "," << "Divider:DividedLite,"
1378 0 : << thisSurface.Name << ",,";
1379 : } else {
1380 0 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << "," << "Divider:Suspended,"
1381 0 : << thisSurface.Name << ",,";
1382 : }
1383 0 : *eiostream << ",N/A,N/A,," << format("{:.2R}", state.dataSurface->SurfWinDividerArea(surf)) << ","
1384 0 : << format("{:.2R}", state.dataSurface->SurfWinDividerArea(surf) / thisSurface.Multiplier) << ",*" << ",N/A"
1385 0 : << ",N/A," << format("{:.2R}", state.dataSurface->FrameDivider(fd).DividerWidth) << ",N/A" << '\n';
1386 : }
1387 : }
1388 1 : } else { // RptType=1 Vertices only
1389 0 : if (thisSurface.BaseSurf == surf) {
1390 0 : BaseSurfName = "";
1391 : } else {
1392 0 : BaseSurfName = thisSurface.BaseSurfName;
1393 : }
1394 :
1395 0 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1396 :
1397 0 : *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << ","
1398 0 : << AlgoName << ",";
1399 0 : *eiostream << fmt::to_string(thisSurface.Sides) << ",";
1400 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1401 0 : if (vert != thisSurface.Sides) {
1402 0 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1403 0 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1404 : } else {
1405 0 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1406 0 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1407 : }
1408 : }
1409 0 : if (thisSurface.Sides == 0) {
1410 0 : *eiostream << '\n';
1411 : }
1412 : }
1413 1 : } // surfaces
1414 : } // zones
1415 :
1416 1 : print(state.files.eio, "{}", eiostream->str());
1417 1 : }
1418 :
1419 0 : void CostInfoOut(EnergyPlusData &state)
1420 : {
1421 :
1422 : // SUBROUTINE INFORMATION:
1423 : // AUTHOR Brent Griffith
1424 : // DATE WRITTEN April 2003
1425 : // MODIFIED na
1426 : // RE-ENGINEERED na
1427 :
1428 : // PURPOSE OF THIS SUBROUTINE:
1429 : // This subroutine produces a file with information about surfaces.
1430 : // for the purpose of producing first cost estimates to include in objective value functions
1431 : // for design optimization
1432 :
1433 : // METHODOLOGY EMPLOYED:
1434 : // Access data in DataSurfaces and report
1435 :
1436 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1437 0 : Array1D_bool uniqueSurf;
1438 :
1439 0 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
1440 : // no error needed, probably in end processing, just return
1441 0 : return;
1442 : }
1443 :
1444 : // need to determine unique surfaces... some surfaces are shared by zones and hence doubled
1445 0 : uniqueSurf.dimension(state.dataSurface->TotSurfaces, true);
1446 :
1447 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1448 0 : auto const &thisSurface = state.dataSurface->Surface(surf);
1449 0 : if (thisSurface.ExtBoundCond > 0) {
1450 0 : if (thisSurface.ExtBoundCond < surf) { // already cycled through
1451 0 : uniqueSurf(surf) = false;
1452 : }
1453 : }
1454 0 : if (thisSurface.Construction == 0) { // throw out others for now
1455 0 : uniqueSurf(surf) = false;
1456 : }
1457 0 : }
1458 :
1459 0 : auto scifile = state.files.sci.open(state, "CostInfoOut", state.files.outputControl.sci);
1460 :
1461 0 : print(scifile, "{:12}{:12}\n", state.dataSurface->TotSurfaces, count(uniqueSurf));
1462 0 : print(scifile, "{}\n", " data for surfaces useful for cost information");
1463 0 : print(scifile, "{}\n", " Number, Name, Construction, class, area, grossarea");
1464 :
1465 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1466 : // if (surface(surf)%class .eq. DataSurfaces::SurfaceClass::IntMass) CYCLE
1467 0 : if (!uniqueSurf(surf)) {
1468 0 : continue;
1469 : }
1470 : // why the heck are constructions == 0 ?
1471 0 : auto &thisSurface = state.dataSurface->Surface(surf);
1472 0 : if (thisSurface.Construction != 0) {
1473 : // Formats
1474 : static constexpr std::string_view Format_801("{:5},{},{},{},{:14.5F},{:14.5F}\n");
1475 0 : print<check_syntax(Format_801)>(scifile,
1476 : Format_801,
1477 : surf,
1478 0 : thisSurface.Name,
1479 0 : state.dataConstruction->Construct(thisSurface.Construction).Name,
1480 0 : cSurfaceClass(thisSurface.Class),
1481 0 : thisSurface.Area,
1482 0 : thisSurface.GrossArea);
1483 : }
1484 0 : }
1485 :
1486 0 : uniqueSurf.deallocate();
1487 0 : }
1488 :
1489 0 : void VRMLOut(EnergyPlusData &state, const std::string &PolygonAction, const std::string &ColorScheme)
1490 : {
1491 :
1492 : // SUBROUTINE INFORMATION:
1493 : // AUTHOR Linda K. Lawrie
1494 : // DATE WRITTEN August 2006
1495 : // MODIFIED na
1496 : // RE-ENGINEERED na
1497 :
1498 : // PURPOSE OF THIS SUBROUTINE:
1499 : // This subroutine produces a file of VRML output for the surfaces.
1500 :
1501 : // METHODOLOGY EMPLOYED:
1502 : // Use the surface absolute coordinate information to produce
1503 : // lines.
1504 :
1505 : // SUBROUTINE PARAMETER DEFINITIONS:
1506 : enum class Color
1507 : {
1508 : Invalid = -1,
1509 : Wall,
1510 : Window,
1511 : FixedShade,
1512 : SubShade,
1513 : Roof,
1514 : Floor,
1515 : BldgShade,
1516 : Num
1517 : };
1518 :
1519 : constexpr static std::array<std::string_view, static_cast<int>(Color::Num)> colorstring = {
1520 : "WALL", "WINDOW", "FIXEDSHADE", "SUBSHADE", "ROOF", "FLOOR", "BLDGSHADE"};
1521 :
1522 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1523 0 : bool ThickPolyline(false);
1524 0 : bool RegularPolyline(false);
1525 0 : std::string PolylineWidth(" 0.55");
1526 0 : bool TriangulateFace(false);
1527 :
1528 : // Formats
1529 : static constexpr std::string_view Format_702("#VRML V2.0 utf8\n");
1530 : static constexpr std::string_view Format_707(
1531 : "WorldInfo {{\n title \"Building - {}\"\n info [\"EnergyPlus Program Version {}\"]\n info [\"Surface Color Scheme {}\"]\n}}\n");
1532 : static constexpr std::string_view Format_800("Shape {{\nappearance DEF {} Appearance {{\nmaterial Material {{ diffuseColor {} }}\n}}\n}}\n");
1533 : static constexpr std::string_view Format_801(
1534 : "Shape {{\nappearance USE {}\ngeometry IndexedFaceSet {{\nsolid TRUE\ncoord DEF {}{} Coordinate {{\npoint [\n");
1535 : static constexpr std::string_view Format_802("{:15.5F} {:15.5F} {:15.5F},\n");
1536 : static constexpr std::string_view Format_803("]\n}}\ncoordIndex [\n");
1537 : static constexpr std::string_view Format_805("]\nccw TRUE\nsolid TRUE\n}}\n}}\n");
1538 :
1539 0 : if (PolygonAction == "TRIANGULATE3DFACE" || PolygonAction == "TRIANGULATE") {
1540 0 : TriangulateFace = true;
1541 0 : } else if (PolygonAction == "THICKPOLYLINE" || PolygonAction.empty()) {
1542 0 : ThickPolyline = true;
1543 0 : } else if (PolygonAction == "REGULARPOLYLINE") {
1544 0 : RegularPolyline = true;
1545 0 : PolylineWidth = " 0";
1546 : } else {
1547 0 : ShowWarningError(state, format("VRMLOut: Illegal key specified for Surfaces with > 4 sides={}", PolygonAction));
1548 0 : ShowContinueError(state, "\"TRIANGULATE 3DFACE\" will be used for any surfaces with > 4 sides.");
1549 0 : TriangulateFace = true;
1550 : }
1551 :
1552 0 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
1553 : // no error needed, probably in end processing, just return
1554 0 : return;
1555 : }
1556 :
1557 0 : auto wrlfile = state.files.wrl.open(state, "VRMLOut", state.files.outputControl.wrl);
1558 :
1559 0 : print(wrlfile, Format_702);
1560 :
1561 0 : if (ColorScheme.empty()) {
1562 0 : print<check_syntax(Format_707)>(
1563 0 : wrlfile, Format_707, state.dataHeatBal->BuildingName, state.dataStrGlobals->VerStringVar, "Default"); // World Info
1564 : } else {
1565 0 : print<check_syntax(Format_707)>(
1566 0 : wrlfile, Format_707, state.dataHeatBal->BuildingName, state.dataStrGlobals->VerStringVar, ColorScheme); // World Info
1567 : }
1568 :
1569 0 : print(wrlfile, "# Zone Names\n");
1570 0 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
1571 0 : print(wrlfile, "# Zone={}:{}\n", zones, normalizeName(state.dataHeatBal->Zone(zones).Name));
1572 : }
1573 :
1574 : // Define the colors:
1575 :
1576 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "FLOOR", "0.502 0.502 0.502");
1577 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "ROOF", "1 1 0");
1578 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "WALL", "0 1 0");
1579 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "WINDOW", "0 1 1");
1580 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "DOOR", "0 1 1");
1581 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "GLASSDOOR", "0 1 1");
1582 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "FIXEDSHADE", "1 0 1");
1583 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "BLDGSHADE", "0 0 1");
1584 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "SUBSHADE", "1 0 1");
1585 0 : print<check_syntax(Format_800)>(wrlfile, Format_800, "BACKCOLOR", "0.502 0.502 0.784");
1586 :
1587 0 : Color colorindex = Color::Invalid;
1588 :
1589 : // Do all detached shading surfaces first
1590 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1591 0 : auto &thisSurface = state.dataSurface->Surface(surf);
1592 0 : if (thisSurface.HeatTransSurf) {
1593 0 : continue;
1594 : }
1595 0 : if (thisSurface.IsAirBoundarySurf) {
1596 0 : continue;
1597 : }
1598 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) {
1599 0 : continue;
1600 : }
1601 0 : if (thisSurface.Sides == 0) {
1602 0 : continue;
1603 : }
1604 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
1605 0 : colorindex = Color::FixedShade;
1606 : }
1607 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
1608 0 : colorindex = Color::BldgShade;
1609 : }
1610 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
1611 0 : print(wrlfile, "# Fixed Shading:{}\n", thisSurface.Name);
1612 0 : } else if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
1613 0 : print(wrlfile, "# Building Shading:{}", thisSurface.Name);
1614 : }
1615 0 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", surf);
1616 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1617 0 : print<check_syntax(Format_802)>(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1618 : }
1619 0 : print<check_syntax(Format_803)>(wrlfile, Format_803);
1620 0 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1621 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1622 0 : print<FormatSyntax::FMT>(wrlfile, " {}", vert - 1);
1623 0 : if (vert == thisSurface.Sides) {
1624 0 : print(wrlfile, " -1\n");
1625 : }
1626 : }
1627 0 : print<check_syntax(Format_805)>(wrlfile, Format_805);
1628 0 : } else { // will be >4 sided polygon with triangulate option
1629 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1630 0 : const int ntri = DXFEarClipping::Triangulate(state,
1631 : thisSurface.Sides,
1632 0 : thisSurface.Vertex,
1633 : mytriangles,
1634 : thisSurface.Azimuth,
1635 : thisSurface.Tilt,
1636 0 : thisSurface.Name,
1637 : thisSurface.Class);
1638 0 : for (int svert = 1; svert <= ntri; ++svert) {
1639 0 : const int vv0 = mytriangles(svert).vv0;
1640 0 : const int vv1 = mytriangles(svert).vv1;
1641 0 : const int vv2 = mytriangles(svert).vv2;
1642 0 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1643 : }
1644 0 : print(wrlfile, Format_805);
1645 0 : mytriangles.deallocate();
1646 0 : }
1647 0 : }
1648 : // ! now do zone surfaces, by zone
1649 0 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
1650 0 : int oldSurfNum = 0;
1651 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1652 0 : auto &thisSurface = state.dataSurface->Surface(surf);
1653 0 : ++oldSurfNum;
1654 0 : if (thisSurface.Zone != zoneNum) {
1655 0 : continue;
1656 : }
1657 0 : if (thisSurface.Sides == 0) {
1658 0 : continue;
1659 : }
1660 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
1661 0 : continue;
1662 : }
1663 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) {
1664 0 : colorindex = Color::Wall;
1665 : }
1666 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) {
1667 0 : colorindex = Color::Roof;
1668 : }
1669 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::TDD_Dome) {
1670 0 : colorindex = Color::Window;
1671 : }
1672 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) {
1673 0 : colorindex = Color::Floor;
1674 : }
1675 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
1676 0 : colorindex = Color::Window;
1677 : }
1678 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) {
1679 0 : colorindex = Color::Window;
1680 : }
1681 :
1682 0 : print(wrlfile, "# {}:{}\n", thisSurface.ZoneName, thisSurface.Name);
1683 0 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", oldSurfNum);
1684 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1685 0 : print(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1686 : }
1687 0 : print<check_syntax(Format_803)>(wrlfile, Format_803);
1688 0 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1689 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1690 0 : print(wrlfile, " {}", vert - 1);
1691 0 : if (vert == thisSurface.Sides) {
1692 0 : print(wrlfile, " -1\n");
1693 : }
1694 : }
1695 0 : print<check_syntax(Format_805)>(wrlfile, Format_805);
1696 0 : } else { // will be >4 sided polygon with triangulate option
1697 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1698 0 : const int ntri = DXFEarClipping::Triangulate(state,
1699 : thisSurface.Sides,
1700 0 : thisSurface.Vertex,
1701 : mytriangles,
1702 : thisSurface.Azimuth,
1703 : thisSurface.Tilt,
1704 0 : thisSurface.Name,
1705 : thisSurface.Class);
1706 0 : for (int svert = 1; svert <= ntri; ++svert) {
1707 0 : const int vv0 = mytriangles(svert).vv0;
1708 0 : const int vv1 = mytriangles(svert).vv1;
1709 0 : const int vv2 = mytriangles(svert).vv2;
1710 0 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1711 : }
1712 0 : print(wrlfile, Format_805);
1713 0 : mytriangles.deallocate();
1714 0 : }
1715 0 : }
1716 : // still have to do shading surfaces for zone
1717 0 : colorindex = Color::SubShade;
1718 0 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1719 0 : auto &thisSurface = state.dataSurface->Surface(surf);
1720 : // !if (surface(surf)%heattranssurf) CYCLE ! Shading with a construction is allowed to be HT surf for daylighting shelves
1721 0 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) {
1722 0 : continue;
1723 : }
1724 0 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zoneNum).Name) {
1725 0 : continue;
1726 : }
1727 0 : if (thisSurface.Sides == 0) {
1728 0 : continue;
1729 : }
1730 0 : print(wrlfile, "# {}:{}\n", thisSurface.ZoneName, thisSurface.Name);
1731 0 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", surf);
1732 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1733 0 : print(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1734 : }
1735 0 : print(wrlfile, Format_803);
1736 0 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1737 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1738 0 : print(wrlfile, " {}", vert - 1);
1739 0 : if (vert == thisSurface.Sides) {
1740 0 : print(wrlfile, " -1\n");
1741 : }
1742 : }
1743 0 : print(wrlfile, Format_805);
1744 0 : } else { // will be >4 sided polygon with triangulate option
1745 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1746 0 : const int ntri = DXFEarClipping::Triangulate(state,
1747 : thisSurface.Sides,
1748 0 : thisSurface.Vertex,
1749 : mytriangles,
1750 : thisSurface.Azimuth,
1751 : thisSurface.Tilt,
1752 0 : thisSurface.Name,
1753 : thisSurface.Class);
1754 0 : for (int svert = 1; svert <= ntri; ++svert) {
1755 0 : const int vv0 = mytriangles(svert).vv0;
1756 0 : const int vv1 = mytriangles(svert).vv1;
1757 0 : const int vv2 = mytriangles(svert).vv2;
1758 0 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1759 : }
1760 0 : print(wrlfile, Format_805);
1761 0 : mytriangles.deallocate();
1762 0 : }
1763 0 : }
1764 : }
1765 :
1766 : // vrml does not have daylighting reference points included
1767 0 : }
1768 :
1769 : } // namespace EnergyPlus
|