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