LCOV - code coverage report
Current view: top level - algs - EdgeMesher.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 220 430 51.2 %
Date: 2020-07-01 15:24:36 Functions: 12 19 63.2 %
Branches: 281 911 30.8 %

           Branch data     Line data    Source code
       1                 :            : #include "meshkit/EdgeMesher.hpp"
       2                 :            : #include "meshkit/Matrix.hpp"
       3                 :            : #include "meshkit/MKCore.hpp"
       4                 :            : #include "meshkit/ModelEnt.hpp"
       5                 :            : #include "meshkit/SizingFunction.hpp"
       6                 :            : #include "meshkit/RegisterMeshOp.hpp"
       7                 :            : #include "moab/ReadUtilIface.hpp"
       8                 :            : #include <vector>
       9                 :            : #include <math.h>
      10                 :            : 
      11                 :            : namespace MeshKit
      12                 :            : {
      13                 :            : 
      14                 :            : //---------------------------------------------------------------------------//
      15                 :            : //Entity Type initilization for edge meshing
      16                 :            : moab::EntityType EdgeMesher_tps[] = {moab::MBVERTEX, moab::MBEDGE, moab::MBMAXTYPE};
      17                 :         40 : const moab::EntityType* EdgeMesher::output_types()
      18                 :         40 :   { return EdgeMesher_tps; }
      19                 :            : 
      20                 :            : //---------------------------------------------------------------------------//
      21                 :            : // Construction Function for Edge Mesher
      22                 :         60 : EdgeMesher::EdgeMesher(MKCore *mk_core, const MEntVector &me_vec) 
      23                 :         60 :         : MeshScheme(mk_core, me_vec), schemeType(EQUAL), ratio(1.2)
      24                 :            : {
      25                 :            : 
      26                 :         60 : }
      27                 :            : #if 0
      28                 :            : //---------------------------------------------IBERRCHK(g_err, "Trouble get the adjacent geometric nodes on a surface.");------------------------------//
      29                 :            : // measure function: compute the distance between the parametric coordinate 
      30                 :            : // ustart and the parametric coordinate uend
      31                 :            : double EdgeMesher::measure(iGeom::EntityHandle ent, double ustart, double uend) const
      32                 :            : {
      33                 :            :         double umin, umax;
      34                 :            : 
      35                 :            :         //get the minimal and maximal parametrical coordinates of the edge
      36                 :            :         iGeom::Error err = mk_core()->igeom_instance()->getEntURange(ent, umin, umax);
      37                 :            :         IBERRCHK(err, "Trouble getting parameter range for edge.");
      38                 :            : 
      39                 :            :         if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to same parameter umax and umin.");
      40                 :            : 
      41                 :            :         //compute the distance for edges
      42                 :            :         double measure;
      43                 :            :         err = mk_core()->igeom_instance()->measure(&ent, 1, &measure);
      44                 :            : 
      45                 :            :         IBERRCHK(err, "Trouble getting edge measure.");
      46                 :            : 
      47                 :            :         return measure * (uend - ustart) / (umax - umin);
      48                 :            : }
      49                 :            : #endif
      50                 :            : //---------------------------------------------------------------------------//
      51                 :            : // setup function: set up the number of intervals for edge meshing through the 
      52                 :            : // sizing function
      53                 :         61 : void EdgeMesher::setup_this()
      54                 :            : {
      55                 :            :     //compute the number of intervals for the associated ModelEnts, from the size set on them
      56                 :            :     //the sizing function they point to, or a default sizing function
      57 [ +  - ][ +  - ]:        352 :   for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
                 [ +  + ]
      58                 :            :   {
      59         [ +  - ]:        291 :     ModelEnt *me = mit->first;
      60                 :            : 
      61                 :            :       //first check to see whether entity is meshed
      62 [ +  - ][ +  + ]:        291 :     if (me->get_meshed_state() >= COMPLETE_MESH || me->mesh_intervals() > 0)
         [ +  - ][ +  + ]
                 [ +  + ]
      63                 :         32 :       continue;
      64                 :            :     
      65 [ +  - ][ +  - ]:        259 :     SizingFunction *sf = mk_core()->sizing_function(me->sizing_function_index());
                 [ +  - ]
      66 [ +  + ][ +  - ]:        263 :     if (!sf && me -> mesh_intervals() < 0 && me -> interval_firmness() == DEFAULT &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  + ]
      67 [ +  - ][ +  - ]:          4 :         mk_core()->sizing_function(0))
      68                 :            :     {
      69 [ +  - ][ +  - ]:          4 :       sf = mk_core()->sizing_function(0);
      70         [ +  - ]:          4 :       me->sizing_function_index(0);
      71                 :            :     }
      72                 :            :     
      73 [ -  + ][ #  # ]:        259 :     if (!sf && me -> mesh_intervals() < 0 && me -> interval_firmness() == DEFAULT)
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
      74                 :            :     {
      75                 :            :         //no sizing set, just assume default #intervals as 4
      76         [ #  # ]:          0 :       me->mesh_intervals(4);
      77         [ #  # ]:          0 :       me->interval_firmness(DEFAULT);
      78                 :            :     }
      79                 :            :     else
      80                 :            :     {
      81                 :            :         //check # intervals first, then size, and just choose for now
      82 [ +  - ][ +  + ]:        259 :       if (sf->intervals() > 0)
      83                 :            :       {
      84 [ +  - ][ -  + ]:         32 :         if (me->constrain_even() && sf->intervals()%2)
         [ #  # ][ #  # ]
                 [ -  + ]
      85 [ #  # ][ #  # ]:          0 :           me -> mesh_intervals(sf->intervals()+1);
      86                 :            :         else
      87 [ +  - ][ +  - ]:         32 :           me -> mesh_intervals(sf->intervals());
      88         [ +  - ]:         32 :         me -> interval_firmness(HARD);
      89                 :            :       }
      90 [ +  - ][ +  - ]:        227 :       else if (sf->size()>0)
      91                 :            :       {
      92 [ +  - ][ +  - ]:        227 :         int intervals = me->measure()/sf->size();
      93         [ -  + ]:        227 :         if (!intervals) intervals++;
      94 [ +  - ][ +  + ]:        227 :         if (me->constrain_even() && intervals%2) intervals++;
         [ +  + ][ +  + ]
      95         [ +  - ]:        227 :         me->mesh_intervals(intervals);
      96         [ +  - ]:        227 :         me->interval_firmness(SOFT);
      97                 :            :       }
      98                 :            :       else
      99         [ #  # ]:          0 :         throw Error(MK_INCOMPLETE_MESH_SPECIFICATION,  "Sizing function for edge had neither positive size nor positive intervals.");
     100                 :            :     }
     101                 :            :   }
     102                 :            : 
     103                 :            :   // now call setup_boundary to treat vertices
     104                 :            :    // Wrong!!!!!!!!!
     105                 :            :   // setup_boundary();
     106                 :            :   /* this is not enough to ensure that vertex mesher will be called before
     107                 :            :     "this" edge mesher
     108                 :            :     the case that fell through the cracks was if the end nodes were already setup
     109                 :            :    then the this_op[0] would not be retrieved, and not inserted "before" the edge mesher MeshOp
     110                 :            :   */
     111                 :         61 :   int dim=0;
     112 [ +  - ][ +  - ]:         61 :   MeshOp * vm = (MeshOp*) mk_core()->construct_meshop(dim);
     113                 :            : 
     114 [ +  - ][ +  - ]:        352 :   for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
                 [ +  + ]
     115                 :            :   {
     116         [ +  - ]:        291 :     ModelEnt *me = mit->first;
     117         [ +  - ]:        291 :     MEntVector children;
     118         [ +  - ]:        291 :     me->get_adjacencies(0, children);
     119         [ +  + ]:        857 :     for (unsigned int i=0; i<children.size(); i++)
     120 [ +  - ][ +  - ]:        566 :       if (children[i]->is_meshops_list_empty())
                 [ +  + ]
     121                 :            :       {
     122 [ +  - ][ +  - ]:        222 :         vm->add_modelent(children[i]);
     123                 :            :       }
     124                 :        291 :   }
     125                 :            :   // in any case, make sure that the vertex mesher is inserted before this edge mesher
     126                 :         61 :   mk_core()->insert_node(vm, this, mk_core()->root_node());
     127                 :            : 
     128                 :            : 
     129                 :         61 : }
     130                 :            : 
     131                 :            : //---------------------------------------------------------------------------//
     132                 :            : // execute function: Generate the mesh for edges
     133                 :         61 : void EdgeMesher::execute_this()
     134                 :            : {
     135         [ +  - ]:         61 :   std::vector<double> coords;
     136         [ +  - ]:        122 :   std::vector<moab::EntityHandle> nodes;
     137                 :            : 
     138 [ +  - ][ +  - ]:        352 :   for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
                 [ +  + ]
     139                 :            :   {
     140         [ +  - ]:        291 :     ModelEnt *me = mit -> first;
     141 [ +  - ][ +  + ]:        291 :     if (me->get_meshed_state() >= COMPLETE_MESH)
     142                 :          4 :         continue;
     143                 :            :     //resize the coords based on the interval setting
     144         [ +  - ]:        287 :     int num_edges = me->mesh_intervals();
     145         [ +  - ]:        287 :     coords.resize(3*(num_edges+1));
     146                 :        287 :     nodes.clear();
     147         [ +  - ]:        287 :     nodes.reserve(num_edges + 1);
     148                 :            : 
     149                 :            :     //get bounding mesh entities, use 1st 2 entries of nodes list temporarily
     150                 :            :     //pick up the boundary end nodes
     151         [ +  - ]:        287 :     me->boundary(0, nodes);
     152                 :            : 
     153                 :        287 :     bool periodic = (nodes.size() == 1);
     154                 :            :     
     155                 :            :     //get coords in list, then move one tuple to the last position
     156 [ +  - ][ +  - ]:        287 :     moab::ErrorCode rval = mk_core()->moab_instance()->get_coords(&nodes[0], nodes.size(), &coords[0]);
         [ +  - ][ +  - ]
                 [ +  - ]
     157 [ -  + ][ #  # ]:        287 :     MBERRCHK(rval, mk_core()->moab_instance());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     158                 :            : 
     159                 :            :     //move the second node to the endmost position in the node list
     160                 :            :     // if periodic, the last node coordinates are also at index 0 in coords array
     161                 :            :     // there is only one node, coords[3+i] are not even initialized
     162         [ +  + ]:        287 :     int index2 = (periodic) ? 0 : 3;
     163         [ +  + ]:       1148 :     for (int i = 0; i < 3; i++)
     164 [ +  - ][ +  - ]:        861 :       coords[3*num_edges+i] = coords[index2+i];
     165                 :            : 
     166                 :        287 :     EdgeSchemeType scheme = schemeType;
     167 [ +  - ][ +  - ]:        287 :     SizingFunction *sz = mk_core()->sizing_function(me->sizing_function_index());
                 [ +  - ]
     168 [ +  - ][ +  + ]:        287 :     if (sz->variable())
     169                 :         19 :       scheme = VARIABLE;
     170                 :            : 
     171                 :            :     //choose the scheme for edge mesher
     172   [ +  -  +  -  :        287 :     switch(scheme)
                +  -  - ]
     173                 :            :     {
     174                 :            :       case EQUAL://equal meshing for edges
     175         [ +  - ]:        264 :           EqualMeshing(me, num_edges, coords);
     176                 :        264 :           break;
     177                 :            :       case BIAS://bias meshing for edges
     178         [ #  # ]:          0 :           BiasMeshing(me, num_edges, coords);
     179                 :          0 :           break;
     180                 :            :       case DUAL://dual bias meshing for edges
     181         [ +  - ]:          4 :           DualBiasMeshing(me, num_edges, coords);
     182                 :          4 :           break;
     183                 :            :       case CURVATURE://curvature-based meshing for edges
     184         [ #  # ]:          0 :           CurvatureMeshing(me, num_edges, coords);
     185                 :          0 :           break;
     186                 :            :       case VARIABLE: // use a var size from sizing function
     187         [ +  - ]:         19 :           VariableMeshing(me, num_edges, coords);
     188                 :         19 :           break;
     189                 :            :       case EQUIGNOMONIC: // used to generate HOMME type meshes on a sphere
     190         [ #  # ]:          0 :           EquiAngleGnomonic(me, num_edges, coords);
     191                 :          0 :           break;
     192                 :            :       default:
     193                 :          0 :           break;                        
     194                 :            :     }
     195                 :            :     //the variable nodes should be resized, node size may be changed in the different scheme for edge meshing
     196         [ +  - ]:        287 :     me->mesh_intervals(num_edges);
     197         [ +  - ]:        287 :     nodes.resize(num_edges+1);
     198                 :            :     
     199                 :            :     //move the other nodes to the end of nodes' list
     200 [ +  + ][ +  - ]:        287 :     if (periodic) nodes[num_edges] = nodes[0];
                 [ +  - ]
     201 [ +  - ][ +  - ]:        271 :     else nodes[num_edges] = nodes[1];
     202                 :            : 
     203                 :            :     //create the vertices' entities on the edge
     204         [ +  + ]:        287 :     if (num_edges > 1) {
     205 [ +  - ][ +  - ]:        239 :       rval = mk_core()->moab_instance()->create_vertices(&coords[3], num_edges - 1, mit -> second);
         [ +  - ][ +  - ]
                 [ +  - ]
     206 [ -  + ][ #  # ]:        239 :       MBERRCHK(rval, mk_core()->moab_instance());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     207                 :            :     }
     208                 :            :     
     209                 :            :     //distribute the nodes into vector
     210                 :        287 :     int j = 1;
     211 [ +  - ][ +  - ]:       2489 :     for (moab::Range::iterator rit = mit -> second.begin(); rit != mit -> second.end(); rit++)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  + ]
     212 [ +  - ][ +  - ]:       2202 :       nodes[j++] = *rit;
     213                 :            : 
     214                 :            :       //get the query interface, which we will use to create the edges directly 
     215                 :            :     moab::ReadUtilIface *iface;
     216 [ +  - ][ +  - ]:        287 :     rval = mk_core() -> moab_instance() -> query_interface(iface);
                 [ +  - ]
     217 [ -  + ][ #  # ]:        287 :     MBERRCHK(rval, mk_core()->moab_instance());              
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     218                 :            : 
     219                 :            :       //create the edges, get a direct ptr to connectivity
     220                 :            :     moab::EntityHandle starth, *connect, *tmp_connect;
     221         [ +  - ]:        287 :     rval = iface -> get_element_connect(num_edges, 2, moab::MBEDGE, 1, starth, connect);
     222 [ -  + ][ #  # ]:        287 :     MBERRCHK(rval, mk_core()->moab_instance());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     223                 :            : 
     224                 :            :       //add edges to range for the MESelection
     225 [ +  - ][ +  - ]:        287 :     mit -> second.insert(starth, starth + num_edges - 1);
     226                 :            : 
     227                 :            :       //now set the connectivity array from the nodes
     228         [ +  - ]:        287 :     tmp_connect = &nodes[0];
     229         [ +  + ]:       2776 :     for (int i = 0; i < num_edges; i++)
     230                 :            :     {
     231                 :       2489 :       connect[0] = tmp_connect[0];
     232                 :       2489 :       connect[1] = tmp_connect[1];
     233                 :            : 
     234                 :            :         //increment connectivity ptr by 2 to go to next edge
     235                 :       2489 :       connect += 2;
     236                 :            :                         
     237                 :            :         //increment tmp_connect by 1, to go to next node
     238                 :       2489 :       tmp_connect++;
     239                 :            :     }
     240                 :            : 
     241                 :            :       //   ok, we are done, commit to ME
     242 [ +  - ][ +  - ]:        287 :     me->commit_mesh(mit->second, COMPLETE_MESH);
     243                 :            :    
     244                 :            :         
     245                 :         61 :   }
     246                 :            : 
     247                 :            :         
     248                 :         61 : }
     249                 :            : 
     250                 :            : //---------------------------------------------------------------------------//
     251                 :            : // Deconstruction function
     252                 :        180 : EdgeMesher::~EdgeMesher()
     253                 :            : {
     254                 :            : 
     255         [ -  + ]:        120 : }
     256                 :            : 
     257                 :            : //---------------------------------------------------------------------------//
     258                 :            : // Create the mesh for edges with the equal distances
     259                 :        264 : void EdgeMesher::EqualMeshing(ModelEnt *ent, int num_edges, std::vector<double> &coords)
     260                 :            : {
     261                 :            :   double umin, umax, measure;
     262                 :            :   (void) measure;
     263                 :            :     //get the u range for the edge
     264 [ +  - ][ +  - ]:        264 :   iGeom::Error gerr =  ent->igeom_instance()->getEntURange(ent->geom_handle(), umin, umax);
                 [ +  - ]
     265         [ +  - ]:        264 :   IBERRCHK(gerr, "Trouble get parameter range for edge.");
     266                 :            : 
     267 [ -  + ][ #  # ]:        264 :   if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");
     268                 :            : 
     269                 :            :   //get the arc length
     270         [ +  - ]:        264 :   measure = ent -> measure();
     271                 :            : 
     272                 :            :   double u, du;
     273 [ -  + ][ #  # ]:        264 :   if (!num_edges) throw Error(MK_BAD_INPUT, "Trying to mesh edge with zero edges.");
     274                 :        264 :   du = (umax - umin)/(double)num_edges;
     275                 :            :         
     276                 :        264 :   u = umin;
     277                 :            :   //distribute the nodes with equal distances
     278         [ +  + ]:       2271 :   for (int i = 1; i < num_edges; i++)
     279                 :            :   {
     280                 :       2007 :     u = umin + i*du;
     281 [ +  - ][ +  - ]:       2007 :     gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, coords[3*i], coords[3*i+1], coords[3*i+2]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     282         [ +  - ]:       2007 :     IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     283                 :            :   }
     284                 :            : 
     285                 :        264 : }
     286                 :            : 
     287                 :            : //---------------------------------------------------------------------------//
     288                 :            : // Create the mesh for edges based on the curvatures
     289                 :          0 : void EdgeMesher::CurvatureMeshing(ModelEnt *ent, int &num_edges, std::vector<double> &coords)
     290                 :            : {
     291                 :            :   double umin, umax, measure;
     292                 :            :   (void) measure;
     293                 :            :   //store the initial edge size, the edge size may be changed during meshing
     294                 :          0 :   int initial_num_edges = num_edges;
     295                 :            : 
     296                 :            :   //get the u range for the edge
     297 [ #  # ][ #  # ]:          0 :   iGeom::Error gerr = ent->igeom_instance() ->getEntURange(ent->geom_handle(), umin, umax);
                 [ #  # ]
     298         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble get parameter range for edge.");
     299                 :            : 
     300 [ #  # ][ #  # ]:          0 :   if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");
     301                 :            : 
     302                 :            :   //get the arc length
     303         [ #  # ]:          0 :   measure = ent -> measure();
     304                 :            : 
     305                 :          0 :   int index = 0;
     306                 :            :   double u, du, uMid;
     307                 :          0 :   du = (umax - umin)/(double)num_edges;
     308                 :            :         
     309         [ #  # ]:          0 :   std::vector<double> NodeCoordinates;
     310         [ #  # ]:          0 :   std::vector<double> TempNode;
     311         [ #  # ]:          0 :   std::vector<double> URecord;            //record the value of U
     312                 :            : 
     313                 :            :   Point3D pts0, pts1, ptsMid;
     314                 :            :   double tmp[3];
     315                 :            : 
     316         [ #  # ]:          0 :   NodeCoordinates.resize(3*(num_edges + 1));
     317                 :            : 
     318         [ #  # ]:          0 :   TempNode.resize(3*1);
     319         [ #  # ]:          0 :   URecord.resize(1);    
     320                 :            : 
     321 [ #  # ][ #  # ]:          0 :   gerr = ent -> igeom_instance() -> getEntUtoXYZ(ent->geom_handle(), umin, TempNode[0], TempNode[1], TempNode[2]);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     322         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble getting U from XYZ along the edge");
     323                 :            :         
     324 [ #  # ][ #  # ]:          0 :   NodeCoordinates[3*0] = TempNode[0];
     325 [ #  # ][ #  # ]:          0 :   NodeCoordinates[3*0+1] = TempNode[1];
     326 [ #  # ][ #  # ]:          0 :   NodeCoordinates[3*0+2] = TempNode[2];
     327                 :            : 
     328         [ #  # ]:          0 :   URecord[0] = umin;
     329                 :            : 
     330                 :          0 :   u = umin;
     331                 :            :   //distribute the mesh nodes on the edge based on the curvature
     332         [ #  # ]:          0 :   for (int i = 1; i < num_edges; i++)
     333                 :            :   {
     334                 :            :     //first distribute the nodes evenly
     335                 :          0 :     u = umin + i*du;
     336 [ #  # ][ #  # ]:          0 :     gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, NodeCoordinates[3*i], NodeCoordinates[3*i+1], NodeCoordinates[3*i+2]);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     337         [ #  # ]:          0 :     IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     338                 :            : 
     339                 :            :     //store the two adjacent mesh nodes on the edge
     340         [ #  # ]:          0 :     pts0.px = NodeCoordinates[3*(i-1)];
     341         [ #  # ]:          0 :     pts0.py = NodeCoordinates[3*(i-1)+1];
     342         [ #  # ]:          0 :     pts0.pz = NodeCoordinates[3*(i-1)+2];
     343                 :            : 
     344         [ #  # ]:          0 :     pts1.px = NodeCoordinates[3*i];
     345         [ #  # ]:          0 :     pts1.py = NodeCoordinates[3*i+1];
     346         [ #  # ]:          0 :     pts1.pz = NodeCoordinates[3*i+2];
     347                 :            : 
     348                 :            :     //get the coordinates for mid point between two adjacent mesh nodes on the edge
     349                 :          0 :     uMid = (u-du+u)/2;
     350 [ #  # ][ #  # ]:          0 :     gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), uMid, tmp[0], tmp[1], tmp[2]);
                 [ #  # ]
     351                 :          0 :     ptsMid.px = tmp[0];
     352                 :          0 :     ptsMid.py = tmp[1];
     353                 :          0 :     ptsMid.pz = tmp[2];
     354                 :            : 
     355                 :            :     //calculate the error and check whether it requires further refinement based on the curvature
     356 [ #  # ][ #  # ]:          0 :     if (!ErrorCalculate(ent, pts0, pts1, ptsMid))
     357                 :            :     {
     358         [ #  # ]:          0 :         DivideIntoMore(ent, pts0, ptsMid, pts1, u-du, u, uMid, index, TempNode, URecord);
     359                 :            :     }
     360                 :            :     
     361                 :            :     // add the other end node to the array, get the next two adjacent mesh nodes
     362                 :          0 :     index++;
     363         [ #  # ]:          0 :     TempNode.resize(3*(index + 1));
     364         [ #  # ]:          0 :     URecord.resize(index + 1);
     365         [ #  # ]:          0 :     TempNode[3*index] = pts1.px;
     366         [ #  # ]:          0 :     TempNode[3*index + 1] = pts1.py;
     367         [ #  # ]:          0 :     TempNode[3*index + 2] = pts1.pz;
     368                 :            : 
     369         [ #  # ]:          0 :     URecord[index] = u; 
     370                 :            :   }
     371                 :            : 
     372                 :            :   //sorting the parametrical coordinate data based on the value of u
     373         [ #  # ]:          0 :   assert(TempNode.size()== (3*URecord.size()) );
     374                 :            :         
     375         [ #  # ]:          0 :   QuickSorting(TempNode, URecord, URecord.size());
     376                 :          0 :   num_edges = URecord.size() - 1;
     377                 :            :         
     378                 :            :   //resize the variable coords
     379         [ #  # ]:          0 :   coords.resize(3*(num_edges+1));       
     380                 :            : 
     381                 :            :   //move the other end node to the endmost of the list
     382         [ #  # ]:          0 :   for (int i = 0; i < 3; i++)
     383 [ #  # ][ #  # ]:          0 :     coords[3*num_edges+i] = coords[3*initial_num_edges+i];
     384                 :            : 
     385                 :            :   //return the mesh nodes       
     386         [ #  # ]:          0 :   for (int i = 1; i < num_edges; i++)
     387                 :            :   {
     388 [ #  # ][ #  # ]:          0 :     coords[3*i] = TempNode[3*i];
     389 [ #  # ][ #  # ]:          0 :     coords[3*i+1] = TempNode[3*i+1];
     390 [ #  # ][ #  # ]:          0 :     coords[3*i+2] = TempNode[3*i+2];
     391                 :          0 :   }
     392                 :            : 
     393                 :          0 : }
     394                 :            : 
     395                 :            : //---------------------------------------------------------------------------//
     396                 :            : // Create the mesh for edges with dual bias distances
     397                 :          4 : void EdgeMesher::DualBiasMeshing(ModelEnt *ent, int &num_edges, std::vector<double> &coords)
     398                 :            : {
     399                 :            :   double umin, umax, measure;
     400                 :            : 
     401                 :            :     //get the u range for the edge
     402 [ +  - ][ +  - ]:          4 :   iGeom::Error gerr = ent->igeom_instance()->getEntURange(ent->geom_handle(), umin, umax);
                 [ +  - ]
     403         [ +  - ]:          4 :   IBERRCHK(gerr, "Trouble get parameter range for edge.");
     404                 :            : 
     405 [ -  + ][ #  # ]:          4 :   if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");
     406                 :            : 
     407                 :            :   //get the arc length
     408         [ +  - ]:          4 :   measure = ent -> measure();
     409                 :            : 
     410                 :            :   double u, L0, dist, u0, u1;
     411                 :            :         
     412                 :            :   //if the node # is odd, node # will increase by 1
     413         [ -  + ]:          4 :   if ((num_edges%2)!=0)
     414                 :            :   {
     415                 :          0 :     num_edges++;
     416         [ #  # ]:          0 :     coords.resize(3*(num_edges+1));
     417                 :            :       //move the other end node's position because the variable coords has been resized.
     418         [ #  # ]:          0 :     for (int k = 0; k < 3; k++)
     419 [ #  # ][ #  # ]:          0 :       coords[3*num_edges + k] = coords[3*num_edges + k - 3];
     420                 :            :   }
     421                 :            : 
     422                 :            :   //default bias ratio is 1.2
     423                 :          4 :   double q = ratio;//
     424                 :            :         
     425                 :            :   //get the distance between the first two nodes
     426         [ +  - ]:          4 :   L0 = 0.5 * measure * (1-q) / (1 - pow(q, num_edges/2));
     427                 :            :                 
     428                 :            :         
     429                 :          4 :   u0 = umin;
     430                 :          4 :   u1 = umax;
     431                 :            :   //distribute the mesh nodes on the edge with dual-bias distances
     432         [ +  + ]:         24 :   for (int i = 1; i < (num_edges/2 + 1); i++)
     433                 :            :   {
     434                 :            :       //distribute the mesh nodes on the one side               
     435         [ +  - ]:         20 :     dist = L0*pow(q, i-1);
     436                 :         20 :     u = u0 + (umax - umin) * dist/measure;
     437         [ +  - ]:         20 :     u = getUCoord(ent, u0, dist, u, umin, umax);
     438                 :         20 :     u0 = u;
     439 [ +  - ][ +  - ]:         20 :     gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, coords[3*i], coords[3*i+1], coords[3*i+2]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     440         [ +  - ]:         20 :     IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     441                 :            : 
     442                 :            :     //distribute the mesh nodes on the other side
     443         [ +  + ]:         20 :     if (i < num_edges/2)
     444                 :            :     {
     445                 :         16 :       u = u1 - (umax-umin) * dist / measure;
     446         [ +  - ]:         16 :       u = getUCoord(ent, u1, dist, u, umin, umax);
     447                 :         16 :       u1 = u;
     448 [ +  - ][ +  - ]:         16 :       gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, coords[3*(num_edges-i)], coords[3*(num_edges-i)+1], coords[3*(num_edges-i)+2]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     449         [ +  - ]:         16 :       IBERRCHK(gerr, "Trouble getting U from XYZ along the edge");
     450                 :            :     }
     451                 :            :                 
     452                 :            :   }
     453                 :            :         
     454                 :          4 : }
     455                 :            : 
     456                 :            : //---------------------------------------------------------------------------//
     457                 :            : // Create the mesh for edges with bias distances
     458                 :          0 : void EdgeMesher::BiasMeshing(ModelEnt *ent, int num_edges, std::vector<double> &coords)
     459                 :            : {
     460                 :            :   double umin, umax, measure;
     461                 :            : 
     462                 :            :   //get the u range for the edge
     463 [ #  # ][ #  # ]:          0 :   iGeom::Error gerr = ent->igeom_instance()->getEntURange(ent->geom_handle(), umin, umax);
                 [ #  # ]
     464         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble get parameter range for edge.");
     465                 :            : 
     466 [ #  # ][ #  # ]:          0 :   if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");
     467                 :            : 
     468                 :            :   //get the arc length
     469         [ #  # ]:          0 :   measure = ent -> measure();
     470                 :            : 
     471                 :          0 :   double u, L0, dist = 0, u0;
     472                 :            :         
     473                 :            :   // the default bias ratio 1.2
     474                 :          0 :   double q = ratio;
     475         [ #  # ]:          0 :   L0 = measure * (1-q) / (1 - pow(q, num_edges));
     476                 :            :                 
     477                 :            :         
     478                 :          0 :   u0 = umin;
     479                 :            :   //distribute the mesh nodes on the edge with bias distances
     480         [ #  # ]:          0 :   for (int i = 1; i < num_edges; i++)
     481                 :            :   {
     482         [ #  # ]:          0 :     dist = L0*pow(q, i-1);
     483                 :          0 :     u = u0 + (umax - umin)*dist/measure;
     484         [ #  # ]:          0 :     u = getUCoord(ent, u0, dist, u, umin, umax);
     485                 :          0 :     u0 = u;
     486 [ #  # ][ #  # ]:          0 :     gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, coords[3*i], coords[3*i+1], coords[3*i+2]);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     487         [ #  # ]:          0 :     IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     488                 :            :   }
     489                 :          0 : }
     490                 :            : 
     491                 :            : //---------------------------------------------------------------------------//
     492                 :            : // Mesh Refinement function based on the curvature: if the error is too big, refine the mesh on the edge
     493                 :          0 : void EdgeMesher::DivideIntoMore(ModelEnt *ent, Point3D p0, Point3D pMid, Point3D p1, double u0, double u1, double uMid, int &index, vector<double> &nodes, vector<double> &URecord)
     494                 :            : {
     495                 :            :   //this is a recursive process, the process continues until the error is smaller than what is required.
     496                 :            :   //first get two adjacent mesh nodes on the edge and coordinates for mid point between two adjacent nodes.
     497                 :            :   //then check the left side and right side whether the error is too big nor not
     498                 :            :   double uu0, uu1, uumid, tmp[3];
     499                 :            :   Point3D pts0, pts1, ptsMid;
     500                 :            :         
     501                 :          0 :   index++;
     502         [ #  # ]:          0 :   nodes.resize(3*(index+1));
     503         [ #  # ]:          0 :   URecord.resize(index+1);
     504         [ #  # ]:          0 :   nodes[3*index] = pMid.px;
     505         [ #  # ]:          0 :   nodes[3*index+1] = pMid.py;
     506         [ #  # ]:          0 :   nodes[3*index+2] = pMid.pz;
     507         [ #  # ]:          0 :   URecord[index] = uMid;
     508                 :            :         
     509                 :            :   //check the left side
     510                 :          0 :   uu0=u0;
     511                 :          0 :   uu1=uMid;
     512                 :          0 :   uumid=(uu0+uu1)/2;
     513                 :          0 :   pts0=p0;
     514                 :          0 :   pts1=pMid;
     515                 :            : 
     516                 :            : 
     517 [ #  # ][ #  # ]:          0 :   iGeom::Error gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), uumid, tmp[0], tmp[1], tmp[2]);
                 [ #  # ]
     518         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     519                 :          0 :   ptsMid.px = tmp[0];
     520                 :          0 :   ptsMid.py = tmp[1];
     521                 :          0 :   ptsMid.pz = tmp[2];
     522                 :            : 
     523                 :            :   //check the error
     524 [ #  # ][ #  # ]:          0 :   if(!ErrorCalculate(ent, pts0, pts1, ptsMid))
     525                 :            :   {
     526                 :            :     //further refinement
     527         [ #  # ]:          0 :     DivideIntoMore(ent, pts0, ptsMid, pts1, uu0, uu1, uumid, index, nodes, URecord);
     528                 :            :   }
     529                 :            :         
     530                 :            :   //check the right side
     531                 :          0 :   uu0 = uMid;
     532                 :          0 :   uu1=u1;
     533                 :          0 :   uumid=(uu0+uu1)/2;
     534                 :          0 :   pts0=pMid;
     535                 :          0 :   pts1=p1;
     536                 :            :   //get the coorindinates for mid point 
     537 [ #  # ][ #  # ]:          0 :   gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), uumid, tmp[0], tmp[1], tmp[2]);
                 [ #  # ]
     538         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     539                 :          0 :   ptsMid.px = tmp[0];
     540                 :          0 :   ptsMid.py = tmp[1];
     541                 :          0 :   ptsMid.pz = tmp[2];
     542                 :            :         
     543                 :            :   //check the error
     544 [ #  # ][ #  # ]:          0 :   if(!ErrorCalculate(ent, pts0, pts1, ptsMid))
     545                 :            :   {
     546                 :            :     //further refinement
     547         [ #  # ]:          0 :     DivideIntoMore(ent, pts0, ptsMid, pts1, uu0, uu1, uumid, index, nodes, URecord);
     548                 :            :   }
     549                 :            :                         
     550                 :          0 : }
     551                 :            : 
     552                 :            : //create the mesh for edges based on variable size from SizingFunction (var)
     553                 :         19 : void EdgeMesher::VariableMeshing(ModelEnt *ent, int &num_edges, std::vector<double> &coords)
     554                 :            : {
     555                 :            :   double umin, umax, measure;
     556                 :            :   (void) measure;
     557                 :            :   // because of that, keep track of the first node position and last node position
     558                 :            :   // first node position does not change, but the last node position do change
     559                 :            :   // coords will contain all nodes, including umax in Urecord!
     560                 :            : 
     561 [ +  - ][ +  - ]:         19 :   SizingFunction *sf = mk_core()->sizing_function(ent->sizing_function_index());
                 [ +  - ]
     562                 :            :   //get the u range for the edge
     563         [ +  - ]:         19 :   iGeom::EntityHandle edge = ent->geom_handle();
     564 [ +  - ][ +  - ]:         19 :   iGeom::Error gerr = ent->igeom_instance() ->getEntURange(edge, umin, umax);
     565         [ +  - ]:         19 :   IBERRCHK(gerr, "Trouble get parameter range for edge.");
     566                 :            : 
     567 [ -  + ][ #  # ]:         19 :   if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");
     568                 :            : 
     569                 :            :   //get the arc length
     570         [ +  - ]:         19 :   measure = ent -> measure();
     571                 :            : 
     572                 :            :   // start advancing for each edge mesh, from the first point position
     573                 :         19 :   double currentPar = umin;
     574                 :            :   double currentPosition[3];
     575         [ +  - ]:         19 :   gerr = ent->igeom_instance() ->getEntUtoXYZ(edge, umin, currentPosition[0],
     576         [ +  - ]:         19 :       currentPosition[1], currentPosition[2] );
     577                 :            : 
     578                 :            :   double endPoint[3];
     579         [ +  - ]:         19 :   gerr = ent->igeom_instance() ->getEntUtoXYZ(edge, umax, endPoint[0],
     580         [ +  - ]:         19 :       endPoint[1], endPoint[2] );
     581         [ +  - ]:         19 :   Vector<3> endpt(endPoint);
     582                 :            : 
     583         [ +  - ]:         19 :   double targetSize = sf->size(currentPosition);
     584                 :         19 :   double startSize = targetSize;
     585                 :            : 
     586         [ +  - ]:         19 :   double endSize = sf->size(endPoint);
     587                 :            :   // advance u such that the next point is at "currentSize" distance
     588                 :            :   // or close to it
     589                 :            :   // try first with a u that is coming from the (umax-umin)/number of edges
     590                 :         19 :   double deltaU = (umax-umin)/num_edges;
     591                 :            :   //coords.clear(); we do not want to clear, as the first node is still fine
     592         [ +  - ]:         19 :   std::vector<double> URecord;    //record the values for u; we may have to adjust all
     593                 :            :   // of them accordingly, and even add one more if we have some evenify problems.
     594                 :            :   // keep in mind that size is just a suggestion, number of intervals is more important for
     595                 :            :   // paver mesher
     596         [ +  - ]:         19 :   Vector<3> pt(currentPosition);
     597                 :            : 
     598                 :            :   //bool notDone = true;
     599                 :         19 :   double prevU = umin;
     600         [ +  + ]:        174 :   while (currentPar + 1.1*deltaU < umax)
     601                 :            :   {
     602                 :            :     // do some binary search; actually, better, do Newton-Raphson, which should converge
     603                 :            :     // faster
     604                 :            :     //
     605                 :        155 :     prevU = currentPar;
     606                 :        155 :     currentPar += deltaU;
     607                 :            :     // adjust current par, such that
     608                 :            :     double point[3];
     609 [ +  - ][ +  - ]:        155 :     gerr=ent->igeom_instance()->getEntUtoXYZ(edge, currentPar, point[0], point[1], point[2] );
     610         [ +  - ]:        155 :     IBERRCHK(gerr, "Trouble getting position at parameter u.");
     611         [ +  - ]:        155 :     Vector<3> ptCandidate(point);
     612 [ +  - ][ +  - ]:        155 :     double compSize = length(ptCandidate-pt);
     613                 :        155 :     int nit = 0;
     614                 :            : 
     615 [ +  + ][ +  - ]:        303 :     while ( (fabs(1.-compSize/targetSize)> 0.02 ) && (nit < 5))// 2% of the target size
     616                 :            :     {
     617                 :            :       // do Newton iteration
     618                 :            :       double tangent[3];
     619 [ +  - ][ +  - ]:        148 :       gerr=ent->igeom_instance() ->getEntTgntU(edge, currentPar, tangent[0], tangent[1], tangent[2] );
     620         [ +  - ]:        148 :       IBERRCHK(gerr, "Trouble getting tangent at parameter u.");
     621         [ +  - ]:        148 :       Vector<3> tang(tangent);
     622 [ +  - ][ +  - ]:        148 :       double dldu = 1./compSize * ((ptCandidate-pt )%tang);
     623                 :        148 :       nit++;// increase iteration count
     624         [ +  - ]:        148 :       if (dldu!=0.)
     625                 :            :       {
     626                 :        148 :         double deu= (targetSize-compSize)/dldu;
     627                 :        148 :         currentPar+=deu;
     628         [ -  + ]:        148 :         if (prevU>currentPar)
     629                 :            :         {
     630                 :        148 :           break; // something is wrong
     631                 :            :         }
     632         [ -  + ]:        148 :         if (umax < currentPar)
     633                 :            :         {
     634                 :          0 :           currentPar = umax;
     635                 :          0 :           break;
     636                 :            :         }
     637 [ +  - ][ +  - ]:        148 :         ent->igeom_instance()->getEntUtoXYZ(edge, currentPar, point[0], point[1], point[2]);
     638         [ +  - ]:        148 :         Vector<3> newPt(point);
     639 [ +  - ][ +  - ]:        148 :         compSize = length(newPt-pt);
     640                 :        148 :         ptCandidate = newPt;
     641                 :            :       }
     642                 :            : 
     643                 :            :     }
     644                 :            :     // we have found an acceptable point/param
     645         [ +  - ]:        155 :     URecord.push_back(currentPar);
     646                 :        155 :     deltaU = currentPar-prevU;// should be greater than 0
     647                 :        155 :     pt = ptCandidate;
     648 [ +  - ][ +  - ]:        155 :     targetSize = sf->size(pt.data());// a new target size, at the current point
     649                 :            : 
     650                 :            : 
     651                 :            : 
     652                 :            :   }
     653                 :            :   // when we are out of here, we need to adjust the URecords, to be more nicely
     654                 :            :   // distributed; also, look at the evenify again
     655                 :         19 :   int sizeU = (int)URecord.size();
     656 [ +  + ][ +  - ]:         19 :   if ((sizeU%2==0) && ent->constrain_even() )
         [ +  + ][ +  + ]
     657                 :            :   {
     658                 :            :     // add one more
     659         [ -  + ]:          4 :     if (sizeU==0)
     660                 :            :     {
     661                 :            :       // just add one in the middle, and call it done
     662         [ #  # ]:          0 :       URecord.push_back( (umin+umax)/2);
     663                 :            :     }
     664                 :            :     else
     665                 :            :     {
     666                 :            :       //at least 2 (maybe 4)
     667 [ +  - ][ +  - ]:          4 :       double lastDelta = URecord[sizeU-1]-URecord[sizeU-2];
     668 [ +  - ][ +  - ]:          4 :       URecord.push_back(URecord[sizeU-1]+lastDelta );
     669                 :            :     }
     670                 :            :   }
     671                 :            :   // now, we have to redistribute, such as the last 2 deltas are about the same
     672                 :            :   // so, we should have after a little work,
     673                 :            :   // umin, umin+c*(URecord[0]-umin), ... umin+c*(URecord[size-1]-umin), umax
     674                 :            :   // what we have now is
     675                 :            :   // umin, URecord[0], ... ,URecord[size-1], and umax could be even outside or inside
     676                 :            :   // keep the last sizes equal
     677                 :            :   //  umin+c(UR[size-2]-umin) + umax = 2*( umin+c*(UR[size-1]-umin))
     678                 :            :   //  c ( 2*(UR[size-1]-umin) -(UR[size-2]-umin) ) = umax - umin
     679                 :            :   // c ( 2*UR[size-1] - UR[size-2] - umin ) = umax - umin
     680                 :            :   // c = (umax-umin)/( 2*UR[size-1] - UR[size-2] - umin)
     681                 :         19 :   sizeU = (int)URecord.size();// it may be bigger by one than the last time
     682         [ +  - ]:         19 :   if (sizeU == 0)
     683                 :            :   {
     684                 :            :     // nothing to do, only one edge to generate
     685                 :            :   }
     686         [ -  + ]:         19 :   else if (sizeU == 1)
     687                 :            :   {
     688                 :            :     // put it according to the sizes at ends, and assume a nice variation for u
     689                 :            :     // (u-umin) / (umax-u) = startSize / endSize
     690                 :            :     // (u-umin)*endSize = (umax-u) * startSize
     691                 :            :     // u(endSize+startSize)=(umax*startSize+umin*endSize)
     692         [ #  # ]:          0 :     URecord[0] = (umax*startSize+umin*endSize)/(startSize+endSize);
     693                 :            : 
     694                 :            :   }
     695                 :            :   else // sizeU>=2, so we can spread the param a little more, assuming nice
     696                 :            :     // uniform mapping
     697                 :            :   {
     698 [ +  - ][ +  - ]:         19 :     double c =  (umax-umin)/( 2*URecord[sizeU-1] - URecord[sizeU-2] - umin);
     699         [ +  + ]:        178 :     for (int i=0; i<sizeU; i++)
     700 [ +  - ][ +  - ]:        159 :       URecord[i] = umin + c*(URecord[i] -umin);// some spreading out
     701                 :            :   }
     702                 :            :   // now, we can finally get the points for each U, U's should be spread out nicely
     703         [ +  - ]:         19 :   URecord.push_back(umax); // just add the last u, for the end point
     704                 :            :   //
     705                 :         19 :   sizeU = (int) URecord.size(); // new size, after pushing the last u, umax
     706                 :         19 :   num_edges = sizeU;// this is the new number of edges; the last one will be the end point
     707                 :            :   // of the edge, corresponding to umax
     708         [ +  - ]:         19 :   coords.resize(3*sizeU+3);
     709                 :            :   // we already know that at i=0 is the first node, start vertex of edge
     710                 :            :   // the rest will be computed from u
     711                 :            :   // even the last one, which is an overkill
     712         [ +  + ]:        197 :   for (int i = 1; i <= num_edges; i++)
     713                 :            :   {
     714         [ +  - ]:        178 :     double u = URecord[i-1];
     715 [ +  - ][ +  - ]:        178 :     gerr = ent->igeom_instance()->getEntUtoXYZ(edge, u, coords[3*i], coords[3*i+1], coords[3*i+2]);
         [ +  - ][ +  - ]
                 [ +  - ]
     716         [ +  - ]:        178 :     IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     717                 :            :   }
     718                 :         19 :   return;
     719                 :            : 
     720                 :            : }
     721                 :            : // number of edges is input here
     722                 :            : //  equal angles are formed at the center of the sphere/cube mesh
     723                 :            : // it is close to bias meshing, but not quite
     724                 :          0 : void EdgeMesher::EquiAngleGnomonic(ModelEnt *ent, int num_edges, std::vector<double> &coords)
     725                 :            : {
     726                 :          0 :   const double MY_PI=3.14159265;
     727                 :          0 :   double deltaAngle=MY_PI/num_edges/2;
     728                 :            :  // double length=ent->measure();// this is an edge
     729                 :            :   double umin, umax;
     730                 :            : 
     731                 :            :   //get the u range for the edge
     732 [ #  # ][ #  # ]:          0 :   iGeom::Error gerr = ent->igeom_instance()->getEntURange(ent->geom_handle(), umin, umax);
                 [ #  # ]
     733         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble get parameter range for edge.");
     734                 :            : 
     735 [ #  # ][ #  # ]:          0 :   if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");
     736                 :            : 
     737                 :            :   // consider that the parametrization is very linear
     738                 :            :   // most of the time u will be from 0 to length of edge, for a cube
     739                 :          0 :   double deltau = umax - umin;
     740                 :            : 
     741                 :          0 :   double u = umin;// u will get different values,
     742                 :            :   // start at u
     743         [ #  # ]:          0 :   for (int i = 1; i < num_edges; i++)
     744                 :            :     {
     745                 :          0 :       double betak=i*deltaAngle;
     746                 :          0 :       double alfak = MY_PI/4-betak;
     747                 :          0 :       double tang_alfak = tan(alfak);
     748                 :          0 :       u = umin+deltau/2*(1-tang_alfak);
     749                 :            : 
     750 [ #  # ][ #  # ]:          0 :       gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, coords[3*i], coords[3*i+1], coords[3*i+2]);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     751         [ #  # ]:          0 :       IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
     752                 :            :     }
     753                 :          0 :   return;
     754                 :            : }
     755                 :            : //---------------------------------------------------------------------------//
     756                 :            : // Rapid sorting the mesh nodes on the edge based on the parametric coordinates. This is a recursive
     757                 :            : // process
     758                 :          0 : void EdgeMesher::RapidSorting(vector<double> &nodes, vector<double> &URecord, int left, int right)
     759                 :            : {
     760                 :            :   int i, j;
     761                 :            :   double middle, iTemp;
     762                 :            :   Point3D TempData;
     763                 :            :         
     764         [ #  # ]:          0 :   middle=URecord[(left+right)/2];
     765                 :          0 :   i=left;
     766                 :          0 :   j=right;
     767                 :            :         
     768         [ #  # ]:          0 :   do
     769                 :            :   {
     770                 :            :       //search the values which are greater than the middle value from the left side            
     771 [ #  # ][ #  # ]:          0 :     while((URecord[i] < middle)&&(i<right))
         [ #  # ][ #  # ]
     772                 :            :     {
     773                 :          0 :       i++;
     774                 :            :     }
     775                 :            :       //search the values which are greater than the middle value from the right side
     776 [ #  # ][ #  # ]:          0 :     while((URecord[j] > middle)&&(j > left))
         [ #  # ][ #  # ]
     777                 :            :     {
     778                 :          0 :       j--;
     779                 :            :     }
     780         [ #  # ]:          0 :     if (i<=j)//find a pair of values
     781                 :            :     {
     782         [ #  # ]:          0 :       iTemp = URecord[i];
     783 [ #  # ][ #  # ]:          0 :       URecord[i] = URecord[j];
     784         [ #  # ]:          0 :       URecord[j]=iTemp;
     785                 :            :                         
     786                 :            :                         
     787         [ #  # ]:          0 :       TempData.px = nodes[3*i];
     788         [ #  # ]:          0 :       TempData.py = nodes[3*i+1];
     789         [ #  # ]:          0 :       TempData.pz = nodes[3*i+2];
     790                 :            : 
     791 [ #  # ][ #  # ]:          0 :       nodes[3*i] = nodes[3*j];
     792 [ #  # ][ #  # ]:          0 :       nodes[3*i+1] = nodes[3*j+1];
     793 [ #  # ][ #  # ]:          0 :       nodes[3*i+2] = nodes[3*j+2];
     794         [ #  # ]:          0 :       nodes[3*j] = TempData.px;
     795         [ #  # ]:          0 :       nodes[3*j+1] = TempData.py;
     796         [ #  # ]:          0 :       nodes[3*j+2] = TempData.pz;                       
     797                 :            :                         
     798                 :          0 :       i++;
     799                 :          0 :       j--;
     800                 :            :     }
     801                 :            :   }while(i<=j);
     802         [ #  # ]:          0 :   if (left < j)
     803         [ #  # ]:          0 :     RapidSorting(nodes, URecord, left, j);
     804         [ #  # ]:          0 :   if (right > i)
     805         [ #  # ]:          0 :     RapidSorting(nodes, URecord, i, right);     
     806                 :          0 : }
     807                 :            : 
     808                 :            : //---------------------------------------------------------------------------//
     809                 :            : // Quick Sorting: this function comes together with the function RapidSorting
     810                 :          0 : void EdgeMesher::QuickSorting(vector<double> &nodes, vector<double> &URecord, int count)
     811                 :            : {
     812                 :          0 :   RapidSorting(nodes, URecord, 0, count-1);
     813                 :          0 : }
     814                 :            : 
     815                 :            : 
     816                 :            : //---------------------------------------------------------------------------//
     817                 :            : // return the x, y, z coordinates from the parametric coordinates
     818                 :         72 : EdgeMesher::Point3D EdgeMesher::getXYZCoords(ModelEnt *ent, double u) const
     819                 :            : {
     820                 :            :   Point3D pts3D;
     821                 :            :   double xyz[3];
     822                 :            : 
     823                 :            : 
     824                 :            :   //get the coordinates in the physical space
     825 [ +  - ][ +  - ]:         72 :   iGeom::Error gerr = ent->igeom_instance()->getEntUtoXYZ(ent->geom_handle(), u, xyz[0], xyz[1], xyz[2]);
                 [ +  - ]
     826         [ +  - ]:         72 :   IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");       
     827                 :            : 
     828                 :         72 :   pts3D.px = xyz[0];
     829                 :         72 :   pts3D.py = xyz[1];
     830                 :         72 :   pts3D.pz = xyz[2];
     831                 :         72 :   return pts3D;
     832                 :            : }
     833                 :            : 
     834                 :            : //---------------------------------------------------------------------------//
     835                 :            : // get the parametric coordinate based on first parametric coordinate ustart and distance in the physical space
     836                 :         36 : double EdgeMesher::getUCoord(ModelEnt *ent, double ustart, double dist, double uguess, double umin, double umax) const
     837                 :            : {
     838                 :            : 
     839         [ +  - ]:         36 :   Point3D p0 = getXYZCoords(ent, ustart);
     840         [ +  - ]:         36 :   Point3D p1 = getXYZCoords(ent, uguess);
     841                 :            : 
     842                 :            : 
     843                 :         36 :   double dx, dy, dz, dl, u=uguess;
     844                 :         36 :   double tol = 1.0E-7;
     845                 :         36 :   int test=0;
     846                 :            : 
     847                 :         36 :   int ntrials=0;
     848                 :            :   while(1)
     849                 :            :   {
     850                 :         36 :     dx = p1.px - p0.px;
     851                 :         36 :     dy = p1.py - p0.py;
     852                 :         36 :     dz = p1.pz - p0.pz;
     853                 :         36 :     dl = sqrt(dx * dx + dy * dy + dz * dz);
     854         [ +  - ]:         36 :     if ( fabs(dl-dist) < tol) break;
     855                 :            :                 
     856                 :          0 :     u = ustart + (u - ustart) * (dist/dl);
     857         [ #  # ]:          0 :     if (u > umax)
     858                 :            :     {
     859                 :          0 :       u=umax;
     860                 :          0 :       test++;
     861         [ #  # ]:          0 :       if (test>10) break;
     862                 :            :     }           
     863         [ #  # ]:          0 :     if (u < umin)
     864                 :            :     {           
     865                 :          0 :       u=umin;
     866                 :          0 :       test++;
     867         [ #  # ]:          0 :       if (test>10) break;
     868                 :            :     }           
     869         [ #  # ]:          0 :     p1 = getXYZCoords(ent, u);
     870                 :            :                 
     871                 :            : 
     872         [ #  # ]:          0 :     if (ntrials++ == 100000)
     873                 :            :     {
     874 [ #  # ][ #  # ]:          0 :       cout << " Warning: Searching for U failed " << endl;
     875                 :            :     }
     876                 :            :   }
     877                 :         36 :   uguess = u;
     878                 :         36 :   return uguess;
     879                 :            : }
     880                 :            : 
     881                 :            : //---------------------------------------------------------------------------//
     882                 :            : // calculate the error: the distance between the mid point of two adjacent 
     883                 :            : // mesh nodes (on the mesh line segments) and mid point on the edge
     884                 :          0 : bool EdgeMesher::ErrorCalculate(ModelEnt *ent, Point3D p0, Point3D p1, Point3D pMid)
     885                 :            : {
     886                 :            :   double lengtha, lengthb, lengthc;
     887                 :            :   double deltax, deltay, deltaz;
     888                 :          0 :   double angle, error, tol=1.0E-3, H;
     889                 :            :   double cvtr_ijk[3], curvature;
     890                 :            :   bool result;
     891                 :            : 
     892                 :            :   //calculate the distance between the first mesh node and mid point on the edge
     893                 :          0 :   deltax = pMid.px-p0.px;
     894                 :          0 :   deltay = pMid.py-p0.py;
     895                 :          0 :   deltaz = pMid.pz-p0.pz;       
     896                 :          0 :   lengtha = sqrt(deltax*deltax + deltay*deltay + deltaz*deltaz);
     897                 :            : 
     898                 :            :   //calculate the distance between two adjacent mesh nodes
     899                 :          0 :   deltax = p1.px-p0.px;
     900                 :          0 :   deltay = p1.py-p0.py;
     901                 :          0 :   deltaz = p1.pz-p0.pz; 
     902                 :          0 :   lengthb = sqrt(deltax*deltax + deltay*deltay + deltaz*deltaz);
     903                 :            : 
     904                 :            :   //calculate the distance between the second mesh node and mid point on the edge
     905                 :          0 :   deltax = pMid.px-p1.px;
     906                 :          0 :   deltay = pMid.py-p1.py;
     907                 :          0 :   deltaz = pMid.pz-p1.pz;       
     908                 :          0 :   lengthc = sqrt(deltax*deltax + deltay*deltay + deltaz*deltaz);
     909                 :            : 
     910                 :            :   //calculate the angle
     911                 :          0 :   angle = acos((lengtha*lengtha + lengthb*lengthb - lengthc*lengthc)/(2*lengtha*lengthb));
     912                 :          0 :   H = fabs(lengtha*sin(angle));
     913                 :            : 
     914                 :            :   //calculate the curvature     
     915 [ #  # ][ #  # ]:          0 :   iGeom::Error gerr = ent->igeom_instance()->getEgCvtrXYZ(ent->geom_handle(), pMid.px, pMid.py, pMid.pz, cvtr_ijk[0], cvtr_ijk[1], cvtr_ijk[2]);
                 [ #  # ]
     916         [ #  # ]:          0 :   IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");               
     917                 :          0 :   curvature = sqrt(cvtr_ijk[0]*cvtr_ijk[0]+cvtr_ijk[1]*cvtr_ijk[1]+cvtr_ijk[2]*cvtr_ijk[2]);
     918                 :          0 :   error= H*curvature;
     919                 :            :         
     920                 :            :         
     921         [ #  # ]:          0 :   if (error > tol)
     922                 :          0 :     result = false;
     923                 :            :   else
     924                 :          0 :     result = true;
     925                 :          0 :   return result;                
     926                 :            : }
     927                 :            : 
     928 [ +  - ][ +  - ]:        156 : }
     929                 :            : 

Generated by: LCOV version 1.11