|
cgma
|
#include <Faceter.hpp>
Definition at line 33 of file Faceter.hpp.
| Faceter::Faceter | ( | RefFace * | face | ) |
Definition at line 45 of file Faceter.cpp.
: thisRefFacePtr(face), gridCellScale(2.5) { globalPointList = new DLIList <CubitPoint*>; gridSearchPtr = NULL; avoidedOverlap = CUBIT_FALSE; }
Definition at line 61 of file Faceter.cpp.
{
if (gridSearchPtr)
delete gridSearchPtr;
if ( globalPointList )
delete globalPointList;
}
| CubitBoolean Faceter::avoid_facet | ( | FaceterPointData * | curr_faceter_data, |
| DLIList< FaceterPointData * > & | order_list | ||
| ) | [private] |
Definition at line 313 of file Faceter.cpp.
{
int ii;
CubitPoint *tmp_point;
FaceterPointData *prev = curr_faceter_data->get_prev();
FaceterPointData *next = curr_faceter_data->get_next();
//get the closest edges to this point.
CubitVector curr_v = curr_faceter_data->coordinates();
CubitVector prev_v = prev->coordinates();
CubitVector next_v = next->coordinates();
double r1 = (curr_v - prev_v).length();
double r2 = (curr_v - next_v).length();
double radius;
double angle;
if ( r1 > r2 )
radius = r1;
else
radius = r2;
gridSearchPtr->set_neighborhood_bounds(curr_v, radius);
DLIList<CubitPoint*> neighborhood_points;
DLIList<CubitPoint*> close_points, loop_list;
gridSearchPtr->get_neighborhood_points(neighborhood_points);
//Loop through and see if there are nodes in here closer
//than the r1 or r2.
FaceterPointData *tmp_faceter;
CubitVector tmp_v;
radius *= radius;
double angle1, angle2;
for (ii = neighborhood_points.size(); ii > 0; ii-- )
{
tmp_point = neighborhood_points.get_and_step();
tmp_faceter = (FaceterPointData*) tmp_point;
if ( tmp_faceter == curr_faceter_data ||
tmp_faceter == prev ||
tmp_faceter == next ||
tmp_faceter == next->get_next() ||
tmp_faceter == prev->get_prev() )
continue;
tmp_v = tmp_faceter->coordinates();
if ( (curr_v-tmp_v).length_squared() < radius )
close_points.append(tmp_point);
}
//Now of these close points if any of them make
//good trinagles for the other nodes then don't do
//this triangle...
CubitBoolean abort_facet = CUBIT_FALSE;
for ( ii = close_points.size(); ii > 0; ii-- )
{
tmp_point = close_points.get_and_step();
loop_list.clean_out();
loop_list.append(tmp_point);
loop_list.append((CubitPoint*)prev);
loop_list.append((CubitPoint*)curr_faceter_data);
loop_list.step();
interior_angle(&loop_list, angle1);
loop_list.clean_out();
loop_list.append((CubitPoint*)curr_faceter_data);
loop_list.append((CubitPoint*)next);
loop_list.append(tmp_point);
loop_list.step();
interior_angle(&loop_list, angle2);
if ( angle1 < DEGREES_TO_RADIANS(160) &&
angle2 < DEGREES_TO_RADIANS(160))
{
int tmp_debug = 1;
if ( tmp_debug )
{
GfxDebug::draw_point(prev->coordinates(), CUBIT_GREEN_INDEX);
GfxDebug::draw_point(curr_faceter_data->coordinates(), CUBIT_RED_INDEX);
GfxDebug::draw_point(tmp_point->coordinates(), CUBIT_BLUE_INDEX);
GfxDebug::draw_point(next->coordinates(), CUBIT_MAGENTA_INDEX);
loop_list.clean_out();
loop_list.append(tmp_point);
loop_list.append((CubitPoint*)prev);
loop_list.append((CubitPoint*)curr_faceter_data);
loop_list.step();
interior_angle(&loop_list, angle1);
}
abort_facet = CUBIT_TRUE;
break;
}
}
if ( abort_facet )
{
//We need to add curr_facerter_data back to the list.
order_list.insert(curr_faceter_data);
//Set the angle above 360...
angle = curr_faceter_data->get_interior_angle();
curr_faceter_data->set_interior_angle(angle + 2*CUBIT_PI);
avoidedOverlap = CUBIT_TRUE;
return CUBIT_TRUE;
}
return CUBIT_FALSE;
}
| CubitStatus Faceter::facet_factory | ( | FaceterPointData * | curr_faceter_data, |
| CubitFacet *& | new_facet, | ||
| DLIList< FaceterPointData * > & | order_list | ||
| ) | [private] |
Definition at line 250 of file Faceter.cpp.
{
double angle;
DLIList<CubitPoint*> loop_list;
new_facet = NULL;
if ( avoid_facet(curr_faceter_data, order_list) )
return CUBIT_SUCCESS;
FaceterPointData *prev = curr_faceter_data->get_prev();
FaceterPointData *next = curr_faceter_data->get_next();
//create the new facet.
//create a triangle from these three points.
new_facet = (CubitFacet*) new FaceterFacetData((CubitPoint*)prev,
(CubitPoint*)curr_faceter_data,
(CubitPoint*)next);
CubitVector facet_normal = new_facet->normal();
CubitVector surface_normal = thisRefFacePtr->normal_at(curr_faceter_data->coordinates());
double dot = facet_normal%surface_normal;
if ( dot < 0 )
{
//new need to try and do this in a different way...
delete new_facet;
new_facet = NULL;
if ( order_list.size() < 3 )
{
PRINT_DEBUG_129("Last triangle is inverted. (surface %d)\n",
thisRefFacePtr->id());
return CUBIT_FAILURE;
}
//Try and create facets on either side of this facet.
return CUBIT_FAILURE;
}
int debug = 1;
if ( debug )
GfxDebug::draw_facet(new_facet, CUBIT_RED_INDEX);
//Now fix up the ordered_list.
//First update the angles.
prev->set_next(next);
next->set_prev(prev);
loop_list.clean_out();
loop_list.append(prev->get_prev());
loop_list.append(prev);
loop_list.append(next);
loop_list.step();
interior_angle(&loop_list, angle);
prev->set_interior_angle(angle);
loop_list.clean_out();
loop_list.append(prev);
loop_list.append(next);
loop_list.append(next->get_next());
loop_list.step();
interior_angle(&loop_list, angle);
next->set_interior_angle(angle);
//Now do basically a sort again. There is probably
//a faster way to do this but there are also much slower
//ways in worst case too. At least this has guaranteed O(nlogn).
order_list.sort(FaceterPointData::sort_by_angle);
CubitPoint *tmp_point = (CubitPoint*) curr_faceter_data;
gridSearchPtr->remove_point(tmp_point);
return CUBIT_SUCCESS;
}
| CubitStatus Faceter::facet_loop | ( | DLIList< CubitPoint * > * | loop_ptr, |
| DLIList< CubitFacet * > & | results | ||
| ) | [private] |
Definition at line 153 of file Faceter.cpp.
{
//Assume there is just this loop and facet it as if there was nothing
//in the middle. This is about the most stupid, simplistic method
//of faceting I could think of. I'm sure anyone reading this could
//think of something more sophisticated and better.
//First get the inteior angle for all of the points.
DLIList <FaceterPointData*> ordered_point_list;
int ii;
double angle;
CubitStatus stat;
CubitPoint *curr_point;
FaceterPointData *curr_faceter_data, *prev, *next;
loop_ptr->reset();
int debug = 0;
for ( ii = 0; ii < loop_ptr->size(); ii++ )
{
stat = interior_angle(loop_ptr, angle);
if ( stat == CUBIT_FAILURE )
return CUBIT_FAILURE;
curr_point = loop_ptr->get_and_step();
if ( debug )
{
PRINT_INFO("%d\n",curr_point->id());
GfxDebug::draw_point( curr_point->coordinates(), CUBIT_ORANGE_INDEX);
}
curr_faceter_data = (FaceterPointData*) curr_point;
prev = (FaceterPointData*) loop_ptr->prev(2);
next = (FaceterPointData*) loop_ptr->get();
if ( angle < CUBIT_RESABS || angle > DEGREES_TO_RADIANS( 359.95 ))
{
PRINT_ERROR("Zero degree angle in loop\n");
RefEdge *owner_e = (RefEdge*) curr_faceter_data->owner();
RefEdge *prev_e = (RefEdge*) prev->owner();
RefEdge *next_e = (RefEdge*) next->owner();
PRINT_ERROR("On edge %d, with next %d and prev %d\n", owner_e->id(),
next_e->id(), prev_e->id());
return CUBIT_FAILURE;
}
curr_faceter_data->set_interior_angle(angle);
curr_faceter_data->set_prev(prev);
curr_faceter_data->set_next(next);
ordered_point_list.append(curr_faceter_data);
}
ordered_point_list.sort(FaceterPointData::sort_by_angle);
//Now go through and just cut off the smallest triangles...
//The list should be ordered largest angle to smallest.
//so go from the end to the front.
CubitFacet *new_facet = NULL;
int safe_size = 4* ordered_point_list.size();
int safe_count = 0;
int redo_count = ordered_point_list.size();
while (ordered_point_list.size() >= 3 &&
safe_count < safe_size )
{
curr_faceter_data = ordered_point_list.pop();
new_facet = NULL;
stat = facet_factory(curr_faceter_data, new_facet, ordered_point_list);
if ( new_facet != NULL )
results.append(new_facet);
if ( stat != CUBIT_SUCCESS )
return stat;
if ( safe_count == redo_count )
{
if ( avoidedOverlap )
{
CubitBoolean reorder = CUBIT_FALSE;
for ( ii = ordered_point_list.size(); ii > 0; ii-- )
{
curr_faceter_data = ordered_point_list.get_and_step();
angle = curr_faceter_data->get_interior_angle();
if ( angle > 2*CUBIT_PI )
{
angle = angle - 2*CUBIT_PI;
curr_faceter_data->set_interior_angle(angle);
reorder = CUBIT_TRUE;
}
}
if ( reorder )
ordered_point_list.sort(FaceterPointData::sort_by_angle);
//set the next redo to be later.
avoidedOverlap = CUBIT_FALSE;
}
redo_count += redo_count;
}
safe_count++;
}
if ( ordered_point_list.size() < 3 )
return CUBIT_SUCCESS;
else
return CUBIT_FAILURE;
}
| CubitStatus Faceter::facet_surface | ( | DLIList< CubitFacet * > & | results, |
| DLIList< CubitPoint * > & | point_list | ||
| ) |
Definition at line 77 of file Faceter.cpp.
{
if ( DEBUG_FLAG(129) )
{
GfxDebug::clear();
GfxDebug::draw_ref_face_edges(thisRefFacePtr);
GfxDebug::flush();
int debug = 0;
if ( debug )
{
GfxDebug::mouse_xforms();
GfxDebug::flush();
}
}
if ( thisRefFacePtr->number_of_Loops() > 1 )
return CUBIT_FAILURE;
//Get the ordered boundary loops.
int ii, jj;
DLIList <DLIList<CubitPoint*>*> boundary_point_loops;
DLIList <CubitPoint*> *tmp_list_ptr;
CubitStatus stat = get_boundary_points( boundary_point_loops );
if ( stat != CUBIT_SUCCESS )
{
//clean up the data...
for ( ii = boundary_point_loops.size(); ii > 0; ii-- )
{
tmp_list_ptr = boundary_point_loops.pop();
for ( jj = tmp_list_ptr->size(); jj > 0; jj-- )
delete tmp_list_ptr->pop();
delete tmp_list_ptr;
}
return stat;
}
//Set up the gridsearch.
double ratio = gridCellScale, cell_size = 0.0;
max_min_edge_ratio(boundary_point_loops, ratio, cell_size);
if (ratio <= gridCellScale) {
ratio = gridCellScale;
}
//Get all of the points into a single list.
for ( ii = boundary_point_loops.size(); ii > 0; ii-- )
{
tmp_list_ptr = boundary_point_loops.get_and_step();
for ( jj = tmp_list_ptr->size(); jj > 0; jj-- )
{
globalPointList->append(tmp_list_ptr->get_and_step());
}
}
gridSearchPtr = new PointGridSearch(*globalPointList,
cell_size,
ratio);
//fill in the grid...
for ( ii = globalPointList->size(); ii > 0; ii-- )
gridSearchPtr->add_point(globalPointList->get_and_step());
//Now start faceting.
stat = facet_loop( boundary_point_loops.get(), results );
//clean up the data...
for ( ii = boundary_point_loops.size(); ii > 0; ii-- )
delete boundary_point_loops.pop();
if ( stat != CUBIT_SUCCESS )
{
//clean the data and return..
for ( ii = results.size(); ii > 0; ii-- )
delete results.pop();
for ( ii = globalPointList->size(); ii > 0; ii-- )
delete globalPointList->pop();
return stat;
}
//Didn't add any points...
point_list += *globalPointList;
return CUBIT_SUCCESS;
}
| CubitStatus Faceter::get_boundary_points | ( | DLIList< DLIList< CubitPoint * > * > & | boundary_point_loops | ) | const [private] |
Definition at line 513 of file Faceter.cpp.
{
DLIList<DLIList<CoEdge*> > co_edge_loops;
thisRefFacePtr->co_edge_loops(co_edge_loops);
int ii, jj;
DLIList <CubitPoint*> *new_point_loop_ptr, tmp_point_list;
RefEdge *ref_edge_ptr;
CoEdge *co_edge_ptr;
CubitStatus stat;
CubitSense sense;
for ( ii = co_edge_loops.size(); ii > 0; ii-- )
{
DLIList <CoEdge*> &co_edge_list_ptr = co_edge_loops.get_and_step();
new_point_loop_ptr = new DLIList <CubitPoint*>;
for ( jj = co_edge_list_ptr.size(); jj > 0; jj-- )
{
co_edge_ptr = co_edge_list_ptr.get_and_step();
ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr();
tmp_point_list.clean_out();
stat = get_curve_facets( ref_edge_ptr, tmp_point_list );
PRINT_DEBUG_129("curve %d has %d points\n",
ref_edge_ptr->id(),
tmp_point_list.size());
if ( !stat )
return CUBIT_FAILURE;
tmp_point_list.reset();
//the points are in order from start vertex to end vertex.
//append them now according to the loop.
sense = co_edge_ptr->get_sense();
if ( CUBIT_FORWARD != sense )
tmp_point_list.reverse();
//Now take off the last point as it is a duplicate with the
//other list...
tmp_point_list.reset();
delete tmp_point_list.pop();
(*new_point_loop_ptr) += tmp_point_list;
}
CubitVector curr, prev;
for ( jj = new_point_loop_ptr->size(); jj > 0; jj-- )
{
prev = new_point_loop_ptr->prev()->coordinates();
curr = new_point_loop_ptr->get_and_step()->coordinates();
if ( prev.about_equal(curr) )
{
PRINT_DEBUG_129("Points within tolerance in boundaryloop.\n");
new_point_loop_ptr->back();
delete new_point_loop_ptr->remove();
}
}
boundary_point_loops.append(new_point_loop_ptr);
}
return CUBIT_SUCCESS;
}
| CubitStatus Faceter::get_curve_facets | ( | RefEdge * | curve, |
| DLIList< CubitPoint * > & | segments | ||
| ) | const [private] |
Definition at line 569 of file Faceter.cpp.
{
//const double COS_ANGLE_TOL = 0.965925826289068312213715; // cos(15)
const double COS_ANGLE_TOL = 0.984807753012208020315654; // cos(10)
//const double COS_ANGLE_TOL = 0.996194698091745545198705; // cos(5)
GMem curve_graphics;
const double dist_tol = GEOMETRY_RESABS;
const double dist_tol_sqr = dist_tol*dist_tol;
Curve* curve_ptr = curve->get_curve_ptr();
curve_ptr->get_geometry_query_engine()->get_graphics( curve_ptr, &curve_graphics );
GPoint* gp = curve_graphics.point_list();
CubitPoint* last = (CubitPoint*) new FaceterPointData( gp->x, gp->y, gp->z );
((FaceterPointData*)last)->owner(dynamic_cast<RefEntity*>(curve));
CubitVector lastv = last->coordinates();
segments.append( last );
GPoint* end = gp + curve_graphics.pointListCount - 1;
for( gp++; gp < end; gp++ )
{
CubitVector pos( gp->x, gp->y, gp->z );
CubitVector step1 = (pos - lastv);
double len1 = step1.length();
if( len1 < dist_tol ) continue;
GPoint* np = gp + 1;
CubitVector next( np->x, np->y, np->z );
CubitVector step2 = next - pos;
double len2 = step2.length();
if( len2 < dist_tol ) continue;
double cosine = (step1 % step2) / (len1 * len2);
if( cosine > COS_ANGLE_TOL ) continue;
last = new FaceterPointData( pos );
((FaceterPointData*)last)->owner(dynamic_cast<RefEntity*>(curve));
segments.append( last );
lastv = last->coordinates();
}
CubitVector last_pos( gp->x, gp->y, gp->z );
segments.last();
while( (last_pos - (segments.get()->coordinates())).length_squared() < dist_tol_sqr )
{
delete segments.pop();
segments.last();
}
CubitPoint *tmp_point = (CubitPoint*) new FaceterPointData( last_pos );
segments.append( tmp_point );
((FaceterPointData*)tmp_point)->owner( dynamic_cast<RefEntity*>(curve) );
// Now check if the segment list is reversed wrt the curve direction.
segments.reset();
double u1, u2;
if( segments.size() > 2 )
{
u1 = curve->u_from_position( (segments.next(1)->coordinates()) );
u2 = curve->u_from_position( (segments.next(2)->coordinates()) );
}
else
{
u1 = curve->u_from_position( (segments.get()->coordinates() ) );
u2 = curve->u_from_position( (segments.next()->coordinates()) );
}
if( (u2 < u1) && (curve->start_param() <= curve->end_param()) )
segments.reverse();
//Make sure we don't have duplicate points.
int jj;
CubitVector curr, prev;
for ( jj = segments.size(); jj > 0; jj-- )
{
prev = segments.prev()->coordinates();
curr = segments.get_and_step()->coordinates();
if ( prev.about_equal(curr) )
{
PRINT_DEBUG_129("Points on curve %d within tolerance...\n", curve->id());
segments.back();
delete segments.remove();
}
}
return CUBIT_SUCCESS;
}
| CubitStatus Faceter::interior_angle | ( | DLIList< CubitPoint * > * | loop_ptr, |
| double & | my_angle | ||
| ) | [private] |
Definition at line 410 of file Faceter.cpp.
{
CubitVector point = loop_ptr->get()->coordinates();
CubitVector to_prev = loop_ptr->prev()->coordinates();
to_prev -= point;
CubitVector to_next = loop_ptr->next()->coordinates();
to_next -= point;
CubitVector surf_norm = thisRefFacePtr->normal_at ( point );
if ( surf_norm.length_squared() < CUBIT_RESABS )
{
//Try getting it at one of the other nodes...
surf_norm = thisRefFacePtr->normal_at(loop_ptr->next()->coordinates() );
if (surf_norm.length_squared() < CUBIT_RESABS )
{
//Try getting it at one of the other nodes...
surf_norm = thisRefFacePtr->normal_at(loop_ptr->prev()->coordinates() );
if (surf_norm.length_squared() < CUBIT_RESABS )
{
PRINT_ERROR("Trying to get normal at point %d on surf %d.\n"
" Normal length being returned equals zero.\n",
loop_ptr->get()->id(), thisRefFacePtr->id() );
return CUBIT_FAILURE;
}
}
}
double angle = surf_norm.vector_angle ( to_next, to_prev );
//Now if the angle is very small (zero) we don't know if this
//should be 0 or 2PI, so do some tests.
const double NEAR_ZERO = DEGREES_TO_RADIANS( 0.15 );
const double NEAR_360 = DEGREES_TO_RADIANS( 359.95 );
if( NEAR_ZERO < angle && angle < NEAR_360 )
{
my_angle = angle;
return CUBIT_SUCCESS;
}
//If we are close to zero or 2PI then take some other loop nodes
//into consideration to see if we can get a better approximation
//as to we are zero or 2 PI.
CubitPoint *prev_node = loop_ptr->prev();
CubitPoint *next_node = loop_ptr->next();
int stop_it = loop_ptr->size();
int count = 0;
while (( angle < NEAR_ZERO || angle > NEAR_360 ) && ( count < stop_it ) )
{
prev_node = loop_ptr->prev( count + 2 );
next_node = loop_ptr->next( count + 2 );
to_prev = prev_node->coordinates() - point;
to_next = next_node->coordinates() - point;
angle = surf_norm.vector_angle ( to_next, to_prev );
count++;
}
const double TWO_PI = 2.0 * CUBIT_PI;
if ( angle < NEAR_ZERO )
my_angle = TWO_PI;
else if( angle < CUBIT_PI )
my_angle = 0.0;
else
my_angle = TWO_PI;
return CUBIT_SUCCESS;
}
| void Faceter::max_min_edge_ratio | ( | DLIList< DLIList< CubitPoint * > * > & | boundary_point_loops, |
| double & | ratio, | ||
| double & | cell_size | ||
| ) | [private] |
Definition at line 472 of file Faceter.cpp.
{
double max_edge_length = CUBIT_DBL_MIN;
double min_edge_length = CUBIT_DBL_MAX;
double sum = 0.0;
int total_count = 0;
DLIList<CubitPoint*> *loopPtr;
CubitPoint *node1, *node2;
CubitVector edge;
for (int i = boundary_point_loops.size(); i > 0; i--) {
loopPtr = boundary_point_loops.get_and_step();
node2 = loopPtr->prev();
for (int j = loopPtr->size(); j > 0; j--) {
node1 = node2;
node2 = loopPtr->get_and_step();
CubitVector p1 = node1->coordinates();
CubitVector p2 = node2->coordinates();
edge = p2-p1;
double edge_length = edge.length_squared();
if (edge_length > max_edge_length) max_edge_length = edge_length;
if (edge_length < min_edge_length) min_edge_length = edge_length;
total_count++;
sum += edge_length;
}
}
if (min_edge_length > CUBIT_RESABS) {
ratio = sqrt(max_edge_length/min_edge_length);
}
else {
ratio = sqrt(max_edge_length);
}
if ( total_count > 0 && sum > 0 )
cell_size = sqrt(sum/total_count);
else
cell_size = 0.0;
}
CubitBoolean Faceter::avoidedOverlap [private] |
Definition at line 53 of file Faceter.hpp.
DLIList<CubitPoint*>* Faceter::globalPointList [private] |
Definition at line 54 of file Faceter.hpp.
const double Faceter::gridCellScale [private] |
Definition at line 52 of file Faceter.hpp.
PointGridSearch* Faceter::gridSearchPtr [private] |
Definition at line 51 of file Faceter.hpp.
RefFace* Faceter::thisRefFacePtr [private] |
Definition at line 50 of file Faceter.hpp.