LCOV - code coverage report
Current view: top level - EnergyPlus - OutputReports.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 803 973 82.5 %
Date: 2024-08-23 23:50:59 Functions: 10 10 100.0 %

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

Generated by: LCOV version 1.14