LCOV - code coverage report
Current view: top level - EnergyPlus - OutputReports.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 27.0 % 1048 283
Test Date: 2025-06-02 12:03:30 Functions: 60.0 % 10 6

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

Generated by: LCOV version 2.0-1