Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, 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 796 : 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 796 : state.dataErrTracking->AskForSurfacesReport = false;
94 :
95 796 : int SurfDetails = 0;
96 796 : bool SurfVert = false;
97 796 : bool SurfDet = false;
98 796 : bool DXFDone = false;
99 796 : bool VRMLDone = false;
100 796 : std::string Option1;
101 796 : std::string Option2;
102 : bool DoReport;
103 :
104 796 : General::ScanForReports(state, "Surfaces", DoReport, "Lines", Option1);
105 796 : if (DoReport) LinesOut(state, Option1);
106 :
107 796 : General::ScanForReports(state, "Surfaces", DoReport, "Vertices");
108 796 : if (DoReport) {
109 5 : if (!SurfVert) {
110 5 : ++SurfDetails;
111 5 : SurfVert = true;
112 : }
113 : }
114 :
115 796 : General::ScanForReports(state, "Surfaces", DoReport, "Details");
116 796 : if (DoReport) {
117 148 : if (!SurfDet) {
118 148 : SurfDetails += 10;
119 148 : SurfDet = true;
120 : }
121 : }
122 :
123 796 : General::ScanForReports(state, "Surfaces", DoReport, "DetailsWithVertices");
124 796 : 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 796 : General::ScanForReports(state, "Surfaces", DoReport, "DXF", Option1, Option2);
136 796 : if (DoReport) {
137 480 : if (!DXFDone) {
138 480 : if (!Option2.empty()) {
139 0 : DataSurfaceColors::SetUpSchemeColors(state, Option2, "DXF");
140 : }
141 480 : DXFOut(state, Option1, Option2);
142 480 : 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 796 : General::ScanForReports(state, "Surfaces", DoReport, "DXF:WireFrame", Option1, Option2);
149 796 : if (DoReport) {
150 29 : if (!DXFDone) {
151 29 : if (!Option2.empty()) {
152 0 : DataSurfaceColors::SetUpSchemeColors(state, Option2, "DXF");
153 : }
154 29 : DXFOutWireFrame(state, Option2);
155 29 : DXFDone = true;
156 : } else {
157 0 : ShowWarningError(state, "ReportSurfaces: DXF output already generated. DXF:WireFrame will not be generated.");
158 : }
159 : }
160 :
161 796 : General::ScanForReports(state, "Surfaces", DoReport, "VRML", Option1, Option2);
162 796 : if (DoReport) {
163 36 : if (!VRMLDone) {
164 36 : VRMLOut(state, Option1, Option2);
165 36 : 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 796 : General::ScanForReports(state, "Surfaces", DoReport, "CostInfo");
172 796 : if (DoReport) {
173 7 : CostInfoOut(state);
174 : }
175 :
176 796 : if (SurfDet || SurfVert) {
177 184 : DetailsForSurfaces(state, SurfDetails);
178 : }
179 796 : }
180 :
181 51 : 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 51 : 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 51 : 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 51 : state.dataOutputReports->lastoption = option;
211 51 : state.dataOutputReports->optiondone = true;
212 :
213 102 : auto slnfile = state.files.sln.open(state, "LinesOut", state.files.outputControl.sln);
214 :
215 51 : if (option != "IDF") {
216 2231 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
217 2185 : auto &thisSurface = state.dataSurface->Surface(surf);
218 2185 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) continue;
219 2185 : if (thisSurface.Sides == 0) continue;
220 2185 : print<FormatSyntax::FMT>(slnfile, "{}:{}\n", thisSurface.ZoneName, thisSurface.Name);
221 10925 : 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 8740 : if (vert != thisSurface.Sides) {
225 6555 : print<check_syntax(fmt700)>(slnfile,
226 : fmt700,
227 6555 : thisSurface.Vertex(vert).x,
228 6555 : thisSurface.Vertex(vert).y,
229 6555 : thisSurface.Vertex(vert).z,
230 6555 : thisSurface.Vertex(vert + 1).x,
231 6555 : thisSurface.Vertex(vert + 1).y,
232 6555 : thisSurface.Vertex(vert + 1).z);
233 : } else {
234 2185 : print<check_syntax(fmt700)>(slnfile,
235 : fmt700,
236 2185 : thisSurface.Vertex(vert).x,
237 2185 : thisSurface.Vertex(vert).y,
238 2185 : thisSurface.Vertex(vert).z,
239 2185 : thisSurface.Vertex(1).x,
240 2185 : thisSurface.Vertex(1).y,
241 2185 : thisSurface.Vertex(1).z);
242 : }
243 : }
244 46 : }
245 : } else {
246 5 : print<FormatSyntax::FMT>(slnfile, "{}\n", " Building North Axis = 0");
247 5 : print<FormatSyntax::FMT>(slnfile, "{}\n", "GlobalGeometryRules,UpperLeftCorner,CounterClockwise,WorldCoordinates;");
248 367 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
249 362 : auto &thisSurface = state.dataSurface->Surface(surf);
250 362 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) continue;
251 322 : if (thisSurface.Sides == 0) continue;
252 : // process heat transfer surfaces
253 322 : print(slnfile, " Surface={}, Name={}, Azimuth={:.1R}\n", cSurfaceClass(thisSurface.Class), thisSurface.Name, thisSurface.Azimuth);
254 322 : print<FormatSyntax::FMT>(slnfile, " {}, !- Number of (X,Y,Z) groups in this surface\n", thisSurface.Sides);
255 1610 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
256 1288 : std::string optcommasemi = ",";
257 1288 : if (vert == thisSurface.Sides) optcommasemi = ";";
258 : static constexpr std::string_view fmtcoord(" {:10.2F},{:10.2F},{:10.2F}{} !- {} {}\n");
259 1288 : print<check_syntax(fmtcoord)>(slnfile,
260 : fmtcoord,
261 1288 : thisSurface.Vertex(vert).x,
262 1288 : thisSurface.Vertex(vert).y,
263 1288 : thisSurface.Vertex(vert).z,
264 : optcommasemi,
265 : vertexstring,
266 : vert);
267 1288 : }
268 5 : }
269 : }
270 51 : }
271 :
272 8942 : static std::string normalizeName(std::string name)
273 : {
274 8942 : std::replace(begin(name), end(name), ' ', '_');
275 8942 : std::replace(begin(name), end(name), ':', '_');
276 8942 : return name;
277 : }
278 :
279 509 : 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 509 : constexpr int lenArr = 4;
298 509 : std::array<Real64, lenArr> StemX = {-10.0, -10.0, -10.0, -10.0};
299 509 : std::array<Real64, lenArr> StemY = {3.0, 3.0, 0.0, 0.0};
300 509 : std::array<Real64, lenArr> StemZ = {0.1, 0.0, 0.0, 0.1};
301 509 : std::array<Real64, lenArr> Head1X = {-10.0, -10.0, -10.5, -10.5};
302 509 : std::array<Real64, lenArr> Head1Y = {3.0, 3.0, 2.133975, 2.133975};
303 509 : std::array<Real64, lenArr> Head1Z = {0.1, 0.0, 0.0, 0.1};
304 509 : std::array<Real64, lenArr> Head2X = {-10.0, -10.0, -9.5, -9.5};
305 509 : std::array<Real64, lenArr> Head2Y = {3.0, 3.0, 2.133975, 2.133975};
306 509 : std::array<Real64, lenArr> Head2Z = {0.1, 0.0, 0.0, 0.1};
307 509 : std::array<Real64, lenArr> NSide1X = {-10.5, -10.5, -10.5, -10.5};
308 509 : std::array<Real64, lenArr> NSide1Y = {4.5, 4.5, 3.5, 3.5};
309 509 : std::array<Real64, lenArr> NSide1Z = {0.1, 0.0, 0.0, 0.1};
310 509 : std::array<Real64, lenArr> NSide2X = {-10.5, -10.5, -9.5, -9.5};
311 509 : std::array<Real64, lenArr> NSide2Y = {4.5, 4.5, 3.5, 3.5};
312 509 : std::array<Real64, lenArr> NSide2Z = {0.1, 0.0, 0.0, 0.1};
313 509 : std::array<Real64, lenArr> NSide3X = {-9.5, -9.5, -9.5, -9.5};
314 509 : std::array<Real64, lenArr> NSide3Y = {4.5, 4.5, 3.5, 3.5};
315 509 : std::array<Real64, lenArr> NSide3Z = {0.1, 0.0, 0.0, 0.1};
316 :
317 509 : if (ColorScheme.empty()) {
318 509 : print(of, Format_708, "Color Scheme", ",", "Default");
319 : } else {
320 0 : print(of, Format_708, "Color Scheme", ",", ColorScheme);
321 : }
322 :
323 509 : Real64 minx = 99999.0;
324 509 : Real64 miny = 99999.0;
325 35904 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
326 35395 : auto &thisSurface = state.dataSurface->Surface(surf);
327 35395 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) continue;
328 166870 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
329 133645 : minx = min(minx, thisSurface.Vertex(vert).x);
330 133645 : miny = min(miny, thisSurface.Vertex(vert).y);
331 : }
332 509 : }
333 :
334 2545 : for (int vert = 0; vert < lenArr; ++vert) {
335 2036 : StemX[vert] += minx;
336 2036 : StemY[vert] += miny;
337 2036 : Head1X[vert] += minx;
338 2036 : Head1Y[vert] += miny;
339 2036 : Head2X[vert] += minx;
340 2036 : Head2Y[vert] += miny;
341 2036 : NSide1X[vert] += minx;
342 2036 : NSide1Y[vert] += miny;
343 2036 : NSide2X[vert] += minx;
344 2036 : NSide2Y[vert] += miny;
345 2036 : NSide3X[vert] += minx;
346 2036 : NSide3Y[vert] += miny;
347 : }
348 :
349 509 : auto &DXFcolorno = state.dataSurfColor->DXFcolorno;
350 :
351 : // This writes "True North" above the Arrow Head
352 509 : print(of, Format_710, "Text - True North");
353 509 : print<check_syntax(Format_800)>(
354 509 : of, Format_800, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)], StemX[0] - 1.0, StemY[0], StemZ[0]);
355 :
356 509 : print(of, Format_710, "Text - Building Title");
357 509 : print<check_syntax(Format_801)>(of,
358 : Format_801,
359 509 : DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)],
360 509 : StemX[0] - 4.0,
361 509 : StemY[0] - 4.0,
362 509 : StemZ[0],
363 1018 : "Building - " + state.dataHeatBal->BuildingName);
364 :
365 : // We want to point the north arrow to true north
366 509 : print(of, Format_710, "North Arrow Stem");
367 509 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
368 509 : print(of, Format_703_1, StemX[0], StemY[0], StemZ[0]);
369 509 : print(of, Format_703_2, StemX[1], StemY[1], StemZ[1]);
370 509 : print(of, Format_703_3, StemX[2], StemY[2], StemZ[2]);
371 509 : print(of, Format_703_4, StemX[3], StemY[3], StemZ[3]);
372 :
373 509 : print(of, Format_710, "North Arrow Head 1");
374 509 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
375 509 : print(of, Format_703_1, Head1X[0], Head1Y[0], Head1Z[0]);
376 509 : print(of, Format_703_2, Head1X[1], Head1Y[1], Head1Z[1]);
377 509 : print(of, Format_703_3, Head1X[2], Head1Y[2], Head1Z[2]);
378 509 : print(of, Format_703_4, Head1X[3], Head1Y[3], Head1Z[3]);
379 :
380 509 : print(of, Format_710, "North Arrow Head 2");
381 509 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
382 509 : print(of, Format_703_1, Head2X[0], Head2Y[0], Head2Z[0]);
383 509 : print(of, Format_703_2, Head2X[1], Head2Y[1], Head2Z[1]);
384 509 : print(of, Format_703_3, Head2X[2], Head2Y[2], Head2Z[2]);
385 509 : print(of, Format_703_4, Head2X[3], Head2Y[3], Head2Z[3]);
386 :
387 509 : print(of, Format_710, "North Arrow Side 1");
388 509 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
389 509 : print(of, Format_703_1, NSide1X[0], NSide1Y[0], NSide1Z[0]);
390 509 : print(of, Format_703_2, NSide1X[1], NSide1Y[1], NSide1Z[1]);
391 509 : print(of, Format_703_3, NSide1X[2], NSide1Y[2], NSide1Z[2]);
392 509 : print(of, Format_703_4, NSide1X[3], NSide1Y[3], NSide1Z[3]);
393 :
394 509 : print(of, Format_710, "North Arrow Side 2");
395 509 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
396 509 : print(of, Format_703_1, NSide2X[0], NSide2Y[0], NSide2Z[0]);
397 509 : print(of, Format_703_2, NSide2X[1], NSide2Y[1], NSide2Z[1]);
398 509 : print(of, Format_703_3, NSide2X[2], NSide2Y[2], NSide2Z[2]);
399 509 : print(of, Format_703_4, NSide2X[3], NSide2Y[3], NSide2Z[3]);
400 :
401 509 : print(of, Format_710, "North Arrow Side 3");
402 509 : print(of, Format_703_0, DXFcolorno[static_cast<int>(DataSurfaceColors::ColorNo::Text)]);
403 509 : print(of, Format_703_1, NSide3X[0], NSide3Y[0], NSide3Z[0]);
404 509 : print(of, Format_703_2, NSide3X[1], NSide3Y[1], NSide3Z[1]);
405 509 : print(of, Format_703_3, NSide3X[2], NSide3Y[2], NSide3Z[2]);
406 509 : print(of, Format_703_4, NSide3X[3], NSide3Y[3], NSide3Z[3]);
407 :
408 509 : print(of, Format_710, "Zone Names");
409 :
410 4335 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
411 7652 : print<check_syntax(Format_710)>(of, Format_710, fmt::format("Zone={}:{}", zones, normalizeName(state.dataHeatBal->Zone(zones).Name)));
412 : }
413 509 : }
414 :
415 509 : 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 509 : if ((int)state.dataDayltg->DaylRefPt.size() > 0) {
422 337 : for (int daylightCtrlNum = 1; daylightCtrlNum <= (int)state.dataDayltg->daylightControl.size(); ++daylightCtrlNum) {
423 280 : auto &thisDaylightControl = state.dataDayltg->daylightControl(daylightCtrlNum);
424 280 : DataSurfaceColors::ColorNo curcolorno = DataSurfaceColors::ColorNo::DaylSensor1;
425 280 : std::string refPtType;
426 280 : if (thisDaylightControl.DaylightMethod == Dayltg::DaylightingMethod::DElight) {
427 3 : refPtType = "DEDayRefPt";
428 277 : } else if (thisDaylightControl.DaylightMethod == Dayltg::DaylightingMethod::SplitFlux) {
429 277 : refPtType = "DayRefPt";
430 : }
431 :
432 735 : for (auto const &refPt : thisDaylightControl.refPts) {
433 455 : print<FormatSyntax::FMT>(of, "999\n{}:{}:{}\n", thisDaylightControl.ZoneName, refPtType, state.dataDayltg->DaylRefPt(refPt.num).Name);
434 455 : print<check_syntax(Format_709)>(of,
435 : Format_709,
436 910 : normalizeName(thisDaylightControl.ZoneName),
437 455 : state.dataSurfColor->DXFcolorno[static_cast<int>(curcolorno)],
438 455 : refPt.absCoords.x,
439 455 : refPt.absCoords.y,
440 455 : refPt.absCoords.z,
441 455 : 0.2);
442 455 : curcolorno = DataSurfaceColors::ColorNo::DaylSensor2; // ref pts 2 and later are this color
443 : }
444 280 : }
445 : }
446 509 : }
447 :
448 480 : 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 480 : bool ThickPolyline(false);
468 480 : bool RegularPolyline(false);
469 480 : std::string PolylineWidth(" 0.55");
470 480 : bool TriangulateFace(false);
471 :
472 : // Formats
473 480 : constexpr std::string_view Format_702(" 0\nSECTION\n 2\nENTITIES\n");
474 480 : constexpr std::string_view Format_707("999\nDXF created from EnergyPlus\n");
475 480 : constexpr std::string_view Format_708("999\n{}{}{}\n");
476 :
477 480 : 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 480 : 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 480 : constexpr std::string_view Format_717(" 0\nSEQEND\n 8\n{}\n");
481 480 : 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 480 : constexpr std::string_view Format_704_0(" 0\n3DFACE\n 8\n{}\n 62\n{:3}\n");
485 480 : constexpr std::string_view Format_704_1(" 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
486 480 : constexpr std::string_view Format_704_2(" 11\n{:15.5F}\n 21\n{:15.5F}\n 31\n{:15.5F}\n");
487 480 : constexpr std::string_view Format_704_3(" 12\n{:15.5F}\n 22\n{:15.5F}\n 32\n{:15.5F}\n");
488 480 : constexpr std::string_view Format_705(" 13\n{:15.5F}\n 23\n{:15.5F}\n 33\n{:15.5F}\n");
489 480 : constexpr std::string_view Format_706(" 0\nENDSEC\n 0\nEOF\n");
490 480 : 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 480 : constexpr std::string_view Format_710("999\n{}\n");
492 :
493 480 : if (PolygonAction == "TRIANGULATE3DFACE" || PolygonAction == "TRIANGULATE" || PolygonAction.empty()) {
494 474 : TriangulateFace = true;
495 474 : RegularPolyline = false;
496 474 : ThickPolyline = false;
497 6 : } else if (PolygonAction == "THICKPOLYLINE") {
498 2 : ThickPolyline = true;
499 2 : RegularPolyline = false;
500 2 : TriangulateFace = false;
501 4 : } else if (PolygonAction == "REGULARPOLYLINE") {
502 4 : RegularPolyline = true;
503 4 : TriangulateFace = false;
504 4 : ThickPolyline = false;
505 4 : 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 480 : 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 960 : auto dxffile = state.files.dxf.open(state, "DXFOut", state.files.outputControl.dxf);
521 :
522 480 : print(dxffile, Format_702); // Start of Entities section
523 :
524 480 : print(dxffile, Format_707); // Comment
525 :
526 480 : print(dxffile, Format_708, "Program Version", ",", state.dataStrGlobals->VerStringVar);
527 :
528 480 : if (PolygonAction.empty()) {
529 0 : print(dxffile, Format_708, "Polygon Action", ",", "Triangulate3DFace");
530 : } else {
531 480 : print(dxffile, Format_708, "Polygon Action", ",", PolygonAction);
532 : }
533 :
534 480 : WriteDXFCommon(state, dxffile, ColorScheme);
535 480 : auto &DXFcolorno = state.dataSurfColor->DXFcolorno;
536 480 : DataSurfaceColors::ColorNo colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
537 : // Do all detached shading surfaces first
538 35204 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
539 34724 : std::string ShadeType;
540 34724 : auto &thisSurface = state.dataSurface->Surface(surf);
541 :
542 34724 : if (thisSurface.HeatTransSurf) continue;
543 1147 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) continue;
544 126 : if (thisSurface.Sides == 0) continue;
545 126 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) colorindex = DataSurfaceColors::ColorNo::ShdDetFix;
546 126 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) colorindex = DataSurfaceColors::ColorNo::ShdDetBldg;
547 126 : if (state.dataSurface->SurfIsPV(surf)) colorindex = DataSurfaceColors::ColorNo::PV;
548 126 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
549 86 : ShadeType = "Fixed Shading";
550 86 : print(dxffile, Format_710, "Fixed Shading:" + thisSurface.Name);
551 40 : } else if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
552 28 : ShadeType = "Building Shading";
553 28 : print(dxffile, Format_710, "Building Shading:" + thisSurface.Name);
554 : }
555 126 : if (thisSurface.Sides <= 4) {
556 126 : print(dxffile, Format_704_0, ShadeType, DXFcolorno[static_cast<int>(colorindex)]);
557 126 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
558 126 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
559 126 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
560 126 : if (thisSurface.Sides == 3) {
561 40 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
562 : } else {
563 86 : 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 35204 : }
610 :
611 : // now do zone surfaces, by zone
612 4222 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
613 3742 : const std::string TempZoneName = normalizeName(state.dataHeatBal->Zone(zones).Name);
614 :
615 1089589 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
616 1085847 : auto &thisSurface = state.dataSurface->Surface(surf);
617 1085847 : if (thisSurface.Zone != zones) continue;
618 33588 : if (thisSurface.Sides == 0) continue;
619 31418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) continue;
620 31418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) colorindex = DataSurfaceColors::ColorNo::Wall;
621 31418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) colorindex = DataSurfaceColors::ColorNo::Roof;
622 31418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) colorindex = DataSurfaceColors::ColorNo::Floor;
623 31418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) colorindex = DataSurfaceColors::ColorNo::Door;
624 31418 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
625 4917 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::Window) colorindex = DataSurfaceColors::ColorNo::Window;
626 4917 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::GlassDoor) colorindex = DataSurfaceColors::ColorNo::GlassDoor;
627 4917 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Dome) colorindex = DataSurfaceColors::ColorNo::TDDDome;
628 4917 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Diffuser) colorindex = DataSurfaceColors::ColorNo::TDDDiffuser;
629 : }
630 31418 : if (state.dataSurface->SurfIsPV(surf)) colorindex = DataSurfaceColors::ColorNo::PV;
631 :
632 31418 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
633 31418 : if (thisSurface.Sides <= 4) {
634 31248 : print(dxffile, Format_704_0, TempZoneName, DXFcolorno[static_cast<int>(colorindex)]);
635 31248 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
636 31248 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
637 31248 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
638 31248 : if (thisSurface.Sides == 3) {
639 127 : print(dxffile, Format_705, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
640 : } else {
641 31121 : print(dxffile, Format_705, thisSurface.Vertex(4).x, thisSurface.Vertex(4).y, thisSurface.Vertex(4).z);
642 : }
643 : } else { // polygon surface
644 170 : if (!TriangulateFace) {
645 30 : Real64 minz = 99999.0;
646 510 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
647 480 : minz = min(minz, thisSurface.Vertex(vert).z);
648 : }
649 30 : print(dxffile, Format_715, TempZoneName, DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
650 510 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
651 480 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
652 : }
653 30 : print(dxffile, Format_717, TempZoneName);
654 : } else {
655 140 : Array1D<DataVectorTypes::dTriangle> mytriangles;
656 :
657 280 : const int ntri = DXFEarClipping::Triangulate(state,
658 : thisSurface.Sides,
659 140 : thisSurface.Vertex,
660 : mytriangles,
661 : thisSurface.Azimuth,
662 : thisSurface.Tilt,
663 140 : thisSurface.Name,
664 : thisSurface.Class);
665 970 : for (int svert = 1; svert <= ntri; ++svert) {
666 830 : const int vv0 = mytriangles(svert).vv0;
667 830 : const int vv1 = mytriangles(svert).vv1;
668 830 : const int vv2 = mytriangles(svert).vv2;
669 830 : print(dxffile,
670 : Format_704,
671 : TempZoneName,
672 830 : DXFcolorno[static_cast<int>(colorindex)],
673 830 : thisSurface.Vertex(vv0).x,
674 830 : thisSurface.Vertex(vv0).y,
675 830 : thisSurface.Vertex(vv0).z,
676 830 : thisSurface.Vertex(vv1).x,
677 830 : thisSurface.Vertex(vv1).y,
678 830 : thisSurface.Vertex(vv1).z,
679 830 : thisSurface.Vertex(vv2).x,
680 830 : thisSurface.Vertex(vv2).y,
681 830 : thisSurface.Vertex(vv2).z);
682 830 : print(dxffile, Format_705, thisSurface.Vertex(vv2).x, thisSurface.Vertex(vv2).y, thisSurface.Vertex(vv2).z);
683 : }
684 140 : mytriangles.deallocate();
685 140 : }
686 : }
687 3742 : }
688 : // still have to do shading surfaces for zone
689 1089589 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
690 1085847 : 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 1085847 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) continue;
693 6412 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zones).Name) continue;
694 1022 : if (thisSurface.Sides == 0) continue;
695 1022 : colorindex = DataSurfaceColors::ColorNo::ShdAtt;
696 1022 : if (state.dataSurface->SurfIsPV(surf)) colorindex = DataSurfaceColors::ColorNo::PV;
697 1022 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
698 1022 : if (thisSurface.Sides <= 4) {
699 1022 : print(dxffile, Format_704_0, TempZoneName, DXFcolorno[static_cast<int>(colorindex)]);
700 1022 : print(dxffile, Format_704_1, thisSurface.Vertex(1).x, thisSurface.Vertex(1).y, thisSurface.Vertex(1).z);
701 1022 : print(dxffile, Format_704_2, thisSurface.Vertex(2).x, thisSurface.Vertex(2).y, thisSurface.Vertex(2).z);
702 1022 : print(dxffile, Format_704_3, thisSurface.Vertex(3).x, thisSurface.Vertex(3).y, thisSurface.Vertex(3).z);
703 1022 : 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 1022 : 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 3742 : }
764 3742 : }
765 :
766 480 : DXFDaylightingReferencePoints(state, dxffile);
767 :
768 4222 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
769 3742 : const DataSurfaceColors::ColorNo curcolorno = DataSurfaceColors::ColorNo::DaylSensor1;
770 :
771 3774 : for (auto const &illumMap : state.dataDayltg->illumMaps) {
772 32 : if (illumMap.zoneIndex != zones) continue;
773 9 : int numRefPt = 0;
774 634 : for (auto const &refPt : illumMap.refPts) {
775 625 : print(dxffile, Format_710, format("{}:MapRefPt:{}", state.dataHeatBal->Zone(zones).Name, ++numRefPt));
776 625 : print(dxffile,
777 : Format_709,
778 1250 : normalizeName(state.dataHeatBal->Zone(zones).Name),
779 625 : DXFcolorno[static_cast<int>(curcolorno)],
780 625 : refPt.absCoords.x,
781 625 : refPt.absCoords.y,
782 625 : refPt.absCoords.z,
783 1250 : 0.05);
784 : }
785 : }
786 : }
787 :
788 480 : print(dxffile, Format_706);
789 480 : }
790 :
791 29 : 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 29 : constexpr std::string_view PolylineWidth = " 0.55";
808 :
809 29 : constexpr std::string_view Format_702(" 0\nSECTION\n 2\nENTITIES\n");
810 29 : constexpr std::string_view Format_707("999\nDXF created from EnergyPlus\n");
811 29 : constexpr std::string_view Format_708("999\n{}{}{}\n");
812 :
813 29 : 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 29 : constexpr std::string_view Format_716(" 0\nVERTEX\n 8\n{}\n 10\n{:15.5F}\n 20\n{:15.5F}\n 30\n{:15.5F}\n");
816 29 : constexpr std::string_view Format_717(" 0\nSEQEND\n 8\n{}\n");
817 29 : constexpr std::string_view Format_706(" 0\nENDSEC\n 0\nEOF\n");
818 29 : constexpr std::string_view Format_710("999\n{}\n");
819 :
820 29 : 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 58 : auto dxffile = state.files.dxf.open(state, "DXFOutWireFrame", state.files.outputControl.dxf);
826 :
827 29 : print(dxffile, Format_702); // Start of Entities section
828 :
829 29 : print(dxffile, Format_707); // Comment
830 :
831 29 : print(dxffile, Format_708, "Program Version", ",", state.dataStrGlobals->VerStringVar);
832 29 : print(dxffile, Format_708, "DXF using Wireframe", ' ', ' ');
833 :
834 29 : WriteDXFCommon(state, dxffile, ColorScheme);
835 :
836 : // Do all detached shading surfaces first
837 29 : int surfcount = 0;
838 29 : DataSurfaceColors::ColorNo colorindex = DataSurfaceColors::ColorNo::Invalid;
839 700 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
840 671 : std::string ShadeType;
841 671 : auto &thisSurface = state.dataSurface->Surface(surf);
842 671 : if (thisSurface.HeatTransSurf) continue;
843 44 : 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 700 : }
867 :
868 : // now do zone surfaces, by zone
869 113 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
870 84 : std::string const SaveZoneName = normalizeName(state.dataHeatBal->Zone(zones).Name);
871 :
872 84 : surfcount = 0;
873 3505 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
874 3421 : auto &thisSurface = state.dataSurface->Surface(surf);
875 3421 : if (thisSurface.Zone != zones) continue;
876 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) continue;
877 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) colorindex = DataSurfaceColors::ColorNo::Wall;
878 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) colorindex = DataSurfaceColors::ColorNo::Roof;
879 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) colorindex = DataSurfaceColors::ColorNo::Floor;
880 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) colorindex = DataSurfaceColors::ColorNo::Door;
881 627 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) {
882 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::Window) colorindex = DataSurfaceColors::ColorNo::Window;
883 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::GlassDoor) colorindex = DataSurfaceColors::ColorNo::GlassDoor;
884 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Dome) colorindex = DataSurfaceColors::ColorNo::TDDDome;
885 68 : if (thisSurface.OriginalClass == DataSurfaces::SurfaceClass::TDD_Diffuser) colorindex = DataSurfaceColors::ColorNo::TDDDiffuser;
886 : }
887 627 : if (state.dataSurface->SurfIsPV(surf)) colorindex = DataSurfaceColors::ColorNo::PV;
888 627 : ++surfcount;
889 :
890 627 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
891 627 : std::string const TempZoneName = format("{}_{}", SaveZoneName, surfcount);
892 627 : Real64 minz = 99999.0;
893 3135 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
894 2508 : minz = min(minz, thisSurface.Vertex(vert).z);
895 : }
896 :
897 627 : print(
898 627 : dxffile, Format_715, TempZoneName, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
899 3135 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
900 2508 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
901 : }
902 627 : print(dxffile, Format_717, TempZoneName);
903 711 : }
904 : // still have to do shading surfaces for zone
905 84 : surfcount = 0;
906 3505 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
907 3421 : auto &thisSurface = state.dataSurface->Surface(surf);
908 3641 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) continue;
909 264 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zones).Name) continue;
910 44 : colorindex = DataSurfaceColors::ColorNo::ShdAtt;
911 44 : if (state.dataSurface->SurfIsPV(surf)) colorindex = DataSurfaceColors::ColorNo::PV;
912 44 : ++surfcount;
913 :
914 44 : print(dxffile, Format_710, thisSurface.ZoneName + ':' + thisSurface.Name);
915 44 : std::string const TempZoneName = format("{}_{}", SaveZoneName, surfcount);
916 44 : Real64 minz = 99999.0;
917 220 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
918 176 : minz = min(minz, thisSurface.Vertex(vert).z);
919 : }
920 :
921 44 : print(
922 44 : dxffile, Format_715, TempZoneName, state.dataSurfColor->DXFcolorno[static_cast<int>(colorindex)], minz, PolylineWidth, PolylineWidth);
923 220 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
924 176 : print(dxffile, Format_716, TempZoneName, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
925 : }
926 44 : print(dxffile, Format_717, TempZoneName);
927 128 : }
928 84 : }
929 :
930 29 : DXFDaylightingReferencePoints(state, dxffile);
931 :
932 29 : print(dxffile, Format_706);
933 29 : }
934 :
935 184 : 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 184 : std::string BaseSurfName;
954 184 : std::string ConstructionName;
955 184 : std::string ScheduleName;
956 184 : std::string IntConvCoeffCalc;
957 184 : std::string ExtConvCoeffCalc;
958 : Real64 NominalUwithConvCoeffs;
959 184 : std::string cNominalU;
960 184 : std::string cNominalUwithConvCoeffs;
961 184 : std::string cSchedMin;
962 184 : std::string cSchedMax;
963 184 : std::string SolarDiffusing;
964 184 : std::string AlgoName;
965 :
966 184 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
967 : // no error needed, probably in end processing, just return
968 0 : return;
969 : }
970 :
971 184 : std::stringstream ss;
972 184 : auto *eiostream = &ss;
973 : //!!! Write Header lines for report
974 184 : if (RptType == 10) { // Details only
975 148 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces\n"; // Format_700
976 148 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces\n"; // Format_700b
977 148 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
978 : *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 "
979 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
980 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
981 148 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides\n"; // Format_7011
982 148 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
983 : *eiostream << ",Transmittance Schedule,Min Schedule Value,Max Schedule Value,Solar Diffusing,Area (Net) {m2},Area (Gross) {m2},Area (Sunlit "
984 : "Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
985 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
986 148 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides\n"; // Format_7011b
987 148 : *eiostream << "! <Frame/Divider Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701c
988 : *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 "
989 148 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal {m}\n"; // Format_7011c
990 36 : } else if (RptType == 11) { // Details with Vertices
991 31 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces"; // Format_700
992 31 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
993 31 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces"; // Format_700b
994 31 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
995 31 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
996 : *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 "
997 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal "
998 : "{m},ExtBoundCondition,ExtConvCoeffCalc,IntConvCoeffCalc,SunExposure,WindExposure,ViewFactorToGround,ViewFactorToSky,"
999 31 : "ViewFactorToGround-IR,ViewFactorToSky-IR,#Sides"; // Format_7011
1000 : *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 "
1001 31 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1002 31 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
1003 : *eiostream << ",Transmittance Schedule,Min Schedule Value,Max Schedule Value,Solar Diffusing,Area (Net) {m2},Area (Gross) {m2},Area (Sunlit "
1004 : "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_7011b
1007 : *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 << "! <Frame/Divider Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701c
1010 : // Vertices are not applicable for window frame and divider, so skip 707
1011 : *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 "
1012 31 : "(Gross) {m2},Area (Sunlit Calc) {m2},Azimuth {deg},Tilt {deg},~Width {m},~Height {m},Reveal {m}\n"; // Format_7011c
1013 : } else { // Vertices only
1014 5 : *eiostream << "! <Zone Surfaces>,Zone Name,# Surfaces"; // Format_700
1015 5 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1016 5 : *eiostream << "! <Shading Surfaces>,Number of Shading Surfaces,# Surfaces"; // Format_700b
1017 5 : *eiostream << ", Vertices are shown starting at Upper-Left-Corner => Counter-Clockwise => World Coordinates\n"; // Format_710
1018 5 : *eiostream << "! <HeatTransfer Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701
1019 5 : *eiostream << ",#Sides"; // Format_7012
1020 : *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 "
1021 5 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1022 5 : *eiostream << "! <Shading Surface>,Surface Name,Surface Class,Base Surface,Heat Transfer Algorithm"; // Format_701b
1023 5 : *eiostream << ",#Sides"; // Format_7012
1024 : *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 "
1025 5 : "{m},Vertex 3 Z {m},Vertex 4 X {m},Vertex 4 Z {m},Vertex 4 Z {m},{etc}\n"; // Format_707
1026 : // Vertices are not applicable for window frame and divider, so skip 701c here
1027 : }
1028 :
1029 : // Do just "detached" shading first
1030 184 : int surf2 = 0;
1031 660 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1032 660 : surf2 = surf;
1033 660 : auto &thisSurface = state.dataSurface->Surface(surf);
1034 660 : if (thisSurface.Zone != 0) break;
1035 184 : }
1036 184 : if ((surf2 - 1) > 0) {
1037 : *eiostream << "Shading Surfaces,"
1038 52 : << "Number of Shading Surfaces," << surf2 - 1 << '\n';
1039 528 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1040 528 : auto &thisSurface = state.dataSurface->Surface(surf);
1041 528 : if (thisSurface.Zone != 0) break;
1042 476 : AlgoName = "None";
1043 476 : *eiostream << "Shading Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << thisSurface.BaseSurfName << ","
1044 476 : << AlgoName << ",";
1045 476 : if (RptType == 10) {
1046 376 : if (thisSurface.SchedShadowSurfIndex > 0) {
1047 264 : ScheduleName = ScheduleManager::GetScheduleName(state, thisSurface.SchedShadowSurfIndex);
1048 264 : cSchedMin = format("{:.2R}", ScheduleManager::GetScheduleMinValue(state, thisSurface.SchedShadowSurfIndex));
1049 264 : cSchedMax = format("{:.2R}", ScheduleManager::GetScheduleMaxValue(state, thisSurface.SchedShadowSurfIndex));
1050 : } else {
1051 112 : ScheduleName = "";
1052 112 : cSchedMin = "0.0";
1053 112 : cSchedMax = "0.0";
1054 : }
1055 376 : *eiostream << ScheduleName << "," << cSchedMin << "," << cSchedMax << "," << ' ' << "," << format("{:.2R}", thisSurface.Area) << ","
1056 1128 : << format("{:.2R}", thisSurface.GrossArea) << "," << format("{:.2R}", thisSurface.NetAreaShadowCalc) << ","
1057 1128 : << format("{:.2R}", thisSurface.Azimuth) << "," << format("{:.2R}", thisSurface.Tilt) << ","
1058 2256 : << format("{:.2R}", thisSurface.Width) << "," << format("{:.2R}", thisSurface.Height) << ",";
1059 376 : *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << '\n';
1060 100 : } else if (RptType == 1) {
1061 0 : *eiostream << fmt::to_string(thisSurface.Sides) << ",";
1062 : } else {
1063 100 : if (thisSurface.SchedShadowSurfIndex > 0) {
1064 60 : ScheduleName = ScheduleManager::GetScheduleName(state, thisSurface.SchedShadowSurfIndex);
1065 60 : cSchedMin = format("{:.2R}", ScheduleManager::GetScheduleMinValue(state, thisSurface.SchedShadowSurfIndex));
1066 60 : cSchedMax = format("{:.2R}", ScheduleManager::GetScheduleMaxValue(state, thisSurface.SchedShadowSurfIndex));
1067 : } else {
1068 40 : ScheduleName = "";
1069 40 : cSchedMin = "0.0";
1070 40 : cSchedMax = "0.0";
1071 : }
1072 100 : *eiostream << ScheduleName << "," << cSchedMin << "," << cSchedMax << "," << ' ' << "," << format("{:.2R}", thisSurface.Area) << ","
1073 300 : << format("{:.2R}", thisSurface.GrossArea) << "," << format("{:.2R}", thisSurface.NetAreaShadowCalc) << ","
1074 300 : << format("{:.2R}", thisSurface.Azimuth) << "," << format("{:.2R}", thisSurface.Tilt) << ","
1075 600 : << format("{:.2R}", thisSurface.Width) << "," << format("{:.2R}", thisSurface.Height) << ",";
1076 100 : *eiostream << ",,,,,,,,,," << fmt::to_string(thisSurface.Sides) << ",";
1077 : }
1078 476 : if (RptType == 10) continue;
1079 488 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1080 388 : if (vert != thisSurface.Sides) {
1081 864 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1082 864 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1083 : } else {
1084 300 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1085 300 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1086 : }
1087 : }
1088 : // This shouldn't happen with shading surface -- always have vertices
1089 100 : if (thisSurface.Sides == 0) *eiostream << '\n';
1090 52 : }
1091 : }
1092 :
1093 2715 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1094 2531 : *eiostream << "Zone Surfaces," << state.dataHeatBal->Zone(ZoneNum).Name << ","
1095 2531 : << (state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast - state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst + 1) << '\n';
1096 1051547 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1097 1049016 : auto &thisSurface = state.dataSurface->Surface(surf);
1098 1049016 : if (thisSurface.Zone != ZoneNum) continue;
1099 23782 : SolarDiffusing = "";
1100 23782 : if (RptType == 10 || RptType == 11) { // Details and Details with Vertices
1101 23449 : if (thisSurface.BaseSurf == surf) {
1102 19586 : BaseSurfName = "";
1103 : } else {
1104 3863 : BaseSurfName = thisSurface.BaseSurfName;
1105 : }
1106 :
1107 23449 : 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 23449 : IntConvCoeffCalc = ConvCoeffCalcs[Convect::HcIntReportVals[static_cast<int>(state.dataHeatBal->Zone(ZoneNum).IntConvAlgo)] - 1];
1112 23449 : ExtConvCoeffCalc = ConvCoeffCalcs[Convect::HcExtReportVals[static_cast<int>(state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo)] - 1];
1113 :
1114 23449 : *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << ","
1115 23449 : << 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 23449 : if (thisSurface.Construction > 0 && thisSurface.Construction <= state.dataHeatBal->TotConstructs) {
1121 23449 : cNominalUwithConvCoeffs = "";
1122 23449 : ConstructionName = state.dataConstruction->Construct(thisSurface.Construction).Name;
1123 23449 : switch (thisSurface.Class) {
1124 11121 : 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 11121 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1128 11103 : NominalUwithConvCoeffs = 1.0 / (0.1197548 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0299387);
1129 : } else {
1130 18 : cNominalUwithConvCoeffs = "[invalid]";
1131 : }
1132 11121 : } break;
1133 3443 : 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 3443 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1137 3443 : NominalUwithConvCoeffs = 1.0 / (0.1620212 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0810106);
1138 : } else {
1139 0 : cNominalUwithConvCoeffs = "[invalid]";
1140 : }
1141 3443 : } break;
1142 2959 : 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 2959 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1146 2959 : NominalUwithConvCoeffs = 1.0 / (0.1074271 + (1.0 / state.dataHeatBal->NominalU(thisSurface.Construction)) + 0.0810106);
1147 : } else {
1148 0 : cNominalUwithConvCoeffs = "[invalid]";
1149 : }
1150 2959 : } break;
1151 5926 : default: {
1152 5926 : if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
1153 5926 : NominalUwithConvCoeffs = state.dataHeatBal->NominalU(thisSurface.Construction);
1154 : } else {
1155 0 : cNominalUwithConvCoeffs = "[invalid]";
1156 : }
1157 5926 : } break;
1158 : }
1159 23449 : if (cNominalUwithConvCoeffs.empty()) {
1160 23431 : cNominalUwithConvCoeffs = format("{:.3R}", NominalUwithConvCoeffs);
1161 : } else {
1162 18 : cNominalUwithConvCoeffs = "[invalid]";
1163 : }
1164 23449 : if ((thisSurface.Class == DataSurfaces::SurfaceClass::Window) || (thisSurface.Class == DataSurfaces::SurfaceClass::TDD_Dome)) {
1165 : // DataSurfaces::SurfaceClass::Window also covers glass doors and TDD:Diffusers
1166 3562 : cNominalU = "N/A";
1167 3562 : if (state.dataSurface->SurfWinSolarDiffusing(surf)) {
1168 0 : SolarDiffusing = "Yes";
1169 : } else {
1170 3562 : SolarDiffusing = "No";
1171 : }
1172 : } else {
1173 19887 : 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 70347 : << format("{:.2R}", thisSurface.Area) << "," << format("{:.2R}", thisSurface.GrossArea) << ","
1183 70347 : << format("{:.2R}", thisSurface.NetAreaShadowCalc) << "," << format("{:.2R}", thisSurface.Azimuth) << ","
1184 70347 : << format("{:.2R}", thisSurface.Tilt) << "," << format("{:.2R}", thisSurface.Width) << ","
1185 164143 : << 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 23449 : auto const &surfIntConv = state.dataSurface->surfIntConv(surf);
1191 23449 : auto const &surfExtConv = state.dataSurface->surfExtConv(surf);
1192 23449 : if (surfIntConv.userModelNum != 0) {
1193 14 : IntConvCoeffCalc = overrideTypeStrs[(int)state.dataSurface->userIntConvModels(surfIntConv.userModelNum).overrideType];
1194 : } else {
1195 23435 : Convect::HcInt hcInt = surfIntConv.model;
1196 23435 : if (hcInt == Convect::HcInt::SetByZone) hcInt = state.dataHeatBal->Zone(ZoneNum).IntConvAlgo;
1197 23435 : IntConvCoeffCalc = ConvCoeffCalcs[Convect::HcIntReportVals[(int)hcInt] - 1];
1198 : }
1199 23449 : if (surfExtConv.userModelNum != 0) {
1200 14 : ExtConvCoeffCalc = overrideTypeStrs[(int)state.dataSurface->userExtConvModels(surfExtConv.userModelNum).overrideType];
1201 : } else {
1202 23435 : Convect::HcExt hcExt = surfExtConv.model;
1203 23435 : if (hcExt == Convect::HcExt::SetByZone) hcExt = state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo;
1204 23435 : ExtConvCoeffCalc = ConvCoeffCalcs[Convect::HcExtReportVals[static_cast<int>(hcExt)] - 1];
1205 : }
1206 23449 : if (thisSurface.ExtBoundCond == DataSurfaces::ExternalEnvironment) {
1207 : *eiostream << "ExternalEnvironment"
1208 8188 : << "," << ExtConvCoeffCalc << "," << IntConvCoeffCalc << ",";
1209 15261 : } else if (thisSurface.ExtBoundCond == DataSurfaces::Ground) {
1210 : *eiostream << "Ground"
1211 : << ","
1212 : << "N/A-Ground"
1213 883 : << "," << IntConvCoeffCalc << ",";
1214 14378 : } else if (thisSurface.ExtBoundCond == DataSurfaces::GroundFCfactorMethod) {
1215 : *eiostream << "FCGround"
1216 : << ","
1217 : << "N/A-FCGround"
1218 160 : << "," << IntConvCoeffCalc << ",";
1219 14218 : } else if (thisSurface.ExtBoundCond == DataSurfaces::KivaFoundation) {
1220 : *eiostream << "Foundation"
1221 : << ","
1222 : << "N/A-Foundation"
1223 15 : << "," << IntConvCoeffCalc << ",";
1224 14203 : } else if (thisSurface.ExtBoundCond == DataSurfaces::OtherSideCoefNoCalcExt ||
1225 14200 : thisSurface.ExtBoundCond == DataSurfaces::OtherSideCoefCalcExt) {
1226 4 : *eiostream << state.dataSurface->OSC(thisSurface.OSCPtr).Name << ","
1227 : << "N/A-OSC"
1228 8 : << "," << IntConvCoeffCalc << ",";
1229 14199 : } else if (thisSurface.ExtBoundCond == DataSurfaces::OtherSideCondModeledExt) {
1230 3 : *eiostream << state.dataSurface->OSCM(thisSurface.OSCMPtr).Name << ","
1231 : << "N/A-OSCM"
1232 6 : << "," << IntConvCoeffCalc << ",";
1233 : } else {
1234 14196 : *eiostream << thisSurface.ExtBoundCondName << ","
1235 : << "Other/Same Surface Int Conv"
1236 14196 : << "," << IntConvCoeffCalc << ",";
1237 : }
1238 23449 : if (thisSurface.ExtSolar) {
1239 : *eiostream << "SunExposed"
1240 8115 : << ",";
1241 : } else {
1242 : *eiostream << "NoSun"
1243 15334 : << ",";
1244 : }
1245 23449 : if (thisSurface.ExtWind) {
1246 : *eiostream << "WindExposed"
1247 8178 : << ",";
1248 : } else {
1249 : *eiostream << "NoWind"
1250 15271 : << ",";
1251 : }
1252 23449 : if (RptType == 10) {
1253 67749 : *eiostream << format("{:.2R}", thisSurface.ViewFactorGround) << "," << format("{:.2R}", thisSurface.ViewFactorSky) << ","
1254 67749 : << format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," << format("{:.2R}", thisSurface.ViewFactorSkyIR) << ","
1255 112915 : << fmt::to_string(thisSurface.Sides) << '\n';
1256 : } else {
1257 2598 : *eiostream << format("{:.2R}", thisSurface.ViewFactorGround) << "," << format("{:.2R}", thisSurface.ViewFactorSky) << ","
1258 2598 : << format("{:.2R}", thisSurface.ViewFactorGroundIR) << "," << format("{:.2R}", thisSurface.ViewFactorSkyIR) << ","
1259 4330 : << fmt::to_string(thisSurface.Sides) << ",";
1260 3990 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1261 3124 : if (vert != thisSurface.Sides) {
1262 7053 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1263 7053 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1264 : } else {
1265 2319 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1266 2319 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1267 : }
1268 : }
1269 866 : if (thisSurface.Sides == 0) *eiostream << '\n';
1270 : }
1271 : // if window, report frame/divider as appropriate
1272 23449 : if (thisSurface.FrameDivider > 0) {
1273 274 : int fd = thisSurface.FrameDivider;
1274 274 : if (state.dataSurface->FrameDivider(fd).FrameWidth > 0.0) {
1275 69 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1276 69 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << ","
1277 138 : << "Frame," << thisSurface.Name << "," << AlgoName << ",";
1278 138 : *eiostream << ",N/A,N/A,," << format("{:.2R}", state.dataSurface->SurfWinFrameArea(surf)) << ","
1279 138 : << format("{:.2R}", state.dataSurface->SurfWinFrameArea(surf) / thisSurface.Multiplier) << ",*"
1280 : << ",N/A"
1281 207 : << ",N/A," << format("{:.2R}", state.dataSurface->FrameDivider(fd).FrameWidth) << ",N/A" << '\n';
1282 : }
1283 274 : if (state.dataSurface->FrameDivider(fd).DividerWidth > 0.0) {
1284 5 : 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 5 : *eiostream << "Frame/Divider Surface," << state.dataSurface->FrameDivider(fd).Name << ","
1289 10 : << "Divider:Suspended," << thisSurface.Name << ",,";
1290 : }
1291 10 : *eiostream << ",N/A,N/A,," << format("{:.2R}", state.dataSurface->SurfWinDividerArea(surf)) << ","
1292 10 : << format("{:.2R}", state.dataSurface->SurfWinDividerArea(surf) / thisSurface.Multiplier) << ",*"
1293 : << ",N/A"
1294 15 : << ",N/A," << format("{:.2R}", state.dataSurface->FrameDivider(fd).DividerWidth) << ",N/A" << '\n';
1295 : }
1296 : }
1297 23449 : } else { // RptType=1 Vertices only
1298 333 : if (thisSurface.BaseSurf == surf) {
1299 286 : BaseSurfName = "";
1300 : } else {
1301 47 : BaseSurfName = thisSurface.BaseSurfName;
1302 : }
1303 :
1304 333 : AlgoName = DataSurfaces::HeatTransAlgoStrs[(int)thisSurface.HeatTransferAlgorithm];
1305 :
1306 333 : *eiostream << "HeatTransfer Surface," << thisSurface.Name << "," << cSurfaceClass(thisSurface.Class) << "," << BaseSurfName << ","
1307 333 : << AlgoName << ",";
1308 333 : *eiostream << fmt::to_string(thisSurface.Sides) << ",";
1309 1505 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1310 1172 : if (vert != thisSurface.Sides) {
1311 2637 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1312 2637 : << format("{:.2R}", thisSurface.Vertex(vert).z) << ",";
1313 : } else {
1314 879 : *eiostream << format("{:.2R}", thisSurface.Vertex(vert).x) << "," << format("{:.2R}", thisSurface.Vertex(vert).y) << ","
1315 879 : << format("{:.2R}", thisSurface.Vertex(vert).z) << '\n';
1316 : }
1317 : }
1318 333 : if (thisSurface.Sides == 0) *eiostream << '\n';
1319 : }
1320 2531 : } // surfaces
1321 : } // zones
1322 :
1323 184 : print(state.files.eio, "{}", eiostream->str());
1324 184 : }
1325 :
1326 7 : 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 7 : Array1D_bool uniqueSurf;
1345 :
1346 7 : 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 7 : uniqueSurf.dimension(state.dataSurface->TotSurfaces, true);
1353 :
1354 428 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1355 421 : auto &thisSurface = state.dataSurface->Surface(surf);
1356 421 : if (thisSurface.ExtBoundCond > 0) {
1357 209 : if (thisSurface.ExtBoundCond < surf) { // already cycled through
1358 82 : uniqueSurf(surf) = false;
1359 : }
1360 : }
1361 421 : if (thisSurface.Construction == 0) { // throw out others for now
1362 30 : uniqueSurf(surf) = false;
1363 : }
1364 7 : }
1365 :
1366 14 : auto scifile = state.files.sci.open(state, "CostInfoOut", state.files.outputControl.sci);
1367 :
1368 7 : print(scifile, "{:12}{:12}\n", state.dataSurface->TotSurfaces, count(uniqueSurf));
1369 7 : print(scifile, "{}\n", " data for surfaces useful for cost information");
1370 7 : print(scifile, "{}\n", " Number, Name, Construction, class, area, grossarea");
1371 :
1372 428 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1373 : // if (surface(surf)%class .eq. DataSurfaces::SurfaceClass::IntMass) CYCLE
1374 421 : if (!uniqueSurf(surf)) continue;
1375 : // why the heck are constructions == 0 ?
1376 309 : auto &thisSurface = state.dataSurface->Surface(surf);
1377 309 : if (thisSurface.Construction != 0) {
1378 : // Formats
1379 : static constexpr std::string_view Format_801("{:5},{},{},{},{:14.5F},{:14.5F}\n");
1380 309 : print<check_syntax(Format_801)>(scifile,
1381 : Format_801,
1382 : surf,
1383 309 : thisSurface.Name,
1384 309 : state.dataConstruction->Construct(thisSurface.Construction).Name,
1385 309 : cSurfaceClass(thisSurface.Class),
1386 309 : thisSurface.Area,
1387 309 : thisSurface.GrossArea);
1388 : }
1389 7 : }
1390 :
1391 7 : uniqueSurf.deallocate();
1392 7 : }
1393 :
1394 36 : 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 36 : std::string ShadeType;
1429 36 : bool ThickPolyline(false);
1430 36 : bool RegularPolyline(false);
1431 36 : std::string PolylineWidth(" 0.55");
1432 36 : bool TriangulateFace(false);
1433 :
1434 : // Formats
1435 : static constexpr std::string_view Format_702("#VRML V2.0 utf8\n");
1436 : static constexpr std::string_view Format_707(
1437 : "WorldInfo {{\n title \"Building - {}\"\n info [\"EnergyPlus Program Version {}\"]\n info [\"Surface Color Scheme {}\"]\n}}\n");
1438 : static constexpr std::string_view Format_800("Shape {{\nappearance DEF {} Appearance {{\nmaterial Material {{ diffuseColor {} }}\n}}\n}}\n");
1439 : static constexpr std::string_view Format_801(
1440 : "Shape {{\nappearance USE {}\ngeometry IndexedFaceSet {{\nsolid TRUE\ncoord DEF {}{} Coordinate {{\npoint [\n");
1441 : static constexpr std::string_view Format_802("{:15.5F} {:15.5F} {:15.5F},\n");
1442 : static constexpr std::string_view Format_803("]\n}}\ncoordIndex [\n");
1443 : static constexpr std::string_view Format_805("]\nccw TRUE\nsolid TRUE\n}}\n}}\n");
1444 :
1445 36 : if (PolygonAction == "TRIANGULATE3DFACE" || PolygonAction == "TRIANGULATE") {
1446 36 : TriangulateFace = true;
1447 0 : } else if (PolygonAction == "THICKPOLYLINE" || PolygonAction.empty()) {
1448 0 : ThickPolyline = true;
1449 0 : } else if (PolygonAction == "REGULARPOLYLINE") {
1450 0 : RegularPolyline = true;
1451 0 : PolylineWidth = " 0";
1452 : } else {
1453 0 : ShowWarningError(state, format("VRMLOut: Illegal key specified for Surfaces with > 4 sides={}", PolygonAction));
1454 0 : ShowContinueError(state, "\"TRIANGULATE 3DFACE\" will be used for any surfaces with > 4 sides.");
1455 0 : TriangulateFace = true;
1456 : }
1457 :
1458 36 : if (state.dataSurface->TotSurfaces > 0 && !allocated(state.dataSurface->Surface)) {
1459 : // no error needed, probably in end processing, just return
1460 0 : return;
1461 : }
1462 :
1463 72 : auto wrlfile = state.files.wrl.open(state, "VRMLOut", state.files.outputControl.wrl);
1464 :
1465 36 : print(wrlfile, Format_702);
1466 :
1467 36 : if (ColorScheme.empty()) {
1468 36 : print<check_syntax(Format_707)>(
1469 36 : wrlfile, Format_707, state.dataHeatBal->BuildingName, state.dataStrGlobals->VerStringVar, "Default"); // World Info
1470 : } else {
1471 0 : print<check_syntax(Format_707)>(
1472 0 : wrlfile, Format_707, state.dataHeatBal->BuildingName, state.dataStrGlobals->VerStringVar, ColorScheme); // World Info
1473 : }
1474 :
1475 36 : print(wrlfile, "# Zone Names\n");
1476 246 : for (int zones = 1; zones <= state.dataGlobal->NumOfZones; ++zones) {
1477 210 : print(wrlfile, "# Zone={}:{}\n", zones, normalizeName(state.dataHeatBal->Zone(zones).Name));
1478 : }
1479 :
1480 : // Define the colors:
1481 :
1482 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "FLOOR", "0.502 0.502 0.502");
1483 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "ROOF", "1 1 0");
1484 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "WALL", "0 1 0");
1485 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "WINDOW", "0 1 1");
1486 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "DOOR", "0 1 1");
1487 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "GLASSDOOR", "0 1 1");
1488 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "FIXEDSHADE", "1 0 1");
1489 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "BLDGSHADE", "0 0 1");
1490 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "SUBSHADE", "1 0 1");
1491 36 : print<check_syntax(Format_800)>(wrlfile, Format_800, "BACKCOLOR", "0.502 0.502 0.784");
1492 :
1493 36 : Color colorindex = Color::Invalid;
1494 :
1495 : // Do all detached shading surfaces first
1496 1834 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1497 1798 : auto &thisSurface = state.dataSurface->Surface(surf);
1498 1798 : if (thisSurface.HeatTransSurf) continue;
1499 148 : if (thisSurface.IsAirBoundarySurf) continue;
1500 132 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Shading) continue;
1501 0 : if (thisSurface.Sides == 0) continue;
1502 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) colorindex = Color::FixedShade;
1503 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) colorindex = Color::BldgShade;
1504 0 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_F) {
1505 0 : ShadeType = "Fixed Shading";
1506 0 : print(wrlfile, "# Fixed Shading:{}\n", thisSurface.Name);
1507 0 : } else if (thisSurface.Class == DataSurfaces::SurfaceClass::Detached_B) {
1508 0 : ShadeType = "Building Shading";
1509 0 : print(wrlfile, "# Building Shading:{}", thisSurface.Name);
1510 : }
1511 0 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", surf);
1512 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1513 0 : print<check_syntax(Format_802)>(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1514 : }
1515 0 : print<check_syntax(Format_803)>(wrlfile, Format_803);
1516 0 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1517 0 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1518 0 : print<FormatSyntax::FMT>(wrlfile, " {}", vert - 1);
1519 0 : if (vert == thisSurface.Sides) print(wrlfile, " -1\n");
1520 : }
1521 0 : print<check_syntax(Format_805)>(wrlfile, Format_805);
1522 0 : } else { // will be >4 sided polygon with triangulate option
1523 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1524 0 : const int ntri = DXFEarClipping::Triangulate(state,
1525 : thisSurface.Sides,
1526 0 : thisSurface.Vertex,
1527 : mytriangles,
1528 : thisSurface.Azimuth,
1529 : thisSurface.Tilt,
1530 0 : thisSurface.Name,
1531 : thisSurface.Class);
1532 0 : for (int svert = 1; svert <= ntri; ++svert) {
1533 0 : const int vv0 = mytriangles(svert).vv0;
1534 0 : const int vv1 = mytriangles(svert).vv1;
1535 0 : const int vv2 = mytriangles(svert).vv2;
1536 0 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1537 : }
1538 0 : print(wrlfile, Format_805);
1539 0 : mytriangles.deallocate();
1540 0 : }
1541 36 : }
1542 : // ! now do zone surfaces, by zone
1543 246 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
1544 210 : int oldSurfNum = 0;
1545 10917 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1546 10707 : auto &thisSurface = state.dataSurface->Surface(surf);
1547 10707 : ++oldSurfNum;
1548 10707 : if (thisSurface.Zone != zoneNum) continue;
1549 1666 : if (thisSurface.Sides == 0) continue;
1550 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::IntMass) continue;
1551 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Wall) colorindex = Color::Wall;
1552 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Roof) colorindex = Color::Roof;
1553 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::TDD_Dome) colorindex = Color::Window;
1554 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Floor) colorindex = Color::Floor;
1555 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Window) colorindex = Color::Window;
1556 1646 : if (thisSurface.Class == DataSurfaces::SurfaceClass::Door) colorindex = Color::Window;
1557 :
1558 1646 : print(wrlfile, "# {}:{}\n", thisSurface.ZoneName, thisSurface.Name);
1559 1646 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", oldSurfNum);
1560 8232 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1561 6586 : print(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1562 : }
1563 1646 : print<check_syntax(Format_803)>(wrlfile, Format_803);
1564 1646 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1565 8214 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1566 6570 : print(wrlfile, " {}", vert - 1);
1567 6570 : if (vert == thisSurface.Sides) print(wrlfile, " -1\n");
1568 : }
1569 1644 : print<check_syntax(Format_805)>(wrlfile, Format_805);
1570 1644 : } else { // will be >4 sided polygon with triangulate option
1571 2 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1572 4 : const int ntri = DXFEarClipping::Triangulate(state,
1573 : thisSurface.Sides,
1574 2 : thisSurface.Vertex,
1575 : mytriangles,
1576 : thisSurface.Azimuth,
1577 : thisSurface.Tilt,
1578 2 : thisSurface.Name,
1579 : thisSurface.Class);
1580 14 : for (int svert = 1; svert <= ntri; ++svert) {
1581 12 : const int vv0 = mytriangles(svert).vv0;
1582 12 : const int vv1 = mytriangles(svert).vv1;
1583 12 : const int vv2 = mytriangles(svert).vv2;
1584 12 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1585 : }
1586 2 : print(wrlfile, Format_805);
1587 2 : mytriangles.deallocate();
1588 2 : }
1589 210 : }
1590 : // still have to do shading surfaces for zone
1591 210 : colorindex = Color::SubShade;
1592 10917 : for (int surf : state.dataSurface->AllSurfaceListReportOrder) {
1593 10707 : auto &thisSurface = state.dataSurface->Surface(surf);
1594 : // !if (surface(surf)%heattranssurf) CYCLE ! Shading with a construction is allowed to be HT surf for daylighting shelves
1595 10707 : if (thisSurface.Class != DataSurfaces::SurfaceClass::Shading) continue;
1596 796 : if (thisSurface.ZoneName != state.dataHeatBal->Zone(zoneNum).Name) continue;
1597 132 : if (thisSurface.Sides == 0) continue;
1598 132 : print(wrlfile, "# {}:{}\n", thisSurface.ZoneName, thisSurface.Name);
1599 132 : print<check_syntax(Format_801)>(wrlfile, Format_801, colorstring[static_cast<int>(colorindex)], "Surf", surf);
1600 660 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1601 528 : print(wrlfile, Format_802, thisSurface.Vertex(vert).x, thisSurface.Vertex(vert).y, thisSurface.Vertex(vert).z);
1602 : }
1603 132 : print(wrlfile, Format_803);
1604 132 : if (thisSurface.Sides <= 4 || !TriangulateFace) {
1605 660 : for (int vert = 1; vert <= thisSurface.Sides; ++vert) {
1606 528 : print(wrlfile, " {}", vert - 1);
1607 528 : if (vert == thisSurface.Sides) print(wrlfile, " -1\n");
1608 : }
1609 132 : print(wrlfile, Format_805);
1610 132 : } else { // will be >4 sided polygon with triangulate option
1611 0 : Array1D<DataVectorTypes::dTriangle> mytriangles;
1612 0 : const int ntri = DXFEarClipping::Triangulate(state,
1613 : thisSurface.Sides,
1614 0 : thisSurface.Vertex,
1615 : mytriangles,
1616 : thisSurface.Azimuth,
1617 : thisSurface.Tilt,
1618 0 : thisSurface.Name,
1619 : thisSurface.Class);
1620 0 : for (int svert = 1; svert <= ntri; ++svert) {
1621 0 : const int vv0 = mytriangles(svert).vv0;
1622 0 : const int vv1 = mytriangles(svert).vv1;
1623 0 : const int vv2 = mytriangles(svert).vv2;
1624 0 : print(wrlfile, " {} {} {} -1\n", vv0 - 1, vv1 - 1, vv2 - 1);
1625 : }
1626 0 : print(wrlfile, Format_805);
1627 0 : mytriangles.deallocate();
1628 0 : }
1629 210 : }
1630 : }
1631 :
1632 : // vrml does not have daylighting reference points included
1633 36 : }
1634 :
1635 : } // namespace EnergyPlus
|