#ifdef WIN32 #define QUIET #endif #include #include "ledsvertex.h" #include "ledsedgeuse.h" #include "ledsface.h" #include "vmerge.h" #include "ledsgeometry.h" #include "genlib.h" #include "mathlib.h" #include "datalib.h" //#define SHOWSIZES //#define TIMEFREE //#define BUFSIZE 1 //#define BUFSIZE 2 //#define BUFSIZE 4 //#define BUFSIZE 8 //#define BUFSIZE 16 //#define BUFSIZE 32 //#define BUFSIZE 64 //#define BUFSIZE 128 #define BUFSIZE 256 //#define BUFSIZE 512 //#define BUFSIZE 1024 //#define BUFSIZE 2048 //#define BUFSIZE 4096 //#define BUFSIZE 8192 CLEDSGeometry::CLEDSGeometry() { m_pLIDmapEU = NULL; m_pLIDmapVtx = NULL; m_pLIDmapFace = NULL; m_boolPtrsUpdated = FALSE; m_pCListEdges = NULL; m_pCListVertices = NULL; m_pCListEUs = NULL; m_pCListFaces = NULL; m_pCListOddEdges = NULL; m_pCListPairedUnmatchedEdges = NULL; m_pCListGreater2Edges = NULL; m_pCLEDSTablesSTL = NULL; m_pEUs = NULL; m_pFaces = NULL; m_pVtxs = NULL; // m_bOneStage = TRUE; m_bPrevPtrs = FALSE; m_pListComponents = NULL; } CLEDSGeometry::~CLEDSGeometry() { Uninit(); } VOID CLEDSGeometry::Init(BOOL bPrevPtrs) { m_pLIDmapEU = new LIDmap; m_pLIDmapVtx = new LIDmap; m_pLIDmapFace = new LIDmap; #ifndef RESORTABLE m_pLIDmapEU->Init(0); m_pLIDmapVtx->Init(0); m_pLIDmapFace->Init(0); #else // for multistage lid build can't we wait and allocate correct size array? m_pLIDmapEU->Init(); m_pLIDmapVtx->Init(); m_pLIDmapFace->Init(); #endif m_pCListEdges = new CList; m_pCListVertices = new CList; m_pCListEUs = new CList; m_pCListFaces = new CList; /* // move to BeginSTLOneStageInfo() and ledstables.h m_pCListEdges->Init(); m_pCListVertices->Init(); m_pCListEUs->Init(); m_pCListFaces->Init(); */ m_pEUs = NULL; m_pFaces = NULL; m_pVtxs = NULL; m_pEUHashTable = NULL; m_pVtxHashTable = NULL; #ifdef LISTARRAY pFaceBuffer = NULL; uiFaceNum = 0; pEUBuffer = NULL; uiEUNum = 0; m_pVertexBuffer = NULL; m_uiVertexNum = 0; #endif m_bPrevPtrs = bPrevPtrs; } VOID CLEDSGeometry::Uninit() { delete m_pLIDmapEU; delete m_pLIDmapVtx; delete m_pLIDmapFace; delete m_pCListVertices; delete m_pCListEdges; delete m_pCListEUs; delete m_pCListFaces; delete [] m_pFaces; delete [] m_pVtxs; if (m_bPrevPtrs) delete [] (CLEDSEdgeUsePrev *)m_pEUs; else delete [] m_pEUs; delete m_pListComponents; } BOOL CLEDSGeometry::Check2Manifold() { CListIter ListIter; CLEDSliteEdgeUse *pEU, *pEUSib, *pEUSibSib; ListIter.Init(m_pCListEdges); pEU = (CLEDSliteEdgeUse *)ListIter.PeekFirst(); while (pEU) { pEUSib = pEU->GetLEDSSiblingEdgeUse(); if (pEUSib == pEU) { if (m_pCListOddEdges==NULL) { m_pCListOddEdges = new CList; m_pCListOddEdges->Init(); } m_pCListOddEdges->InsertLast(pEU, 0); pEU = ListIter.PeekNext(); continue; } pEUSibSib = pEUSib->GetLEDSSiblingEdgeUse(); if (pEUSibSib == pEU) { // check to see if they both point in same direction if ((pEUSib->GetLEDSRootVtx()!=pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx()) || (pEU->GetLEDSRootVtx()!=pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx())){ ASSERT(pEU->GetLEDSRootVtx()==pEUSib->GetLEDSRootVtx()); ASSERT(pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx() == pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx()); if (m_pCListPairedUnmatchedEdges==NULL) { m_pCListPairedUnmatchedEdges = new CList; m_pCListPairedUnmatchedEdges->Init(); } // add it to paired unmatched edges list if both in same dir m_pCListPairedUnmatchedEdges->InsertLast(pEU, 0); } // otherwise it's normal and we don't add it to any lists } else { // It has more than one sib. int count = 2; int parity; // Check if 1st sibling points in same (parity 0) // or opposite (parity 2) direction. if ((pEUSib->GetLEDSRootVtx()!=pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx()) || (pEU->GetLEDSRootVtx()!=pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx())) { ASSERT(pEU->GetLEDSRootVtx()==pEUSib->GetLEDSRootVtx()); ASSERT(pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx() == pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx()); parity = 2; } else if ((pEUSib->GetLEDSRootVtx()==pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx()) || (pEU->GetLEDSRootVtx()==pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx())) { parity = 0; } else { // siblings should fall in one of above categories. fprintf (stderr, "Problems w/ following non-manifold edge. Aborting.\n"); pEU->Display(); ASSERT(FALSE); } CLEDSliteEdgeUse *pEUcur = pEUSib; // Check if additional siblings point in same (parity++) // or opposite (parity--) direction. while ((pEUSib = pEUcur->GetLEDSSiblingEdgeUse()) != pEU) { if (pEUSib == NULL) break; if ((pEUSib->GetLEDSRootVtx() != pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx()) || (pEU->GetLEDSRootVtx() != pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx())){ ASSERT(pEU->GetLEDSRootVtx() == pEUSib->GetLEDSRootVtx()); ASSERT(pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx() == pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx()); parity ++; } else if ((pEUSib->GetLEDSRootVtx() == pEU->GetLEDSNCEdgeUse()->GetLEDSRootVtx()) || (pEU->GetLEDSRootVtx() == pEUSib->GetLEDSNCEdgeUse()->GetLEDSRootVtx())) { parity--; } else { // siblings should fall in one of above categories. fprintf (stderr, "Problems w/ following non-manifold edge. Aborting.\n"); pEUcur->Display(); ASSERT(FALSE); } count++; pEUcur = pEUSib; } if ((count%2) == 1) { if (m_pCListOddEdges==NULL) { m_pCListOddEdges = new CList; m_pCListOddEdges->Init(); } m_pCListOddEdges->InsertLast(pEU, 0); } else if (parity != 0) { fprintf (stdout, "Parity problem; odd number of edge uses > 2 for edge:\n"); pEU->Display(); if (m_pCListPairedUnmatchedEdges==NULL) { m_pCListPairedUnmatchedEdges = new CList; m_pCListPairedUnmatchedEdges->Init(); } m_pCListPairedUnmatchedEdges->InsertLast(pEU, 0); } else { if (m_pCListGreater2Edges == NULL) { m_pCListGreater2Edges = new CList; m_pCListGreater2Edges->Init(); } m_pCListGreater2Edges->InsertLast(pEU, 0); } } pEU = ListIter.PeekNext(); } if (m_pCListOddEdges && m_pCListOddEdges->GetLength() > 0) fprintf(stdout, "%ld edges in shell have an odd number of edge uses.\n", m_pCListOddEdges->GetLength()); if (m_pCListPairedUnmatchedEdges && m_pCListPairedUnmatchedEdges->GetLength() > 0) fprintf(stdout, "%ld edges have an edge use(s) in the wrong direction.\n", m_pCListPairedUnmatchedEdges->GetLength()); if (m_pCListGreater2Edges && m_pCListGreater2Edges->GetLength() > 0) fprintf(stdout, "%ld edges in shell have greater than 2 edge uses.\n", m_pCListGreater2Edges->GetLength()); if ((m_pCListOddEdges && m_pCListOddEdges->GetLength() > 0) || (m_pCListPairedUnmatchedEdges && m_pCListPairedUnmatchedEdges->GetLength() > 0) || (m_pCListGreater2Edges && m_pCListGreater2Edges->GetLength() > 0)) return FALSE; else return TRUE; } // return tManifold if part is already 2-manifold, tPseudoManifold if part // can be made pseudo-2-manifold, tNonManifold otherwise. // If bMark is true, mark any non-pseudo-manifold edges. BrepType CLEDSGeometry::CheckPseudo2Manifold(BOOL bMark) { if (Check2Manifold()) { if (bMark) fprintf(stdout, "Part is 2-manifold.\n"); return tManifold; } else if (bMark) { CListIter CListIterEdges; CLEDSliteEdgeUse *pEdge; if (m_pCListOddEdges && m_pCListOddEdges->GetLength() > 0) { CListIterEdges.Init(m_pCListOddEdges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { SetNonmanifoldEdge(pEdge); pEdge = CListIterEdges.PeekNext(); } } if (m_pCListPairedUnmatchedEdges && m_pCListPairedUnmatchedEdges->GetLength() > 0) { CListIterEdges.Init(m_pCListPairedUnmatchedEdges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { SetNonmanifoldEdge(pEdge); pEdge = CListIterEdges.PeekNext(); } } if ((m_pCListGreater2Edges) && (!SortCheckEdges(bMark))) { return tNonManifold; } else if ((m_pCListOddEdges && m_pCListOddEdges->GetLength() > 0) || (m_pCListPairedUnmatchedEdges && m_pCListPairedUnmatchedEdges->GetLength() > 0)) { return tNonManifold; } else return tPseudoManifold; } else { if ((m_pCListOddEdges && m_pCListOddEdges->GetLength() > 0) || (m_pCListPairedUnmatchedEdges && m_pCListPairedUnmatchedEdges->GetLength() > 0)) return tNonManifold; // otherwise, we do some sorting on the edges with >2 edge uses // return SortCheckEdges(FALSE); } } VOID CLEDSGeometry::CleanupManifoldTesting() { CLEDSliteEdgeUse *pEdge; CListIter CListIterEdges; if (m_pCListOddEdges && m_pCListOddEdges->GetLength() > 0) { CListIterEdges.Init(m_pCListOddEdges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { m_pCListOddEdges->Remove(pEdge); pEdge = CListIterEdges.PeekNext(); } delete m_pCListOddEdges; m_pCListOddEdges = NULL; } if (m_pCListPairedUnmatchedEdges && m_pCListPairedUnmatchedEdges->GetLength() > 0) { CListIterEdges.Init(m_pCListPairedUnmatchedEdges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { m_pCListPairedUnmatchedEdges->Remove(pEdge); pEdge = CListIterEdges.PeekNext(); } delete m_pCListPairedUnmatchedEdges; m_pCListPairedUnmatchedEdges = NULL; } if (m_pCListGreater2Edges && m_pCListGreater2Edges->GetLength() > 0) { CListIterEdges.Init(m_pCListGreater2Edges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { m_pCListGreater2Edges->Remove(pEdge); pEdge = CListIterEdges.PeekNext(); } delete m_pCListGreater2Edges; m_pCListGreater2Edges = NULL; } } // Divide this into multiple functions! // return tPseudoManifold if part can be made pseudo-2-manifold, // tNonManifold otherwise. BrepType CLEDSGeometry::SortCheckEdges(BOOL bMark) { ASSERT (m_pCListGreater2Edges); CListIter CListIterEdges; CLEDSliteEdgeUse *pEdge, *pEUfirst, *pEUcur; Point Pt1, Pt2; Vector vEdge, vAdjust, *pvEU; DOUBLE dFrac; UINT_32 uiCount; BrepType bReturnVal = tPseudoManifold; CListIterEdges.Init(m_pCListGreater2Edges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { pEUcur = pEUfirst = pEdge; // compute normalized vector for the edge (subroutine?) Pt1 = pEUcur->GetLEDSRootVtx()->GetPoint(); Pt2 = pEUcur->GetLEDSNCEdgeUse()->GetLEDSRootVtx()->GetPoint(); vEdge.Set((Pt1(X) - Pt2(X)), (Pt1(Y) - Pt2(Y)), (Pt1(Z) - Pt2(Z)), 0.0); vEdge.Normalize(); // Calculate projected face vector for each edge use along edge uiCount = 0; do { uiCount++; pvEU = new Vector; // calculate vector along face Pt1 = pEUcur->GetLEDSNCEdgeUse()->GetLEDSRootVtx()->GetPoint(); Pt2 = pEUcur->GetLEDSNCEdgeUse()->GetLEDSNCEdgeUse()-> GetLEDSRootVtx()->GetPoint(); pvEU->Set((Pt1(X) - Pt2(X)), (Pt1(Y) - Pt2(Y)), (Pt1(Z) - Pt2(Z)), 0.0); // project vector on face into plane perpendicular to edge dFrac = pvEU->Dot(vEdge); pvEU->Set((FLOAT)((*pvEU)(X) - dFrac*vEdge(X)), (FLOAT)((*pvEU)(Y) - dFrac*vEdge(Y)), (FLOAT)((*pvEU)(Z) - dFrac*vEdge(Z)), 0.0f); pvEU->Normalize(); // store projected vector with the edge use pEUcur->SetExtra(pvEU); pEUcur = pEUcur->GetLEDSSiblingEdgeUse(); } while (pEUcur && (pEUcur != pEUfirst)); Vector vCross, *pvFirst, *pvEUcur; DOUBLE dAngle; CList *pCListA, *pCListB; pCListA = new CList; pCListA->Init(); pCListB = new CList; pCListB->Init(); pvFirst = (Vector *)pEUfirst->GetExtra(); pEUcur = pEUfirst; while ((pEUcur = pEUcur->GetLEDSSiblingEdgeUse()) != pEUfirst) { ASSERT(pEUcur); pvEUcur = (Vector *)pEUcur->GetExtra(); vCross = pvFirst->Cross(*pvEUcur); vCross.Normalize(); dAngle = AngleBetween(*pvFirst, *pvEUcur); if (vCross == vEdge) { pCListA->Insert(pEUcur, dAngle); } else if (vCross == -vEdge) { pCListB->Insert(pEUcur, dAngle); } else { fprintf (stderr, "\nOverlapping or coincident triangles at following non-manifold edge.\n"); pEUcur->Display(); fprintf (stderr, "Not supported. Aborting.\n"); ASSERT (FALSE); } } // Next we read through listA forwards followed by listB backwards // and relink the sibling pointers in that order. RelinkSibs(pEUcur, pCListA, pCListB); // Now we check that the face normals alternate properly if (!CheckAlternatingFaceNormals(pEUcur)) { if (bMark) { bReturnVal = tNonManifold; fprintf(stdout, "\nSorted face normals didn't alternate for edge below.\n"); fprintf(stdout, "Self intersections?\n"); pEUcur->Display(); // What do we want to mark here? } else { return tNonManifold; } } // And now if we want to divide up the pseudo-2-manifold // edges, we could do so. But should be a separate function // that can rely on sorted edges. Actually, it needs to know // which is reference EU - but that shouldn't have changed. pEdge = CListIterEdges.PeekNext(); } DivideEdges(); return (bReturnVal); } // assumes the edges have already been properly sorted! VOID CLEDSGeometry::DivideEdges() { CListIter CListIterEdges; CLEDSliteEdgeUse *pEdge, *pEUfirst, *pEUcur, *pEUcurPr, *pEUnext; CListIterEdges.Init(m_pCListGreater2Edges); pEdge = CListIterEdges.PeekFirst(); while (pEdge) { pEUcur = pEUfirst = pEdge;//->GetLEDSSiblingEdgeUse(); do { pEUcurPr = pEUcur->GetLEDSSiblingEdgeUse(); pEUnext = pEUcurPr->GetLEDSSiblingEdgeUse(); pEUcurPr->SetLEDSSiblingEdgeUse(pEUcur); // pEUcurPr->SetSiblingEdgeUse(pEUcur->GetLID()); pEUcurPr->SetExtra(NULL); pEUcur->SetLEDSSiblingEdgeUse(pEUcurPr); // pEUcur->SetSiblingEdgeUse(pEUcurPr->GetLID()); pEUcur->SetExtra(NULL); // do I want to put newly separated edges into the edge list? if (pEUcur != pEUfirst) { m_pCListEUs->InsertLast(pEUcur, 0); } pEUcur = pEUnext; } while (pEUcur && (pEUcur != pEUfirst)); pEdge = CListIterEdges.PeekNext(); } } BOOL CLEDSGeometry::CheckAlternatingFaceNormals(CLEDSliteEdgeUse *pEdge) { CLEDSliteVertex *pRootVtxLast, *pRootVtxCur; CLEDSliteEdgeUse *pEUcur, *pEUfirst = pEdge; pRootVtxLast = pEUfirst->GetLEDSRootVtx(); pEUcur = pEUfirst->GetLEDSSiblingEdgeUse(); while (pEUcur && (pEUcur != pEUfirst)){ pRootVtxCur = pEUcur->GetLEDSRootVtx(); if (pRootVtxCur == pRootVtxLast) return FALSE; pRootVtxLast = pRootVtxCur; pEUcur = pEUcur->GetLEDSSiblingEdgeUse(); } return TRUE; } VOID CLEDSGeometry::RelinkSibs(CLEDSliteEdgeUse *pEUfirst, CList *pCListA, CList *pCListB) { CListIter ListIter; CLEDSliteEdgeUse *pEUcur, *pEUlast = pEUfirst; ListIter.Init(pCListA); pEUcur = ListIter.PeekFirst(); while (pEUcur) { pEUlast->SetLEDSSiblingEdgeUse(pEUcur); // pEUlast->SetSiblingEdgeUse(pEUcur->GetLID()); pEUlast = pEUcur; pEUcur = ListIter.PeekNext(); } ListIter.Init(pCListB); pEUcur = ListIter.PeekLast(); while (pEUcur) { pEUlast->SetLEDSSiblingEdgeUse(pEUcur); // pEUlast->SetSiblingEdgeUse(pEUcur->GetLID()); pEUlast = pEUcur; pEUcur = ListIter.PeekPrev(); } pEUlast->SetLEDSSiblingEdgeUse(pEUfirst); // pEUlast->SetSiblingEdgeUse(pEUfirst->GetLID()); } VOID CLEDSGeometry::SetNonmanifoldEdge(CLEDSliteEdgeUse *pEU) { /* pEU->SetExtra((VOID *)NONMANIFOLD); pEU->GetLEDSRootVtx()->SetExtra((VOID *)NONMANIFOLD); pEU->GetLEDSOtherVtx()->SetExtra((VOID *)NONMANIFOLD); */ } #ifdef RESORTABLE // Uses the stored LIDs to update direct pointers in the LEDS VOID CLEDSGeometry::UpdateLEDSPtrs() { // CHANGE/FIX THIS // This function currently ignores the possibility of inner contours // and assumes that random accesses to pLIDmap are ok (eg that it // fits in memory). CListIter CListIterIntVtx; CLEDSVertex *pVtx; CListIterIntVtx.Init(m_pCListVertices); pVtx = (CLEDSVertex *)CListIterIntVtx.PeekFirst(); while (pVtx) { pVtx->SetLEDSFirstEU((CLEDSEdgeUse *)m_pLIDmapEU-> GetPtr(pVtx->GetFirstEU())); #ifdef LEDSDEBUG pVtx->Display(); #endif pVtx = (CLEDSVertex *)CListIterIntVtx.PeekNext(); } CListIter CListIterIntFace; CLEDSFace *pFace; CListIterIntFace.Init(m_pCListFaces); pFace = (CLEDSFace *)CListIterIntFace.PeekFirst(); while (pFace) { pFace->SetLEDSOuterContourEU((CLEDSEdgeUse *)m_pLIDmapEU-> GetPtr(pFace->GetOuterContourEU())); #ifdef LEDSDEBUG pFace->Display(); #endif pFace = (CLEDSFace *)CListIterIntFace.PeekNext(); } CListIter CListIterIntEdgeUse; CLEDSEdgeUse *pEdgeUse; CListIterIntEdgeUse.Init(m_pCListEUs); pEdgeUse = (CLEDSEdgeUse *)CListIterIntEdgeUse.PeekFirst(); while (pEdgeUse) { pEdgeUse->SetLEDSSiblingEdgeUse((CLEDSEdgeUse *) m_pLIDmapEU-> GetPtr(pEdgeUse->GetSiblingEdgeUse())); pEdgeUse->SetLEDSNCEdgeUse((CLEDSEdgeUse *)m_pLIDmapEU-> GetPtr(pEdgeUse->GetNCEdgeUse())); pEdgeUse->SetLEDSNVEdgeUse((CLEDSEdgeUse *)m_pLIDmapEU-> GetPtr(pEdgeUse->GetNVEdgeUse())); pEdgeUse->SetLEDSRootVtx((CLEDSVertex *)m_pLIDmapVtx-> GetPtr(pEdgeUse->GetRootVtx())); pEdgeUse->SetLEDSFace((CLEDSFace *)m_pLIDmapFace-> GetPtr(pEdgeUse->GetFace())); #ifdef LEDSDEBUG pEdgeUse->Display(); #endif pEdgeUse = (CLEDSEdgeUse *)CListIterIntEdgeUse.PeekNext(); } m_boolPtrsUpdated = TRUE; } #endif VOID CLEDSGeometry::TestIterators(void) { CListIter CListIterIntFace; CLEDSliteContourIter ContourIter; CLEDSliteFace *pFace; CLEDSliteFaceIter FaceIter; CLEDSliteVertex *p1stVtx, *pVtx; CLEDSliteEdgeUse *p1stEU, *pEU = NULL /*(Steve)*/; CListIter CListIterIntEdge; CLEDSliteEdgeUse *pEdge; CLEDSliteSiblingIter SiblingIter; #ifdef LEDSDEBUG cout << "*****The vertices and edge uses of each face*****" << endl; #endif pVtx = NULL; CListIterIntFace.Init(m_pCListFaces); pFace = CListIterIntFace.PeekFirst(); while (pFace) { #ifdef LEDSDEBUG pFace->Display(); #endif FaceIter.Init(pFace); pVtx = p1stVtx = (CLEDSVertex *)FaceIter.PeekFirstCVertex(); do { #ifdef LEDSDEBUG pVtx->Display(); #endif pVtx = (CLEDSVertex *)FaceIter.PeekNextCVertex(); } while (pVtx != p1stVtx); p1stEU = pFace->GetLEDSOuterContourEU(); ContourIter.Init(p1stEU); // (This will display the first one last) while (pEU != p1stEU) { pEU = ContourIter.PeekNextContourEU(); #ifdef LEDSDEBUG pEU->Display(); #endif } pFace = CListIterIntFace.PeekNext(); } CListIter CListIterIntVtx; CLEDSliteVtxEdgeIter VtxEdgeIter; #ifdef LEDSDEBUG cout << "*****The edges from each vertex*****" << endl; #endif CListIterIntVtx.Init(m_pCListVertices); pVtx = CListIterIntVtx.PeekFirst(); while (pVtx) { #ifdef LEDSDEBUG pVtx->Display(); #endif VtxEdgeIter.Init(pVtx); pEU = p1stEU = VtxEdgeIter.PeekFirstVtxEdgeEU(); do { #ifdef LEDSDEBUG pEU->Display(); #endif pEU = VtxEdgeIter.PeekNextVtxEdgeEU(); } while (pEU != p1stEU); pVtx = CListIterIntVtx.PeekNext(); } #ifdef LEDSDEBUG cout << "*****The siblings of each edge *****" << endl; #endif CListIterIntEdge.Init(m_pCListEdges); pEdge = CListIterIntEdge.PeekFirst(); while (pEdge) { #ifdef LEDSDEBUG pEdge->Display(); #endif SiblingIter.Init(pEdge); pEU = NULL; while (pEU != pEdge) { pEU = SiblingIter.PeekNextSiblingEU(); #ifdef LEDSDEBUG pEU->Display(); #endif } pEdge = CListIterIntEdge.PeekNext(); } } // Run the slicer. VOID CLEDSGeometry::Slice(FLOAT fThickness, Vector vUp, INT_32 iPrecisionExp, FLOAT fScale) { /* temp for data structure size measuring instead fprintf(stdout, "leds face size %d\n", sizeof(CLEDSliteFace)); fprintf(stdout, "leds vertex size %d\n", sizeof(CLEDSliteVertex)); fprintf(stdout, "leds edge use size %d\n", sizeof(CLEDSliteEdgeUse)); */ /* CSlices *pSlices; Timer timer; timer.Start(); DOUBLE secs; if (CheckPseudo2Manifold(FALSE)) { fprintf(stdout, "Pseudo2Manifold\n"); timer.Stop(); secs = timer.GetSeconds(); fprintf(stdout, "Pseudo2Manifold testing took %f seconds\n",secs); timer.Start(); pSlices = new CSlices; pSlices->SetThickness(fThickness); pSlices->SetScale(fScale); pSlices->SetvUp(vUp); pSlices->SetPrecisionExp(iPrecisionExp); pSlices->Init(this, m_pCListVertices); timer.Stop(); secs = timer.GetSeconds(); fprintf(stdout, "Slicer initialization took %f seconds\n",secs); timer.Start(); pSlices->SliceIt(); timer.Stop(); secs = timer.GetSeconds(); fprintf(stdout, "Slicing took %f seconds\n",secs); delete pSlices; } else fprintf(stdout, "Not pseudo2Manifold\n"); */ } /* Get and print basic info about faces for analysis program */ VOID CLEDSGeometry::AnalyzeFaces() { fprintf(stdout, "%ld faces.\n", m_pCListFaces->GetLength()); } /* Get and print basic info about edges for analysis program */ FLOAT CLEDSGeometry::AnalyzeEdges(DataFile *pListUnmatchedVerts) { CListIter CListIterIntEdge; CLEDSliteSiblingIter SiblingIter; UINT_32 uiNumForward, uiNumBackward, uiFaces, uiSoFar, i; CLEDSliteVertex *pFirstEURootVtx, *pOtherVtx; CLEDSliteEdgeUse *pEdge, *pEU; CDynamicArray arrayEdgeStats; FLOAT fMinLen = FLT_MAX; arrayEdgeStats.Init(4); CListIterIntEdge.Init(m_pCListEdges); pEdge = CListIterIntEdge.PeekFirst(); while (pEdge) { if (pEdge->GetLength() < fMinLen) fMinLen = pEdge->GetLength(); pFirstEURootVtx = pEdge->GetLEDSRootVtx(); uiNumForward = uiNumBackward = 0; SiblingIter.Init(pEdge); pEU = NULL; while (pEU != pEdge) { pEU = SiblingIter.PeekNextSiblingEU(); if (pEU->GetLEDSRootVtx() == pFirstEURootVtx) uiNumForward++; else uiNumBackward++; } if (uiNumForward != uiNumBackward) { #ifndef NDEBUG fprintf(stdout, "There is %ld edge use from ", uiNumForward); pFirstEURootVtx->GetPoint().Display(); fprintf(stdout, "to "); pEdge->GetLEDSOtherVtx()->GetPoint().Display(); fprintf(stdout, "but %ld edge uses in the opposite sense.\n", uiNumBackward); #endif if (pListUnmatchedVerts) { pOtherVtx = pEdge->GetLEDSNCEdgeUse()->GetLEDSRootVtx(); /* pListUnmatchedVerts->InsertForward(pOtherVtx, (INT_32)pOtherVtx); pListUnmatchedVerts->InsertForward(pFirstEURootVtx, (INT_32)pFirstEURootVtx); */ /* pListUnmatchedVerts->InsertLast(pOtherVtx, 0); pListUnmatchedVerts->InsertLast(pFirstEURootVtx, 0); */ pListUnmatchedVerts->AddItem(pOtherVtx); pListUnmatchedVerts->AddItem(pFirstEURootVtx); } } uiFaces = uiNumForward + uiNumBackward; if (!(*arrayEdgeStats.GetItem(uiFaces))) arrayEdgeStats.AddItem(1, uiFaces); else { uiSoFar = *arrayEdgeStats.GetItem(uiFaces); arrayEdgeStats.AddItem(uiSoFar+1, uiFaces); } pEdge = CListIterIntEdge.PeekNext(); } fprintf(stdout, "%ld edges.\n", m_pCListEdges->GetLength()); for (i=1; i<=(arrayEdgeStats.GetLastIndex()); i++) { if ((uiFaces = *arrayEdgeStats.GetItem(i))) fprintf(stdout, "\t%ld edges have %ld faces adjacent.\n", uiFaces, i); } return (fMinLen); } /* Get and print basic info about vertices for analysis program */ VOID CLEDSGeometry::AnalyzeVertices(FLOAT *pfMinX, FLOAT *pfMinY, FLOAT *pfMinZ, FLOAT *pfMaxX, FLOAT *pfMaxY, FLOAT *pfMaxZ) { CListIter CListIterIntVert; CLEDSliteVtxEdgeIter VtxEdgeIter; UINT_32 uiOrder, uiSoFar, i; CLEDSliteVertex *pVert; CLEDSliteEdgeUse *pFirstEU, *pEU; CDynamicArray arrayVertStats; Point pt; *pfMaxX = *pfMaxY = *pfMaxZ = -FLT_MAX; *pfMinX = *pfMinY = *pfMinZ = FLT_MAX; arrayVertStats.Init(20); CListIterIntVert.Init(m_pCListVertices); pVert = CListIterIntVert.PeekFirst(); while (pVert) { pt = pVert->GetPoint(); if (pt(X) > *pfMaxX) { *pfMaxX = pt(X); } else if (pt(X) < *pfMinX) { *pfMinX = pt(X); } if (pt(Y) > *pfMaxY) { *pfMaxY = pt(Y); } else if (pt(Y) < *pfMinY) { *pfMinY = pt(Y); } if (pt(Z) > *pfMaxZ) { *pfMaxZ = pt(Z); } else if (pt(Z) < *pfMinZ) { *pfMinZ = pt(Z); } VtxEdgeIter.Init(pVert); pFirstEU = VtxEdgeIter.PeekFirstVtxEdgeEU(); uiOrder = 0; pEU = NULL; while (pEU != pFirstEU) { pEU = VtxEdgeIter.PeekNextVtxEdgeEU(); uiOrder++; } if (!(*arrayVertStats.GetItem(uiOrder))) arrayVertStats.AddItem(1, uiOrder); else { uiSoFar = *arrayVertStats.GetItem(uiOrder); arrayVertStats.AddItem(uiSoFar+1, uiOrder); } pVert = CListIterIntVert.PeekNext(); } fprintf(stdout, "Bounding Box Info:\n"); fprintf(stdout, "\tMin X = %f, Max X = %f\n", *pfMinX, *pfMaxX); fprintf(stdout, "\tMin Y = %f, Max Y = %f\n", *pfMinY, *pfMaxY); fprintf(stdout, "\tMin Z = %f, Max Z = %f\n", *pfMinZ, *pfMaxZ); fprintf(stdout, "%ld vertices.\n", m_pCListVertices->GetLength()); for (i=1; i<=(arrayVertStats.GetLastIndex()); i++) { if ((uiOrder = (*arrayVertStats.GetItem(i)))) fprintf(stdout, "\t%ld vertices have valence %ld.\n", uiOrder, i); } } BOOL CLEDSGeometry::Analyze(DataFile *pListUnmatchedVerts, FLOAT fEpsilon) { FLOAT fMinX, fMinY, fMinZ, fMaxX, fMaxY, fMaxZ; FLOAT fMinEdgeLen; BrepType bPseudo; UINT_32 uiNumMerged; bPseudo = CheckPseudo2Manifold(TRUE); if (bPseudo == tManifold) { /* UINT_32 uiGenus = ((2 - m_pCLEDSTablesSTL->GetFaceCount() + (m_pCLEDSTablesSTL->GetEUcount()/2) - m_pCLEDSTablesSTL->GetVtxCount())/2); */ fprintf(stdout, "Shell is 2-manifold with genus %d.\n", m_uiGenus); } else if (bPseudo == tPseudoManifold) { fprintf(stdout, "Shell is pseudo-2-manifold.\n"); } else fprintf(stdout, "Shell is not pseudo-2-manifold.\n"); AnalyzeVertices(&fMinX, &fMinY, &fMinZ, &fMaxX, &fMaxY, &fMaxZ); fMinEdgeLen = AnalyzeEdges(pListUnmatchedVerts); AnalyzeFaces(); if ((!bPseudo) && pListUnmatchedVerts) { if (fEpsilon < 0) { fEpsilon = .1f*fMinEdgeLen; } fprintf(stdout, "Merging unmatched vertices within %f.\n",fEpsilon); uiNumMerged = MergeVertices(pListUnmatchedVerts, fEpsilon, fMinX, fMinY, fMinZ, fMaxX, fMaxY, fMaxZ); } CleanupManifoldTesting(); if ((!bPseudo) && uiNumMerged > 0) return (this->Analyze(NULL, fEpsilon)); else return bPseudo; } UINT_32 CLEDSGeometry::MergeVertices(DataFile *pListUnmatchedVerts, FLOAT fEps, FLOAT fMinX, FLOAT fMinY, FLOAT fMinZ, FLOAT fMaxX, FLOAT fMaxY, FLOAT fMaxZ) { DataFileIter CDataIterVert; CLEDSliteVertex *pVert, *pExistingVert, *pLastVert = NULL; // CLEDSliteEdgeUse *pFirstNewEU, *pNewEU, *pPrevEU; // CLEDSliteEdgeUse *pFirstExistingEU, *pExistingEU; UINT_32 uiPtsMerged = 0; CEpsilonVtxMerger *pMerger; pMerger = new CEpsilonVtxMerger; pMerger->Init(fEps, fMinX, fMinY, fMinZ, fMaxX, fMaxY, fMaxZ); // they aren't LIDs, but we just want duplicates contiguous in list pListUnmatchedVerts->Sort(lidCompare); CDataIterVert.Init(pListUnmatchedVerts); // pVert = *CDataIterVert.PeekFirstItem(); // while (pVert) while (CDataIterVert.Valid()) { pVert = *CDataIterVert.PeekNextItem(); if (pVert != pLastVert) { pExistingVert = pMerger->StoreVertex(pVert); if ((pExistingVert != NULL) && (pExistingVert != pVert)){ uiPtsMerged++; #ifndef NDEBUG fprintf(stdout, "Merging vertices: "); pVert->Display(); fprintf(stdout, "\t and: "); pExistingVert->Display(); #endif pExistingVert->MergeVtx(pVert); } } pLastVert = pVert; // pVert = *CDataIterVert.PeekNextItem(); } #ifndef NDEBUG fprintf(stdout, "Merged %lu vertices.\n", uiPtsMerged); #endif return uiPtsMerged; } VOID CLEDSGeometry::TestStuff() { CListIter CListIterIntFaces; CLEDSliteFace *pFace; CLEDSliteEdgeUse *pEUFirst, *pEU; //CLEDSEdgeUsePrev *pEUFirst, *pEU; CListIterIntFaces.Init(m_pCListFaces); pFace = CListIterIntFaces.PeekFirst(); while (pFace) { fprintf(stdout, "\nFace vertices:\n"); pEUFirst = pFace->GetLEDSOuterContourEU(); pEU = pEUFirst->GetLEDSPrevCEdgeUse(); fprintf(stdout, "\t"); pEU->GetLEDSRootVtx()->GetPoint().Display(); do { pEU = pEU->GetLEDSPrevCEdgeUse(); fprintf(stdout, "\t"); pEU->GetLEDSRootVtx()->GetPoint().Display(); } while (pEU != pEUFirst); pFace = CListIterIntFaces.PeekNext(); } /* CLEDSVertex *pVertexBuffer, *pVtx; CLEDSFace *pFaceBuffer; CLEDSEdgeUse *pEUBuffer, *pEU; Timer timer; timer.Start(); pEUBuffer = new CLEDSEdgeUse[30000]; pFaceBuffer = new CLEDSFace[10000]; pVertexBuffer = new CLEDSVertex[5000]; int i; for (i=0; i<30000; i++) { pEU = &pEUBuffer[i]; pEU->Init(); pVtx = &(pVertexBuffer[i%5000]); if ((i%5)==0) { pVtx->Init(vid1, this); pVtx->SetLEDSFirstEU(pEU); pEU->SetLEDSNVEdgeUse(pEU); } else { // We've seen this vertex before pPrevEU = pVtx->GetLEDSFirstEU(); pEU->SetLEDSNVEdgeUse(pPrevEU->GetLEDSNVEdgeUse()); pPrevEU->SetLEDSNVEdgeUse(pEU); } pEU->SetLEDSRootVtx(pVtx); for (i=0; i<10000; i++) { pFaceBuffer[i].Init(); } for (i=0; i<5000; i++) { pVertexBuffer[i].Init(); } timer.Stop(); DOUBLE secs = timer.GetSeconds(); fprintf(stdout, "Allocating, initializing took %f seconds\n",secs); */ } // // Creation and initialization of data structures // // STL multi-stage build functions VOID CLEDSGeometry::BeginSTLlidInfo() { #ifdef CHANGE_SIX m_pCListEdges->Init(); #endif //m_pCLEDSTablesSTL = new CLEDSTables; m_pCLEDSTablesSTL = new CLEDSTables >; m_pCLEDSTablesSTL->PreInit(this, m_bPrevPtrs); #ifdef TIMEFREE UINT_32 i; DataTripleFile,LID,LID,LID> *plidPrFile; Timer timer; timer.Start(); plidPrFile = new DataTripleFile,LID,LID,LID>; UINT_32 size = 12000000; plidPrFile->Init(size); for (i = 0; i < size; i++) plidPrFile->AddTriple(i,i,i); timer.Stop(); DOUBLE foo = timer.GetSeconds(); fprintf(stdout, "Building lid DataPairFile of size %ld took %f seconds\n", size, foo); Timer timer2; timer2.Start(); delete plidPrFile; timer2.Stop(); foo = timer2.GetSeconds(); fprintf(stdout, "Freeing lid DataPairFile of size %ld took %f seconds\n", size, foo); #endif } VOID CLEDSGeometry::EndSTLlidInfo() { #ifndef QUIET #ifdef __OS_IRIX__ struct rusage *prusage; long lPageFaultsPrev, lPageFaultsNow; #endif #endif if (m_pLIDmapVtx->GetCurrentLID() > 0) { #ifndef QUIET Timer timer, timer2, timer3, timer4, timer5; timer2.Start(); #endif m_pCLEDSTablesSTL->Process(&m_pEUs); #ifndef QUIET timer2.Stop(); DOUBLE foo = timer2.GetSeconds(); fprintf(stdout, "m_pCLEDSTablesSTL->Process() took %f seconds\n",foo); #ifdef __OS_IRIX__ prusage = new struct rusage; getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults so far: %d\n", lPageFaultsPrev); #endif timer.Start(); #endif m_pCLEDSTablesSTL->BuildVertices(&m_pVtxs, &m_pEUs, &m_pFaces); #ifndef QUIET timer.Stop(); foo = timer.GetSeconds(); fprintf(stdout, "BuildVertices took %f seconds\n",foo); #ifdef __OS_IRIX__ getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow; lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults during BuildVertices: %d\n", lPageFaultsNow - lPageFaultsPrev); #endif timer3.Start(); #endif m_pCLEDSTablesSTL->BuildEUs(&m_pEUs, &m_pVtxs, &m_pFaces); #ifndef QUIET timer3.Stop(); foo = timer3.GetSeconds(); fprintf(stdout, "BuildEUs took %f seconds\n",foo); #ifdef __OS_IRIX__ getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow; lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults during BuildEUs: %d\n", lPageFaultsNow - lPageFaultsPrev); #endif timer4.Start(); #endif m_pCLEDSTablesSTL->BuildFaces(&m_pFaces, &m_pEUs); #ifndef QUIET timer4.Stop(); foo = timer4.GetSeconds(); fprintf(stdout, "BuildFaces took %f seconds\n",foo); #ifdef __OS_IRIX__ getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow; lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults during BuildFaces: %d\n", lPageFaultsNow - lPageFaultsPrev); #endif #endif #ifdef CHANGE_G #ifndef QUIET timer5.Start(); #endif m_pCLEDSTablesSTL->BuildLists(&m_pEUs, &m_pVtxs, &m_pFaces); #ifndef QUIET timer5.Stop(); foo = timer5.GetSeconds(); fprintf(stdout, "BuildLists took %f seconds\n",foo); #ifdef __OS_IRIX__ getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow; lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults during BuildLists: %d\n", lPageFaultsNow - lPageFaultsPrev); #endif #endif #endif #ifdef LEDSDEBUG TestIterators(); #endif //Test iterator through edge list (doesn't have all EUs) #ifdef LEDSDEBUG CListIter CListIterIntEdge; CLEDSEdgeUse *pEdge; CListIterIntEdge.Init(m_pCListEdges); pEdge = (CLEDSEdgeUse *)CListIterIntEdge.PeekFirst(); while (pEdge) { pEdge->Display(); pEdge = (CLEDSEdgeUse *)CListIterIntEdge.PeekNext(); } #endif } #ifndef QUIET #ifdef __OS_IRIX__ getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow; lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults so Far: %d\n", lPageFaultsNow); #endif #endif delete m_pCLEDSTablesSTL; #ifndef QUIET #ifdef __OS_IRIX__ getrusage(RUSAGE_SELF, prusage); lPageFaultsPrev = lPageFaultsNow; lPageFaultsNow = prusage->ru_majflt; fprintf(stdout, "Page Faults during delete ledstables: %d\n", lPageFaultsNow - lPageFaultsPrev); #endif #endif INT_32 iGenus = ((2 - m_pCLEDSTablesSTL->GetFaceCount() + (m_pCLEDSTablesSTL->GetEUcount()/2) - m_pCLEDSTablesSTL->GetVtxCount())/2); m_uiGenus = (UINT_32)iGenus; } //// 1-stage build functions VOID CLEDSGeometry::OneStageAddFaceIC(CLEDSliteFace *pFace, CLEDSliteEdgeUse *pEU) { CListInt *pListInner = pFace->GetLEDSListInner(); if (!pListInner) { pListInner = new CListInt; pListInner->InsertLast(pEU, 0); pFace->SetLEDSListInner(pListInner); } else { pListInner->InsertLast(pEU,0); } } CLEDSliteFace *CLEDSGeometry::GetNewFace() { #ifndef LISTARRAY #ifdef BUFSIZE static CLEDSliteFace *pFaceBuffer; static UINT_32 uiFaceNum = BUFSIZE; #endif #endif CLEDSliteFace *pFace; #ifdef BUFSIZE if (uiFaceNum == BUFSIZE) { // Initialization needs to allocate the first one. #ifdef LISTARRAY m_pCListFaces->InsertArray(pFaceBuffer, sizeof(CLEDSliteFace), BUFSIZE); #endif pFaceBuffer = new CLEDSliteFace[BUFSIZE]; uiFaceNum = 0; } pFace = &(pFaceBuffer[uiFaceNum++]); #else pFace = new CLEDSliteFace; #endif pFace->Init(this); #ifndef LISTARRAY m_pCListFaces->InsertLast(pFace, 0); #endif return pFace; } CLEDSliteEdgeUse *CLEDSGeometry::GetNewEU() { #ifndef LISTARRAY #ifdef BUFSIZE static CLEDSliteEdgeUse *pEUBuffer; static UINT_32 uiEUNum = BUFSIZE; #endif #endif CLEDSliteEdgeUse *pEU; #ifdef BUFSIZE if (uiEUNum == BUFSIZE) { #ifdef LISTARRAY m_pCListEUs->InsertArray(pEUBuffer, sizeof(CLEDSliteEdgeUse), BUFSIZE); #endif if (m_bPrevPtrs) pEUBuffer = new CLEDSEdgeUsePrev[BUFSIZE]; else pEUBuffer = new CLEDSliteEdgeUse[BUFSIZE]; uiEUNum = 0; } // Hmm, built-in arrays don't follow virtual pointers if (m_bPrevPtrs) pEU = &(((CLEDSEdgeUsePrev *)pEUBuffer)[uiEUNum++]); else pEU = &(pEUBuffer[uiEUNum++]); #else if (m_bPrevPtrs) pEU = new CLEDSEdgeUsePrev; else pEU = new CLEDSliteEdgeUse; #endif pEU->Init(this); #ifndef LISTARRAY m_pCListEUs->InsertLast(pEU, 0); #endif return pEU; } //// STL 1-stage build functions VOID CLEDSGeometry::STLOneStageAddEdge(CLEDSliteEdgeUse *pEU, Point *pPt1, Point *pPt2) { CLEDSliteVertex *pVtx1, **ppVtx1; CLEDSliteVertex *pVtx2, **ppVtx2; CLEDSliteEdgeUse *pPrevEU, **ppPrevEU, *pPrevEU2; #ifndef LISTARRAY #ifdef BUFSIZE static CLEDSliteVertex *pVertexBuffer; static UINT_32 uiVertexNum = BUFSIZE; #endif #endif Triple Triple1, Triple2; Triple1.SetTriple((*pPt1)(X), (*pPt1)(Y), (*pPt1)(Z)); Triple2.SetTriple((*pPt2)(X), (*pPt2)(Y), (*pPt2)(Z)); #ifdef BUFSIZE if (uiVertexNum == BUFSIZE) { #ifdef LISTARRAY m_pCListVertices->InsertArray(pVertexBuffer, sizeof(CLEDSliteVertex), BUFSIZE); #endif pVertexBuffer = new CLEDSliteVertex[BUFSIZE]; uiVertexNum = 0; } #endif ppVtx1 = m_pVtxHashTable->Peek(Triple1); if (ppVtx1) { // We've seen this vertex before pVtx1 = *ppVtx1; if (!(pVtx1->GetLEDSFirstEU())) { // hmm, I don't think we should ever get here. replace with assert? // make a circular list of one elt with the FirstEU and NVEdgeUse pts pVtx1->SetLEDSFirstEU(pEU); pEU->SetLEDSNVEdgeUse(pEU); } else { pPrevEU = pVtx1->GetLEDSFirstEU(); // insert the new EU after the first one off the vtx. pEU->SetLEDSNVEdgeUse(pPrevEU->GetLEDSNVEdgeUse()); pPrevEU->SetLEDSNVEdgeUse(pEU); } } else { // This is a new vertex we haven't seen before. #ifdef BUFSIZE pVtx1 = &(pVertexBuffer[uiVertexNum++]); #else pVtx1 = new CLEDSliteVertex; #endif pVtx1->Init(*pPt1, this); // make a circular list of one elt with the FirstEU and NVEdgeUse pts pVtx1->SetLEDSFirstEU(pEU); pEU->SetLEDSNVEdgeUse(pEU); // add it to list of vertices #ifndef LISTARRAY m_pCListVertices->InsertLast(pVtx1, 0); // add it to the vtx hash table m_pVtxHashTable->Insert(&pVtx1, Triple1); #endif } // in either case, finish initializing the EU. pEU->SetLEDSRootVtx(pVtx1); #ifdef BUFSIZE if (uiVertexNum == BUFSIZE) { #ifdef LISTARRAY m_pCListVertices->InsertArray(pVertexBuffer, sizeof(CLEDSliteVertex), BUFSIZE); #endif pVertexBuffer = new CLEDSliteVertex[BUFSIZE]; uiVertexNum = 0; } #endif ppVtx2 = m_pVtxHashTable->Peek(Triple2); if (ppVtx2) { // We've seen this vertex before pVtx2 = *ppVtx2; } else { // This is a new vertex we haven't seen before. #ifdef BUFSIZE pVtx2 = &(pVertexBuffer[uiVertexNum++]); #else pVtx2 = new CLEDSliteVertex; #endif pVtx2->Init(*pPt2, this); // add it to list of vertices #ifndef LISTARRAY m_pCListVertices->InsertLast(pVtx2, 0); // add it to the vtx hash table m_pVtxHashTable->Insert(&pVtx2, Triple2); #endif } Pair prEndPts; // order the endpts "lexicographically," // since we want to hash the undirected edge if (pVtx1 < pVtx2) prEndPts.Init((UINT_32)pVtx1, (UINT_32)pVtx2); else prEndPts.Init((UINT_32)pVtx2, (UINT_32)pVtx1); // Check to see if the edge is in the hash table already ppPrevEU = m_pEUHashTable->Peek(prEndPts); if (ppPrevEU) { pPrevEU = *ppPrevEU; pPrevEU2 = pPrevEU->GetLEDSSiblingEdgeUse(); if (pPrevEU2) { pEU->SetLEDSSiblingEdgeUse(pPrevEU2); } else { pEU->SetLEDSSiblingEdgeUse(pPrevEU); } pPrevEU->SetLEDSSiblingEdgeUse(pEU); } else { // it's a new edge; add it to the edge list. m_pCListEdges->InsertLast(pEU, 0); // add it to the veu hash table m_pEUHashTable->Insert(&pEU, prEndPts); } } VOID CLEDSGeometry::BeginSTLOneStageInfo() { m_pCListEdges->Init(); m_pCListVertices->Init(); m_pCListEUs->Init(); m_pCListFaces->Init(); m_pVtxHashTable = new COpenHashTable >; // m_pVtxHashTable->Init(8191); m_pVtxHashTable->Init(); #ifdef SHOWSIZES size_t size = sizeof(*(m_pVtxHashTable->GetData())); fprintf(stdout, "Vertex Hash table entry sizeof is %d\n", size); #endif // m_pEUHashTable = new COpenHashTable >; // m_pEUHashTable = new COpenHashTable >; m_pEUHashTable = new COpenHashTable >; // m_pEUHashTable->Init(20011); m_pEUHashTable->Init(); #ifdef SHOWSIZES size = sizeof(*(m_pEUHashTable->GetData())); fprintf(stdout, "Edge Hash table entry sizeof is %d\n", size); #endif #ifdef LISTARRAY if (m_bPrevPtrs) pEUBuffer = new CLEDSEdgeUsePrev[BUFSIZE]; else pEUBuffer = new CLEDSliteEdgeUse[BUFSIZE]; pFaceBuffer = new CLEDSliteFace[BUFSIZE]; m_pVertexBuffer = new CLEDSliteVertex[BUFSIZE]; #endif } VOID CLEDSGeometry::EndSTLOneStageInfo() { #ifdef LISTARRAY m_pCListEUs->InsertArray(pEUBuffer, sizeof(CLEDSliteEdgeUse), uiEUNum); m_pCListFaces->InsertArray(pFaceBuffer, sizeof(CLEDSliteFace), uiFaceNum); m_pCListVertices->InsertArray(m_pVertexBuffer, sizeof(CLEDSliteVertex), m_uiVertexNum); #endif delete m_pVtxHashTable; delete m_pEUHashTable; m_pEUHashTable = NULL; m_pVtxHashTable = NULL; m_boolPtrsUpdated = TRUE; } //// SIF 1-stage build functions VOID CLEDSGeometry::BeginSIFOneStageInfo() { m_pCListEdges->Init(); m_pCListVertices->Init(); m_pCListEUs->Init(); m_pCListFaces->Init(); m_pEUHashTable = new COpenHashTable >; // m_pEUHashTable->Init(20011); m_pEUHashTable->Init(); #ifdef LISTARRAY if (m_bPrevPtrs) pEUBuffer = new CLEDSEdgeUsePrev[BUFSIZE]; else pEUBuffer = new CLEDSliteEdgeUse[BUFSIZE]; pFaceBuffer = new CLEDSliteFace[BUFSIZE]; #endif } VOID CLEDSGeometry::EndSIFOneStageInfo() { #ifdef LISTARRAY m_pCListEUs->InsertArray(pEUBuffer, sizeof(CLEDSliteEdgeUse), uiEUNum); m_pCListFaces->InsertArray(pFaceBuffer, sizeof(CLEDSliteFace), uiFaceNum); #endif delete m_pEUHashTable; m_pEUHashTable = NULL; m_boolPtrsUpdated = TRUE; } VOID CLEDSGeometry::SIFOneStageInitVertexList(UINT_32 uiNumVertices) { m_pVertexBuffer = new CLEDSliteVertex[uiNumVertices]; m_pPointBuffer = new Point[uiNumVertices]; m_uiVertexNum = uiNumVertices; } VOID CLEDSGeometry::SIFOneStageInitTriangleList(UINT_32 uiNumTriangles) { // BUG!!! (OPTIMIZATION opportunity, really) -- can allocate // number of faces and edge uses exactly for SIF 2.0 input } VOID CLEDSGeometry::SIFOneStageAddVertex(UINT_32 uiID, FLOAT fX, FLOAT fY, FLOAT fZ, FLOAT fW) { CLEDSliteVertex *pVtx; Point *pPtCur; ASSERT(uiID < m_uiVertexNum); pVtx = &(m_pVertexBuffer[uiID]); pPtCur = &(m_pPointBuffer[uiID]); pPtCur->Set(fX, fY, fZ, fW); pVtx->Init(*pPtCur, this); m_pCListVertices->InsertLast(pVtx, 0); } VOID CLEDSGeometry::SIFOneStageAddEdge(CLEDSliteEdgeUse *pEU, UINT_32 uiVtx1, UINT_32 uiVtx2) { CLEDSliteVertex *pVtx1, *pVtx2; CLEDSliteEdgeUse *pPrevEU, **ppPrevEU, *pPrevEU2; Pair prEndPts; ASSERT(uiVtx1 < m_uiVertexNum); ASSERT(uiVtx2 < m_uiVertexNum); pVtx1 = &(m_pVertexBuffer[uiVtx1]); pVtx2 = &(m_pVertexBuffer[uiVtx2]); if (!(pVtx1->GetLEDSFirstEU())) { // make a circular list of one elt with the FirstEU and NVEdgeUse pts pVtx1->SetLEDSFirstEU(pEU); pEU->SetLEDSNVEdgeUse(pEU); } else { pPrevEU = pVtx1->GetLEDSFirstEU(); // insert the new EU after the first one off the vtx. pEU->SetLEDSNVEdgeUse(pPrevEU->GetLEDSNVEdgeUse()); pPrevEU->SetLEDSNVEdgeUse(pEU); } // in either case, finish initializing the EU. pEU->SetLEDSRootVtx(pVtx1); // "order" the endpts lexicographically, // since we want to hash the undirected edge if (pVtx1 < pVtx2) prEndPts.Init((UINT_32)pVtx1, (UINT_32)pVtx2); else prEndPts.Init((UINT_32)pVtx2, (UINT_32)pVtx1); // Check to see if the edge is in the hash table already ppPrevEU = m_pEUHashTable->Peek(prEndPts); if (ppPrevEU) { pPrevEU = *ppPrevEU; pPrevEU2 = pPrevEU->GetLEDSSiblingEdgeUse(); if (pPrevEU2) { pEU->SetLEDSSiblingEdgeUse(pPrevEU2); } else { pEU->SetLEDSSiblingEdgeUse(pPrevEU); } pPrevEU->SetLEDSSiblingEdgeUse(pEU); } else { // it's a new edge; add it to the edge list. m_pCListEdges->InsertLast(pEU, 0); // add it to the veu hash table m_pEUHashTable->Insert(&pEU, prEndPts); } } VOID CLEDSGeometry::WriteSTL(FILE *fpOutputFile) { CListIter CListIterIntFace; CLEDSliteFace *pFace; CListIterIntFace.Init(m_pCListFaces); pFace = CListIterIntFace.PeekFirst(); while (pFace) { //WriteSTLTriangle(Point); pFace->WriteSTL(fpOutputFile); pFace = CListIterIntFace.PeekNext(); } } // Define this here to avoid mathlib/datalib interdependence UINT_32 Hash(const Pair & ptPr) { UINT_32 ui1, ui2; /* Point Pt; Pt = ptPr.GetFirst(); ui1 = Hash(Pt); Pt = ptPr.GetSecond(); ui2 = Hash(Pt); */ ui1 = Hash(ptPr.GetFirst()); ui2 = Hash(ptPr.GetSecond()); return (ui1 + ui2); } UINT_32 Hash(Triple & floatTrip) { UINT_32 ui, uiX, uiY, uiZ; FLOAT fX, fY, fZ; fX = floatTrip.GetFirst(); fY = floatTrip.GetSecond(); fZ = floatTrip.GetThird(); uiX = *((UINT_32 *)(&fX)); uiY = *((UINT_32 *)(&fY)); uiZ = *((UINT_32 *)(&fZ)); ui = uiX + uiY + uiZ; return (ui); }