Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array2D.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/DXFEarClipping.hh>
57 : #include <EnergyPlus/Data/EnergyPlusData.hh>
58 : #include <EnergyPlus/DataSurfaces.hh>
59 : #include <EnergyPlus/UtilityRoutines.hh>
60 :
61 : namespace EnergyPlus {
62 :
63 : namespace DXFEarClipping {
64 :
65 : // Module containing the routines dealing with triangulating a polygon of >4 sides
66 :
67 : // Module information:
68 : // Author Linda Lawrie
69 : // Date written October 2005
70 :
71 : // Purpose of this module:
72 : // This module provides the techniques and back up procedures for producing a triangulated
73 : // polygon from a >4 sided figure. It is only used for DXF output.
74 :
75 : // Methodology employed:
76 : // Ear clipping has turned out to be the simplest, most robust technique.
77 :
78 0 : bool InPolygon(Vector const &point, Array1D<Vector> &poly, int const nsides)
79 : {
80 : // this routine is not used in the current scheme
81 :
82 : // Return value
83 : bool InPolygon;
84 :
85 : // Argument array dimensioning
86 0 : EP_SIZE_CHECK(poly, nsides);
87 :
88 : // Locals
89 : //'Return TRUE if the point (xp,yp) lies inside the circumcircle
90 : //'made up by points (x1,y1) (x2,y2) (x3,y3)
91 : //'The circumcircle centre is returned in (xc,yc) and the radius r
92 : //'NOTE: A point on the edge is inside the circumcircle
93 :
94 0 : Real64 constexpr epsilon(0.0000001);
95 : Real64 costheta;
96 : Real64 m1;
97 : Real64 m2;
98 : Real64 acosval;
99 :
100 : // Object Data
101 0 : Vector p1;
102 0 : Vector p2;
103 :
104 0 : InPolygon = false;
105 :
106 0 : Real64 anglesum = 0.0;
107 :
108 0 : for (int vert = 1; vert <= nsides - 1; ++vert) {
109 :
110 0 : p1.x = poly(vert).x - point.x;
111 0 : p1.y = poly(vert).y - point.y;
112 0 : p1.z = poly(vert).z - point.z;
113 :
114 0 : p2.x = poly(vert + 1).x - point.x;
115 0 : p2.y = poly(vert + 1).y - point.y;
116 0 : p2.z = poly(vert + 1).z - point.z;
117 :
118 0 : m1 = Modulus(p1);
119 0 : m2 = Modulus(p2);
120 :
121 0 : if (m1 * m2 <= epsilon) {
122 0 : InPolygon = true;
123 0 : break;
124 : } else {
125 0 : costheta = (p1.x * p2.x + p1.y * p2.y + p1.z * p2.z) / (m1 * m2);
126 0 : acosval = std::acos(costheta);
127 0 : anglesum += acosval;
128 : }
129 : }
130 :
131 0 : if (std::abs(anglesum - Constant::TwoPi) <= epsilon) {
132 0 : InPolygon = true;
133 : }
134 :
135 0 : return InPolygon;
136 0 : }
137 :
138 0 : Real64 Modulus(Vector const &point)
139 : {
140 : // this routine is not used in the current scheme
141 :
142 : // Return value
143 : Real64 rModulus;
144 :
145 0 : rModulus = std::sqrt(point.x * point.x + point.y * point.y + point.z * point.z);
146 :
147 0 : return rModulus;
148 : }
149 :
150 0 : int Triangulate(EnergyPlusData &state,
151 : int const nsides, // number of sides to polygon
152 : Array1D<Vector> &polygon,
153 : Array1D<dTriangle> &outtriangles,
154 : Real64 const surfazimuth, // surface azimuth angle (outward facing normal)
155 : Real64 const surftilt, // surface tilt angle
156 : std::string const &surfname, // surface name (for error messages)
157 : DataSurfaces::SurfaceClass surfclass // surface class
158 : )
159 : {
160 :
161 : // Subroutine information:
162 : // Author Linda Lawrie
163 : // Date written October 2005
164 :
165 : // Purpose of this subroutine:
166 : // This routine is a self-contained triangulation calculation from a polygon
167 : // of 3D vertices, nsides, to a returned set (as possible) of triangles -- noted
168 : // by vertex numbers.
169 :
170 : // Argument array dimensioning
171 0 : EP_SIZE_CHECK(polygon, nsides);
172 :
173 : // Subroutine parameter definitions:
174 0 : Real64 constexpr point_tolerance(0.00001);
175 :
176 : // Subroutine local variable declarations:
177 0 : Array1D_int ears(nsides);
178 0 : Array1D_int r_angles(nsides);
179 0 : Array1D<Real64> rangles(nsides);
180 0 : Array1D_int c_vertices(nsides);
181 0 : Array2D_int earvert(nsides, 3);
182 0 : Array1D_bool removed(nsides);
183 0 : Array1D_int earverts(3);
184 0 : Array1D<Real64> xvt(nsides);
185 0 : Array1D<Real64> yvt(nsides);
186 0 : Array1D<Real64> zvt(nsides);
187 :
188 : int nears;
189 : int nrangles;
190 : int ncverts;
191 :
192 : // Object Data
193 0 : Array1D<Vector_2d> vertex(nsides);
194 0 : Array1D<dTriangle> Triangle(nsides);
195 :
196 0 : if (surfclass == DataSurfaces::SurfaceClass::Floor || surfclass == DataSurfaces::SurfaceClass::Roof ||
197 : surfclass == DataSurfaces::SurfaceClass::Overhang) {
198 0 : CalcRfFlrCoordinateTransformation(nsides, polygon, surfazimuth, surftilt, xvt, yvt, zvt);
199 0 : for (int svert = 1; svert <= nsides; ++svert) {
200 0 : for (int mvert = svert + 1; mvert <= nsides; ++mvert) {
201 0 : if (std::abs(xvt(svert) - xvt(mvert)) <= point_tolerance) xvt(svert) = xvt(mvert);
202 0 : if (std::abs(zvt(svert) - zvt(mvert)) <= point_tolerance) zvt(svert) = zvt(mvert);
203 : }
204 : }
205 0 : for (int svert = 1; svert <= nsides; ++svert) {
206 0 : vertex(svert).x = xvt(svert);
207 0 : vertex(svert).y = zvt(svert);
208 : // if (trackit) write(outputfiledebug,*) 'x=',xvt(svert),' y=',zvt(svert)
209 : }
210 0 : } else {
211 0 : CalcWallCoordinateTransformation(nsides, polygon, surfazimuth, surftilt, xvt, yvt, zvt);
212 0 : for (int svert = 1; svert <= nsides; ++svert) {
213 0 : for (int mvert = svert + 1; mvert <= nsides; ++mvert) {
214 0 : if (std::abs(xvt(svert) - xvt(mvert)) <= point_tolerance) xvt(svert) = xvt(mvert);
215 0 : if (std::abs(zvt(svert) - zvt(mvert)) <= point_tolerance) zvt(svert) = zvt(mvert);
216 : }
217 : }
218 0 : for (int svert = 1; svert <= nsides; ++svert) {
219 0 : vertex(svert).x = xvt(svert);
220 0 : vertex(svert).y = zvt(svert);
221 : }
222 : }
223 :
224 : // find ears
225 0 : int nvertcur = nsides;
226 0 : int ncount = 0;
227 0 : int svert = 1;
228 0 : int mvert = 2;
229 0 : int evert = 3;
230 0 : removed = false;
231 0 : while (nvertcur > 3) {
232 0 : generate_ears(state, nsides, vertex, ears, nears, r_angles, nrangles, c_vertices, ncverts, removed, earverts, rangles);
233 0 : if (!any_gt(ears, 0)) {
234 0 : ShowWarningError(state,
235 0 : format("DXFOut: Could not triangulate surface=\"{}\", type=\"{}\", check surface vertex order(entry)",
236 : surfname,
237 0 : DataSurfaces::cSurfaceClass(surfclass)));
238 0 : ++state.dataDXFEarClipping->errcount;
239 0 : if (state.dataDXFEarClipping->errcount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
240 0 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
241 : }
242 0 : if (state.dataGlobal->DisplayExtraWarnings) {
243 0 : ShowMessage(state, format(" surface={} class={}", surfname, DataSurfaces::cSurfaceClass(surfclass)));
244 :
245 0 : for (int j = 1; j <= nsides; ++j) {
246 0 : ShowMessage(state, format(" side={} ({:.1R},{:.1R},{:.1R})", j, polygon(j).x, polygon(j).y, polygon(j).z));
247 : }
248 0 : ShowMessage(state, format(" number of triangles found={:12}", ncount));
249 0 : for (int j = 1; j <= nrangles; ++j) {
250 0 : ShowMessage(state, format(" r angle={} vert={} deg={:.1R}", j, r_angles(j), rangles(j) * Constant::RadToDeg));
251 : }
252 : }
253 0 : break; // while loop
254 : }
255 0 : if (nears > 0) {
256 0 : svert = earverts(1);
257 0 : mvert = earverts(2);
258 0 : evert = earverts(3);
259 : // remove ear
260 0 : ++ncount;
261 0 : removed(mvert) = true;
262 0 : earvert(ncount, 1) = svert;
263 0 : earvert(ncount, 2) = mvert;
264 0 : earvert(ncount, 3) = evert;
265 0 : --nvertcur;
266 : }
267 0 : if (nvertcur == 3) {
268 0 : int j = 1;
269 0 : ++ncount;
270 0 : for (int i = 1; i <= nsides; ++i) {
271 0 : if (removed(i)) continue;
272 0 : earvert(ncount, j) = i;
273 0 : ++j;
274 : }
275 : }
276 : }
277 :
278 0 : int ntri = ncount;
279 :
280 0 : for (int i = 1; i <= ntri; ++i) {
281 0 : Triangle(i).vv0 = earvert(i, 1);
282 0 : Triangle(i).vv1 = earvert(i, 2);
283 0 : Triangle(i).vv2 = earvert(i, 3);
284 : }
285 :
286 0 : outtriangles.allocate(ntri);
287 0 : for (int i = 1; i <= ntri; ++i) {
288 0 : outtriangles(i) = Triangle(i);
289 : }
290 :
291 0 : return ntri;
292 0 : }
293 :
294 0 : Real64 angle_2dvector(Real64 const xa, // vertex coordinate
295 : Real64 const ya, // vertex coordinate
296 : Real64 const xb, // vertex coordinate
297 : Real64 const yb, // vertex coordinate
298 : Real64 const xc, // vertex coordinate
299 : Real64 const yc // vertex coordinate
300 : )
301 : {
302 :
303 : // Function information:
304 : // Author Linda Lawrie
305 : // Date written October 2005
306 :
307 : // Purpose of this function:
308 : // This function calculates the angle between two sides of a 2d polygon.
309 : // It computes the interior angle in radians at vertex
310 : // (XB,YB) of the chain formed by the directed edges from
311 : // (XA,YA) to (XB,YB) to (XC,YC). The interior is to the
312 : // left of the two directed edges.
313 :
314 : // References:
315 : // Geometry Tools for Computer Graphics
316 :
317 : // Return value
318 : Real64 angle; // the angle, between 0 and 2*PI.
319 :
320 : // angle is set to PI/2 in the degenerate case.
321 :
322 : // Function parameter definitions:
323 0 : Real64 constexpr epsilon(0.0000001);
324 :
325 0 : Real64 x1 = xa - xb;
326 0 : Real64 y1 = ya - yb;
327 0 : Real64 x2 = xc - xb;
328 0 : Real64 y2 = yc - yb;
329 :
330 0 : Real64 t = std::sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2));
331 0 : if (t == 0.0E+00) t = 1.0E+00;
332 :
333 0 : t = (x1 * x2 + y1 * y2) / t;
334 :
335 0 : if ((1.0E+00 - epsilon) < std::abs(t)) {
336 0 : t = sign(1.0E+00, t);
337 : }
338 :
339 0 : angle = std::acos(t);
340 :
341 0 : if (x2 * y1 - y2 * x1 < 0.0E+00) {
342 0 : angle = 2.0E+00 * Constant::Pi - angle;
343 : }
344 :
345 0 : return angle;
346 : }
347 :
348 0 : bool polygon_contains_point_2d(int const nsides, // number of sides (vertices)
349 : Array1D<Vector_2d> &polygon, // points of polygon
350 : Vector_2d const &point // point to be tested
351 : )
352 : {
353 :
354 : // Function information:
355 : // Author Linda Lawrie
356 : // Date written October 2005
357 :
358 : // Purpose of this function:
359 : // Determine if a point is inside a simple 2d polygon. For a simple polygon (one whose
360 : // boundary never crosses itself). The polygon does not need to be convex.
361 :
362 : // References:
363 : // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
364 : // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
365 :
366 : // Return value
367 : bool inside; // return value, true=inside, false = not inside
368 :
369 : // Argument array dimensioning
370 0 : EP_SIZE_CHECK(polygon, nsides);
371 :
372 : // Function local variable declarations:
373 : int ip1;
374 :
375 0 : inside = false;
376 :
377 0 : for (int i = 1; i <= nsides; ++i) {
378 :
379 0 : if (i < nsides) {
380 0 : ip1 = i + 1;
381 : } else {
382 0 : ip1 = 1;
383 : }
384 :
385 0 : if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
386 0 : if ((point.x - polygon(i).x) - (point.y - polygon(i).y) * (polygon(ip1).x - polygon(i).x) / (polygon(ip1).y - polygon(i).y) < 0) {
387 0 : inside = !inside;
388 : }
389 : }
390 : }
391 :
392 0 : return inside;
393 : }
394 :
395 0 : void generate_ears(EnergyPlusData &state,
396 : int const nvert, // number of vertices in polygon
397 : Array1D<Vector_2d> &vertex,
398 : Array1D_int &ears, // number of ears possible (dimensioned to nvert)
399 : int &nears, // number of ears found
400 : Array1D_int &r_vertices, // number of reflex vertices (>180) possible
401 : int &nrverts, // number of reflex vertices found (>=180)
402 : Array1D_int &c_vertices, // number of convex vertices
403 : int &ncverts, // number of convex vertices found (< 180)
404 : Array1D_bool &removed, // array that shows if a vertex has been removed (calling routine)
405 : Array1D_int &earvert, // vertex indicators for first ear
406 : Array1D<Real64> &rangles)
407 : {
408 :
409 : // Subroutine information:
410 : // Author Linda Lawrie
411 : // Date written October 2005
412 :
413 : // Purpose of this subroutine:
414 : // This routine generates "ears", "reflex angles" and "convex angles" of the polygon
415 : // based on the method set for in the reference.
416 :
417 : // Methodology employed:
418 : // No elegance used here. Always starts with first vertex in polygon.
419 :
420 : // References:
421 : // Geometric Tools for Computer Graphics, Philip Schneider, David Eberly. 2003. Ear
422 : // clipping for triangulation is described in Chapter 13 on Polygon Partitioning. Also
423 : // described in a small article "Triangulation by Ear Clipping", David Eberly, http://www.geometrictools.com
424 :
425 : // Argument array dimensioning
426 0 : EP_SIZE_CHECK(vertex, nvert);
427 0 : EP_SIZE_CHECK(ears, nvert);
428 0 : EP_SIZE_CHECK(r_vertices, nvert);
429 0 : EP_SIZE_CHECK(c_vertices, nvert);
430 0 : EP_SIZE_CHECK(removed, nvert);
431 0 : EP_SIZE_CHECK(earvert, 3);
432 0 : EP_SIZE_CHECK(rangles, nvert);
433 :
434 : // Subroutine local variable declarations:
435 : bool inpoly; // in polygon or not
436 :
437 : // Object Data
438 0 : Vector_2d point; // structure for point
439 0 : Array1D<Vector_2d> testtri(3); // structure for triangle
440 :
441 : // initialize, always recalculate
442 0 : ears = 0;
443 0 : r_vertices = 0;
444 0 : rangles = 0.0;
445 0 : nears = 0;
446 0 : nrverts = 0;
447 0 : c_vertices = 0;
448 0 : ncverts = 0;
449 :
450 0 : for (int svert = 1; svert <= nvert; ++svert) {
451 0 : if (removed(svert)) continue;
452 : // have starting vertex. now need middle and end
453 0 : int mvert = svert + 1;
454 0 : for (int j = 1; j <= nvert; ++j) {
455 0 : if (mvert > nvert) mvert = 1;
456 0 : if (removed(mvert)) {
457 0 : ++mvert;
458 0 : if (mvert > nvert) mvert = 1;
459 : } else {
460 0 : break;
461 : }
462 : }
463 0 : int evert = mvert + 1;
464 0 : for (int j = 1; j <= nvert; ++j) {
465 0 : if (evert > nvert) evert = 1;
466 0 : if (removed(evert)) {
467 0 : ++evert;
468 0 : if (evert > nvert) evert = 1;
469 : } else {
470 0 : break;
471 : }
472 : }
473 :
474 : // have gotten start, middle and ending vertices. test for reflex angle
475 :
476 0 : Real64 ang = angle_2dvector(vertex(svert).x, vertex(svert).y, vertex(mvert).x, vertex(mvert).y, vertex(evert).x, vertex(evert).y);
477 :
478 0 : if (ang > Constant::Pi) { // sufficiently close to 180 degrees.
479 0 : ++nrverts;
480 0 : r_vertices(nrverts) = mvert;
481 0 : rangles(nrverts) = ang;
482 0 : continue;
483 : } else {
484 0 : ++ncverts;
485 0 : c_vertices(ncverts) = mvert;
486 : }
487 :
488 : // convex angle, see if it's an ear
489 0 : testtri(1) = vertex(svert);
490 0 : testtri(2) = vertex(mvert);
491 0 : testtri(3) = vertex(evert);
492 0 : int tvert = evert;
493 0 : for (int j = 4; j <= nvert; ++j) {
494 0 : ++tvert;
495 0 : if (tvert > nvert) tvert = 1;
496 0 : if (removed(tvert)) continue;
497 0 : point = vertex(tvert);
498 0 : inpoly = polygon_contains_point_2d(3, testtri, point);
499 0 : if (!inpoly) continue;
500 0 : break;
501 : }
502 : // if (trackit) then
503 : // write(outputfiledebug,*) ' triangle=',svert,mvert,evert
504 : // write(outputfiledebug,*) ' vertex1=',vertex(svert)%x,vertex(svert)%y
505 : // write(outputfiledebug,*) ' vertex2=',vertex(mvert)%x,vertex(mvert)%y
506 : // write(outputfiledebug,*) ' vertex3=',vertex(evert)%x,vertex(evert)%y
507 : // write(outputfiledebug,*) ' inpoly=',inpoly
508 : // endif
509 0 : if (!inpoly) {
510 : // found an ear
511 0 : ++nears;
512 0 : ears(nears) = mvert;
513 0 : if (nears == 1) {
514 0 : earvert(1) = svert;
515 0 : earvert(2) = mvert;
516 0 : earvert(3) = evert;
517 : }
518 0 : if (state.dataDXFEarClipping->trackit) {
519 0 : print(state.files.debug, "ear={} triangle={:12}{:12}{:12}\n", nears, svert, mvert, evert);
520 : }
521 : }
522 : }
523 0 : }
524 :
525 0 : void CalcWallCoordinateTransformation(int const nsides,
526 : Array1D<Vector> &polygon,
527 : Real64 const surfazimuth,
528 : [[maybe_unused]] Real64 const surftilt, // unused1208
529 : Array1D<Real64> &xvt,
530 : Array1D<Real64> &yvt,
531 : Array1D<Real64> &zvt)
532 : {
533 :
534 : // Subroutine information:
535 : // Author Linda Lawrie
536 : // Date written October 2005
537 :
538 : // Purpose of this subroutine:
539 : // This routine transforms a "wall" (normally vertical polygon) to a south facing (180 deg outward
540 : // normal) polygon in 2 d (y vertices are then ignored).
541 :
542 : // Methodology employed:
543 : // Standard angle rotation
544 :
545 : // Argument array dimensioning
546 0 : EP_SIZE_CHECK(polygon, nsides);
547 0 : EP_SIZE_CHECK(xvt, nsides);
548 0 : EP_SIZE_CHECK(yvt, nsides);
549 0 : EP_SIZE_CHECK(zvt, nsides);
550 :
551 : // convert surface (wall) to facing 180 (outward normal)
552 :
553 0 : Real64 const alpha = surfazimuth;
554 :
555 0 : Real64 const alpha180 = 180.0 - alpha; // amount to rotate
556 0 : Real64 const alphrad = alpha180 / Constant::RadToDeg;
557 0 : Real64 const cos_alphrad = std::cos(alphrad);
558 0 : Real64 const sin_alphrad = std::sin(alphrad);
559 :
560 0 : for (int i = 1; i <= nsides; ++i) {
561 0 : xvt(i) = cos_alphrad * polygon(i).x + sin_alphrad * polygon(i).y;
562 0 : yvt(i) = -sin_alphrad * polygon(i).x + cos_alphrad * polygon(i).y;
563 0 : zvt(i) = polygon(i).z;
564 : }
565 0 : }
566 :
567 0 : void CalcRfFlrCoordinateTransformation(int const nsides,
568 : Array1D<Vector> &polygon,
569 : [[maybe_unused]] Real64 const surfazimuth, // unused1208
570 : Real64 const surftilt,
571 : Array1D<Real64> &xvt,
572 : Array1D<Real64> &yvt,
573 : Array1D<Real64> &zvt)
574 : {
575 :
576 : // Subroutine information:
577 : // Author Linda Lawrie
578 : // Date written October 2005
579 :
580 : // Purpose of this subroutine:
581 : // This routine transforms a roof/floor (normally flat polygon) to a flat
582 : // polygon in 2 d (z vertices are then ignored).
583 :
584 : // Standard angle rotation
585 :
586 : // Argument array dimensioning
587 0 : EP_SIZE_CHECK(polygon, nsides);
588 0 : EP_SIZE_CHECK(xvt, nsides);
589 0 : EP_SIZE_CHECK(yvt, nsides);
590 0 : EP_SIZE_CHECK(zvt, nsides);
591 :
592 : // Subroutine local variable declarations:
593 :
594 0 : Real64 const alpha = -surftilt;
595 0 : Real64 const alphrad = alpha / Constant::RadToDeg;
596 0 : Real64 const cos_alphrad = std::cos(alphrad);
597 0 : Real64 const sin_alphrad = std::sin(alphrad);
598 :
599 0 : for (int i = 1; i <= nsides; ++i) {
600 0 : xvt(i) = polygon(i).x;
601 0 : yvt(i) = cos_alphrad * polygon(i).x + sin_alphrad * polygon(i).y;
602 0 : zvt(i) = -sin_alphrad * polygon(i).x + cos_alphrad * polygon(i).y;
603 : }
604 0 : }
605 :
606 : // void reorder([[maybe_unused]] int &nvert) // unused1208
607 : //{
608 :
609 : // // Locals
610 : // // type (Vector_2d) nvertex(nvert)
611 : // // integer i
612 : // // type (Vector_2d) point
613 : // // integer nrep
614 :
615 : // // Vertex, nverts is in cw order, reorder for calc
616 :
617 : // // nrep=1
618 : // // nvertex(1)=vertex(1)
619 : // // do i=nvert,1,-1
620 : // // nvertex(nrep)=vertex(i)
621 : // // nrep=nrep+1
622 : // // enddo
623 : // // do i=1,nvert
624 : // // vertex(i)=nvertex(i)
625 : // // enddo
626 : //}
627 :
628 : } // namespace DXFEarClipping
629 :
630 : } // namespace EnergyPlus
|