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 801 : 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 801 : state.dataErrTracking->AskForSurfacesReport = false;
94 :
95 801 : int SurfDetails = 0;
96 801 : bool SurfVert = false;
97 801 : bool SurfDet = false;
98 801 : bool DXFDone = false;
99 801 : bool VRMLDone = false;
100 801 : std::string Option1;
101 801 : std::string Option2;
102 : bool DoReport;
103 :
104 2403 : General::ScanForReports(state, "Surfaces", DoReport, "Lines", Option1);
105 801 : if (DoReport) {
106 52 : LinesOut(state, Option1);
107 : }
108 :
109 2403 : General::ScanForReports(state, "Surfaces", DoReport, "Vertices");
110 801 : if (DoReport) {
111 5 : if (!SurfVert) {
112 5 : ++SurfDetails;
113 5 : SurfVert = true;
114 : }
115 : }
116 :
117 2403 : General::ScanForReports(state, "Surfaces", DoReport, "Details");
118 801 : if (DoReport) {
119 149 : if (!SurfDet) {
120 149 : SurfDetails += 10;
121 149 : SurfDet = true;
122 : }
123 : }
124 :
125 2403 : General::ScanForReports(state, "Surfaces", DoReport, "DetailsWithVertices");
126 801 : if (DoReport) {
127 31 : if (!SurfDet) {
128 31 : SurfDetails += 10;
129 31 : SurfDet = true;
130 : }
131 31 : if (!SurfVert) {
132 31 : ++SurfDetails;
133 31 : SurfVert = true;
134 : }
135 : }
136 :
137 2403 : General::ScanForReports(state, "Surfaces", DoReport, "DXF", Option1, Option2);
138 801 : if (DoReport) {
139 483 : if (!DXFDone) {
140 483 : if (!Option2.empty()) {
141 0 : DataSurfaceColors::SetUpSchemeColors(state, Option2, "DXF");
142 : }
143 483 : DXFOut(state, Option1, Option2);
144 483 : 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 2403 : General::ScanForReports(state, "Surfaces", DoReport, "DXF:WireFrame", Option1, Option2);
151 801 : if (DoReport) {
152 29 : if (!DXFDone) {
153 29 : if (!Option2.empty()) {
154 0 : DataSurfaceColors::SetUpSchemeColors(state, Option2, "DXF");
155 : }
156 29 : DXFOutWireFrame(state, Option2);
157 29 : DXFDone = true;
158 : } else {
159 0 : ShowWarningError(state, "ReportSurfaces: DXF output already generated. DXF:WireFrame will not be generated.");
160 : }
161 : }
162 :
163 2403 : General::ScanForReports(state, "Surfaces", DoReport, "VRML", Option1, Option2);
164 801 : if (DoReport) {
165 36 : if (!VRMLDone) {
166 36 : VRMLOut(state, Option1, Option2);
167 36 : 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 2403 : General::ScanForReports(state, "Surfaces", DoReport, "CostInfo");
174 801 : if (DoReport) {
175 7 : CostInfoOut(state);
176 : }
177 :
178 801 : if (SurfDet || SurfVert) {
179 185 : DetailsForSurfaces(state, SurfDetails);
180 : }
181 801 : }
182 :
183 52 : 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 52 : 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 52 : 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 52 : state.dataOutputReports->lastoption = option;
213 52 : state.dataOutputReports->optiondone = true;
214 :
215 104 : auto slnfile = state.files.sln.open(state, "LinesOut", state.files.outputControl.sln);
216 :
217 52 : if (option != "IDF") {
218 2282 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
219 2235 : auto &thisSurface = state.dataSurface->Surface(surf);
220 2235 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
221 0 : continue;
222 : }
223 2235 : if (thisSurface.Sides == 0) {
224 0 : continue;
225 : }
226 2235 : print<FormatSyntax::FMT>(slnfile, "{}:{}\n", thisSurface.ZoneName, thisSurface.Name);
227 11175 : 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 8940 : if (vert != thisSurface.Sides) {
231 6705 : print<check_syntax(fmt700)>(slnfile,
232 : fmt700,
233 6705 : thisSurface.Vertex(vert).x,
234 6705 : thisSurface.Vertex(vert).y,
235 6705 : thisSurface.Vertex(vert).z,
236 6705 : thisSurface.Vertex(vert + 1).x,
237 6705 : thisSurface.Vertex(vert + 1).y,
238 6705 : thisSurface.Vertex(vert + 1).z);
239 : } else {
240 2235 : print<check_syntax(fmt700)>(slnfile,
241 : fmt700,
242 2235 : thisSurface.Vertex(vert).x,
243 2235 : thisSurface.Vertex(vert).y,
244 2235 : thisSurface.Vertex(vert).z,
245 2235 : thisSurface.Vertex(1).x,
246 2235 : thisSurface.Vertex(1).y,
247 2235 : thisSurface.Vertex(1).z);
248 : }
249 : }
250 47 : }
251 : } else {
252 5 : print<FormatSyntax::FMT>(slnfile, "{}\n", " Building North Axis = 0");
253 5 : print<FormatSyntax::FMT>(slnfile, "{}\n", "GlobalGeometryRules,UpperLeftCorner,CounterClockwise,WorldCoordinates;");
254 367 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
255 362 : auto &thisSurface = state.dataSurface->Surface(surf);
256 362 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
257 40 : continue;
258 : }
259 322 : if (thisSurface.Sides == 0) {
260 0 : continue;
261 : }
262 : // process heat transfer surfaces
263 322 : print(slnfile, " Surface={}, Name={}, Azimuth={:.1R}\n", cSurfaceClass(thisSurface.Class), thisSurface.Name, thisSurface.Azimuth);
264 322 : print<FormatSyntax::FMT>(slnfile, " {}, !- Number of (X,Y,Z) groups in this surface\n", thisSurface.Sides);
265 1610 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
266 1288 : std::string optcommasemi = ",";
267 1288 : if (vert == thisSurface.Sides) {
268 322 : optcommasemi = ";";
269 : }
270 : static constexpr std::string_view fmtcoord(" {:10.2F},{:10.2F},{:10.2F}{} !- {} {}\n");
271 1288 : print<check_syntax(fmtcoord)>(slnfile,
272 : fmtcoord,
273 1288 : thisSurface.Vertex(vert).x,
274 1288 : thisSurface.Vertex(vert).y,
275 1288 : thisSurface.Vertex(vert).z,
276 : optcommasemi,
277 : vertexstring,
278 : vert);
279 1288 : }
280 5 : }
281 : }
282 52 : }
283 :
284 9272 : static std::string normalizeName(std::string name)
285 : {
286 18544 : std::replace(begin(name), end(name), ' ', '_');
287 18544 : std::replace(begin(name), end(name), ':', '_');
288 9272 : return name;
289 : }
290 :
291 512 : 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 512 : constexpr int lenArr = 4;
310 512 : std::array<Real64, lenArr> StemX = {-10.0, -10.0, -10.0, -10.0};
311 512 : std::array<Real64, lenArr> StemY = {3.0, 3.0, 0.0, 0.0};
312 512 : std::array<Real64, lenArr> StemZ = {0.1, 0.0, 0.0, 0.1};
313 512 : std::array<Real64, lenArr> Head1X = {-10.0, -10.0, -10.5, -10.5};
314 512 : std::array<Real64, lenArr> Head1Y = {3.0, 3.0, 2.133975, 2.133975};
315 512 : std::array<Real64, lenArr> Head1Z = {0.1, 0.0, 0.0, 0.1};
316 512 : std::array<Real64, lenArr> Head2X = {-10.0, -10.0, -9.5, -9.5};
317 512 : std::array<Real64, lenArr> Head2Y = {3.0, 3.0, 2.133975, 2.133975};
318 512 : std::array<Real64, lenArr> Head2Z = {0.1, 0.0, 0.0, 0.1};
319 512 : std::array<Real64, lenArr> NSide1X = {-10.5, -10.5, -10.5, -10.5};
320 512 : std::array<Real64, lenArr> NSide1Y = {4.5, 4.5, 3.5, 3.5};
321 512 : std::array<Real64, lenArr> NSide1Z = {0.1, 0.0, 0.0, 0.1};
322 512 : std::array<Real64, lenArr> NSide2X = {-10.5, -10.5, -9.5, -9.5};
323 512 : std::array<Real64, lenArr> NSide2Y = {4.5, 4.5, 3.5, 3.5};
324 512 : std::array<Real64, lenArr> NSide2Z = {0.1, 0.0, 0.0, 0.1};
325 512 : std::array<Real64, lenArr> NSide3X = {-9.5, -9.5, -9.5, -9.5};
326 512 : std::array<Real64, lenArr> NSide3Y = {4.5, 4.5, 3.5, 3.5};
327 512 : std::array<Real64, lenArr> NSide3Z = {0.1, 0.0, 0.0, 0.1};
328 :
329 512 : if (ColorScheme.empty()) {
330 512 : print(of, Format_708, "Color Scheme", ",", "Default");
331 : } else {
332 0 : print(of, Format_708, "Color Scheme", ",", ColorScheme);
333 : }
334 :
335 512 : Real64 minx = 99999.0;
336 512 : Real64 miny = 99999.0;
337 37096 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
338 36584 : auto &thisSurface = state.dataSurface->Surface(surf);
339 36584 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
340 2305 : continue;
341 : }
342 172140 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
343 137861 : minx = min(minx, thisSurface.Vertex(vert).x);
344 137861 : miny = min(miny, thisSurface.Vertex(vert).y);
345 : }
346 512 : }
347 :
348 2560 : for (int vert = 0; vert < lenArr; ++vert) {
349 2048 : StemX[vert] += minx;
350 2048 : StemY[vert] += miny;
351 2048 : Head1X[vert] += minx;
352 2048 : Head1Y[vert] += miny;
353 2048 : Head2X[vert] += minx;
354 2048 : Head2Y[vert] += miny;
355 2048 : NSide1X[vert] += minx;
356 2048 : NSide1Y[vert] += miny;
357 2048 : NSide2X[vert] += minx;
358 2048 : NSide2Y[vert] += miny;
359 2048 : NSide3X[vert] += minx;
360 2048 : NSide3Y[vert] += miny;
361 : }
362 :
363 512 : auto &DXFcolorno = state.dataSurfColor->DXFcolorno;
364 :
365 : // This writes "True North" above the Arrow Head
366 512 : print(of, Format_710, "Text - True North");
367 512 : print<check_syntax(Format_800)>(
368 512 : of, Format_800, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)], StemX[0] - 1.0, StemY[0], StemZ[0]);
369 :
370 512 : print(of, Format_710, "Text - Building Title");
371 512 : print<check_syntax(Format_801)>(of,
372 : Format_801,
373 512 : DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)],
374 512 : StemX[0] - 4.0,
375 512 : StemY[0] - 4.0,
376 512 : StemZ[0],
377 1024 : "Building - " + state.dataHeatBal->BuildingName);
378 :
379 : // We want to point the north arrow to true north
380 512 : print(of, Format_710, "North Arrow Stem");
381 512 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
382 512 : print(of, Format_703_1, StemX[0], StemY[0], StemZ[0]);
383 512 : print(of, Format_703_2, StemX[1], StemY[1], StemZ[1]);
384 512 : print(of, Format_703_3, StemX[2], StemY[2], StemZ[2]);
385 512 : print(of, Format_703_4, StemX[3], StemY[3], StemZ[3]);
386 :
387 512 : print(of, Format_710, "North Arrow Head 1");
388 512 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
389 512 : print(of, Format_703_1, Head1X[0], Head1Y[0], Head1Z[0]);
390 512 : print(of, Format_703_2, Head1X[1], Head1Y[1], Head1Z[1]);
391 512 : print(of, Format_703_3, Head1X[2], Head1Y[2], Head1Z[2]);
392 512 : print(of, Format_703_4, Head1X[3], Head1Y[3], Head1Z[3]);
393 :
394 512 : print(of, Format_710, "North Arrow Head 2");
395 512 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
396 512 : print(of, Format_703_1, Head2X[0], Head2Y[0], Head2Z[0]);
397 512 : print(of, Format_703_2, Head2X[1], Head2Y[1], Head2Z[1]);
398 512 : print(of, Format_703_3, Head2X[2], Head2Y[2], Head2Z[2]);
399 512 : print(of, Format_703_4, Head2X[3], Head2Y[3], Head2Z[3]);
400 :
401 512 : print(of, Format_710, "North Arrow Side 1");
402 512 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
403 512 : print(of, Format_703_1, NSide1X[0], NSide1Y[0], NSide1Z[0]);
404 512 : print(of, Format_703_2, NSide1X[1], NSide1Y[1], NSide1Z[1]);
405 512 : print(of, Format_703_3, NSide1X[2], NSide1Y[2], NSide1Z[2]);
406 512 : print(of, Format_703_4, NSide1X[3], NSide1Y[3], NSide1Z[3]);
407 :
408 512 : print(of, Format_710, "North Arrow Side 2");
409 512 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
410 512 : print(of, Format_703_1, NSide2X[0], NSide2Y[0], NSide2Z[0]);
411 512 : print(of, Format_703_2, NSide2X[1], NSide2Y[1], NSide2Z[1]);
412 512 : print(of, Format_703_3, NSide2X[2], NSide2Y[2], NSide2Z[2]);
413 512 : print(of, Format_703_4, NSide2X[3], NSide2Y[3], NSide2Z[3]);
414 :
415 512 : print(of, Format_710, "North Arrow Side 3");
416 512 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
417 512 : print(of, Format_703_1, NSide3X[0], NSide3Y[0], NSide3Z[0]);
418 512 : print(of, Format_703_2, NSide3X[1], NSide3Y[1], NSide3Z[1]);
419 512 : print(of, Format_703_3, NSide3X[2], NSide3Y[2], NSide3Z[2]);
420 512 : print(of, Format_703_4, NSide3X[3], NSide3Y[3], NSide3Z[3]);
421 :
422 512 : print(of, Format_710, "Zone Names");
423 :
424 4479 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
425 7934 : print<check_syntax(Format_710)>(of, Format_710, fmt::format("Zone={}:{}", zones, normalizeName(state.dataHeatBal->Zone(zones).Name)));
426 : }
427 512 : }
428 :
429 512 : 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 512 : if ((int)state.dataDayltg->DaylRefPt.size() > 0) {
436 386 : for (int daylightCtrlNum = 1; daylightCtrlNum <= (int)state.dataDayltg->daylightControl.size(); ++daylightCtrlNum) {
437 328 : auto &thisDaylightControl = state.dataDayltg->daylightControl(daylightCtrlNum);
438 328 : DataSurfaceColors::ColorNo curcolorno = DataSurfaceColors::ColorNo::DaylSensor1;
439 328 : std::string refPtType;
440 328 : if (thisDaylightControl.DaylightMethod == Dayltg::DaylightingMethod::DElight) {
441 3 : refPtType = "DEDayRefPt";
442 325 : } else if (thisDaylightControl.DaylightMethod == Dayltg::DaylightingMethod::SplitFlux) {
443 325 : refPtType = "DayRefPt";
444 : }
445 :
446 831 : for (auto const &refPt : thisDaylightControl.refPts) {
447 503 : print<FormatSyntax::FMT>(of, "999\n{}:{}:{}\n", thisDaylightControl.ZoneName, refPtType, state.dataDayltg->DaylRefPt(refPt.num).Name);
448 503 : print<check_syntax(Format_709)>(of,
449 : Format_709,
450 1006 : normalizeName(thisDaylightControl.ZoneName),
451 503 : state.dataSurfColor->DXFcolorno[static_cast<int>(curcolorno)],
452 503 : refPt.absCoords.x,
453 503 : refPt.absCoords.y,
454 503 : refPt.absCoords.z,
455 503 : 0.2);
456 503 : curcolorno = DataSurfaceColors::ColorNo::DaylSensor2; // ref pts 2 and later are this color
457 : }
458 328 : }
459 : }
460 512 : }
461 :
462 483 : 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 483 : bool ThickPolyline(false);
482 483 : bool RegularPolyline(false);
483 483 : std::string PolylineWidth(" 0.55");
484 483 : bool TriangulateFace(false);
485 :
486 : // Formats
487 483 : constexpr std::string_view Format_702(" 0\nSECTION\n 2\nENTITIES\n");
488 483 : constexpr std::string_view Format_707("999\nDXF created from EnergyPlus\n");
489 483 : constexpr std::string_view Format_708("999\n{}{}{}\n");
490 :
491 483 : 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 483 : 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 483 : constexpr std::string_view Format_717(" 0\nSEQEND\n 8\n{}\n");
495 483 : 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 483 : constexpr std::string_view Format_704_0(" 0\n3DFACE\n 8\n{}\n 62\n{:3}\n");
499 483 : constexpr std::string_view Format_704_1(" 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
500 483 : constexpr std::string_view Format_704_2(" 11\n{:15.5F}\n 21\n{:15.5F}\n 31\n{:15.5F}\n");
501 483 : constexpr std::string_view Format_704_3(" 12\n{:15.5F}\n 22\n{:15.5F}\n 32\n{:15.5F}\n");
502 483 : constexpr std::string_view Format_705(" 13\n{:15.5F}\n 23\n{:15.5F}\n 33\n{:15.5F}\n");
503 483 : constexpr std::string_view Format_706(" 0\nENDSEC\n 0\nEOF\n");
504 483 : 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 483 : constexpr std::string_view Format_710("999\n{}\n");
506 :
507 483 : if (PolygonAction == "TRIANGULATE3DFACE" || PolygonAction == "TRIANGULATE" || PolygonAction.empty()) {
508 477 : TriangulateFace = true;
509 477 : RegularPolyline = false;
510 477 : ThickPolyline = false;
511 6 : } else if (PolygonAction == "THICKPOLYLINE") {
512 2 : ThickPolyline = true;
513 2 : RegularPolyline = false;
514 2 : TriangulateFace = false;
515 4 : } else if (PolygonAction == "REGULARPOLYLINE") {
516 4 : RegularPolyline = true;
517 4 : TriangulateFace = false;
518 4 : ThickPolyline = false;
519 4 : 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 483 : 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 966 : auto dxffile = state.files.dxf.open(state, "DXFOut", state.files.outputControl.dxf);
535 :
536 483 : print(dxffile, Format_702); // Start of Entities section
537 :
538 483 : print(dxffile, Format_707); // Comment
539 :
540 483 : print(dxffile, Format_708, "Program Version", ",", state.dataStrGlobals->VerStringVar);
541 :
542 483 : if (PolygonAction.empty()) {
543 0 : print(dxffile, Format_708, "Polygon Action", ",", "Triangulate3DFace");
544 : } else {
545 483 : print(dxffile, Format_708, "Polygon Action", ",", PolygonAction);
546 : }
547 :
548 483 : WriteDXFCommon(state, dxffile, ColorScheme);
549 483 : auto &DXFcolorno = state.dataSurfColor->DXFcolorno;
550 483 : DataSurfaceColors::ColorNo colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
551 : // Do all detached shading surfaces first
552 36396 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
553 35913 : std::string ShadeType;
554 35913 : auto &thisSurface = state.dataSurface->Surface(surf);
555 :
556 35913 : if (thisSurface.HeatTransSurf) {
557 34712 : continue;
558 : }
559 1201 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) {
560 1075 : continue;
561 : }
562 126 : if (thisSurface.Sides == 0) {
563 0 : continue;
564 : }
565 126 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
566 86 : colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
567 : }
568 126 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
569 28 : colorindex = DataSurfaceColors::ColorNo::ShdDetBldg;
570 : }
571 126 : if (state.dataSurface->SurfIsPV(surf)) {
572 15 : colorindex = DataSurfaceColors::ColorNo::PV;
573 : }
574 126 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
575 86 : ShadeType = "Fixed Shading";
576 86 : print(dxffile, Format_710, "Fixed Shading:" + thisSurface.Name);
577 40 : } else if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
578 28 : ShadeType = "Building Shading";
579 28 : print(dxffile, Format_710, "Building Shading:" + thisSurface.Name);
580 : }
581 126 : if (thisSurface.Sides <= 4) {
582 126 : print(dxffile, Format_704_0, ShadeType, DXFcolorno[static_cast<int>(colorindex)]);
583 126 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
584 126 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
585 126 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
586 126 : if (thisSurface.Sides == 3) {
587 40 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
588 : } else {
589 86 : 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 36396 : }
636 :
637 : // now do zone surfaces, by zone
638 4366 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
639 3883 : const std::string TempZoneName = normalizeName(state.dataHeatBal->Zone(zones).Name);
640 :
641 1233225 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
642 1229342 : auto &thisSurface = state.dataSurface->Surface(surf);
643 1229342 : if (thisSurface.Zone != zones) {
644 1194619 : continue;
645 : }
646 34723 : if (thisSurface.Sides == 0) {
647 2305 : continue;
648 : }
649 32418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
650 0 : continue;
651 : }
652 32418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) {
653 17204 : colorindex = DataSurfaceColors::ColorNo::Wall;
654 : }
655 32418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) {
656 4523 : colorindex = DataSurfaceColors::ColorNo::Roof;
657 : }
658 32418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) {
659 5236 : colorindex = DataSurfaceColors::ColorNo::Floor;
660 : }
661 32418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) {
662 401 : colorindex = DataSurfaceColors::ColorNo::Door;
663 : }
664 32418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
665 5052 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::Window) {
666 4755 : colorindex = DataSurfaceColors::ColorNo::Window;
667 : }
668 5052 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::GlassDoor) {
669 295 : colorindex = DataSurfaceColors::ColorNo::GlassDoor;
670 : }
671 5052 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Dome) {
672 0 : colorindex = DataSurfaceColors::ColorNo::TDDDome;
673 : }
674 5052 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Diffuser) {
675 2 : colorindex = DataSurfaceColors::ColorNo::TDDDiffuser;
676 : }
677 : }
678 32418 : if (state.dataSurface->SurfIsPV(surf)) {
679 33 : colorindex = DataSurfaceColors::ColorNo::PV;
680 : }
681 :
682 32418 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
683 32418 : if (thisSurface.Sides <= 4) {
684 32248 : print(dxffile, Format_704_0, TempZoneName, DXFcolorno[static_cast<int>(colorindex)]);
685 32248 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
686 32248 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
687 32248 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
688 32248 : if (thisSurface.Sides == 3) {
689 127 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
690 : } else {
691 32121 : print(dxffile, Format_705, thisSurface.Vertex(4).x, thisSurface.Vertex(4).y, thisSurface.Vertex(4).z);
692 : }
693 : } else { // polygon surface
694 170 : if (!TriangulateFace) {
695 30 : Real64 minz = 99999.0;
696 510 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
697 480 : minz = min(minz, thisSurface.Vertex(vert).z);
698 : }
699 30 : print(dxffile, Format_715, TempZoneName, DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
700 510 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
701 480 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
702 : }
703 30 : print(dxffile, Format_717, TempZoneName);
704 : } else {
705 140 : Array1D<DataVectorTypes::dTriangle> mytriangles;
706 :
707 280 : const int ntri = DXFEarClipping::Triangulate(state,
708 : thisSurface.Sides,
709 140 : thisSurface.Vertex,
710 : mytriangles,
711 : thisSurface.Azimuth,
712 : thisSurface.Tilt,
713 140 : thisSurface.Name,
714 : thisSurface.Class);
715 970 : for (int svert = 1; svert <= ntri; ++svert) {
716 830 : const int vv0 = mytriangles(svert).vv0;
717 830 : const int vv1 = mytriangles(svert).vv1;
718 830 : const int vv2 = mytriangles(svert).vv2;
719 830 : print(dxffile,
720 : Format_704,
721 : TempZoneName,
722 830 : DXFcolorno[static_cast<int>(colorindex)],
723 830 : thisSurface.Vertex(vv0).x,
724 830 : thisSurface.Vertex(vv0).y,
725 830 : thisSurface.Vertex(vv0).z,
726 830 : thisSurface.Vertex(vv1).x,
727 830 : thisSurface.Vertex(vv1).y,
728 830 : thisSurface.Vertex(vv1).z,
729 830 : thisSurface.Vertex(vv2).x,
730 830 : thisSurface.Vertex(vv2).y,
731 830 : thisSurface.Vertex(vv2).z);
732 830 : print(dxffile, Format_705, thisSurface.Vertex(vv2).x, thisSurface.Vertex(vv2).y, thisSurface.Vertex(vv2).z);
733 : }
734 140 : mytriangles.deallocate();
735 140 : }
736 : }
737 3883 : }
738 : // still have to do shading surfaces for zone
739 1233225 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
740 1229342 : 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 1229342 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) {
743 1216406 : continue;
744 : }
745 12936 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zones).Name) {
746 11860 : continue;
747 : }
748 1076 : if (thisSurface.Sides == 0) {
749 0 : continue;
750 : }
751 1076 : colorindex = DataSurfaceColors::ColorNo::ShdAtt;
752 1076 : if (state.dataSurface->SurfIsPV(surf)) {
753 0 : colorindex = DataSurfaceColors::ColorNo::PV;
754 : }
755 1076 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
756 1076 : if (thisSurface.Sides <= 4) {
757 1076 : print(dxffile, Format_704_0, TempZoneName, DXFcolorno[static_cast<int>(colorindex)]);
758 1076 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
759 1076 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
760 1076 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
761 1076 : 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 1076 : 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 3883 : }
822 3883 : }
823 :
824 483 : DXFDaylightingReferencePoints(state, dxffile);
825 :
826 4366 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
827 3883 : const DataSurfaceColors::ColorNo curcolorno = DataSurfaceColors::ColorNo::DaylSensor1;
828 :
829 3915 : for (auto const &illumMap : state.dataDayltg->illumMaps) {
830 32 : if (illumMap.zoneIndex != zones) {
831 23 : continue;
832 : }
833 9 : int numRefPt = 0;
834 634 : for (auto const &refPt : illumMap.refPts) {
835 625 : print(dxffile, Format_710, format("{}:MapRefPt:{}", state.dataHeatBal->Zone(zones).Name, ++numRefPt));
836 625 : print(dxffile,
837 : Format_709,
838 1250 : normalizeName(state.dataHeatBal->Zone(zones).Name),
839 625 : DXFcolorno[static_cast<int>(curcolorno)],
840 625 : refPt.absCoords.x,
841 625 : refPt.absCoords.y,
842 625 : refPt.absCoords.z,
843 1250 : 0.05);
844 : }
845 : }
846 : }
847 :
848 483 : print(dxffile, Format_706);
849 483 : }
850 :
851 29 : 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 29 : constexpr std::string_view PolylineWidth = " 0.55";
868 :
869 29 : constexpr std::string_view Format_702(" 0\nSECTION\n 2\nENTITIES\n");
870 29 : constexpr std::string_view Format_707("999\nDXF created from EnergyPlus\n");
871 29 : constexpr std::string_view Format_708("999\n{}{}{}\n");
872 :
873 29 : 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 29 : 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 29 : constexpr std::string_view Format_717(" 0\nSEQEND\n 8\n{}\n");
877 29 : constexpr std::string_view Format_706(" 0\nENDSEC\n 0\nEOF\n");
878 29 : constexpr std::string_view Format_710("999\n{}\n");
879 :
880 29 : 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 58 : auto dxffile = state.files.dxf.open(state, "DXFOutWireFrame", state.files.outputControl.dxf);
886 :
887 29 : print(dxffile, Format_702); // Start of Entities section
888 :
889 29 : print(dxffile, Format_707); // Comment
890 :
891 29 : print(dxffile, Format_708, "Program Version", ",", state.dataStrGlobals->VerStringVar);
892 29 : print(dxffile, Format_708, "DXF using Wireframe", ' ', ' ');
893 :
894 29 : WriteDXFCommon(state, dxffile, ColorScheme);
895 :
896 : // Do all detached shading surfaces first
897 29 : int surfcount = 0;
898 29 : DataSurfaceColors::ColorNo colorindex = DataSurfaceColors::ColorNo::Invalid;
899 700 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
900 671 : std::string ShadeType;
901 671 : auto &thisSurface = state.dataSurface->Surface(surf);
902 671 : if (thisSurface.HeatTransSurf) {
903 627 : continue;
904 : }
905 44 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) {
906 44 : 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 700 : }
937 :
938 : // now do zone surfaces, by zone
939 113 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
940 84 : std::string const SaveZoneName = normalizeName(state.dataHeatBal->Zone(zones).Name);
941 :
942 84 : surfcount = 0;
943 3505 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
944 3421 : auto &thisSurface = state.dataSurface->Surface(surf);
945 3421 : if (thisSurface.Zone != zones) {
946 2794 : continue;
947 : }
948 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
949 0 : continue;
950 : }
951 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) {
952 333 : colorindex = DataSurfaceColors::ColorNo::Wall;
953 : }
954 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) {
955 84 : colorindex = DataSurfaceColors::ColorNo::Roof;
956 : }
957 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) {
958 128 : colorindex = DataSurfaceColors::ColorNo::Floor;
959 : }
960 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) {
961 14 : colorindex = DataSurfaceColors::ColorNo::Door;
962 : }
963 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
964 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::Window) {
965 46 : colorindex = DataSurfaceColors::ColorNo::Window;
966 : }
967 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::GlassDoor) {
968 22 : colorindex = DataSurfaceColors::ColorNo::GlassDoor;
969 : }
970 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Dome) {
971 0 : colorindex = DataSurfaceColors::ColorNo::TDDDome;
972 : }
973 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Diffuser) {
974 0 : colorindex = DataSurfaceColors::ColorNo::TDDDiffuser;
975 : }
976 : }
977 627 : if (state.dataSurface->SurfIsPV(surf)) {
978 0 : colorindex = DataSurfaceColors::ColorNo::PV;
979 : }
980 627 : ++surfcount;
981 :
982 627 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
983 627 : std::string const TempZoneName = format("{}_{}", SaveZoneName, surfcount);
984 627 : Real64 minz = 99999.0;
985 3135 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
986 2508 : minz = min(minz, thisSurface.Vertex(vert).z);
987 : }
988 :
989 627 : print(
990 627 : dxffile, Format_715, TempZoneName, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
991 3135 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
992 2508 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
993 : }
994 627 : print(dxffile, Format_717, TempZoneName);
995 711 : }
996 : // still have to do shading surfaces for zone
997 84 : surfcount = 0;
998 3505 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
999 3421 : auto &thisSurface = state.dataSurface->Surface(surf);
1000 3421 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) {
1001 3377 : continue;
1002 : }
1003 264 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zones).Name) {
1004 220 : continue;
1005 : }
1006 44 : colorindex = DataSurfaceColors::ColorNo::ShdAtt;
1007 44 : if (state.dataSurface->SurfIsPV(surf)) {
1008 0 : colorindex = DataSurfaceColors::ColorNo::PV;
1009 : }
1010 44 : ++surfcount;
1011 :
1012 44 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
1013 44 : std::string const TempZoneName = format("{}_{}", SaveZoneName, surfcount);
1014 44 : Real64 minz = 99999.0;
1015 220 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1016 176 : minz = min(minz, thisSurface.Vertex(vert).z);
1017 : }
1018 :
1019 44 : print(
1020 44 : dxffile, Format_715, TempZoneName, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
1021 220 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1022 176 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1023 : }
1024 44 : print(dxffile, Format_717, TempZoneName);
1025 128 : }
1026 84 : }
1027 :
1028 29 : DXFDaylightingReferencePoints(state, dxffile);
1029 :
1030 29 : print(dxffile, Format_706);
1031 29 : }
1032 :
1033 185 : 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 185 : std::string BaseSurfName;
1052 185 : std::string ConstructionName;
1053 185 : std::string IntConvCoeffCalc;
1054 185 : std::string ExtConvCoeffCalc;
1055 : Real64 NominalUwithConvCoeffs;
1056 185 : std::string cNominalU;
1057 185 : std::string cNominalUwithConvCoeffs;
1058 185 : std::string SolarDiffusing;
1059 185 : std::string AlgoName;
1060 :
1061 185 : 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 185 : std::stringstream ss;
1067 185 : auto *eiostream = &ss;
1068 : //!!! Write Header lines for report
1069 185 : if (RptType == 10) { // Details only
1070 149 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces\n"; // Format_700
1071 149 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces\n"; // Format_700b
1072 149 : *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 149 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides\n"; // Format_7011
1077 149 : *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 149 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides\n"; // Format_7011b
1082 149 : *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 149 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal {m}\n"; // Format_7011c
1085 36 : } else if (RptType == 11) { // Details with Vertices
1086 31 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces"; // Format_700
1087 31 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1088 31 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces"; // Format_700b
1089 31 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1090 31 : *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 31 : "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 31 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1097 31 : *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 31 : "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 31 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1104 31 : *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 31 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal {m}\n"; // Format_7011c
1108 : } else { // Vertices only
1109 5 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces"; // Format_700
1110 5 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1111 5 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces"; // Format_700b
1112 5 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1113 5 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
1114 5 : *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 5 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1117 5 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
1118 5 : *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 5 : "{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 185 : int surf2 = 0;
1126 711 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1127 711 : surf2 = surf;
1128 711 : auto const &thisSurface = state.dataSurface->Surface(surf);
1129 711 : if (thisSurface.Zone != 0) {
1130 185 : break;
1131 : }
1132 185 : }
1133 185 : if ((surf2 - 1) > 0) {
1134 53 : std::string ScheduleName;
1135 53 : std::string cSchedMin;
1136 53 : std::string cSchedMax;
1137 53 : *eiostream << "Shading Surfaces," << "Number of Shading Surfaces," << surf2 - 1 << '\n';
1138 579 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1139 579 : auto &thisSurface = state.dataSurface->Surface(surf);
1140 579 : if (thisSurface.Zone != 0) {
1141 53 : break;
1142 : }
1143 526 : AlgoName = "None";
1144 526 : *eiostream << "Shading Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << thisSurface.BaseSurfName << ","
1145 526 : << AlgoName << ",";
1146 526 : if (RptType == 10) {
1147 426 : if (thisSurface.shadowSurfSched != nullptr) {
1148 264 : ScheduleName = thisSurface.shadowSurfSched->Name;
1149 264 : cSchedMin = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1150 264 : cSchedMax = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1151 : } else {
1152 162 : ScheduleName = "";
1153 162 : cSchedMin = "0.0";
1154 162 : cSchedMax = "0.0";
1155 : }
1156 426 : *eiostream << ScheduleName << "," << cSchedMin << "," << cSchedMax << "," << ' ' << "," << format("{:.2R}", thisSurface.Area) << ","
1157 1278 : << format("{:.2R}", thisSurface.GrossArea) << "," << format("{:.2R}", thisSurface.NetAreaShadowCalc) << ","
1158 1278 : << format("{:.2R}", thisSurface.Azimuth) << "," << format("{:.2R}", thisSurface.Tilt) << ","
1159 2556 : << format("{:.2R}", thisSurface.Width) << "," << format("{:.2R}", thisSurface.Height) << ",";
1160 426 : *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << '\n';
1161 100 : } else if (RptType == 1) {
1162 0 : *eiostream << fmt::to_string(thisSurface.Sides) << ",";
1163 : } else {
1164 100 : if (thisSurface.shadowSurfSched != nullptr) {
1165 60 : ScheduleName = thisSurface.shadowSurfSched->Name;
1166 60 : cSchedMin = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1167 60 : cSchedMax = format("{:.2R}", thisSurface.shadowSurfSched->getMinVal(state));
1168 : } else {
1169 40 : ScheduleName = "";
1170 40 : cSchedMin = "0.0";
1171 40 : cSchedMax = "0.0";
1172 : }
1173 100 : *eiostream << ScheduleName << "," << cSchedMin << "," << cSchedMax << "," << ' ' << "," << format("{:.2R}", thisSurface.Area) << ","
1174 300 : << format("{:.2R}", thisSurface.GrossArea) << "," << format("{:.2R}", thisSurface.NetAreaShadowCalc) << ","
1175 300 : << format("{:.2R}", thisSurface.Azimuth) << "," << format("{:.2R}", thisSurface.Tilt) << ","
1176 600 : << format("{:.2R}", thisSurface.Width) << "," << format("{:.2R}", thisSurface.Height) << ",";
1177 100 : *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << ",";
1178 : }
1179 526 : if (RptType == 10) {
1180 426 : continue;
1181 : }
1182 488 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1183 388 : if (vert != thisSurface.Sides) {
1184 864 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1185 864 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1186 : } else {
1187 300 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1188 300 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1189 : }
1190 : }
1191 : // This shouldn't happen with shading surface -- always have vertices
1192 100 : if (thisSurface.Sides == 0) {
1193 0 : *eiostream << '\n';
1194 : }
1195 53 : }
1196 53 : }
1197 :
1198 2846 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1199 2661 : *eiostream << "Zone Surfaces," << state.dataHeatBal->Zone(ZoneNum).Name << ","
1200 2661 : << (state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast - state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst + 1) << '\n';
1201 1194677 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1202 1192016 : auto &thisSurface = state.dataSurface->Surface(surf);
1203 1192016 : if (thisSurface.Zone != ZoneNum) {
1204 1167184 : continue;
1205 : }
1206 24832 : SolarDiffusing = "";
1207 24832 : if (RptType == 10 || RptType == 11) { // Details and Details with Vertices
1208 24499 : if (thisSurface.BaseSurf == surf) {
1209 20511 : BaseSurfName = "";
1210 : } else {
1211 3988 : BaseSurfName = thisSurface.BaseSurfName;
1212 : }
1213 :
1214 24499 : 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 24499 : IntConvCoeffCalc = ConvCoeffCalcs[Convect::HcIntReportVals[static_cast<int>(state.dataHeatBal->Zone(ZoneNum).IntConvAlgo)] - 1];
1219 24499 : ExtConvCoeffCalc = ConvCoeffCalcs[Convect::HcExtReportVals[static_cast<int>(state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo)] - 1];
1220 :
1221 24499 : *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << ","
1222 24499 : << 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 24499 : if (thisSurface.Construction > 0 && thisSurface.Construction <= state.dataHeatBal->TotConstructs) {
1228 24499 : cNominalUwithConvCoeffs = "";
1229 24499 : ConstructionName = state.dataConstruction->Construct(thisSurface.Construction).Name;
1230 24499 : switch (thisSurface.Class) {
1231 11648 : 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 11648 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1235 11630 : NominalUwithConvCoeffs = 1.0 / (0.1197548 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0299387);
1236 : } else {
1237 18 : cNominalUwithConvCoeffs = "[invalid]";
1238 : }
1239 11648 : } break;
1240 3573 : 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 3573 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1244 3573 : NominalUwithConvCoeffs = 1.0 / (0.1620212 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0810106);
1245 : } else {
1246 0 : cNominalUwithConvCoeffs = "[invalid]";
1247 : }
1248 3573 : } break;
1249 3097 : 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 3097 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1253 3097 : NominalUwithConvCoeffs = 1.0 / (0.1074271 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0810106);
1254 : } else {
1255 0 : cNominalUwithConvCoeffs = "[invalid]";
1256 : }
1257 3097 : } break;
1258 6181 : default: {
1259 6181 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1260 6181 : NominalUwithConvCoeffs = state.dataHeatBal->NominalU(thisSurface.Construction);
1261 : } else {
1262 0 : cNominalUwithConvCoeffs = "[invalid]";
1263 : }
1264 6181 : } break;
1265 : }
1266 24499 : if (cNominalUwithConvCoeffs.empty()) {
1267 24481 : cNominalUwithConvCoeffs = format("{:.3R}", NominalUwithConvCoeffs);
1268 : } else {
1269 18 : cNominalUwithConvCoeffs = "[invalid]";
1270 : }
1271 24499 : if ((thisSurface.Class == DataSurfaces::SurfaceClass::Window) || (thisSurface.Class == DataSurfaces::SurfaceClass::TDD_Dome)) {
1272 : // DataSurfaces::SurfaceClass::Window also covers glass doors and TDD:Diffusers
1273 3687 : cNominalU = "N/A";
1274 7374 : if (state.dataSurface->SurfWinSolarDiffusing(surf)) {
1275 0 : SolarDiffusing = "Yes";
1276 : } else {
1277 3687 : SolarDiffusing = "No";
1278 : }
1279 : } else {
1280 20812 : 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 73497 : << format("{:.2R}", thisSurface.Area) << "," << format("{:.2R}", thisSurface.GrossArea) << ","
1290 73497 : << format("{:.2R}", thisSurface.NetAreaShadowCalc) << "," << format("{:.2R}", thisSurface.Azimuth) << ","
1291 73497 : << format("{:.2R}", thisSurface.Tilt) << "," << format("{:.2R}", thisSurface.Width) << ","
1292 171493 : << 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 24499 : auto const &surfIntConv = state.dataSurface->surfIntConv(surf);
1298 24499 : auto const &surfExtConv = state.dataSurface->surfExtConv(surf);
1299 24499 : if (surfIntConv.userModelNum != 0) {
1300 14 : IntConvCoeffCalc = overrideTypeStrs[(int)state.dataSurface->userIntConvModels(surfIntConv.userModelNum).overrideType];
1301 : } else {
1302 24485 : Convect::HcInt hcInt = surfIntConv.model;
1303 24485 : if (hcInt == Convect::HcInt::SetByZone) {
1304 24485 : hcInt = state.dataHeatBal->Zone(ZoneNum).IntConvAlgo;
1305 : }
1306 24485 : IntConvCoeffCalc = ConvCoeffCalcs[Convect::HcIntReportVals[(int)hcInt] - 1];
1307 : }
1308 24499 : if (surfExtConv.userModelNum != 0) {
1309 14 : ExtConvCoeffCalc = overrideTypeStrs[(int)state.dataSurface->userExtConvModels(surfExtConv.userModelNum).overrideType];
1310 : } else {
1311 24485 : Convect::HcExt hcExt = surfExtConv.model;
1312 24485 : if (hcExt == Convect::HcExt::SetByZone) {
1313 24473 : hcExt = state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo;
1314 : }
1315 24485 : ExtConvCoeffCalc = ConvCoeffCalcs[Convect::HcExtReportVals[static_cast<int>(hcExt)] - 1];
1316 : }
1317 24499 : if (thisSurface.ExtBoundCond == DataSurfaces::ExternalEnvironment) {
1318 8494 : *eiostream << "ExternalEnvironment" << "," << ExtConvCoeffCalc << "," << IntConvCoeffCalc << ",";
1319 16005 : } else if (thisSurface.ExtBoundCond == DataSurfaces::Ground) {
1320 918 : *eiostream << "Ground" << "," << "N/A-Ground" << "," << IntConvCoeffCalc << ",";
1321 15087 : } else if (thisSurface.ExtBoundCond == DataSurfaces::GroundFCfactorMethod) {
1322 160 : *eiostream << "FCGround" << "," << "N/A-FCGround" << "," << IntConvCoeffCalc << ",";
1323 14927 : } else if (thisSurface.ExtBoundCond == DataSurfaces::KivaFoundation) {
1324 15 : *eiostream << "Foundation" << "," << "N/A-Foundation" << "," << IntConvCoeffCalc << ",";
1325 14912 : } else if (thisSurface.ExtBoundCond == DataSurfaces::OtherSideCoefNoCalcExt ||
1326 14909 : thisSurface.ExtBoundCond == DataSurfaces::OtherSideCoefCalcExt) {
1327 4 : *eiostream << state.dataSurface->OSC(thisSurface.OSCPtr).Name << "," << "N/A-OSC" << "," << IntConvCoeffCalc << ",";
1328 14908 : } else if (thisSurface.ExtBoundCond == DataSurfaces::OtherSideCondModeledExt) {
1329 3 : *eiostream << state.dataSurface->OSCM(thisSurface.OSCMPtr).Name << "," << "N/A-OSCM" << "," << IntConvCoeffCalc << ",";
1330 : } else {
1331 14905 : *eiostream << thisSurface.ExtBoundCondName << "," << "Other/Same Surface Int Conv" << "," << IntConvCoeffCalc << ",";
1332 : }
1333 24499 : if (thisSurface.ExtSolar) {
1334 8421 : *eiostream << "SunExposed" << ",";
1335 : } else {
1336 16078 : *eiostream << "NoSun" << ",";
1337 : }
1338 24499 : if (thisSurface.ExtWind) {
1339 8484 : *eiostream << "WindExposed" << ",";
1340 : } else {
1341 16015 : *eiostream << "NoWind" << ",";
1342 : }
1343 24499 : if (RptType == 10) {
1344 70899 : *eiostream << format("{:.2R}", thisSurface.ViewFactorGround) << "," << format("{:.2R}", thisSurface.ViewFactorSky) << ","
1345 70899 : << format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," << format("{:.2R}", thisSurface.ViewFactorSkyIR) << ","
1346 118165 : << fmt::to_string(thisSurface.Sides) << '\n';
1347 : } else {
1348 2598 : *eiostream << format("{:.2R}", thisSurface.ViewFactorGround) << "," << format("{:.2R}", thisSurface.ViewFactorSky) << ","
1349 2598 : << format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," << format("{:.2R}", thisSurface.ViewFactorSkyIR) << ","
1350 4330 : << fmt::to_string(thisSurface.Sides) << ",";
1351 3990 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1352 3124 : if (vert != thisSurface.Sides) {
1353 7053 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1354 7053 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1355 : } else {
1356 2319 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1357 2319 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1358 : }
1359 : }
1360 866 : if (thisSurface.Sides == 0) {
1361 93 : *eiostream << '\n';
1362 : }
1363 : }
1364 : // if window, report frame/divider as appropriate
1365 24499 : if (thisSurface.FrameDivider > 0) {
1366 274 : int fd = thisSurface.FrameDivider;
1367 274 : if (state.dataSurface->FrameDivider(fd).FrameWidth > 0.0) {
1368 69 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1369 69 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << "," << "Frame," << thisSurface.Name
1370 138 : << "," << AlgoName << ",";
1371 138 : *eiostream << ",N/A,N/A,," << format("{:.2R}", state.dataSurface->SurfWinFrameArea(surf)) << ","
1372 138 : << format("{:.2R}", state.dataSurface->SurfWinFrameArea(surf) / thisSurface.Multiplier) << ",*" << ",N/A"
1373 207 : << ",N/A," << format("{:.2R}", state.dataSurface->FrameDivider(fd).FrameWidth) << ",N/A" << '\n';
1374 : }
1375 274 : if (state.dataSurface->FrameDivider(fd).DividerWidth > 0.0) {
1376 5 : 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 5 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << "," << "Divider:Suspended,"
1381 10 : << thisSurface.Name << ",,";
1382 : }
1383 10 : *eiostream << ",N/A,N/A,," << format("{:.2R}", state.dataSurface->SurfWinDividerArea(surf)) << ","
1384 10 : << format("{:.2R}", state.dataSurface->SurfWinDividerArea(surf) / thisSurface.Multiplier) << ",*" << ",N/A"
1385 15 : << ",N/A," << format("{:.2R}", state.dataSurface->FrameDivider(fd).DividerWidth) << ",N/A" << '\n';
1386 : }
1387 : }
1388 24499 : } else { // RptType=1 Vertices only
1389 333 : if (thisSurface.BaseSurf == surf) {
1390 286 : BaseSurfName = "";
1391 : } else {
1392 47 : BaseSurfName = thisSurface.BaseSurfName;
1393 : }
1394 :
1395 333 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1396 :
1397 333 : *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << ","
1398 333 : << AlgoName << ",";
1399 333 : *eiostream << fmt::to_string(thisSurface.Sides) << ",";
1400 1505 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1401 1172 : if (vert != thisSurface.Sides) {
1402 2637 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1403 2637 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1404 : } else {
1405 879 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1406 879 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1407 : }
1408 : }
1409 333 : if (thisSurface.Sides == 0) {
1410 40 : *eiostream << '\n';
1411 : }
1412 : }
1413 2661 : } // surfaces
1414 : } // zones
1415 :
1416 185 : print(state.files.eio, "{}", eiostream->str());
1417 185 : }
1418 :
1419 7 : 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 7 : Array1D_bool uniqueSurf;
1438 :
1439 7 : 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 7 : uniqueSurf.dimension(state.dataSurface->TotSurfaces, true);
1446 :
1447 428 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1448 421 : auto const &thisSurface = state.dataSurface->Surface(surf);
1449 421 : if (thisSurface.ExtBoundCond > 0) {
1450 209 : if (thisSurface.ExtBoundCond < surf) { // already cycled through
1451 82 : uniqueSurf(surf) = false;
1452 : }
1453 : }
1454 421 : if (thisSurface.Construction == 0) { // throw out others for now
1455 30 : uniqueSurf(surf) = false;
1456 : }
1457 7 : }
1458 :
1459 14 : auto scifile = state.files.sci.open(state, "CostInfoOut", state.files.outputControl.sci);
1460 :
1461 7 : print(scifile, "{:12}{:12}\n", state.dataSurface->TotSurfaces, count(uniqueSurf));
1462 7 : print(scifile, "{}\n", " data for surfaces useful for cost information");
1463 7 : print(scifile, "{}\n", " Number, Name, Construction, class, area, grossarea");
1464 :
1465 428 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1466 : // if (surface(surf)%class .eq. DataSurfaces::SurfaceClass::IntMass) CYCLE
1467 421 : if (!uniqueSurf(surf)) {
1468 112 : continue;
1469 : }
1470 : // why the heck are constructions == 0 ?
1471 309 : auto &thisSurface = state.dataSurface->Surface(surf);
1472 309 : if (thisSurface.Construction != 0) {
1473 : // Formats
1474 : static constexpr std::string_view Format_801("{:5},{},{},{},{:14.5F},{:14.5F}\n");
1475 309 : print<check_syntax(Format_801)>(scifile,
1476 : Format_801,
1477 : surf,
1478 309 : thisSurface.Name,
1479 309 : state.dataConstruction->Construct(thisSurface.Construction).Name,
1480 309 : cSurfaceClass(thisSurface.Class),
1481 309 : thisSurface.Area,
1482 309 : thisSurface.GrossArea);
1483 : }
1484 7 : }
1485 :
1486 7 : uniqueSurf.deallocate();
1487 7 : }
1488 :
1489 36 : 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 36 : bool ThickPolyline(false);
1524 36 : bool RegularPolyline(false);
1525 36 : std::string PolylineWidth(" 0.55");
1526 36 : 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 36 : if (PolygonAction == "TRIANGULATE3DFACE" || PolygonAction == "TRIANGULATE") {
1540 36 : 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 36 : 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 72 : auto wrlfile = state.files.wrl.open(state, "VRMLOut", state.files.outputControl.wrl);
1558 :
1559 36 : print(wrlfile, Format_702);
1560 :
1561 36 : if (ColorScheme.empty()) {
1562 36 : print<check_syntax(Format_707)>(
1563 36 : 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 36 : print(wrlfile, "# Zone Names\n");
1570 246 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
1571 210 : print(wrlfile, "# Zone={}:{}\n", zones, normalizeName(state.dataHeatBal->Zone(zones).Name));
1572 : }
1573 :
1574 : // Define the colors:
1575 :
1576 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "FLOOR", "0.502 0.502 0.502");
1577 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "ROOF", "1 1 0");
1578 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "WALL", "0 1 0");
1579 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "WINDOW", "0 1 1");
1580 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "DOOR", "0 1 1");
1581 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "GLASSDOOR", "0 1 1");
1582 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "FIXEDSHADE", "1 0 1");
1583 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "BLDGSHADE", "0 0 1");
1584 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "SUBSHADE", "1 0 1");
1585 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "BACKCOLOR", "0.502 0.502 0.784");
1586 :
1587 36 : Color colorindex = Color::Invalid;
1588 :
1589 : // Do all detached shading surfaces first
1590 1834 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1591 1798 : auto &thisSurface = state.dataSurface->Surface(surf);
1592 1798 : if (thisSurface.HeatTransSurf) {
1593 1650 : continue;
1594 : }
1595 148 : if (thisSurface.IsAirBoundarySurf) {
1596 16 : continue;
1597 : }
1598 132 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) {
1599 132 : 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 36 : }
1648 : // ! now do zone surfaces, by zone
1649 246 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
1650 210 : int oldSurfNum = 0;
1651 10917 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1652 10707 : auto &thisSurface = state.dataSurface->Surface(surf);
1653 10707 : ++oldSurfNum;
1654 10707 : if (thisSurface.Zone != zoneNum) {
1655 9041 : continue;
1656 : }
1657 1666 : if (thisSurface.Sides == 0) {
1658 20 : continue;
1659 : }
1660 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) {
1661 0 : continue;
1662 : }
1663 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) {
1664 857 : colorindex = Color::Wall;
1665 : }
1666 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) {
1667 217 : colorindex = Color::Roof;
1668 : }
1669 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::TDD_Dome) {
1670 0 : colorindex = Color::Window;
1671 : }
1672 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) {
1673 355 : colorindex = Color::Floor;
1674 : }
1675 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
1676 217 : colorindex = Color::Window;
1677 : }
1678 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) {
1679 0 : colorindex = Color::Window;
1680 : }
1681 :
1682 1646 : print(wrlfile, "# {}:{}\n", thisSurface.ZoneName, thisSurface.Name);
1683 1646 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", oldSurfNum);
1684 8232 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1685 6586 : print(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1686 : }
1687 1646 : print<check_syntax(Format_803)>(wrlfile, Format_803);
1688 1646 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1689 8214 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1690 6570 : print(wrlfile, " {}", vert - 1);
1691 6570 : if (vert == thisSurface.Sides) {
1692 1644 : print(wrlfile, " -1\n");
1693 : }
1694 : }
1695 1644 : print<check_syntax(Format_805)>(wrlfile, Format_805);
1696 1644 : } else { // will be >4 sided polygon with triangulate option
1697 2 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1698 4 : const int ntri = DXFEarClipping::Triangulate(state,
1699 : thisSurface.Sides,
1700 2 : thisSurface.Vertex,
1701 : mytriangles,
1702 : thisSurface.Azimuth,
1703 : thisSurface.Tilt,
1704 2 : thisSurface.Name,
1705 : thisSurface.Class);
1706 14 : for (int svert = 1; svert <= ntri; ++svert) {
1707 12 : const int vv0 = mytriangles(svert).vv0;
1708 12 : const int vv1 = mytriangles(svert).vv1;
1709 12 : const int vv2 = mytriangles(svert).vv2;
1710 12 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1711 : }
1712 2 : print(wrlfile, Format_805);
1713 2 : mytriangles.deallocate();
1714 2 : }
1715 210 : }
1716 : // still have to do shading surfaces for zone
1717 210 : colorindex = Color::SubShade;
1718 10917 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1719 10707 : 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 10707 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) {
1722 9911 : continue;
1723 : }
1724 796 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zoneNum).Name) {
1725 664 : continue;
1726 : }
1727 132 : if (thisSurface.Sides == 0) {
1728 0 : continue;
1729 : }
1730 132 : print(wrlfile, "# {}:{}\n", thisSurface.ZoneName, thisSurface.Name);
1731 132 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", surf);
1732 660 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1733 528 : print(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1734 : }
1735 132 : print(wrlfile, Format_803);
1736 132 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1737 660 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1738 528 : print(wrlfile, " {}", vert - 1);
1739 528 : if (vert == thisSurface.Sides) {
1740 132 : print(wrlfile, " -1\n");
1741 : }
1742 : }
1743 132 : print(wrlfile, Format_805);
1744 132 : } 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 210 : }
1764 : }
1765 :
1766 : // vrml does not have daylighting reference points included
1767 36 : }
1768 :
1769 : } // namespace EnergyPlus
|