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 142 : 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 142 : EP_SIZE_CHECK(polygon, nsides);
172 :
173 : // Subroutine parameter definitions:
174 142 : Real64 constexpr point_tolerance(0.00001);
175 :
176 : // Subroutine local variable declarations:
177 142 : Array1D_int ears(nsides);
178 142 : Array1D_int r_angles(nsides);
179 142 : Array1D<Real64> rangles(nsides);
180 142 : Array1D_int c_vertices(nsides);
181 142 : Array2D_int earvert(nsides, 3);
182 142 : Array1D_bool removed(nsides);
183 142 : Array1D_int earverts(3);
184 142 : Array1D<Real64> xvt(nsides);
185 142 : Array1D<Real64> yvt(nsides);
186 142 : Array1D<Real64> zvt(nsides);
187 :
188 : int nears;
189 : int nrangles;
190 : int ncverts;
191 :
192 : // Object Data
193 142 : Array1D<Vector_2d> vertex(nsides);
194 142 : Array1D<dTriangle> Triangle(nsides);
195 :
196 142 : if (surfclass == DataSurfaces::SurfaceClass::Floor || surfclass == DataSurfaces::SurfaceClass::Roof ||
197 : surfclass == DataSurfaces::SurfaceClass::Overhang) {
198 142 : CalcRfFlrCoordinateTransformation(nsides, polygon, surfazimuth, surftilt, xvt, yvt, zvt);
199 1270 : for (int svert = 1; svert <= nsides; ++svert) {
200 5272 : for (int mvert = svert + 1; mvert <= nsides; ++mvert) {
201 4144 : if (std::abs(xvt(svert) - xvt(mvert)) <= point_tolerance) {
202 676 : xvt(svert) = xvt(mvert);
203 : }
204 4144 : if (std::abs(zvt(svert) - zvt(mvert)) <= point_tolerance) {
205 816 : zvt(svert) = zvt(mvert);
206 : }
207 : }
208 : }
209 1270 : for (int svert = 1; svert <= nsides; ++svert) {
210 1128 : vertex(svert).x = xvt(svert);
211 1128 : vertex(svert).y = zvt(svert);
212 : // if (trackit) write(outputfiledebug,*) 'x=',xvt(svert),' y=',zvt(svert)
213 : }
214 142 : } else {
215 0 : CalcWallCoordinateTransformation(nsides, polygon, surfazimuth, surftilt, xvt, yvt, zvt);
216 0 : for (int svert = 1; svert <= nsides; ++svert) {
217 0 : for (int mvert = svert + 1; mvert <= nsides; ++mvert) {
218 0 : if (std::abs(xvt(svert) - xvt(mvert)) <= point_tolerance) {
219 0 : xvt(svert) = xvt(mvert);
220 : }
221 0 : if (std::abs(zvt(svert) - zvt(mvert)) <= point_tolerance) {
222 0 : zvt(svert) = zvt(mvert);
223 : }
224 : }
225 : }
226 0 : for (int svert = 1; svert <= nsides; ++svert) {
227 0 : vertex(svert).x = xvt(svert);
228 0 : vertex(svert).y = zvt(svert);
229 : }
230 : }
231 :
232 : // find ears
233 142 : int nvertcur = nsides;
234 142 : int ncount = 0;
235 142 : int svert = 1;
236 142 : int mvert = 2;
237 142 : int evert = 3;
238 142 : removed = false;
239 843 : while (nvertcur > 3) {
240 702 : generate_ears(state, nsides, vertex, ears, nears, r_angles, nrangles, c_vertices, ncverts, removed, earverts, rangles);
241 702 : if (!any_gt(ears, 0)) {
242 2 : ShowWarningError(state,
243 2 : format("DXFOut: Could not triangulate surface=\"{}\", type=\"{}\", check surface vertex order(entry)",
244 : surfname,
245 2 : DataSurfaces::cSurfaceClass(surfclass)));
246 1 : ++state.dataDXFEarClipping->errcount;
247 1 : if (state.dataDXFEarClipping->errcount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
248 3 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
249 : }
250 1 : if (state.dataGlobal->DisplayExtraWarnings) {
251 0 : ShowMessage(state, format(" surface={} class={}", surfname, DataSurfaces::cSurfaceClass(surfclass)));
252 :
253 0 : for (int j = 1; j <= nsides; ++j) {
254 0 : ShowMessage(state, format(" side={} ({:.1R},{:.1R},{:.1R})", j, polygon(j).x, polygon(j).y, polygon(j).z));
255 : }
256 0 : ShowMessage(state, format(" number of triangles found={:12}", ncount));
257 0 : for (int j = 1; j <= nrangles; ++j) {
258 0 : ShowMessage(state, format(" r angle={} vert={} deg={:.1R}", j, r_angles(j), rangles(j) * Constant::RadToDeg));
259 : }
260 : }
261 1 : break; // while loop
262 : }
263 701 : if (nears > 0) {
264 701 : svert = earverts(1);
265 701 : mvert = earverts(2);
266 701 : evert = earverts(3);
267 : // remove ear
268 701 : ++ncount;
269 701 : removed(mvert) = true;
270 701 : earvert(ncount, 1) = svert;
271 701 : earvert(ncount, 2) = mvert;
272 701 : earvert(ncount, 3) = evert;
273 701 : --nvertcur;
274 : }
275 701 : if (nvertcur == 3) {
276 141 : int j = 1;
277 141 : ++ncount;
278 1261 : for (int i = 1; i <= nsides; ++i) {
279 1120 : if (removed(i)) {
280 697 : continue;
281 : }
282 423 : earvert(ncount, j) = i;
283 423 : ++j;
284 : }
285 : }
286 : }
287 :
288 142 : int ntri = ncount;
289 :
290 984 : for (int i = 1; i <= ntri; ++i) {
291 842 : Triangle(i).vv0 = earvert(i, 1);
292 842 : Triangle(i).vv1 = earvert(i, 2);
293 842 : Triangle(i).vv2 = earvert(i, 3);
294 : }
295 :
296 142 : outtriangles.allocate(ntri);
297 984 : for (int i = 1; i <= ntri; ++i) {
298 842 : outtriangles(i) = Triangle(i);
299 : }
300 :
301 142 : return ntri;
302 142 : }
303 :
304 4420 : Real64 angle_2dvector(Real64 const xa, // vertex coordinate
305 : Real64 const ya, // vertex coordinate
306 : Real64 const xb, // vertex coordinate
307 : Real64 const yb, // vertex coordinate
308 : Real64 const xc, // vertex coordinate
309 : Real64 const yc // vertex coordinate
310 : )
311 : {
312 :
313 : // Function information:
314 : // Author Linda Lawrie
315 : // Date written October 2005
316 :
317 : // Purpose of this function:
318 : // This function calculates the angle between two sides of a 2d polygon.
319 : // It computes the interior angle in radians at vertex
320 : // (XB,YB) of the chain formed by the directed edges from
321 : // (XA,YA) to (XB,YB) to (XC,YC). The interior is to the
322 : // left of the two directed edges.
323 :
324 : // References:
325 : // Geometry Tools for Computer Graphics
326 :
327 : // Return value
328 : Real64 angle; // the angle, between 0 and 2*PI.
329 :
330 : // angle is set to PI/2 in the degenerate case.
331 :
332 : // Function parameter definitions:
333 4420 : Real64 constexpr epsilon(0.0000001);
334 :
335 4420 : Real64 x1 = xa - xb;
336 4420 : Real64 y1 = ya - yb;
337 4420 : Real64 x2 = xc - xb;
338 4420 : Real64 y2 = yc - yb;
339 :
340 4420 : Real64 t = std::sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2));
341 4420 : if (t == 0.0E+00) {
342 0 : t = 1.0E+00;
343 : }
344 :
345 4420 : t = (x1 * x2 + y1 * y2) / t;
346 :
347 4420 : if ((1.0E+00 - epsilon) < std::abs(t)) {
348 81 : t = sign(1.0E+00, t);
349 : }
350 :
351 4420 : angle = std::acos(t);
352 :
353 4420 : if (x2 * y1 - y2 * x1 < 0.0E+00) {
354 1102 : angle = 2.0E+00 * Constant::Pi - angle;
355 : }
356 :
357 4420 : return angle;
358 : }
359 :
360 12980 : bool polygon_contains_point_2d(int const nsides, // number of sides (vertices)
361 : Array1D<Vector_2d> &polygon, // points of polygon
362 : Vector_2d const &point // point to be tested
363 : )
364 : {
365 :
366 : // Function information:
367 : // Author Linda Lawrie
368 : // Date written October 2005
369 :
370 : // Purpose of this function:
371 : // Determine if a point is inside a simple 2d polygon. For a simple polygon (one whose
372 : // boundary never crosses itself). The polygon does not need to be convex.
373 :
374 : // References:
375 : // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
376 : // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
377 :
378 : // Return value
379 : bool inside; // return value, true=inside, false = not inside
380 :
381 : // Argument array dimensioning
382 12980 : EP_SIZE_CHECK(polygon, nsides);
383 :
384 : // Function local variable declarations:
385 : int ip1;
386 :
387 12980 : inside = false;
388 :
389 51920 : for (int i = 1; i <= nsides; ++i) {
390 :
391 38940 : if (i < nsides) {
392 25960 : ip1 = i + 1;
393 : } else {
394 12980 : ip1 = 1;
395 : }
396 :
397 38940 : if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
398 9180 : if ((point.x - polygon(i).x) - (point.y - polygon(i).y) * (polygon(ip1).x - polygon(i).x) / (polygon(ip1).y - polygon(i).y) < 0) {
399 4423 : inside = !inside;
400 : }
401 : }
402 : }
403 :
404 12980 : return inside;
405 : }
406 :
407 702 : void generate_ears(EnergyPlusData &state,
408 : int const nvert, // number of vertices in polygon
409 : Array1D<Vector_2d> &vertex,
410 : Array1D_int &ears, // number of ears possible (dimensioned to nvert)
411 : int &nears, // number of ears found
412 : Array1D_int &r_vertices, // number of reflex vertices (>180) possible
413 : int &nrverts, // number of reflex vertices found (>=180)
414 : Array1D_int &c_vertices, // number of convex vertices
415 : int &ncverts, // number of convex vertices found (< 180)
416 : Array1D_bool &removed, // array that shows if a vertex has been removed (calling routine)
417 : Array1D_int &earvert, // vertex indicators for first ear
418 : Array1D<Real64> &rangles)
419 : {
420 :
421 : // Subroutine information:
422 : // Author Linda Lawrie
423 : // Date written October 2005
424 :
425 : // Purpose of this subroutine:
426 : // This routine generates "ears", "reflex angles" and "convex angles" of the polygon
427 : // based on the method set for in the reference.
428 :
429 : // Methodology employed:
430 : // No elegance used here. Always starts with first vertex in polygon.
431 :
432 : // References:
433 : // Geometric Tools for Computer Graphics, Philip Schneider, David Eberly. 2003. Ear
434 : // clipping for triangulation is described in Chapter 13 on Polygon Partitioning. Also
435 : // described in a small article "Triangulation by Ear Clipping", David Eberly, http://www.geometrictools.com
436 :
437 : // Argument array dimensioning
438 702 : EP_SIZE_CHECK(vertex, nvert);
439 702 : EP_SIZE_CHECK(ears, nvert);
440 702 : EP_SIZE_CHECK(r_vertices, nvert);
441 702 : EP_SIZE_CHECK(c_vertices, nvert);
442 702 : EP_SIZE_CHECK(removed, nvert);
443 702 : EP_SIZE_CHECK(earvert, 3);
444 702 : EP_SIZE_CHECK(rangles, nvert);
445 :
446 : // Subroutine local variable declarations:
447 : bool inpoly; // in polygon or not
448 :
449 : // Object Data
450 702 : Vector_2d point; // structure for point
451 702 : Array1D<Vector_2d> testtri(3); // structure for triangle
452 :
453 : // initialize, always recalculate
454 702 : ears = 0;
455 702 : r_vertices = 0;
456 702 : rangles = 0.0;
457 702 : nears = 0;
458 702 : nrverts = 0;
459 702 : c_vertices = 0;
460 702 : ncverts = 0;
461 :
462 6734 : for (int svert = 1; svert <= nvert; ++svert) {
463 6032 : if (removed(svert)) {
464 2713 : continue;
465 : }
466 : // have starting vertex. now need middle and end
467 4420 : int mvert = svert + 1;
468 6032 : for (int j = 1; j <= nvert; ++j) {
469 6032 : if (mvert > nvert) {
470 664 : mvert = 1;
471 : }
472 6032 : if (removed(mvert)) {
473 1612 : ++mvert;
474 1612 : if (mvert > nvert) {
475 38 : mvert = 1;
476 : }
477 : } else {
478 4420 : break;
479 : }
480 : }
481 4420 : int evert = mvert + 1;
482 6032 : for (int j = 1; j <= nvert; ++j) {
483 6032 : if (evert > nvert) {
484 664 : evert = 1;
485 : }
486 6032 : if (removed(evert)) {
487 1612 : ++evert;
488 1612 : if (evert > nvert) {
489 38 : evert = 1;
490 : }
491 : } else {
492 4420 : break;
493 : }
494 : }
495 :
496 : // have gotten start, middle and ending vertices. test for reflex angle
497 :
498 4420 : Real64 ang = angle_2dvector(vertex(svert).x, vertex(svert).y, vertex(mvert).x, vertex(mvert).y, vertex(evert).x, vertex(evert).y);
499 :
500 4420 : if (ang > Constant::Pi) { // sufficiently close to 180 degrees.
501 1101 : ++nrverts;
502 1101 : r_vertices(nrverts) = mvert;
503 1101 : rangles(nrverts) = ang;
504 1101 : continue;
505 : } else {
506 3319 : ++ncverts;
507 3319 : c_vertices(ncverts) = mvert;
508 : }
509 :
510 : // convex angle, see if it's an ear
511 3319 : testtri(1) = vertex(svert);
512 3319 : testtri(2) = vertex(mvert);
513 3319 : testtri(3) = vertex(evert);
514 3319 : int tvert = evert;
515 19878 : for (int j = 4; j <= nvert; ++j) {
516 17286 : ++tvert;
517 17286 : if (tvert > nvert) {
518 1864 : tvert = 1;
519 : }
520 17286 : if (removed(tvert)) {
521 4306 : continue;
522 : }
523 12980 : point = vertex(tvert);
524 12980 : inpoly = polygon_contains_point_2d(3, testtri, point);
525 12980 : if (!inpoly) {
526 12253 : continue;
527 : }
528 727 : break;
529 : }
530 : // if (trackit) then
531 : // write(outputfiledebug,*) ' triangle=',svert,mvert,evert
532 : // write(outputfiledebug,*) ' vertex1=',vertex(svert)%x,vertex(svert)%y
533 : // write(outputfiledebug,*) ' vertex2=',vertex(mvert)%x,vertex(mvert)%y
534 : // write(outputfiledebug,*) ' vertex3=',vertex(evert)%x,vertex(evert)%y
535 : // write(outputfiledebug,*) ' inpoly=',inpoly
536 : // endif
537 3319 : if (!inpoly) {
538 : // found an ear
539 2592 : ++nears;
540 2592 : ears(nears) = mvert;
541 2592 : if (nears == 1) {
542 701 : earvert(1) = svert;
543 701 : earvert(2) = mvert;
544 701 : earvert(3) = evert;
545 : }
546 2592 : if (state.dataDXFEarClipping->trackit) {
547 0 : print(state.files.debug, "ear={} triangle={:12}{:12}{:12}\n", nears, svert, mvert, evert);
548 : }
549 : }
550 : }
551 702 : }
552 :
553 0 : void CalcWallCoordinateTransformation(int const nsides,
554 : Array1D<Vector> &polygon,
555 : Real64 const surfazimuth,
556 : [[maybe_unused]] Real64 const surftilt, // unused1208
557 : Array1D<Real64> &xvt,
558 : Array1D<Real64> &yvt,
559 : Array1D<Real64> &zvt)
560 : {
561 :
562 : // Subroutine information:
563 : // Author Linda Lawrie
564 : // Date written October 2005
565 :
566 : // Purpose of this subroutine:
567 : // This routine transforms a "wall" (normally vertical polygon) to a south facing (180 deg outward
568 : // normal) polygon in 2 d (y vertices are then ignored).
569 :
570 : // Methodology employed:
571 : // Standard angle rotation
572 :
573 : // Argument array dimensioning
574 0 : EP_SIZE_CHECK(polygon, nsides);
575 0 : EP_SIZE_CHECK(xvt, nsides);
576 0 : EP_SIZE_CHECK(yvt, nsides);
577 0 : EP_SIZE_CHECK(zvt, nsides);
578 :
579 : // convert surface (wall) to facing 180 (outward normal)
580 :
581 0 : Real64 const alpha = surfazimuth;
582 :
583 0 : Real64 const alpha180 = 180.0 - alpha; // amount to rotate
584 0 : Real64 const alphrad = alpha180 / Constant::RadToDeg;
585 0 : Real64 const cos_alphrad = std::cos(alphrad);
586 0 : Real64 const sin_alphrad = std::sin(alphrad);
587 :
588 0 : for (int i = 1; i <= nsides; ++i) {
589 0 : xvt(i) = cos_alphrad * polygon(i).x + sin_alphrad * polygon(i).y;
590 0 : yvt(i) = -sin_alphrad * polygon(i).x + cos_alphrad * polygon(i).y;
591 0 : zvt(i) = polygon(i).z;
592 : }
593 0 : }
594 :
595 142 : void CalcRfFlrCoordinateTransformation(int const nsides,
596 : Array1D<Vector> &polygon,
597 : [[maybe_unused]] Real64 const surfazimuth, // unused1208
598 : Real64 const surftilt,
599 : Array1D<Real64> &xvt,
600 : Array1D<Real64> &yvt,
601 : Array1D<Real64> &zvt)
602 : {
603 :
604 : // Subroutine information:
605 : // Author Linda Lawrie
606 : // Date written October 2005
607 :
608 : // Purpose of this subroutine:
609 : // This routine transforms a roof/floor (normally flat polygon) to a flat
610 : // polygon in 2 d (z vertices are then ignored).
611 :
612 : // Standard angle rotation
613 :
614 : // Argument array dimensioning
615 142 : EP_SIZE_CHECK(polygon, nsides);
616 142 : EP_SIZE_CHECK(xvt, nsides);
617 142 : EP_SIZE_CHECK(yvt, nsides);
618 142 : EP_SIZE_CHECK(zvt, nsides);
619 :
620 : // Subroutine local variable declarations:
621 :
622 142 : Real64 const alpha = -surftilt;
623 142 : Real64 const alphrad = alpha / Constant::RadToDeg;
624 142 : Real64 const cos_alphrad = std::cos(alphrad);
625 142 : Real64 const sin_alphrad = std::sin(alphrad);
626 :
627 1270 : for (int i = 1; i <= nsides; ++i) {
628 1128 : xvt(i) = polygon(i).x;
629 1128 : yvt(i) = cos_alphrad * polygon(i).x + sin_alphrad * polygon(i).y;
630 1128 : zvt(i) = -sin_alphrad * polygon(i).x + cos_alphrad * polygon(i).y;
631 : }
632 142 : }
633 :
634 : // void reorder([[maybe_unused]] int &nvert) // unused1208
635 : //{
636 :
637 : // // Locals
638 : // // type (Vector_2d) nvertex(nvert)
639 : // // integer i
640 : // // type (Vector_2d) point
641 : // // integer nrep
642 :
643 : // // Vertex, nverts is in cw order, reorder for calc
644 :
645 : // // nrep=1
646 : // // nvertex(1)=vertex(1)
647 : // // do i=nvert,1,-1
648 : // // nvertex(nrep)=vertex(i)
649 : // // nrep=nrep+1
650 : // // enddo
651 : // // do i=1,nvert
652 : // // vertex(i)=nvertex(i)
653 : // // enddo
654 : //}
655 :
656 : } // namespace DXFEarClipping
657 :
658 : } // namespace EnergyPlus
|