MeshKit  1.0
CAMALSurfEval.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines