Branch data Line data Source code
1 : : #include <iostream>
2 : : #include "CAMALSurfEval.hpp"
3 : : #include "meshkit/ModelEnt.hpp"
4 : : #include "meshkit/MKCore.hpp"
5 : : #include "meshkit/SizingFunction.hpp"
6 : :
7 : : namespace MeshKit
8 : : {
9 : :
10 : 42 : CAMALSurfEval::CAMALSurfEval(ModelEnt *me)
11 : 42 : : modelEnt(me)
12 : : {
13 : 42 : }
14 : :
15 [ - + ]: 84 : CAMALSurfEval::~CAMALSurfEval() {}
16 : :
17 : 84 : double CAMALSurfEval::area()
18 : : {
19 [ + - ]: 84 : return (modelEnt->dimension() != 2 ? -1.0 : modelEnt->measure());
20 : : }
21 : :
22 : 57 : void CAMALSurfEval::bounding_box(double box_min[3], double box_max[3])
23 : : {
24 : 57 : iGeom::Error err = modelEnt->igeom_instance()->getEntBoundBox(modelEnt->geom_handle(),
25 : 57 : box_min[0], box_min[1], box_min[2],
26 : 57 : box_max[0], box_max[1], box_max[2]);
27 : 57 : IBERRCHK(err, "Trouble getting entity bounding box.");
28 : 57 : }
29 : :
30 : 8982 : void CAMALSurfEval::move_to_surface(double& x, double& y, double& z)
31 : : {
32 : : double close[3];
33 [ + - ]: 8982 : modelEnt->evaluate(x, y, z, close);
34 : 8982 : x = close[0];
35 : 8982 : y = close[1];
36 : 8982 : z = close[2];
37 : 8982 : }
38 : :
39 : 0 : void CAMALSurfEval::move_to_surface(double& x, double& y, double& z,
40 : : double& u_guess, double& v_guess)
41 : : {
42 : 0 : move_to_surface(x, y, z);
43 : 0 : }
44 : :
45 : 4208 : bool CAMALSurfEval::normal_at(double x, double y, double z,
46 : : double& nx, double& ny, double& nz)
47 : : {
48 : : double norm[3];
49 [ + - ]: 4208 : modelEnt->evaluate(x, y, z, NULL, norm);
50 : 4208 : nx = norm[0];
51 : 4208 : ny = norm[1];
52 : 4208 : nz = norm[2];
53 : 4208 : return true;
54 : : }
55 : :
56 : 0 : bool CAMALSurfEval::normal_at(double x, double y, double z,
57 : : double& u_guess, double& v_guess,
58 : : double& nx, double& ny, double& nz)
59 : : {
60 : : double norm[3];
61 [ # # ]: 0 : modelEnt->evaluate(x, y, z, NULL, norm);
62 : 0 : nx = norm[0];
63 : 0 : ny = norm[1];
64 : 0 : nz = norm[2];
65 : 0 : return true;
66 : : }
67 : :
68 : 84 : bool CAMALSurfEval::is_planar()
69 : : {
70 [ + - ]: 84 : std::string surf_type;
71 [ + - ][ + - ]: 84 : iGeom::Error err = modelEnt->igeom_instance()->getFaceType(modelEnt->geom_handle(), surf_type);
[ + - ]
72 [ + - ][ + - ]: 84 : if (iBase_SUCCESS != err || (surf_type != "plane")) return false;
[ + + ][ + + ]
73 : 84 : else return true;
74 : : }
75 : :
76 : 19 : bool CAMALSurfEval::is_parametric()
77 : : {
78 : 19 : bool is_param = false;
79 [ + - ][ + - ]: 19 : iGeom::Error err = modelEnt->igeom_instance()->isEntParametric(modelEnt->geom_handle(), is_param);
[ + - ]
80 [ + - ]: 19 : IBERRCHK(err, "Trouble getting whether entity is parametric");
81 : 19 : return is_param;
82 : : }
83 : :
84 : 12 : bool CAMALSurfEval::is_periodic_in_u(double& u_period)
85 : : {
86 : 12 : bool per_u = false, per_v = false;
87 [ + - ][ + - ]: 12 : iGeom::Error err = modelEnt->igeom_instance()->isEntPeriodic(modelEnt->geom_handle(), per_u, per_v);
[ + - ]
88 [ + - ]: 12 : IBERRCHK(err, "Trouble getting whether entity is periodic");
89 : 12 : return per_u;
90 : : }
91 : :
92 : 12 : bool CAMALSurfEval::is_periodic_in_v(double& v_period)
93 : : {
94 : 12 : bool per_u = false, per_v = false;
95 [ + - ][ + - ]: 12 : iGeom::Error err = modelEnt->igeom_instance()->isEntPeriodic(modelEnt->geom_handle(), per_u, per_v);
[ + - ]
96 [ + - ]: 12 : IBERRCHK(err, "Trouble getting whether entity is periodic");
97 : 12 : return per_v;
98 : : }
99 : :
100 : 12 : void CAMALSurfEval::get_param_range_u(double& u_low, double& u_high)
101 : : {
102 : : double vmin, vmax;
103 [ + - ][ + - ]: 12 : iGeom::Error err = modelEnt->igeom_instance()->getEntUVRange(modelEnt->geom_handle(), u_low, vmin, u_high, vmax);
[ + - ]
104 [ + - ]: 12 : IBERRCHK(err, "Trouble getting entity parameter ranges.");
105 : 12 : }
106 : :
107 : 0 : void CAMALSurfEval::get_param_range_v(double& v_low, double& v_high)
108 : : {
109 : : double umin, umax;
110 [ # # ][ # # ]: 0 : iGeom::Error err = modelEnt->igeom_instance()->getEntUVRange(modelEnt->geom_handle(), umin, v_low, umax, v_high);
[ # # ]
111 [ # # ]: 0 : IBERRCHK(err, "Trouble getting entity parameter ranges.");
112 : 0 : }
113 : :
114 : 0 : bool CAMALSurfEval::uv_from_position(double x, double y, double z,
115 : : double& u, double& v)
116 : :
117 : : {
118 : 0 : iGeom::Error err = modelEnt->igeom_instance()->getEntXYZtoUV(modelEnt->geom_handle(), x, y, z, u, v);
119 : 0 : IBERRCHK(err, "Trouble getting parameters from position.");
120 [ # # ]: 0 : if (err)
121 : 0 : return false;
122 : 0 : return true;
123 : : }
124 : :
125 : 0 : bool CAMALSurfEval::uv_from_position(double x, double y, double z,
126 : : double& u, double& v,
127 : : double& cx, double& cy, double& cz)
128 : : {
129 : 0 : iGeom::Error err = modelEnt->igeom_instance()->getEntXYZtoUV(modelEnt->geom_handle(), x, y, z, u, v);
130 : 0 : IBERRCHK(err, "Trouble getting parameters from position.");
131 : 0 : err = modelEnt->igeom_instance()->getEntUVtoXYZ(modelEnt->geom_handle(), u, v, cx, cy, cz);
132 : 0 : IBERRCHK(err, "Trouble getting position from parameters.");
133 [ # # ]: 0 : if (err)
134 : 0 : return false;
135 : 0 : return true;
136 : : }
137 : :
138 : 0 : void CAMALSurfEval::position_from_uv(double u, double v,
139 : : double& x, double& y, double& z)
140 : : {
141 : 0 : iGeom::Error err = modelEnt->igeom_instance()->getEntUVtoXYZ(modelEnt->geom_handle(), u, v, x, y, z);
142 : 0 : IBERRCHK(err, "Trouble getting position from parameters.");
143 : 0 : }
144 : :
145 : 0 : void CAMALSurfEval::distortion_at_uv(double u, double v,
146 : : double du[3], double dv[3])
147 : : {
148 : 0 : iGeom::Error err = modelEnt->igeom_instance()->getEnt1stDrvt(modelEnt->geom_handle(), u, v,
149 : 0 : du[0], du[1], du[2],
150 : 0 : dv[0], dv[1], dv[2]);
151 : 0 : IBERRCHK(err, "Trouble getting 1st derivative from parameters.");
152 : 0 : }
153 : :
154 : : // this could be inlined
155 : 0 : double tArea(double * a, double *b, double *c, double * normal)
156 : : {
157 : 0 : double result = 0;
158 : : // ( ( B-A ) X (C-A) ) * normal
159 : 0 : double AB[3] = { b[0] - a[0], b[1] - a[1], b[2] - a[2] };
160 : 0 : double AC[3] = { c[0] - a[0], c[1] - a[1], c[2] - a[2] };
161 : 0 : result += (AB[1] * AC[2] - AB[2] * AC[1]) * normal[0];
162 : 0 : result += (AB[2] * AC[0] - AB[0] * AC[2]) * normal[1];
163 : 0 : result += (AB[0] * AC[1] - AB[1] * AC[0]) * normal[2];
164 : 0 : return result;
165 : : }
166 : :
167 : : // decide if the boundary loops are positively oriented around normal
168 : : // use the normal at the first node on the boundary
169 : : // It should work even if the first node is on an interior loop, not external loop
170 : : // it should work in most cases, except the surface is highly distorted, and the projected area of an internal
171 : : // loop is higher than the projected area of an external loop
172 : : // it is specific to Camal advancing front algorithms (Paver and TriAdvance)
173 : 0 : void CAMALSurfEval::correct_orientation(std::vector<int> & loop_sizes,
174 : : std::vector<int> & loops, std::vector<double> & bdy_coords)
175 : : {
176 : : // first, normal at the initial point on the boundary
177 : 0 : double normal[3] = { 0, 0, 0 };
178 [ # # ][ # # ]: 0 : /*this->*/normal_at(bdy_coords[0], bdy_coords[1], bdy_coords[2], normal[0],
[ # # ]
179 [ # # ]: 0 : normal[1], normal[2]);
180 : :
181 : 0 : double oriented_area = 0.;
182 : 0 : unsigned int start_current_loop = 0;
183 [ # # ]: 0 : for (unsigned int k = 0; k < loop_sizes.size(); k++)
184 : : {
185 : : // for each loop, compute the oriented area of each triangle
186 [ # # ]: 0 : int current_loop_size = loop_sizes[k];
187 [ # # ]: 0 : int startIndex = loops[start_current_loop];
188 [ # # ]: 0 : for ( int i = 1; i < current_loop_size - 1; i++)
189 : : {
190 [ # # ]: 0 : int i1 = loops[start_current_loop + i];
191 [ # # ]: 0 : int i2 = loops[start_current_loop + (i + 1)];
192 : :
193 [ # # ][ # # ]: 0 : double oArea = tArea(&bdy_coords[3 * startIndex], &bdy_coords[3 * i1],
194 [ # # ][ # # ]: 0 : &bdy_coords[3 * i2], normal);
195 : 0 : oriented_area += oArea;
196 : : }
197 : 0 : start_current_loop += current_loop_size;
198 : : }
199 [ # # ]: 0 : if (oriented_area < 0.)
200 : : { // correct orientation
201 : 0 : unsigned int start_current_loop = 0;
202 [ # # ]: 0 : for (unsigned int k = 0; k < loop_sizes.size(); k++)
203 : : {
204 : : // for each loop, switch index 1 with last, 2, with first before last...
205 [ # # ]: 0 : int current_loop_size = loop_sizes[k];
206 [ # # ]: 0 : std::reverse(&loops[start_current_loop + 1], &loops[start_current_loop
207 [ # # ][ # # ]: 0 : + current_loop_size]);
208 : 0 : start_current_loop += current_loop_size;
209 : : }
210 : : }
211 : 0 : }
212 : :
213 [ + - ][ + - ]: 156 : } // namespace MeshKit
|