LCOV - code coverage report
Current view: top level - EnergyPlus - OutputReports.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 81.6 % 1048 855
Test Date: 2025-06-02 07:23:51 Functions: 100.0 % 10 10

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

Generated by: LCOV version 2.0-1