LCOV - code coverage report
Current view: top level - EnergyPlus - OutputReports.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 28.3 % 958 271
Test Date: 2025-05-22 16:09:37 Functions: 60.0 % 10 6

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

Generated by: LCOV version 2.0-1