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