//================================================================================== //Function: skin_2d (PUBLIC) //Description: creates a skin of the given mesh entities. //================================================================================== CubitStatus ChollaSkinTool::skin_2d(DLIList<FacetEntity*> &facet_list, ChollaSurface *&facet_surface_mesh_ptr) { if(facet_list.size() == 0){ return CUBIT_SUCCESS; } int debugflag=0; if (debugflag) { dcolor(CUBIT_YELLOW); dldraw( facet_list ); dview(); dcolor(CUBIT_RED); } CubitStatus rv = CUBIT_SUCCESS; int block_id; // create a ChollaSurface if we have to (only if this is a 2D model) FacetEntity *face_ptr = facet_list.get(); TDGeomFacet *td_gm = TDGeomFacet::get_geom_facet( face_ptr ); block_id = td_gm->get_block_id(); if (!facet_surface_mesh_ptr) { facet_surface_mesh_ptr = new ChollaSurface(block_id); // associate all of the tooldata on the faces of this surf with the new ChollaSurface int ii; for (ii=0; ii<facet_list.size(); ii++) { face_ptr = facet_list.get_and_step(); facet_surface_mesh_ptr->add_facet( face_ptr ); td_gm = TDGeomFacet::get_geom_facet( face_ptr ); td_gm->add_cholla_surf( facet_surface_mesh_ptr ); td_gm->set_hit_flag( facet_surface_mesh_ptr->get_id() ); } } // create a single ChollaCurve for this surface (assumes one loop of edges) ChollaCurve *fcm_ptr = new ChollaCurve( block_id ); facet_surface_mesh_ptr->add_curve( fcm_ptr ); fcm_ptr->add_surface( facet_surface_mesh_ptr ); // loop through all faces on this surface searching for the boundary edges int jj, kk, ll; for ( kk = 0; kk < facet_list.size(); kk++) { face_ptr = facet_list.get_and_step(); DLIList<CubitFacetEdge*> edge_list; face_ptr->edges( edge_list ); // loop through each edge on this face searching for boundary edges for (jj=edge_list.size(); jj > 0; jj--) { CubitFacetEdge *edge_ptr = edge_list.get_and_step(); // check if this edge has already been processed from an adjacent surface. // If it has, then tool data would have already been defined at this edge // and by definition would be at the boundary (only tooldatas on edges // at the boundary ofa surface are created) TDGeomFacet *td_gm_edge = TDGeomFacet::get_geom_facet(edge_ptr); int on_boundary = 0; if (td_gm_edge != NULL) { on_boundary = 1; // check for internal C-zero edge if (edge_ptr->num_adj_facets() == 2) { TDFacetBoundaryEdge *td_fbe = TDFacetBoundaryEdge::get_facet_boundary_edge( edge_ptr ); if (td_fbe != NULL) { if (td_fbe->is_internal_edge()) { on_boundary = 0; } } } } // check for general case where no tool data yet defined else { DLIList<FacetEntity*> adj_face_list; // check the adjacent faces to this edge. If only one adjacent face, then // it is on the boundary. If more than one face, then the other face(s) // must be associated with a surface other than facet_surface_mesh_ptr // in order to be on the boundary edge_ptr->get_parents( adj_face_list ); if (adj_face_list.size() <= 1) { on_boundary = 1; } else { for (ll=adj_face_list.size(); ll> 0 && !on_boundary; ll--) { FacetEntity *adj_face_ptr = adj_face_list.get_and_step(); if (adj_face_ptr != face_ptr) { TDGeomFacet *td_gm_adjface = TDGeomFacet::get_geom_facet(adj_face_ptr); DLIList<ChollaSurface*> surf_list; td_gm_adjface->get_cholla_surfs( surf_list ); // if it doesn't have an associated surface yet, then it is // a neighboring surface that has not been defined yet (this // should only occur for the 2D case) if (surf_list.size() == 0) { on_boundary = 1; } else { // there should only be one surface associated with // each face - otherwise we've screwed up somewhere assert ( surf_list.size() == 1 ); // if the surface is not the same as the current surface // then we are at the boundary ChollaSurface *check_bsm_ptr = surf_list.get(); if (facet_surface_mesh_ptr != check_bsm_ptr) { on_boundary = 1; } } } } } } if (on_boundary) { // create a tool data if needed if (td_gm_edge == NULL) { TDGeomFacet::add_geom_facet(edge_ptr, -1); td_gm_edge = TDGeomFacet::get_geom_facet( edge_ptr ); edge_ptr->set_as_feature(); } // add the pointer to this surface onto the edge tool data td_gm_edge->add_cholla_surf( facet_surface_mesh_ptr ); // add this edge to the curve fcm_ptr->add_facet( edge_ptr ); if (mydebug) dedraw(edge_ptr); } } } return rv; }
CubitStatus ChollaCurve::order_edges() { int i; bool periodic = false; if (NULL == startPoint) { DLIList<ChollaPoint *> cholla_points = get_points(); periodic = (cholla_points.size() == 1); ChollaPoint *chpt = cholla_points.get(); CubitPoint *start_point = dynamic_cast<CubitPoint *> (chpt->get_facets()); this->set_start( start_point ); if (NULL == start_point) return CUBIT_FAILURE; start_point->set_as_feature(); if (periodic) { this->set_end(start_point); } else { chpt = cholla_points.step_and_get(); CubitPoint *end_point = dynamic_cast<CubitPoint *> (chpt->get_facets()); if (NULL == end_point) return CUBIT_FAILURE; this->set_end(end_point); end_point->set_as_feature(); } } assert(startPoint); assert(endPoint); if (curveEdgeList.size() > 1) { DLIList<CubitFacetEdge*> edges_ordered; CAST_LIST(curveEdgeList, edges_ordered, CubitFacetEdge); CubitStatus stat = CubitFacetEdge::order_edge_list(edges_ordered, startPoint, endPoint); if (CUBIT_FAILURE == stat) return CUBIT_FAILURE; // store the edges in the correct order clean_out_edges(); edges_ordered.reset(); for (i=0; i< edges_ordered.size(); i++) { this->add_facet(edges_ordered.get_and_step()); } } // make sure all the edges are oriented correctly DLIList<FacetEntity *> flist = this->get_facet_list(); flist.reset(); DLIList<CubitFacetEdge *> elist; CAST_LIST( flist, elist, CubitFacetEdge ); elist.reset(); CubitPoint *cur_pt = startPoint, *tmp_pt; for ( i = elist.size(); i > 0; i-- ) { CubitFacetEdge *edge_ptr = elist.get_and_step(); CubitPoint *point0_ptr = edge_ptr->point(0); CubitPoint *point1_ptr = edge_ptr->point(1); if (point0_ptr != cur_pt) { assert( cur_pt == point1_ptr ); edge_ptr->flip(); tmp_pt = point0_ptr; point0_ptr = point1_ptr; point1_ptr = tmp_pt; assert( point0_ptr == edge_ptr->point(0) && point1_ptr == edge_ptr->point(1) ); } cur_pt = point1_ptr; } int mydebug = 0; if (mydebug) { int i; DLIList<FacetEntity *> flist = this->get_facet_list(); flist.reset(); DLIList<CubitFacetEdge *> elist; CAST_LIST( flist, elist, CubitFacetEdge ); elist.reset(); for ( i = elist.size(); i > 0; i-- ) { CubitFacetEdge *edge = elist.get_and_step(); CubitVector pt0_v = edge->point(0)->coordinates(); CubitVector pt1_v = edge->point(1)->coordinates(); GfxDebug::draw_point(pt0_v, CUBIT_GREEN ); GfxDebug::draw_point(pt1_v, CUBIT_RED ); GfxDebug::draw_line( pt0_v, pt1_v, CUBIT_YELLOW ); GfxDebug::flush(); int view = 0; if (view) dview(); } } return CUBIT_SUCCESS; }
/* Derivation from the fortran version of CONREC by Paul Bourke view ! view of the data ilb,iub ! bounds for first coordinate (column), inclusive jlb,jub ! bounds for second coordinate (row), inclusive xCoords ! column coordinates (first index) yCoords ! row coordinates (second index) nc ! number of contour levels z ! contour levels in increasing order */ static Carta::Lib::Algorithms::ContourConrec::Result conrecFaster( Carta::Lib::NdArray::RawViewInterface * view, int ilb, int iub, int jlb, int jub, const VD & xCoords, const VD & yCoords, int nc, double * z ) { // we will only need two rows in memory at any given time // int nRows = jub - jlb + 1; int nCols = iub - ilb + 1; double * rows[2] { nullptr, nullptr }; std::vector < double > row1( nCols ), row2( nCols ); rows[0] = & row1[0]; rows[1] = & row2[0]; int nextRowToReadIn = 0; auto updateRows = [&] () -> void { CARTA_ASSERT( nextRowToReadIn < view-> dims()[1] ); // make a row view into the view SliceND rowSlice; rowSlice.next().start( nextRowToReadIn ).end( nextRowToReadIn + 1 ); auto rawRowView = view-> getView( rowSlice ); nextRowToReadIn++; // make a double view of this raw row view Carta::Lib::NdArray::Double dview( rawRowView, true ); // shift the row up // note: we could avoid this memory copy if we swapped row[] pointers instead, // and alternately read in the data into row1,row2..., for a miniscule performance // gain and lot more complicated algorithm row1 = row2; // read in the data into row2 int i = 0; dview.forEach([&] ( const double & val ) { row2[i++] = val; } ); CARTA_ASSERT( i == nCols ); }; updateRows(); // NdArray::Double doubleView( view, false ); // auto acc = [& doubleView] ( int col, int row ) { // return doubleView.get( { col, row } // ); // }; // to keep the data accessor easy, we use this lambda, and hope the compiler // optimizes it into an inline expression... :) auto acc = [&] ( int col, int row ) { row -= nextRowToReadIn - 2; return rows[row][col]; }; Carta::Lib::Algorithms::ContourConrec::Result result; if ( nc < 1 ) { return result; } result.resize( nc ); #define xsect( p1, p2 ) ( h[p2] * xh[p1] - h[p1] * xh[p2] ) / ( h[p2] - h[p1] ) #define ysect( p1, p2 ) ( h[p2] * yh[p1] - h[p1] * yh[p2] ) / ( h[p2] - h[p1] ) int m1, m2, m3, case_value; double dmin, dmax, x1 = 0, x2 = 0, y1 = 0, y2 = 0; int i, j, k, m; double h[5]; int sh[5]; double xh[5], yh[5]; int im[4] = { 0, 1, 1, 0 }, jm[4] = { 0, 0, 1, 1 }; int castab[3][3][3] = { { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } }, { { 0, 3, 4 }, { 1, 3, 1 }, { 4, 3, 0 } }, { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } } }; double temp1, temp2; // original code went from bottom to top, not sure why // for ( j = ( jub - 1 ) ; j >= jlb ; j-- ) { for ( j = jlb ; j < jub ; j++ ) { updateRows(); for ( i = ilb ; i < iub ; i++ ) { temp1 = std::min( acc( i, j ), acc( i, j + 1 ) ); temp2 = std::min( acc( i + 1, j ), acc( i + 1, j + 1 ) ); dmin = std::min( temp1, temp2 ); // early abort if one of the values is not finite if ( ! std::isfinite( dmin ) ) { continue; } temp1 = std::max( acc( i, j ), acc( i, j + 1 ) ); temp2 = std::max( acc( i + 1, j ), acc( i + 1, j + 1 ) ); dmax = std::max( temp1, temp2 ); if ( dmax < z[0] || dmin > z[nc - 1] ) { continue; } for ( k = 0 ; k < nc ; k++ ) { if ( z[k] < dmin || z[k] > dmax ) { continue; } for ( m = 4 ; m >= 0 ; m-- ) { if ( m > 0 ) { h[m] = acc( i + im[m - 1], j + jm[m - 1] ) - z[k]; xh[m] = xCoords[i + im[m - 1]]; yh[m] = yCoords[j + jm[m - 1]]; } else { h[0] = 0.25 * ( h[1] + h[2] + h[3] + h[4] ); xh[0] = 0.50 * ( xCoords[i] + xCoords[i + 1] ); yh[0] = 0.50 * ( yCoords[j] + yCoords[j + 1] ); } if ( h[m] > 0.0 ) { sh[m] = 1; } else if ( h[m] < 0.0 ) { sh[m] = - 1; } else { sh[m] = 0; } } /* Note: at this stage the relative heights of the corners and the centre are in the h array, and the corresponding coordinates are in the xh and yh arrays. The centre of the box is indexed by 0 and the 4 corners by 1 to 4 as shown below. Each triangle is then indexed by the parameter m, and the 3 vertices of each triangle are indexed by parameters m1,m2,and m3. It is assumed that the centre of the box is always vertex 2 though this isimportant only when all 3 vertices lie exactly on the same contour level, in which case only the side of the box is drawn. vertex 4 +-------------------+ vertex 3 | \ / | | \ m-3 / | | \ / | | \ / | | m=2 X m=2 | the centre is vertex 0 | / \ | | / \ | | / m=1 \ | | / \ | vertex 1 +-------------------+ vertex 2 */ /* Scan each triangle in the box */ for ( m = 1 ; m <= 4 ; m++ ) { m1 = m; m2 = 0; if ( m != 4 ) { m3 = m + 1; } else { m3 = 1; } if ( ( case_value = castab[sh[m1] + 1][sh[m2] + 1][sh[m3] + 1] ) == 0 ) { continue; } switch ( case_value ) { case 1 : /* Line between vertices 1 and 2 */ x1 = xh[m1]; y1 = yh[m1]; x2 = xh[m2]; y2 = yh[m2]; break; case 2 : /* Line between vertices 2 and 3 */ x1 = xh[m2]; y1 = yh[m2]; x2 = xh[m3]; y2 = yh[m3]; break; case 3 : /* Line between vertices 3 and 1 */ x1 = xh[m3]; y1 = yh[m3]; x2 = xh[m1]; y2 = yh[m1]; break; case 4 : /* Line between vertex 1 and side 2-3 */ x1 = xh[m1]; y1 = yh[m1]; x2 = xsect( m2, m3 ); y2 = ysect( m2, m3 ); break; case 5 : /* Line between vertex 2 and side 3-1 */ x1 = xh[m2]; y1 = yh[m2]; x2 = xsect( m3, m1 ); y2 = ysect( m3, m1 ); break; case 6 : /* Line between vertex 3 and side 1-2 */ x1 = xh[m3]; y1 = yh[m3]; x2 = xsect( m1, m2 ); y2 = ysect( m1, m2 ); break; case 7 : /* Line between sides 1-2 and 2-3 */ x1 = xsect( m1, m2 ); y1 = ysect( m1, m2 ); x2 = xsect( m2, m3 ); y2 = ysect( m2, m3 ); break; case 8 : /* Line between sides 2-3 and 3-1 */ x1 = xsect( m2, m3 ); y1 = ysect( m2, m3 ); x2 = xsect( m3, m1 ); y2 = ysect( m3, m1 ); break; case 9 : /* Line between sides 3-1 and 1-2 */ x1 = xsect( m3, m1 ); y1 = ysect( m3, m1 ); x2 = xsect( m1, m2 ); y2 = ysect( m1, m2 ); break; default : break; } // switch // add the line segment to the result // ConrecLine( x1, y1, x2, y2, k ); if ( std::isfinite( x1 ) && std::isfinite( y1 ) && std::isfinite( x2 ) && std::isfinite( y2 ) ) { QPolygonF poly; poly.append( QPointF( x1, y1 ) ); poly.append( QPointF( x2, y2 ) ); result[k].push_back( poly ); } } /* m */ } /* k - contour */ } /* i */ } /* j */ return result; #undef xsect #undef ysect } // conrecFaster
//============================================================================= //Function: build_curve_from_edges //Description: insert the ordered and oriented edges into this cholla curve //Notes: traverses starting at start_point and gathers facet edges until it // runs into another curve. // start_point is an existing CubitPoint at either end of the curve // max_edges is the maximum number of edges on this curve. should be // known beforehand (used for error checking). // // ***this function used to be part of split_curve. *** //Author: sjowen //Return: //Date: 09/07/2009 //============================================================================= CubitStatus ChollaCurve::build_curve_from_edges( CubitPoint *start_point, int periodic, int max_edges, CubitFacetEdge *start_edge_ptr, ChollaCurve *parent_curve ) { // find the first edge. Match the chollacurve owner with this curve // do this only if the start_edge_ptr was not passed in DLIList<CubitFacetEdge *> point_edge_list; start_point->edges(point_edge_list); CubitFacetEdge *edge_ptr; if (start_edge_ptr == NULL) { for (int ii=0; ii<point_edge_list.size() && !start_edge_ptr; ii++) { edge_ptr = point_edge_list.get_and_step(); TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( edge_ptr ); // assumes that the TDGeomFacet info has already been set up for the edges assert(td_geom != NULL); DLIList<ChollaCurve *> cholla_curves; td_geom->get_cholla_curves(cholla_curves); // currently should be only one-to-one relationship // could also be edge on surface in which case no curves associated assert(cholla_curves.size() <= 1); if (cholla_curves.size()) { if (cholla_curves.get() == this) start_edge_ptr = edge_ptr; } } assert(start_edge_ptr != NULL); // didn't find an edge that marched this chollacurve } // create a new curve to hold the edge info this->set_start( start_point ); start_point->set_as_feature(); this->add_facet( start_edge_ptr ); int iedgecount = 0; edge_ptr = start_edge_ptr; CubitPoint *point0_ptr = start_point, *point1_ptr; CubitPoint *end_point = NULL; while(!end_point) { point1_ptr = edge_ptr->other_point( point0_ptr ); if ((edge_ptr = parent_curve->next_edge( point1_ptr, edge_ptr )) == NULL) { end_point = point1_ptr; } else { iedgecount++; if (iedgecount > max_edges) { PRINT_ERROR("ChollaCurve has start, but no end\n"); return CUBIT_FAILURE; } this->add_facet( edge_ptr ); if (periodic && point1_ptr == start_point) end_point = start_point; point0_ptr = point1_ptr; } } this->set_end( end_point ); end_point->set_as_feature(); // make sure all the edges are oriented correctly int i; DLIList<FacetEntity *> flist = this->get_facet_list(); flist.reset(); DLIList<CubitFacetEdge *> elist; CAST_LIST( flist, elist, CubitFacetEdge ); elist.reset(); CubitPoint *cur_pt = start_point, *tmp_pt; for ( i = elist.size(); i > 0; i-- ) { edge_ptr = elist.get_and_step(); point0_ptr = edge_ptr->point(0); point1_ptr = edge_ptr->point(1); if (point0_ptr != cur_pt) { assert( cur_pt == point1_ptr ); edge_ptr->flip(); tmp_pt = point0_ptr; point0_ptr = point1_ptr; point1_ptr = tmp_pt; assert( point0_ptr == edge_ptr->point(0) && point1_ptr == edge_ptr->point(1) ); } cur_pt = point1_ptr; } int mydebug = 0; if (mydebug) { int i; DLIList<FacetEntity *> flist = this->get_facet_list(); flist.reset(); DLIList<CubitFacetEdge *> elist; CAST_LIST( flist, elist, CubitFacetEdge ); elist.reset(); for ( i = elist.size(); i > 0; i-- ) { CubitFacetEdge *edge = elist.get_and_step(); CubitVector pt0_v = edge->point(0)->coordinates(); CubitVector pt1_v = edge->point(1)->coordinates(); GfxDebug::draw_point(pt0_v, CUBIT_GREEN ); GfxDebug::draw_point(pt1_v, CUBIT_RED ); GfxDebug::draw_line( pt0_v, pt1_v, CUBIT_YELLOW ); GfxDebug::flush(); int view = 0; if (view) dview(); } } return CUBIT_SUCCESS; }