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