LCOV - code coverage report
Current view: top level - EnergyPlus - PierceSurface.hh (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 41.0 % 161 66
Test Date: 2025-06-02 07:23:51 Functions: 33.3 % 3 1

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : #ifndef EnergyPlus_PierceSurface_hh_INCLUDED
      49              : #define EnergyPlus_PierceSurface_hh_INCLUDED
      50              : 
      51              : // Purpose: Functions for checking if a ray hits a surface
      52              : //
      53              : // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
      54              : //
      55              : // History:
      56              : //  Jun 2015: Last update of legacy version based on DOE-2 DPIERC
      57              : //  Jan 2016: Initial release
      58              : //
      59              : // Notes:
      60              : //  This is filling the role of the former PierceSurface function authored by Fred Winkelmann and based on
      61              : //   DOE-2.1E subroutine DPIERC and some aspects of this version are analogous
      62              : //  To match the former behavior rays with origin exactly on the surface are treated as not hitting
      63              : //  These functions are VERY performance critical for daylighting and solar reflection
      64              : //   This high-performance implementation was built to complement the octree system for scalability of those systems
      65              : //  This has been carefully designed for speed but is probably not be optimal yet
      66              : //   For EnergyPlus most surfaces are rectangular so that is the most important for performance
      67              : //   Inlining, storing preprocessed values in Surface, 2D projection, & short circuiting are used here for speed
      68              : //   Agressive inlining options may be needed to get peak performance
      69              : //   Don't make changes here without validating the performance impact
      70              : 
      71              : // EnergyPlus Headers
      72              : #include <EnergyPlus/DataSurfaces.hh>
      73              : #include <EnergyPlus/EnergyPlus.hh>
      74              : #include <EnergyPlus/Platform.hh>
      75              : 
      76              : // ObjexxFCL Headers
      77              : #include <ObjexxFCL/Vector2.hh>
      78              : #include <ObjexxFCL/Vector3.hh>
      79              : #include <ObjexxFCL/Vector4.hh>
      80              : 
      81              : // C++ Headers
      82              : #include <algorithm>
      83              : #include <cassert>
      84              : #include <limits>
      85              : 
      86              : namespace EnergyPlus {
      87              : 
      88            0 : inline bool PierceSurface_Triangular(DataSurfaces::Surface2D const &s2d, // 2D surface
      89              :                                      Vector2<Real64> const &h2d          // 2D hit point
      90              : )
      91              : {
      92              :     // Purpose: Check if a 2D hit point is in a triangular 2D surface
      93              :     //
      94              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
      95              :     //
      96              :     // History:
      97              :     //  Jan 2016: Initial release
      98              :     //
      99              :     // Notes:
     100              :     //  Pulled this case out into separate function to facilitate inlining
     101              : 
     102              :     using DataSurfaces::Surface2D;
     103            0 :     Surface2D::Vertices const &vs(s2d.vertices); // 2D surface vertices
     104            0 :     Surface2D::Vectors const &es(s2d.edges);     // 2D surface edge vectors
     105            0 :     if (es[0].cross(h2d - vs[0]) < 0.0) {
     106            0 :         return false;
     107              :     }
     108            0 :     if (es[1].cross(h2d - vs[1]) < 0.0) {
     109            0 :         return false;
     110              :     }
     111            0 :     if (es[2].cross(h2d - vs[2]) < 0.0) {
     112            0 :         return false;
     113              :     }
     114            0 :     return true;
     115              : } // PierceSurface_Triangular()
     116              : 
     117        23976 : inline bool PierceSurface_Convex(DataSurfaces::Surface2D const &s2d, // 2D surface
     118              :                                  Vector2<Real64> const &h2d          // 2D hit point
     119              : )
     120              : {
     121              :     // Purpose: Check if a 2D hit point is in a convex 2D surface
     122              :     //
     123              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     124              :     //
     125              :     // History:
     126              :     //  Jan 2016: Initial release
     127              :     //
     128              :     // Notes:
     129              :     //  Pulled this rare case out into separate function to facilitate inlining
     130              :     //  This is O( n ) complexity so it is isn't used for many-vertex surfaces
     131              : 
     132              :     using DataSurfaces::Surface2D;
     133        23976 :     Surface2D::Vertices const &vs(s2d.vertices); // 2D surface vertices
     134        23976 :     Surface2D::Vectors const &es(s2d.edges);     // 2D surface edge vectors
     135        23976 :     Surface2D::Vertices::size_type const n(vs.size());
     136        23976 :     assert(n >= 3u);
     137        23976 :     switch (n) {
     138            0 :     case 8:
     139            0 :         if (es[7].cross(h2d - vs[7]) < 0.0) {
     140            0 :             return false;
     141              :         }
     142              :         // fallthrough
     143              :     case 7:
     144            0 :         if (es[6].cross(h2d - vs[6]) < 0.0) {
     145            0 :             return false;
     146              :         }
     147              :         // fallthrough
     148              :     case 6:
     149            0 :         if (es[5].cross(h2d - vs[5]) < 0.0) {
     150            0 :             return false;
     151              :         }
     152              :         // fallthrough
     153              :     case 5:
     154            0 :         if (es[4].cross(h2d - vs[4]) < 0.0) {
     155            0 :             return false;
     156              :         }
     157              :         // fallthrough
     158              :     case 4:
     159        23976 :         if (es[3].cross(h2d - vs[3]) < 0.0) {
     160         5978 :             return false;
     161              :         }
     162              :         // fallthrough
     163              :     case 3:
     164        17998 :         if (es[2].cross(h2d - vs[2]) < 0.0) {
     165           18 :             return false;
     166              :         }
     167        17980 :         if (es[1].cross(h2d - vs[1]) < 0.0) {
     168           18 :             return false;
     169              :         }
     170        17962 :         if (es[0].cross(h2d - vs[0]) < 0.0) {
     171         5902 :             return false;
     172              :         }
     173        12060 :         return true;
     174            0 :     default:
     175            0 :         for (Surface2D::Vertices::size_type i = 0; i < n; ++i) {
     176            0 :             if (es[i].cross(h2d - vs[i]) < 0.0) {
     177            0 :                 return false;
     178              :             }
     179              :         }
     180            0 :         return true;
     181              :     }
     182              : } // PierceSurface_Convex()
     183              : 
     184            0 : inline bool PierceSurface_Nonconvex(DataSurfaces::Surface2D const &s2d, // 2D surface
     185              :                                     Vector2<Real64> const &h2d          // 2D hit point
     186              : )
     187              : {
     188              :     // Purpose: Check if a 2D hit point is in a 2D possibly nonconvex surface
     189              :     //
     190              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     191              :     //
     192              :     // History:
     193              :     //  Jan 2016: Initial release
     194              :     //
     195              :     // Notes:
     196              :     //  Pulled this rare case out into separate function to facilitate inlining
     197              :     //  This works for nonconvex "simple" (no edge crossings) polygons
     198              :     //  This is also a fast O( log n ) algorithm for many-vertex convex surfaces
     199              : 
     200              :     using DataSurfaces::Surface2D;
     201              :     using size_type = Surface2D::Vertices::size_type;
     202              :     using Slab = DataSurfaces::Surface2DSlab;
     203              :     using Vertex2D = Vector2<Real64>;
     204            0 :     assert(s2d.vertices.size() >= 3u);
     205            0 :     Surface2D::Slabs const &slabs(s2d.slabs);    // 2D surface y slice slabs
     206            0 :     Surface2D::SlabYs const &slabYs(s2d.slabYs); // 2D surface slab y coordinates
     207            0 :     assert(slabYs.size() > 0u);
     208            0 :     Real64 const yHit(h2d.y); // Hit point y coordinate
     209              : 
     210              :     // Find slab with y range containing hit point
     211            0 :     auto const iHit(std::lower_bound(slabYs.begin(), slabYs.end(), yHit));
     212            0 :     assert((yHit >= slabYs.front()) && (yHit <= slabYs.back())); // Passed bounding box check so hit point in slabs y range
     213            0 :     assert(iHit != slabYs.end());                                // Hit point can't be above all slabs: passed bounding box check
     214            0 :     size_type const iSlab(std::min(static_cast<size_type>(iHit - 1 - slabYs.begin()), slabs.size())); // Hit slab index
     215            0 :     Slab const &slab(slabs[iSlab]);
     216              : 
     217              :     // Check hit point within slab bounding box x range
     218            0 :     Real64 const xHit(h2d.x); // Hit point x coordinate
     219            0 :     if ((xHit < slab.xl) || (xHit > slab.xu)) {
     220            0 :         return false; // Hit point outside slab bounding box
     221              :     }
     222              : 
     223              :     // Find edge pair surrounding hit point
     224            0 :     Slab::Edges const &slabEdges(slab.edges);
     225            0 :     Slab::EdgesXY const &slabEdgesXY(slab.edgesXY);
     226            0 :     size_type const nEdges(slabEdges.size());
     227            0 :     assert(nEdges >= 2u);
     228            0 :     if (nEdges == 2) { // 2 edges
     229            0 :         Slab::Edge const se0(slabEdges[0]);
     230            0 :         Slab::EdgeXY const eXY0(slabEdgesXY[0]);
     231            0 :         Vertex2D v0(s2d.vertices[se0]);
     232            0 :         Surface2D::Edge e0(s2d.edges[se0]);
     233            0 :         Real64 const x0(v0.x + (yHit - v0.y) * eXY0);
     234            0 :         if (xHit < x0) {
     235            0 :             return false; // Hit point x is left of left edge
     236              :         }
     237            0 :         Slab::Edge const se1(slabEdges[1]);
     238            0 :         Slab::EdgeXY const eXY1(slabEdgesXY[1]);
     239            0 :         Vertex2D v1(s2d.vertices[se1]);
     240            0 :         Surface2D::Edge e1(s2d.edges[se1]);
     241            0 :         Real64 const x1(v1.x + (yHit - v1.y) * eXY1);
     242            0 :         if (x1 < xHit) {
     243            0 :             return false; // Hit point is right of right edge
     244              :         }
     245            0 :     } else { // 4+ edges: Binary search for edges surrounding hit point
     246            0 :         assert(nEdges >= 4u);
     247            0 :         assert(nEdges % 2 == 0u);
     248            0 :         size_type l(0u), u(nEdges - 1);
     249            0 :         Slab::Edge const il(slabEdges[l]);
     250            0 :         Slab::EdgeXY const eXYl(slabEdgesXY[l]);
     251            0 :         Vertex2D const &vl(s2d.vertices[il]);
     252            0 :         Surface2D::Edge const el(s2d.edges[il]);
     253            0 :         Real64 const xl(vl.x + (yHit - vl.y) * eXYl);
     254            0 :         if (xHit < xl) {
     255            0 :             return false; // Hit point x is left of leftmost edge
     256              :         }
     257            0 :         Slab::Edge const iu(slabEdges[u]);
     258            0 :         Slab::EdgeXY const eXYu(slabEdgesXY[u]);
     259            0 :         Vertex2D const &vu(s2d.vertices[iu]);
     260            0 :         Surface2D::Edge const eu(s2d.edges[iu]);
     261            0 :         Real64 const xu(vu.x + (yHit - vu.y) * eXYu);
     262            0 :         if (xu < xHit) {
     263            0 :             return false; // Hit point is right of rightmost edge
     264              :         }
     265            0 :         while (u - l > 1u) {
     266            0 :             size_type const m((l + u) / 2);
     267            0 :             Slab::Edge const im(slabEdges[m]);
     268            0 :             Slab::EdgeXY const eXYm(slabEdgesXY[m]);
     269            0 :             Vertex2D const &vm(s2d.vertices[im]);
     270            0 :             Surface2D::Edge const em(s2d.edges[im]);
     271            0 :             Real64 xm(vm.x + (yHit - vm.y) * eXYm);
     272            0 :             if (xHit <= xm) {
     273            0 :                 u = m;
     274              :             } else {
     275            0 :                 l = m;
     276              :             }
     277            0 :         }
     278            0 :         assert(u - l == 1u);
     279            0 :         if (u % 2 == 0u) {
     280            0 :             return false; // Outside of nonconvex surface polygon
     281              :         }
     282            0 :     }
     283            0 :     return true;
     284            0 : } // PierceSurface_nonconvex()
     285              : 
     286              : ALWAYS_INLINE
     287              : bool PierceSurface_polygon(DataSurfaces::SurfaceData const &surface, // Surface
     288              :                            Vector3<Real64> const &hitPt              // Ray-plane intersection point
     289              : )
     290              : {
     291              :     // Purpose: Check if hit point on surface plane is in surface polygon
     292              :     //
     293              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     294              :     //
     295              :     // History:
     296              :     //  Jan 2016: Initial release
     297              : 
     298              :     using DataSurfaces::nVerticesBig;
     299              :     using DataSurfaces::Surface2D;
     300              :     using Vertex2D = Vector2<Real64>;
     301     52430718 :     Surface2D const &s2d(surface.surface2d);
     302     52430718 :     int const axis(s2d.axis);
     303     52430718 :     Vertex2D const h2d(axis == 0 ? hitPt.y : hitPt.x, axis == 2 ? hitPt.y : hitPt.z); // Hit point in 2D surface's plane
     304     52430718 :     if ((h2d.x < s2d.vl.x) || (s2d.vu.x < h2d.x) || (h2d.y < s2d.vl.y) || (s2d.vu.y < h2d.y)) {
     305     51354136 :         return false; // Misses 2D surface bounding box
     306              :     }
     307      1076582 :     ShapeCat const shapeCat(surface.shapeCat);
     308      1076582 :     if (shapeCat == ShapeCat::Rectangular) { // Rectangular is most common: Special case algorithm is faster but assumes these are really rectangular
     309      1052606 :         Vertex2D const v0h(h2d - s2d.vertices[0]);
     310      1052606 :         Real64 const he1(v0h.dot(s2d.edges[0]));
     311      1052606 :         if ((he1 < 0.0) || (he1 > s2d.s1)) {
     312        34677 :             return false;
     313              :         }
     314      1017929 :         Real64 const he3(-v0h.dot(s2d.edges[3]));
     315      1017929 :         if ((he3 < 0.0) || (he3 > s2d.s3)) {
     316         7512 :             return false;
     317              :         }
     318      1010417 :         return true;
     319      1076582 :     } else if (shapeCat == ShapeCat::Triangular) { // Cross products all nonnegative <=> Hit point in triangle
     320            0 :         return PierceSurface_Triangular(s2d, h2d);
     321        47952 :     } else if ((shapeCat == ShapeCat::Nonconvex) ||
     322        23976 :                (s2d.vertices.size() >= nVerticesBig)) { // O( log n ) algorithm for nonconvex and many-vertex convex surfaces
     323            0 :         return PierceSurface_Nonconvex(s2d, h2d);
     324        23976 :     } else if (shapeCat == ShapeCat::Convex) { // O( n ) algorithm for convex surface without too many vertices
     325        23976 :         return PierceSurface_Convex(s2d, h2d);
     326              :     } else {
     327            0 :         return false; // Should we assert here also?
     328              :     }
     329     52430718 : } // PierceSurface_Polygon()
     330              : 
     331              : ALWAYS_INLINE
     332              : bool PierceSurface(DataSurfaces::SurfaceData const &surface, // Surface
     333              :                    Vector3<Real64> const &rayOri,            // Ray origin point
     334              :                    Vector3<Real64> const &rayDir,            // Ray direction vector
     335              :                    Vector3<Real64> &hitPt                    // Ray-plane intersection point
     336              : )
     337              : {
     338              :     // Purpose: Check if a ray hits a surface and return the point of intersection
     339              :     //  with the surface's plane if they intersect.
     340              :     //  Convex and concave surfaces with 3 or more vertices are supported.
     341              :     //
     342              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     343              :     //
     344              :     // History:
     345              :     //  Jan 2016: Initial release
     346              : 
     347              :     // Find ray intersection with surface plane
     348    128188365 :     DataSurfaces::SurfaceData::Plane const &plane(surface.plane);
     349    128188365 :     Real64 const den((plane.x * rayDir.x) + (plane.y * rayDir.y) + (plane.z * rayDir.z));
     350     76035379 :     if (den == 0.0) { // Ray is parallel to plane: This not treated as piercing even if ray lies in plane
     351         8539 :         return false;
     352              :     } else { // Ray's line intersects plane
     353    128179826 :         Real64 const num(-((plane.x * rayOri.x) + (plane.y * rayOri.y) + (plane.z * rayOri.z) + plane.w));
     354    128179826 :         if (num * den <=
     355              :             0.0) { // Ray points away from surface or ray origin is on surface: This looks odd but is fast way to check for different signs
     356     75916562 :             return false;
     357              :         } else {                                 // Ray points toward surface: Compute hit point
     358     52263264 :             Real64 const t(num / den);           // Ray parameter at plane intersection: hitPt = rayOri + t * rayDir
     359     52263264 :             hitPt.x = rayOri.x + (t * rayDir.x); // Compute by coordinate to avoid Vertex temporaries
     360     52263264 :             hitPt.y = rayOri.y + (t * rayDir.y);
     361     52263264 :             hitPt.z = rayOri.z + (t * rayDir.z);
     362              :         }
     363              :     }
     364              : 
     365              :     // Check if hit point is in surface polygon
     366     52263264 :     return PierceSurface_polygon(surface, hitPt);
     367              : } // PierceSurface()
     368              : 
     369              : ALWAYS_INLINE
     370              : bool PierceSurface(EnergyPlusData &state,
     371              :                    int const iSurf,               // Surface index
     372              :                    Vector3<Real64> const &rayOri, // Ray origin point
     373              :                    Vector3<Real64> const &rayDir, // Ray direction vector
     374              :                    Vector3<Real64> &hitPt         // Ray-plane intersection point
     375              : )
     376              : {
     377              :     // Purpose: Overload taking surface index instead of surface
     378              :     //
     379              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     380              :     //
     381              :     // History:
     382              :     //  Jan 2016: Initial release
     383              : 
     384    112246618 :     return PierceSurface(state.dataSurface->Surface(iSurf), rayOri, rayDir, hitPt);
     385              : } // PierceSurface()
     386              : 
     387              : ALWAYS_INLINE
     388              : bool PierceSurface(DataSurfaces::SurfaceData const &surface, // Surface
     389              :                    Vector3<Real64> const &rayOri,            // Ray origin point
     390              :                    Vector3<Real64> const &rayDir,            // Ray direction unit vector
     391              :                    Real64 const dMax,                        // Max distance from rayOri to hit point
     392              :                    Vector3<Real64> &hitPt                    // Ray-plane intersection point
     393              : )
     394              : {
     395              :     // Purpose: Check if a ray hits a surface and return the point of intersection
     396              :     //  with the surface's plane if they intersect.
     397              :     //  Convex and concave surfaces with 3 or more vertices are supported.
     398              :     //  This overload limits the ray-surface distance for a hit.
     399              :     //
     400              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     401              :     //
     402              :     // History:
     403              :     //  Jan 2016: Initial release
     404              : 
     405              :     // Input checks
     406     15473387 :     assert(std::abs(rayDir.mag_squared() - 1.0) <
     407              :            6 * std::numeric_limits<Real64>::epsilon()); // Check unit vector (6x is rough estimate. Increase slightly as needed.)
     408     15473387 :     assert(dMax >= 0.0);                                // Distance must be nonnegative
     409              : 
     410              :     // Find ray intersection with surface plane
     411     15473387 :     DataSurfaces::SurfaceData::Plane const &plane(surface.plane);
     412     15473387 :     Real64 const den((plane.x * rayDir.x) + (plane.y * rayDir.y) + (plane.z * rayDir.z));
     413     15473387 :     if (den == 0.0) { // Ray is parallel to plane: This not treated as piercing even if ray lies in plane
     414         1426 :         return false;
     415              :     } else { // Ray's line intersects plane
     416     15471961 :         Real64 const num(-((plane.x * rayOri.x) + (plane.y * rayOri.y) + (plane.z * rayOri.z) + plane.w));
     417     15471961 :         if (num * den <=
     418              :             0.0) { // Ray points away from surface or ray origin is on surface: This looks odd but is fast way to check for different signs
     419      8768288 :             return false;
     420              :         } else {                       // Ray points toward surface: Compute hit point
     421      6703673 :             Real64 const t(num / den); // Ray parameter at plane intersection: hitPt = rayOri + t * rayDir
     422      6703673 :             if (t > dMax) {
     423      6536219 :                 return false; // Hit point exceeds distance from rayOri limit
     424              :             }
     425       167454 :             hitPt.x = rayOri.x + (t * rayDir.x); // Compute by coordinate to avoid Vertex temporaries
     426       167454 :             hitPt.y = rayOri.y + (t * rayDir.y);
     427       167454 :             hitPt.z = rayOri.z + (t * rayDir.z);
     428              :         }
     429              :     }
     430              : 
     431              :     // Check if hit point is in surface polygon
     432       167454 :     return PierceSurface_polygon(surface, hitPt);
     433              : } // PierceSurface()
     434              : 
     435              : ALWAYS_INLINE
     436              : bool PierceSurface(EnergyPlusData &state,
     437              :                    int const iSurf,               // Surface index
     438              :                    Vector3<Real64> const &rayOri, // Ray origin point
     439              :                    Vector3<Real64> const &rayDir, // Ray direction unit vector
     440              :                    Real64 const dMax,             // Max distance from rayOri to hit point
     441              :                    Vector3<Real64> &hitPt         // Ray-plane intersection point
     442              : )
     443              : {
     444              :     // Purpose: Overload taking surface index instead of surface
     445              :     //
     446              :     // Author: Stuart Mentzer (Stuart_Mentzer@objexx.com)
     447              :     //
     448              :     // History:
     449              :     //  Jan 2016: Initial release
     450              : 
     451     24867122 :     return PierceSurface(state.dataSurface->Surface(iSurf), rayOri, rayDir, dMax, hitPt);
     452              : }
     453              : 
     454              : } // namespace EnergyPlus
     455              : 
     456              : #endif
        

Generated by: LCOV version 2.0-1