MeshKit
1.0
|
00001 #include <iostream> 00002 #include "CAMALSurfEval.hpp" 00003 #include "meshkit/ModelEnt.hpp" 00004 #include "meshkit/MKCore.hpp" 00005 #include "meshkit/SizingFunction.hpp" 00006 00007 namespace MeshKit 00008 { 00009 00010 CAMALSurfEval::CAMALSurfEval(ModelEnt *me) 00011 : modelEnt(me) 00012 { 00013 } 00014 00015 CAMALSurfEval::~CAMALSurfEval() {} 00016 00017 double CAMALSurfEval::area() 00018 { 00019 return (modelEnt->dimension() != 2 ? -1.0 : modelEnt->measure()); 00020 } 00021 00022 void CAMALSurfEval::bounding_box(double box_min[3], double box_max[3]) 00023 { 00024 iGeom::Error err = modelEnt->igeom_instance()->getEntBoundBox(modelEnt->geom_handle(), 00025 box_min[0], box_min[1], box_min[2], 00026 box_max[0], box_max[1], box_max[2]); 00027 IBERRCHK(err, "Trouble getting entity bounding box."); 00028 } 00029 00030 void CAMALSurfEval::move_to_surface(double& x, double& y, double& z) 00031 { 00032 double close[3]; 00033 modelEnt->evaluate(x, y, z, close); 00034 x = close[0]; 00035 y = close[1]; 00036 z = close[2]; 00037 } 00038 00039 void CAMALSurfEval::move_to_surface(double& x, double& y, double& z, 00040 double& u_guess, double& v_guess) 00041 { 00042 move_to_surface(x, y, z); 00043 } 00044 00045 bool CAMALSurfEval::normal_at(double x, double y, double z, 00046 double& nx, double& ny, double& nz) 00047 { 00048 double norm[3]; 00049 modelEnt->evaluate(x, y, z, NULL, norm); 00050 nx = norm[0]; 00051 ny = norm[1]; 00052 nz = norm[2]; 00053 return true; 00054 } 00055 00056 bool CAMALSurfEval::normal_at(double x, double y, double z, 00057 double& u_guess, double& v_guess, 00058 double& nx, double& ny, double& nz) 00059 { 00060 double norm[3]; 00061 modelEnt->evaluate(x, y, z, NULL, norm); 00062 nx = norm[0]; 00063 ny = norm[1]; 00064 nz = norm[2]; 00065 return true; 00066 } 00067 00068 bool CAMALSurfEval::is_planar() 00069 { 00070 std::string surf_type; 00071 iGeom::Error err = modelEnt->igeom_instance()->getFaceType(modelEnt->geom_handle(), surf_type); 00072 if (iBase_SUCCESS != err || (surf_type != "plane")) return false; 00073 else return true; 00074 } 00075 00076 bool CAMALSurfEval::is_parametric() 00077 { 00078 bool is_param = false; 00079 iGeom::Error err = modelEnt->igeom_instance()->isEntParametric(modelEnt->geom_handle(), is_param); 00080 IBERRCHK(err, "Trouble getting whether entity is parametric"); 00081 return is_param; 00082 } 00083 00084 bool CAMALSurfEval::is_periodic_in_u(double& u_period) 00085 { 00086 bool per_u = false, per_v = false; 00087 iGeom::Error err = modelEnt->igeom_instance()->isEntPeriodic(modelEnt->geom_handle(), per_u, per_v); 00088 IBERRCHK(err, "Trouble getting whether entity is periodic"); 00089 return per_u; 00090 } 00091 00092 bool CAMALSurfEval::is_periodic_in_v(double& v_period) 00093 { 00094 bool per_u = false, per_v = false; 00095 iGeom::Error err = modelEnt->igeom_instance()->isEntPeriodic(modelEnt->geom_handle(), per_u, per_v); 00096 IBERRCHK(err, "Trouble getting whether entity is periodic"); 00097 return per_v; 00098 } 00099 00100 void CAMALSurfEval::get_param_range_u(double& u_low, double& u_high) 00101 { 00102 double vmin, vmax; 00103 iGeom::Error err = modelEnt->igeom_instance()->getEntUVRange(modelEnt->geom_handle(), u_low, vmin, u_high, vmax); 00104 IBERRCHK(err, "Trouble getting entity parameter ranges."); 00105 } 00106 00107 void CAMALSurfEval::get_param_range_v(double& v_low, double& v_high) 00108 { 00109 double umin, umax; 00110 iGeom::Error err = modelEnt->igeom_instance()->getEntUVRange(modelEnt->geom_handle(), umin, v_low, umax, v_high); 00111 IBERRCHK(err, "Trouble getting entity parameter ranges."); 00112 } 00113 00114 bool CAMALSurfEval::uv_from_position(double x, double y, double z, 00115 double& u, double& v) 00116 00117 { 00118 iGeom::Error err = modelEnt->igeom_instance()->getEntXYZtoUV(modelEnt->geom_handle(), x, y, z, u, v); 00119 IBERRCHK(err, "Trouble getting parameters from position."); 00120 if (err) 00121 return false; 00122 return true; 00123 } 00124 00125 bool CAMALSurfEval::uv_from_position(double x, double y, double z, 00126 double& u, double& v, 00127 double& cx, double& cy, double& cz) 00128 { 00129 iGeom::Error err = modelEnt->igeom_instance()->getEntXYZtoUV(modelEnt->geom_handle(), x, y, z, u, v); 00130 IBERRCHK(err, "Trouble getting parameters from position."); 00131 err = modelEnt->igeom_instance()->getEntUVtoXYZ(modelEnt->geom_handle(), u, v, cx, cy, cz); 00132 IBERRCHK(err, "Trouble getting position from parameters."); 00133 if (err) 00134 return false; 00135 return true; 00136 } 00137 00138 void CAMALSurfEval::position_from_uv(double u, double v, 00139 double& x, double& y, double& z) 00140 { 00141 iGeom::Error err = modelEnt->igeom_instance()->getEntUVtoXYZ(modelEnt->geom_handle(), u, v, x, y, z); 00142 IBERRCHK(err, "Trouble getting position from parameters."); 00143 } 00144 00145 void CAMALSurfEval::distortion_at_uv(double u, double v, 00146 double du[3], double dv[3]) 00147 { 00148 iGeom::Error err = modelEnt->igeom_instance()->getEnt1stDrvt(modelEnt->geom_handle(), u, v, 00149 du[0], du[1], du[2], 00150 dv[0], dv[1], dv[2]); 00151 IBERRCHK(err, "Trouble getting 1st derivative from parameters."); 00152 } 00153 00154 // this could be inlined 00155 double tArea(double * a, double *b, double *c, double * normal) 00156 { 00157 double result = 0; 00158 // ( ( B-A ) X (C-A) ) * normal 00159 double AB[3] = { b[0] - a[0], b[1] - a[1], b[2] - a[2] }; 00160 double AC[3] = { c[0] - a[0], c[1] - a[1], c[2] - a[2] }; 00161 result += (AB[1] * AC[2] - AB[2] * AC[1]) * normal[0]; 00162 result += (AB[2] * AC[0] - AB[0] * AC[2]) * normal[1]; 00163 result += (AB[0] * AC[1] - AB[1] * AC[0]) * normal[2]; 00164 return result; 00165 } 00166 00167 // decide if the boundary loops are positively oriented around normal 00168 // use the normal at the first node on the boundary 00169 // It should work even if the first node is on an interior loop, not external loop 00170 // it should work in most cases, except the surface is highly distorted, and the projected area of an internal 00171 // loop is higher than the projected area of an external loop 00172 // it is specific to Camal advancing front algorithms (Paver and TriAdvance) 00173 void CAMALSurfEval::correct_orientation(std::vector<int> & loop_sizes, 00174 std::vector<int> & loops, std::vector<double> & bdy_coords) 00175 { 00176 // first, normal at the initial point on the boundary 00177 double normal[3] = { 0, 0, 0 }; 00178 /*this->*/normal_at(bdy_coords[0], bdy_coords[1], bdy_coords[2], normal[0], 00179 normal[1], normal[2]); 00180 00181 double oriented_area = 0.; 00182 unsigned int start_current_loop = 0; 00183 for (unsigned int k = 0; k < loop_sizes.size(); k++) 00184 { 00185 // for each loop, compute the oriented area of each triangle 00186 int current_loop_size = loop_sizes[k]; 00187 int startIndex = loops[start_current_loop]; 00188 for ( int i = 1; i < current_loop_size - 1; i++) 00189 { 00190 int i1 = loops[start_current_loop + i]; 00191 int i2 = loops[start_current_loop + (i + 1)]; 00192 00193 double oArea = tArea(&bdy_coords[3 * startIndex], &bdy_coords[3 * i1], 00194 &bdy_coords[3 * i2], normal); 00195 oriented_area += oArea; 00196 } 00197 start_current_loop += current_loop_size; 00198 } 00199 if (oriented_area < 0.) 00200 { // correct orientation 00201 unsigned int start_current_loop = 0; 00202 for (unsigned int k = 0; k < loop_sizes.size(); k++) 00203 { 00204 // for each loop, switch index 1 with last, 2, with first before last... 00205 int current_loop_size = loop_sizes[k]; 00206 std::reverse(&loops[start_current_loop + 1], &loops[start_current_loop 00207 + current_loop_size]); 00208 start_current_loop += current_loop_size; 00209 } 00210 } 00211 } 00212 00213 } // namespace MeshKit