/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] [1] Source File of the Transportation Mode Algebra May, 2010 Jianqiu Xu [TOC] 1 Overview This source file essentially contains the necessary implementations of doing triangulation for polygon with and without holes. The original implementation is from Atul Narkhede and Dinesh Manocha [TOC] 1 Overview 2 Defines and includes */ #include "Triangulate.h" using namespace Copied_from_Algebra_TransportationMode; using namespace std; namespace Copied_from_Algebra_TransportationMode { ////////////////////////////////////////////////////////////////////////////// /////////// another implementation of triangulation ///////////////////////// /////////// 2011.7 from code project///////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// Dimension GlobDim::mDim = DIM_NONE; /* initialize the polygon, input points */ /* void HPolygon::Init( const char name[]) { int n, ni; double x, y; FILE *f = fopen( name, "rt"); if (!f) THROW_FILE( "can not open file", name); printf( "Reading file: %s\n", name ); fscanf( f, "%d", &n); mtabSize.resize( n); for ( int i=0; i& vertices_x, vector& vertices_y) { int n = ncontours; mtabSize.resize(n); int point_id = 1; int count = 0; for ( int i = 0; i< n; i++){ int ni = cntr[i]; mtabSize[i] = ni; // cout<<"ni "<::iterator itri; IterGCell itr; for ( itr = grid.CellBegin(); itr != grid.CellEnd(); ++itr) { itri = mtabCell.insert( mtabCell.end(), HTri() ); (*itri).rIndex( 0) = (*(*itr)->Node( 0))->Index(); (*itri).rIndex( 1) = (*(*itr)->Node( 1))->Index(); (*itri).rIndex( 2) = (*(*itr)->Node( 2))->Index(); } } /* new form of triangulation */ /* int HPolygon::Triangulation2(int ncontours, int cntr[], vector& vertices_x, vector& vertices_y) { //try // { // HPolygon poly; // if ( argc != 3 ){ // printf("usage: hgrd [input file with points] // [output tecplot file]\n"); // return 1; // } // poly.Init( argv[1]); // poly.Triangulate(); // poly.WriteTEC( argv[2]); // } // catch ( Except *pe) // { // ASSERT( pe); // TRACE_EXCEPTION( *pe); // TRACE_TO_STDERR( *pe); // delete pe; // } // for(unsigned int i = 0;i < vertices_x.size();i++){ // cout< ZERO ); t1 = vv * vv1 / vv.module(); t2 = vv * vv2 / vv.module(); h1 = (vv.X()*vv1.Y() - vv.Y()*vv1.X()) / vv.module(); h2 = (vv.X()*vv2.Y() - vv.Y()*vv2.X()) / vv.module(); if ( fabs( h2 - h1) < ZERO) return false; t = t1 - (t2 - t1)/(h2 - h1) * h1; if ( t > 0.0 && t < vv.module() && h1 * h2 < ZERO ) return true; else return false; } bool AreNeigbours( const IterGCell& ic1, const IterGCell& ic2) { char sbuf[256]; bool b1, b2; // TRACE2( "itrcl = %d %d", ic1, *ic1); // (*ic1)->DumpTri(); // TRACE2( "itrcl = %d %d", ic2, *ic2); // (*ic2)->DumpTri(); b1 = b2 = false; for ( int i=0; iCell(i) != NULL) if ( (*ic1)->Cell(i) == ic2 ) b1 = true; // if ( (*ic2)->Cell(i) != NULL) if ( (*ic2)->Cell(i) == ic1 ) b2 = true; } sprintf( sbuf, " b1 = %d b2 = %d", static_cast(b1), static_cast(b2) ); TM_TRACE( sbuf); if ( !b1 || !b2) THROW_INTERNAL( "Not neighbours found"); return true; } /* class HGrdTri main class for triangulation, grid */ HGrdTri::HGrdTri() : mbIsOutside( false) { for ( MGInt i=0; i ZERO && d1 < -ZERO) ) return false; else return true; } bool HGrdTri::IsVisibleDump( const IterGCell& icl, const Vect2D& vct) { // static Vect2D vfac, v1, v2; // static MGFloat d1, d2; // static char sbuf[1024]; Vect2D vfac, v1, v2; MGFloat d1, d2; THROW_INTERNAL("Should not be used !!!"); if ( Cell(0) == icl ) { v1 = *( (*Node(0)) ) - *( (*Node(2)) ); v2 = *( (*Node(1)) ) - *( (*Node(2)) ); vfac = vct - *( (*Node(2)) ); } else if ( Cell(1) == icl ) { v1 = *( (*Node(1)) ) - *( (*Node(0)) ); v2 = *( (*Node(2)) ) - *( (*Node(0)) ); vfac = vct - *( (*Node(0)) ); } else if ( Cell(2) == icl ) { v1 = *( (*Node(2)) ) - *( (*Node(1)) ); v2 = *( (*Node(0)) ) - *( (*Node(1)) ); vfac = vct - *( (*Node(1)) ); } else { ASSERT( 0); } d1 = v1.X()*vfac.Y() - v1.Y()*vfac.X(); d2 = v2.X()*vfac.Y() - v2.Y()*vfac.X(); if ( d1 * d2 > ZERO ) { TM_TRACE2( "v1 = (%lg %lg)", v1.X(), v1.Y() ); TM_TRACE2( "v2 = (%lg %lg)", v2.X(), v2.Y() ); TM_TRACE2( "vf = (%lg %lg)", vfac.X(), vfac.Y() ); TM_TRACE2( "d1 = %lg d1 = %lg", d1, d2 ); return false; } else return true; } /* for a grid, set its neighbors */ void HGrdTri::SetNeighbour( const IterGCell& itrcl) { static HGrdTri *ptr; // ASSERT( itrcl != NULL); ASSERT( itrcl != (IterGCell)NULL); ptr = (*itrcl); ASSERT( ptr); if ( ( ptr->Node(1) == Node(0) && ptr->Node(0) == Node(1) ) || ( ptr->Node(0) == Node(0) && ptr->Node(2) == Node(1) ) || ( ptr->Node(2) == Node(0) && ptr->Node(1) == Node(1) ) ) { rCell(0) = itrcl; } else if ( ( ptr->Node(1) == Node(1) && ptr->Node(0) == Node(2) ) || ( ptr->Node(0) == Node(1) && ptr->Node(2) == Node(2) ) || ( ptr->Node(2) == Node(1) && ptr->Node(1) == Node(2) ) ) { rCell(1) = itrcl; } else if ( ( ptr->Node(1) == Node(2) && ptr->Node(0) == Node(0) ) || ( ptr->Node(0) == Node(2) && ptr->Node(2) == Node(0) ) || ( ptr->Node(2) == Node(2) && ptr->Node(1) == Node(0) ) ) { rCell(2) = itrcl; } } void HGrdTri::NullifyThis( HGrdTri *pcl) { for ( MGInt i=0; iPntLf() == Node(0) && pseg->PntLf() == Node(1) ) || ( pseg->PntRt() == Node(0) && pseg->PntRt() == Node(1) ) ) { // rCell(0) = NULL; rCell(0) = (IterGCell)NULL; } else if ( ( pseg->PntLf() == Node(1) && pseg->PntLf() == Node(2) ) || ( pseg->PntRt() == Node(1) && pseg->PntRt() == Node(2) ) ) { // rCell(1) = NULL; rCell(1) = (IterGCell)NULL; } else if ( ( pseg->PntLf() == Node(2) && pseg->PntLf() == Node(0) ) || ( pseg->PntRt() == Node(2) && pseg->PntRt() == Node(0) ) ) { // rCell(2) = NULL; rCell(2) = (IterGCell)NULL; } } void HGrdTri::InvalidateNeighb() { for ( MGInt i=0; iNullifyThis( this); } } bool HGrdTri::IsInside( const Vect2D& vct) { // ::TODO:: new and faster algorithm should be introduced MGFloat alf; alf = ::Angle( vct, *(*Node(0)), *(*Node(1)) ); alf += ::Angle( vct, *(*Node(1)), *(*Node(2)) ); alf += ::Angle( vct, *(*Node(2)), *(*Node(0)) ); if ( fabs(alf) < M_PI ) return false; else return true; } /* set the center point of a triangle */ bool HGrdTri::SetCircCenter() { static MGFloat x1, y1, x2, y2, x3, y3; static MGFloat xr, yr, d; x1 = (*Node(0))->X(); y1 = (*Node(0))->Y(); x2 = (*Node(1))->X(); y2 = (*Node(1))->Y(); x3 = (*Node(2))->X(); y3 = (*Node(2))->Y(); d = y3*(x2 - x1) + y2*(x1 - x3) + y1*(x3 - x2); if ( fabs( d) < ZERO) { //guenther: xr = 0.5*(min(x3,min(x1,x2)) + max(x3,min(x1,x2))); yr = 0.5*(min(y3,min(y1,y2)) + max(y3,min(y1,y2))); mCircCenter = Vect2D( xr, yr); return false; DumpTri(); // TM_TRACE1( "d = %lg", d); printf("%.6f\n", d); printf("(%.7f %.7f)\n", x1, y1); printf("(%.7f %.7f)\n", x2, y2); printf("(%.7f %.7f)\n", x3, y3); // cout<<"SetCircCenter() "<<"error "<PntLf())); v2 = *(*(pseg->PntRt())); // if ( iclprv == NULL) if ( iclprv == (IterGCell)NULL){ if ( Node(0) == pseg->PntLf() ) { v3 = *(*Node(1)); v4 = *(*Node(2)); itrnb = Cell(1); if ( Node(1) == pseg->PntRt() || Node(2) == pseg->PntRt() ) // return NULL; return (IterGCell)NULL; } else if ( Node(1) == pseg->PntLf() ) { v3 = *(*Node(2)); v4 = *(*Node(0)); itrnb = Cell(2); if ( Node(2) == pseg->PntRt() || Node(0) == pseg->PntRt() ) // return NULL; return (IterGCell)NULL; } else if ( Node(2) == pseg->PntLf() ) { v3 = *(*Node(0)); v4 = *(*Node(1)); itrnb = Cell(0); if ( Node(0) == pseg->PntRt() || Node(1) == pseg->PntRt() ) // return NULL; return (IterGCell)NULL; } else { THROW_INTERNAL("NextCell - seg: node not found"); } if ( ::CheckCrossing( v1, v2, v3, v4 ) == true) { return itrnb; } else // return NULL; return (IterGCell)NULL; } else { int k; for ( int i=0; iPntLf(); ipnt2 = (*itr)->PntRt(); alf += ::Angle( vct, *(*ipnt1), *(*ipnt2) ); } return alf; } /* class HGrid */ HGrid::~HGrid() { CollGPnt::iterator itrpnt; CollGCell::iterator itrcell; for ( itrpnt = mcolPnt.begin(); itrpnt != mcolPnt.end(); itrpnt++) if ( (*itrpnt) != NULL) delete (*itrpnt); for ( itrcell = mcolCell.begin(); itrcell != mcolCell.end(); itrcell++) if ( (*itrcell) != NULL) delete (*itrcell); } void HGrid::Init( const vector& tabp, const vector& tabn ) { MGInt i, j, nprev; IterFro ifro; HGrdPnt *ppnt; IterGPnt ip0, ipp, ipa; HFroSeg *pfro; Vect2D v0, v1, v2; map< Vect2D, IterGPnt> mapNod; map< Vect2D, IterGPnt>::iterator imap; // char sbuf[512]; //double d; nprev = 0; for ( i=0; i<(MGInt)tabn.size(); ++i) { v1 = tabp[nprev]; v2 = tabp[nprev+tabn[i]-1]; // d = (v2-v1).module(); if ( (v2-v1).module() < ZERO) { ifro = mcolFro.insert( mcolFro.end(), HFront() ); imap = mapNod.find( tabp[nprev]); if ( imap != mapNod.end() ) { ip0 = ipp = ipa = (*imap).second; } else { ppnt = MGNEW HGrdPnt( tabp[nprev]); ppnt->rIndex() = nprev; ip0 = ipp = ipa = InsertPoint( ppnt); mapNod.insert( map< Vect2D, IterGPnt>::value_type( *ppnt, ipa)); } v0 = *(*ip0); for ( j=1; j ZERO) { if ( j != tabn[i]-1 || (tabp[nprev+j] - v0 ).module() > ZERO) { imap = mapNod.find( tabp[nprev+j]); if ( imap != mapNod.end() ) { ipa = (*imap).second; ppnt = *ipa; } else { ppnt = MGNEW HGrdPnt( tabp[nprev+j]); ppnt->rIndex() = nprev+j; ipa = InsertPoint( ppnt); mapNod.insert( map< Vect2D, IterGPnt>::value_type( *ppnt, ipa) ); } pfro = MGNEW HFroSeg( ipp, ipa); (*ifro).insert( (*ifro).end(), pfro); ipp = ipa; } } } v1 = *(*ipp); v2 = *(*ip0); if ( (v2 - v1).module() > ZERO) { pfro = MGNEW HFroSeg( ipp, ip0); (*ifro).insert( (*ifro).end(), pfro); } } nprev += tabn[i]; } IterFro itrfro; IterFSeg itrsg; IterGPnt ip1, ip2; for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); ++itrfro) { // TRACE1( "Front size = %d\n", (*itrfro).size() ); itrsg = (*itrfro).begin(); ip0 = (*itrsg)->PntLf(); ip1 = (*itrsg)->PntRt(); for ( ++itrsg; itrsg != (*itrfro).end(); ++itrsg) { if ( (*itrsg)->PntLf() != ip1 ) { TM_TRACE( "Front not consistent !!!\n"); } ip1 = (*itrsg)->PntRt(); v1 = *(*(*itrsg)->PntLf()); v2 = *(*(*itrsg)->PntRt()); if ( (v2 - v1).module() < ZERO) TM_TRACE1( "seg length = %24.16lg\n", (v2 - v1).module() ); } if ( ip0 != ip1 ) { TM_TRACE( "Front not consistent (closure problem) !!!\n"); } } // ASSERT(0); #ifdef _DEBUG FILE *f = fopen( "front.plt", "wt"); int isize = 0; for ( isize = 0, itrfro = mcolFro.begin(); itrfro != mcolFro.end(); ++itrfro, ++isize) { fprintf( f, "VARIABLES = \"X\", \"Y\"\n" ); fprintf( f, "ZONE I=%d F=POINT\n", (*itrfro).size()+1); for ( itrsg = (*itrfro).begin(); itrsg != (*itrfro).end(); ++itrsg) { v1 = *(*(*itrsg)->PntLf()); v2 = *(*(*itrsg)->PntRt()); fprintf( f, "%lg %lg\n", v1.X(), v1.Y() ); } fprintf( f, "%lg %lg\n", v2.X(), v2.Y() ); } fclose( f); #endif // _DEBUG } HFroSeg* HGrid::NewFace( MGInt i, IterGCell icl) { HFroSeg* psg; THROW_ALLOC( psg = MGNEW HFroSeg() ); switch ( i) { case 0: psg->rPntLf() = (*icl)->Node(0); psg->rPntRt() = (*icl)->Node(1); // if ( icl != NULL ){ if ( icl != (IterGCell)NULL ){ psg->rCellUp() = icl; psg->rCellLo() = (*icl)->Cell(0); } break; case 1: psg->rPntLf() = (*icl)->Node(1); psg->rPntRt() = (*icl)->Node(2); // if ( icl != NULL) if ( icl != (IterGCell)NULL){ psg->rCellUp() = icl; psg->rCellLo() = (*icl)->Cell(1); } break; case 2: psg->rPntLf() = (*icl)->Node(2); psg->rPntRt() = (*icl)->Node(0); // if ( icl != NULL) if ( icl != (IterGCell)NULL){ psg->rCellUp() = icl; psg->rCellLo() = (*icl)->Cell(2); } break; default: if ( psg) delete psg; ASSERT( 0); return NULL; }; return psg; } /* check neighbor */ bool HGrid::CheckNeighb( IterGCell icl, CollFSeg& lstsg, const Vect2D& vct, const IterGCell& ipvcl) { HGrdTri *pthis; pthis = (HGrdTri*)( (*icl) ); if ( pthis->IsInsideCirc( vct ) == true ) { HGrdTri *ptri; HFroSeg *pseg; IterGCell itri; IterGPnt ipnt; bool bVis; for ( int i=0; iCell(i) != ipvcl || ipvcl == NULL) if ( (*icl)->Cell(i) != ipvcl || ipvcl == (IterGCell)NULL){ pseg = NewFace( i, icl); // this allocate memory for pseg !!! itri = (*icl)->Cell(i); bVis = false; // if ( itri != NULL ) if ( itri != (IterGCell)NULL ) if ( (*itri)->IsOutside() == true) // itri = NULL; itri = (IterGCell)NULL; // if ( itri != NULL) if ( itri != (IterGCell)NULL){ ptri = (HGrdTri*)( (*itri) ); ASSERT( ptri); bVis = ptri->IsVisible( icl, vct); } // if ( itri != NULL && bVis) if ( itri != (IterGCell)NULL && bVis){ if ( CheckNeighb( itri, lstsg, vct, icl ) == true ) { delete pseg; } else { lstsg.insert( lstsg.end(), pseg ); // pseg->rCellUp() = NULL; pseg->rCellUp() = (IterGCell)NULL; } } else { lstsg.insert( lstsg.end(), pseg ); // pseg->rCellUp() = NULL; pseg->rCellUp() = (IterGCell)NULL; } } } ptri = (HGrdTri*)( (*icl) ); ptri->InvalidateNeighb(); mcolCell.erase( icl); delete ptri; return true; } return false; } MGInt HGrid::InsertPointIntoMesh( IterGPnt pntitr) { Vect2D vct; IterGCell itrcl, itrcl2, itrcl0, itrclout; HGrdTri *ptri; CollFSeg *plstsg; IterFSeg itrsg, itrsg2; HFroSeg *pseg; static int num = 0; ++num; vct = *(*pntitr); // sprintf( sbuf, "POINT No = %d; x=%14.8lg, y=%14.8lg", num, vct.X(), vct.Y()); // TRACE1( "%s", sbuf); itrcl = mcolCell.begin(); do { itrcl0 = (*itrcl)->NextCell( vct); // if ( itrcl0 == NULL) if ( itrcl0 == (IterGCell)NULL) break; itrcl = itrcl0; } while ( true); THROW_ALLOC( plstsg = MGNEW CollFSeg ); // next function creates segments bounding Delaunay cavity (stored in plstsg) // removes cavity triangles from mcolCell; // ALL ITERATORS TO THOSE CELLS ARE THEN INVALID !!! // iterators to those cells are set to NULL // CheckNeighb( itrcl, *plstsg, vct, NULL); CheckNeighb( itrcl, *plstsg, vct, (IterGCell)NULL); // sorting segments stored in plstsg itrsg = plstsg->end(); itrsg--; do { for ( itrsg2 = plstsg->begin(); itrsg2 != plstsg->end(); itrsg2++) { if ( (*itrsg)->PntLf() == (*itrsg2)->PntRt() ) { pseg = (*itrsg2); plstsg->erase( itrsg2); itrsg = plstsg->insert( itrsg, pseg ); break; } } } while ( itrsg != plstsg->begin() ); // creating new triangles and connections between triangles in Delaunay cavity // itrcl0 = itrcl2 = NULL; itrcl0 = itrcl2 = (IterGCell)NULL; for ( itrsg = plstsg->begin(); itrsg != plstsg->end(); itrsg++) { THROW_ALLOC( ptri = MGNEW HGrdTri ); itrclout = (*itrsg)->CellLo(); ptri->rNode(0) = (*itrsg)->PntLf(); ptri->rNode(1) = (*itrsg)->PntRt(); ptri->rNode(2) = pntitr; ptri->rCell(0) = itrclout; if ( ptri->SetCircCenter() ) { /*deleted by Guenther FILE *f = fopen( "cavity.plt", "wt"); ExportTECTmp( f); fclose( f); TM_TRACE1( "num = %d", num); TM_TRACE2( "new point = %lg %lg", vct.X(), vct.Y() ); TM_TRACE1( "no of segs bounding cavity = %d", plstsg->size() ); FILE *ff = fopen( "cavity_front.plt", "wt"); fprintf( ff, "VARIABLES = \"X\", \"Y\"\n"); fprintf( ff, "ZONE I=%d F=POINT\n", (int) (plstsg->size()+1) ); fprintf( ff, "%lg %lg\n", (*(*plstsg->begin())->PntLf())->X(), (*(*plstsg->begin())->PntLf())->Y() ); for ( itrsg = plstsg->begin(); itrsg != plstsg->end(); itrsg++) fprintf( ff, "%lg %lg\n", (*(*itrsg)->PntRt())->X(), (*(*itrsg)->PntRt())->Y() ); fclose( ff); THROW_INTERNAL("Flat triangle !!!"); */ } itrcl = InsertCell( ptri); // if ( itrclout != NULL) if ( itrclout != (IterGCell)NULL) (*itrclout)->SetNeighbour( itrcl); // if ( itrcl0 == NULL) if ( itrcl0 == (IterGCell)NULL) itrcl0 = itrcl; // if ( itrcl2 != NULL) if ( itrcl2 != (IterGCell)NULL){ (*itrcl)->rCell(2) = itrcl2; (*itrcl2)->rCell(1) = itrcl; } itrcl2 = itrcl; } // if ( itrcl2 != NULL && itrcl0 != NULL) if ( itrcl2 != (IterGCell)NULL && itrcl0 != (IterGCell)NULL) { (*itrcl0)->rCell(2) = itrcl2; (*itrcl2)->rCell(1) = itrcl0; } // removing all segments stored in plstsg for ( itrsg = plstsg->begin(); itrsg != plstsg->end(); itrsg++) if ( (*itrsg) != NULL ) delete (*itrsg); if ( plstsg) delete plstsg; return num; } bool HGrid::PointExists( const Vect2D& vct) { // Leaf *pndlf; // IterFacGPnt ipn; // // pndlf = mPntQTree.ClosestItem( vct ); // if ( pndlf != NULL) // { // ipn = pndlf->Data(); // // if ( fabs( (*ipn)->X() - vct.X() ) < ZERO && // fabs( (*ipn)->Y() - vct.Y() ) < ZERO ) // { // return true; // } // } // return false; } // creates basic trinagulation (two triangles) and inserts all boundary points void HGrid::InitTriangles() { CollGPnt::iterator itr; Vect2D vmin, vmax, vct; bool bFirst = true; HGrdPnt *pnd1, *pnd2, *pnd3, *pnd4; HGrdTri *ptri1, *ptri2; IterGPnt ind1, ind2, ind3, ind4; IterGCell itri1, itri2; // ind1 = ind2 = ind3 = ind4 = NULL; ind1 = ind2 = ind3 = ind4 = (IterGPnt)NULL; // itri1 = itri2 = NULL; itri1 = itri2 = (IterGCell)NULL; // finding limits for ( itr = mcolPnt.begin(); itr != mcolPnt.end(); itr++) { vct = *(*itr); if ( bFirst) { vmin = vmax = vct; bFirst = false; } else { if ( vct.X() > vmax.X() ) vmax.rX() = vct.X(); if ( vct.Y() > vmax.Y() ) vmax.rY() = vct.Y(); if ( vct.X() < vmin.X() ) vmin.rX() = vct.X(); if ( vct.Y() < vmin.Y() ) vmin.rY() = vct.Y(); } } vct = (vmax - vmin)/1.5; vmax += vct; vmin -= vct; mBox = HRect( vmin.X(), vmin.Y(), vmax.X(), vmax.Y() ); // creating starting triangulation containing two cells and four points THROW_ALLOC( pnd1 = MGNEW HGrdPnt( vmin) ); THROW_ALLOC( pnd2 = MGNEW HGrdPnt( vmax.X(), vmin.Y()) ); THROW_ALLOC( pnd3 = MGNEW HGrdPnt( vmax) ); THROW_ALLOC( pnd4 = MGNEW HGrdPnt( vmin.X(), vmax.Y()) ); THROW_ALLOC( ptri1 = MGNEW HGrdTri() ); THROW_ALLOC( ptri2 = MGNEW HGrdTri() ); mind1 = ind1 = InsertPoint( pnd1); mind2 = ind2 = InsertPoint( pnd2); mind3 = ind3 = InsertPoint( pnd3); mind4 = ind4 = InsertPoint( pnd4); itri1 = InsertCell( ptri1); itri2 = InsertCell( ptri2); ptri1->rNode(0) = ind1; ptri1->rNode(1) = ind2; ptri1->rNode(2) = ind3; ptri2->rNode(0) = ind3; ptri2->rNode(1) = ind4; ptri2->rNode(2) = ind1; ptri1->rCell(2) = itri2; ptri2->rCell(2) = itri1; ptri1->SetCircCenter(); ptri2->SetCircCenter(); // inserting frontal points into mesh IterFro itrfro; IterFSeg itrsg; map mapNod; map::iterator imap; for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); itrfro++) { for ( itrsg = (*itrfro).begin(); itrsg != (*itrfro).end(); itrsg++) { itr = (*itrsg)->rPntRt(); if ( ( imap = mapNod.find( *itr) ) == mapNod.end() ) { InsertPointIntoMesh( itr); mapNod.insert( map::value_type( *itr, 0) ); } } } #ifdef _DEBUG FILE *ftmp = fopen( "initial.plt", "wt"); ExportTECTmp( ftmp); fclose( ftmp); #endif // _DEBUG } bool HGrid::IsOutside( const Vect2D& vct) { IterFro itrfro; IterFSeg itrsg; Vect2D v1, v2; double x; //// winding algorithm // MGFloat alf; // for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); itrfro++) // { // alf += (*itrfro).Angle( vct); // } // if ( fabs(alf) < M_PI ) // return true; // else // return false; // ray casting algorithm MGInt cross = 0; for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); itrfro++) for ( itrsg = (*itrfro).begin(); itrsg != (*itrfro).end(); itrsg++) { v1 = *(*(*itrsg)->PntLf()); v2 = *(*(*itrsg)->PntRt()); if ( ( v1.Y() > vct.Y() && v2.Y() <= vct.Y() ) || ( v2.Y() > vct.Y() && v1.Y() <= vct.Y() ) ) { // x = ( v1.X()*v2.Y() - v1.Y()*v2.X() ) / ( v2.Y() - v1.Y() ); x = (v2.X() - v1.X())*(vct.Y() - v1.Y())/(v2.Y() - v1.Y()) + v1.X(); if ( x > vct.X() ) ++cross; } } if ( (cross % 2) == 1 ) return false; else return true; } void HGrid::FlagOuterTris() { IterFro itrfro; IterFSeg itrsg; IterGCell itr, itrnb, itrcl;; Vect2D vout, vcnt, vc1, vc2; CollGCell colCell; // // flaging all triangles lying outside domain using N^2 algo // for ( itr = mcolCell.begin(); itr != mcolCell.end(); itr++) // { // if( IsOutside( (*itr)->Center() ) ) // (*itr)->rIsOutside() = true; // else // (*itr)->rIsOutside() = false; // } Vect2D v1, v2, vct; // MGInt cross = 0; HGrdTri *ptri; MGFloat x, y1, y2; multimap mapCell; multimap::iterator imap, ifirst, ilast; for ( itr = mcolCell.begin(); itr != mcolCell.end(); itr++) { vct = (*itr)->Center(); (*itr)->rCross() = 0; mapCell.insert( multimap::value_type( vct.Y(), (*itr) ) ); } for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); itrfro++) for ( itrsg = (*itrfro).begin(); itrsg != (*itrfro).end(); itrsg++) { v1 = *(*(*itrsg)->PntLf()); v2 = *(*(*itrsg)->PntRt()); if ( v1.Y() > v2.Y() ) { y1 = v2.Y(); y2 = v1.Y(); } else { y1 = v1.Y(); y2 = v2.Y(); } ifirst = mapCell.lower_bound( y1 ); ilast = mapCell.upper_bound( y2 ); for ( imap = ifirst; imap != ilast; ++imap) { ptri = (*imap).second; vct = ptri->Center(); if ( ( v1.Y() > vct.Y() && v2.Y() <= vct.Y() ) || ( v2.Y() > vct.Y() && v1.Y() <= vct.Y() ) ) { x = (v2.X() - v1.X())*(vct.Y() - v1.Y())/(v2.Y() - v1.Y()) + v1.X(); if ( x > vct.X() ) ++(ptri->rCross()); } } } for ( itr = mcolCell.begin(); itr != mcolCell.end(); itr++) { if ( ((*itr)->rCross() % 2) == 1 ) (*itr)->rIsOutside() = false; else (*itr)->rIsOutside() = true; } } void HGrid::RemoveOuterTris() { IterGCell itr, itr2; HGrdTri *ptri; // itr2 = NULL; itr2 = (IterGCell)NULL; for ( itr = mcolCell.begin(); itr != mcolCell.end(); itr++) { // if ( itr2 != NULL) if ( itr2 != (IterGCell)NULL){ ptri = *itr2; (*itr2)->InvalidateNeighb(); mcolCell.erase( itr2); delete ptri; itr2 = (IterGCell)NULL; } if ( (*itr)->IsOutside() ) itr2 = itr; } // if ( itr2 != NULL) if ( itr2 != (IterGCell)NULL){ ptri = *itr2; (*itr2)->InvalidateNeighb(); mcolCell.erase( itr2); delete ptri; itr2 = (IterGCell)NULL; } if ( *mind1) delete *mind1; if ( *mind2) delete *mind2; if ( *mind3) delete *mind3; if ( *mind4) delete *mind4; mcolPnt.erase( mind1); mcolPnt.erase( mind2); mcolPnt.erase( mind3); mcolPnt.erase( mind4); mind1 = (IterGPnt)NULL; mind2 = (IterGPnt)NULL; mind3 = (IterGPnt)NULL; mind4 = (IterGPnt)NULL; } bool HGrid::CheckSwapTriangles( HGrdTri *ptri1, HGrdTri *ptri2) { HGrdTri tri1, tri2; tri1 = *ptri1; tri2 = *ptri2; SwapTriangles( &tri1, &tri2, false); if ( !tri1.Check() || !tri2.Check() ) return false; //Guenther //if ( tri1.Area() < 0 || tri2.Area() < 0 ) // return false; return true; } /* switch two triangles */ void HGrid::SwapTriangles( HGrdTri *ptri1, HGrdTri *ptri2, bool bgo) { MGInt ifc1, ifc2; IterGPnt ip1, ip2, ip3, ip4; IterGCell ic1, ic2, ic3, ic4; IterGCell itri1, itri2; // TRACE( "--- swapping !!!"); if ( ptri2->Node(1) == ptri1->Node(0) && ptri2->Node(0) == ptri1->Node(1) ) { ip1 = ptri2->Node(1); ip2 = ptri2->Node(2); ip3 = ptri2->Node(0); ip4 = ptri1->Node(2); ifc1 = 0; ifc2 = 0; ic1 = ptri2->Cell(1); ic2 = ptri2->Cell(2); ic3 = ptri1->Cell(1); ic4 = ptri1->Cell(2); itri1 = ptri2->Cell(0); itri2 = ptri1->Cell(0); } else if ( ptri2->Node(0) == ptri1->Node(0) && ptri2->Node(2) == ptri1->Node(1) ) { ip1 = ptri2->Node(0); ip2 = ptri2->Node(1); ip3 = ptri2->Node(2); ip4 = ptri1->Node(2); ifc1 = 0; ifc2 = 2; ic1 = ptri2->Cell(0); ic2 = ptri2->Cell(1); ic3 = ptri1->Cell(1); ic4 = ptri1->Cell(2); itri1 = ptri2->Cell(2); itri2 = ptri1->Cell(0); } else if ( ptri2->Node(2) == ptri1->Node(0) && ptri2->Node(1) == ptri1->Node(1) ) { ip1 = ptri2->Node(2); ip2 = ptri2->Node(0); ip3 = ptri2->Node(1); ip4 = ptri1->Node(2); ifc1 = 0; ifc2 = 1; ic1 = ptri2->Cell(2); ic2 = ptri2->Cell(0); ic3 = ptri1->Cell(1); ic4 = ptri1->Cell(2); itri1 = ptri2->Cell(1); itri2 = ptri1->Cell(0); } else if ( ptri2->Node(1) == ptri1->Node(2) && ptri2->Node(0) == ptri1->Node(0) ) { ip1 = ptri2->Node(1); ip2 = ptri2->Node(2); ip3 = ptri2->Node(0); ip4 = ptri1->Node(1); ifc1 = 2; ifc2 = 0; ic1 = ptri2->Cell(1); ic2 = ptri2->Cell(2); ic3 = ptri1->Cell(0); ic4 = ptri1->Cell(1); itri1 = ptri2->Cell(0); itri2 = ptri1->Cell(2); } else if ( ptri2->Node(0) == ptri1->Node(2) && ptri2->Node(2) == ptri1->Node(0) ) { ip1 = ptri2->Node(0); ip2 = ptri2->Node(1); ip3 = ptri2->Node(2); ip4 = ptri1->Node(1); ifc1 = 2; ifc2 = 2; ic1 = ptri2->Cell(0); ic2 = ptri2->Cell(1); ic3 = ptri1->Cell(0); ic4 = ptri1->Cell(1); itri1 = ptri2->Cell(2); itri2 = ptri1->Cell(2); } else if ( ptri2->Node(2) == ptri1->Node(2) && ptri2->Node(1) == ptri1->Node(0) ) { ip1 = ptri2->Node(2); ip2 = ptri2->Node(0); ip3 = ptri2->Node(1); ip4 = ptri1->Node(1); ifc1 = 2; ifc2 = 1; ic1 = ptri2->Cell(2); ic2 = ptri2->Cell(0); ic3 = ptri1->Cell(0); ic4 = ptri1->Cell(1); itri1 = ptri2->Cell(1); itri2 = ptri1->Cell(2); } else if ( ptri2->Node(1) == ptri1->Node(1) && ptri2->Node(0) == ptri1->Node(2) ) { ip1 = ptri2->Node(1); ip2 = ptri2->Node(2); ip3 = ptri2->Node(0); ip4 = ptri1->Node(0); ifc1 = 1; ifc2 = 0; ic1 = ptri2->Cell(1); ic2 = ptri2->Cell(2); ic3 = ptri1->Cell(2); ic4 = ptri1->Cell(0); itri1 = ptri2->Cell(0); itri2 = ptri1->Cell(1); } else if ( ptri2->Node(0) == ptri1->Node(1) && ptri2->Node(2) == ptri1->Node(2) ) { ip1 = ptri2->Node(0); ip2 = ptri2->Node(1); ip3 = ptri2->Node(2); ip4 = ptri1->Node(0); ifc1 = 1; ifc2 = 2; ic1 = ptri2->Cell(0); ic2 = ptri2->Cell(1); ic3 = ptri1->Cell(2); ic4 = ptri1->Cell(0); itri1 = ptri2->Cell(2); itri2 = ptri1->Cell(1); } else if ( ptri2->Node(2) == ptri1->Node(1) && ptri2->Node(1) == ptri1->Node(2) ) { ip1 = ptri2->Node(2); ip2 = ptri2->Node(0); ip3 = ptri2->Node(1); ip4 = ptri1->Node(0); ifc1 = 1; ifc2 = 1; ic1 = ptri2->Cell(2); ic2 = ptri2->Cell(0); ic3 = ptri1->Cell(2); ic4 = ptri1->Cell(0); itri1 = ptri2->Cell(1); itri2 = ptri1->Cell(1); } ASSERT( itri1 != (IterGCell)NULL && itri2 != (IterGCell)NULL); ptri1->rNode(0) = ip2; ptri1->rNode(1) = ip4; ptri1->rNode(2) = ip1; ptri1->rCell(0) = itri2; ptri1->rCell(1) = ic4; ptri1->rCell(2) = ic1; ptri2->rNode(0) = ip4; ptri2->rNode(1) = ip2; ptri2->rNode(2) = ip3; ptri2->rCell(0) = itri1; ptri2->rCell(1) = ic2; ptri2->rCell(2) = ic3; if ( bgo) { if ( ic1 != (IterGCell)NULL ){ if ( (*ic1)->Cell(0) == itri2) (*ic1)->rCell(0) = itri1; else if ( (*ic1)->Cell(1) == itri2) (*ic1)->rCell(1) = itri1; else if ( (*ic1)->Cell(2) == itri2) (*ic1)->rCell(2) = itri1; else ASSERT(0); } if ( ic3 != (IterGCell)NULL){ if ( (*ic3)->Cell(0) == itri1) (*ic3)->rCell(0) = itri2; else if ( (*ic3)->Cell(1) == itri1) (*ic3)->rCell(1) = itri2; else if ( (*ic3)->Cell(2) == itri1) (*ic3)->rCell(2) = itri2; else ASSERT(0); } } } /* checking bounding */ void HGrid::CheckBoundIntegr() { // char sbuf[256]; IterFro itrfro; IterFSeg itrsg; Vect2D v1, v2, v3, v4; // CollGCell colCell; CollGCell colPath; CollFSeg colSeg; IterFSeg iseg; IterGCell itr, itrnb, itrcl; Vect2D vcnt; bool bReady, bFound; // MGInt k, i=0; MGInt k; list lstCell; list::iterator itrtmp; multimap< HGrdPnt*, IterGCell > mapNod; pair< multimap< HGrdPnt*, IterGCell >::iterator, multimap< HGrdPnt*, IterGCell >::iterator> range[2]; // no of points per froseg multimap< HGrdPnt*, IterGCell >::iterator itrmap1, itrmap2; // getting number of front segments int no = 0; for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); itrfro++) for ( itrsg = (*itrfro).begin(); itrsg != (*itrfro).end(); itrsg++) ++no; for ( itr = mcolCell.begin(); itr != mcolCell.end(); itr++) for ( k=0; k::value_type(*(*itr)->Node(k), itr) ); int iii=0; int nrec = 0; for ( itrfro = mcolFro.begin(); itrfro != mcolFro.end(); itrfro++) for ( itrsg = (*itrfro).begin(); itrsg != (*itrfro).end(); itrsg++) { ++iii; //if ( iii - 1000*(iii/1000) == 0) // printf( "triang. iter = %d / %d nrec = %d\n", iii, no, nrec); range[0] = mapNod.equal_range( *(*itrsg)->PntLf() ); range[1] = mapNod.equal_range( *(*itrsg)->PntRt() ); bReady = false; for ( itrmap1=range[0].first; itrmap1!=range[0].second; itrmap1++) { itrcl = (*itrmap1).second; lstCell.insert( lstCell.begin(), itrcl ); for ( itrmap2=range[1].first; itrmap2!=range[1].second; itrmap2++) { if ( *itrcl == *(*itrmap2).second ) { bReady = true; goto out_of_loops; } } } out_of_loops: // the segment is missing - must be recovered if ( ! bReady) { ++nrec; //printf( "triang. iter = %d / %d nrec = %d\n", iii, no, nrec); v1 = *(*((*itrsg)->PntLf())); v2 = *(*((*itrsg)->PntRt())); // TRACE( "\n" ); // sprintf( sbuf, "seg (%lg, %lg) (%lg, %lg) - lstCell.size = %d", // v1.X(), v1.Y(), v2.X(), v2.Y(), lstCell.size() ); // TRACE( sbuf); bFound = false; for ( itrtmp = lstCell.begin(); itrtmp != lstCell.end(); ++itrtmp) { itr = *itrtmp; if(( itrnb = (*itr)->NextCell( *itrsg, (IterGCell)NULL) ) != (IterGCell)NULL) { bFound = true; break; } } if ( bFound) { IterGCell itr1, itr2, itro1=(IterGCell)NULL, itro2=(IterGCell)NULL; stack stackCell; // CheckGrid(); itr1 = itr; itr2 = itrnb; // TRACE2( "v1 = %lg %lg", v1.X(), v1.Y() ); // TRACE2( "v2 = %lg %lg", v2.X(), v2.Y() ); int niter = 0; do { ++niter; // TRACE( "--- loop start"); // TRACE2( "itrcl = %d / %d", itr1, *itr1); // (*itr1)->DumpTri(); // TRACE2( "itrcl = %d / %d", itr2, *itr2); // (*itr2)->DumpTri(); // check if swap is possible if not then try with another triangles while ( /*! (*itr2)->IsVisible( itr1, v1) ||*/ ! CheckSwapTriangles( *itr1, *itr2 ) || ( itr1 == itro1 && itr2 == itro2 ) ) // avoid swaping the same triangles again { stackCell.push( itr1); itr = itr2; itr2 = (*itr)->NextCell( *itrsg, itr1); itr1 = itr; //Guenther //ASSERT( itr2 != (IterGCell)NULL); } itro1 = itr1; itro2 = itr2; // pre swapping - remove itr1 and itr2 from map for ( k=0; k< NUM_TRI; ++k) { range[0] = mapNod.equal_range( *(*itr1)->Node(k) ); for ( itrmap1=range[0].first; itrmap1!=range[0].second; itrmap1++) { if ( (*itrmap1).second == itr1 ) { mapNod.erase( itrmap1); break; } } range[0] = mapNod.equal_range( *(*itr2)->Node(k) ); for ( itrmap1=range[0].first; itrmap1!=range[0].second; itrmap1++) { if ( (*itrmap1).second == itr2 ) { mapNod.erase( itrmap1); break; } } } if ( ! CheckSwapTriangles( *itr1, *itr2 ) ) THROW_INTERNAL( "Recovery: Swap not possible !!!"); SwapTriangles( *itr1, *itr2 ); // post swapping - insert modified itr1 and itr2 into map for ( k=0; k< NUM_TRI; ++k) { mapNod.insert( multimap::value_type( *(*itr1)->Node(k), itr1) ); mapNod.insert( multimap::value_type( *(*itr2)->Node(k), itr2) ); } if ( stackCell.empty() ) { itrcl = (IterGCell)NULL; itrnb = (IterGCell)NULL; if((itr = (*itr1)->NextCell( (*itrsg), (IterGCell)NULL )) != (IterGCell)NULL) { itrcl = itr1; itrnb = itr; } if ( (itr = (*itr2)->NextCell( (*itrsg), (IterGCell)NULL )) != (IterGCell)NULL) { itrcl = itr2; itrnb = itr; } itr1 = itrcl; itr2 = itrnb; } else{ itr1 = stackCell.top(); stackCell.pop(); if ( stackCell.empty() ) itr2 = (*itr1)->NextCell(*itrsg, (IterGCell)NULL); else itr2 = (*itr1)->NextCell(*itrsg, (IterGCell)stackCell.top()); } } while ( itr1 != (IterGCell)NULL && itr2 != (IterGCell)NULL); (*itrsg)->mbtmp = true; } else { char sbuf[1024]; sprintf( sbuf, "recovery problem with seg(%lg, %lg)(%lg, %lg)", v1.X(), v1.Y(), v2.X(), v2.Y() ); TM_TRACE( sbuf); TM_TRACE1( "recovwry lstCell.size = %d", lstCell.size() ); TM_TRACE1( "%d edges already recovered", nrec); FILE *ff = fopen( "lstcell.plt", "wt"); for ( itrtmp = lstCell.begin(); itrtmp != lstCell.end(); ++itrtmp) { (*(*itrtmp))->DumpTEC( ff); } fclose( ff); printf( "%s\n", sbuf); printf( "recovery lstCell.size = %d\n", (int)lstCell.size() ); (*itrsg)->mbtmp = true; FILE *f = fopen( "recovery.plt", "wt"); ExportTECTmp( f); fclose( f); //Guenther // THROW_INTERNAL( "Recovery problem !!!"); } } lstCell.erase( lstCell.begin(), lstCell.end() ); } // printf( "%d edges recovered\n", nrec); } void HGrid::Generate() { clock_t start, tstart, finish; double duration; try { tstart = clock(); start = clock(); InitTriangles(); finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; // printf( "InitTriangles() - %2.1f seconds\n\n", duration ); //FILE *f = fopen( "ini.plt", "wt"); //ExportTECTmp( f); //fclose( f); TM_TRACE( "CheckBoundIntegr()"); // printf( "CheckBoundIntegr()\n"); start = clock(); CheckBoundIntegr(); finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; // printf( "CheckBoundIntegr() - %2.1f seconds\n\n", duration ); TM_TRACE( "FlagOuterTris()"); // printf( "FlagOuterTris()\n"); FlagOuterTris(); TM_TRACE( "RemoveOuterTris()"); // printf( "RemoveOuterTris()\n"); RemoveOuterTris(); finish = clock(); duration = (double)(finish - tstart) / CLOCKS_PER_SEC; // printf( "Generation total - %2.1f seconds\n\n", duration ); // FILE *f = fopen( "param.plt", "wt"); // ExportTECTmp( f); // fclose( f); } catch ( Except *pe) { ASSERT( pe); TM_TRACE_EXCEPTION( *pe); TM_TRACE_TO_STDERR( *pe); delete pe; } } void HGrid::ExportTECTmp( FILE *f) { IterGPnt pntitr; Vect2D vct; IterGCell cellitr, itrcl; MGInt id1, id2, id3, id4; MGInt ltri, ltmp; map > tmpMap; TM_TRACE( "ExportTEC"); fprintf( f, "TITLE = \"surface\"\n"); fprintf( f, "VARIABLES = \"X\", \"Y\"\n"); fprintf( f, "ZONE T=\"TRIANGLES\", "); fprintf( f, "N=%2ld, ", (long int) mcolPnt.size() ); fprintf( f, "E=%2d, F=FEPOINT, ET=QUADRILATERAL C=BLACK\n ", ltri = (MGInt)mcolCell.size() ); ltmp = 0; for ( pntitr = mcolPnt.begin(); pntitr != mcolPnt.end(); pntitr++) { ltmp++; vct = *(*pntitr); fprintf( f, "%20.10lg %20.10lg\n", vct.X(), vct.Y() ); tmpMap.insert( map >::value_type((void*)(*pntitr), ltmp )); } TM_TRACE( "after Pnt"); ltri = 0; for ( cellitr = mcolCell.begin(); cellitr != mcolCell.end(); cellitr++) { ltri++; pntitr = (*cellitr)->Node(0); id1 = tmpMap[ (*pntitr)]; pntitr = (*cellitr)->Node(1); id2 = tmpMap[ (*pntitr)]; pntitr = (*cellitr)->Node(2); id4 = id3 = tmpMap[ (*pntitr)]; fprintf( f, "%9ld %9ld %9ld %9ld\n", (long int)id1, (long int)id2, (long int)id3, (long int)id4 ); } TM_TRACE( "after Cells"); } void HGrid::CheckGrid() { // char sbuf[256]; bool bFound; IterGCell itr, itrnb; // TRACE("CheckGrid()\n"); for ( itr = mcolCell.begin(); itr != mcolCell.end(); ++itr) { // sprintf( sbuf, "cel = %d | %d %d %d", itr, (*itr)->Cell(0), //(*itr)->Cell(1), (*itr)->Cell(2) ); // TRACE( sbuf); for ( int i=0; iCell(i); if ( itrnb != (IterGCell)NULL){ ASSERT( *itrnb ); bFound = false; for ( int k=0; kCell(k) == itr ) bFound = true; } } if ( ! bFound) { THROW_INTERNAL( "Cells pointers are not consistent !"); } } } } void HGrid::WriteFrontTEC( const char name[]) { } INIT_TRACE; }