#include "ledsvertex.h" #include "ledsedgeuse.h" #include "ledsface.h" #include "ledsgeometry.h" // (Steve) #include using namespace std; ////////////////////////////////////////////////////////////////////////////// // CLEDSliteVertex Class // CLEDSliteVertex::CLEDSliteVertex() { m_uiID = 0; m_pledsFirstEU = NULL; m_pExtra = NULL; // this makes the pt null Null(); } CLEDSliteVertex::~CLEDSliteVertex() { // Uninit(); } // We may change identifiers from ints to strings VOID CLEDSliteVertex::Init(Point pt, CLEDSGeometry *pCLEDSGeometry) { CVertex::Init(); m_pt = pt; m_pCLEDSGeometry = pCLEDSGeometry; } VOID CLEDSliteVertex::Init(Point pt, CLEDSliteEdgeUse *pledsFirstEU, CLEDSGeometry *pCLEDSGeometry) { CVertex::Init(); m_pt = pt; m_pledsFirstEU = pledsFirstEU; m_pCLEDSGeometry = pCLEDSGeometry; } VOID CLEDSliteVertex::Uninit() { m_uiID = 0; m_pledsFirstEU = NULL; m_pExtra = NULL; CVertex::Uninit(); } VOID CLEDSliteVertex::RemoveZeroLengthEdges(CLEDSliteVertex *pVtx1, CLEDSliteVertex *pVtx2) { CLEDSliteVtxEdgeIter VtxEdgeIter1, VtxEdgeIter2; CLEDSliteEdgeUse *pFirstEU1, *pEU1;// *pNextInContourEU; VtxEdgeIter1.Init(pVtx1); pFirstEU1 = VtxEdgeIter1.PeekFirstVtxEdgeEU(); pEU1 = NULL; while (pEU1 != pFirstEU1) { pEU1 = VtxEdgeIter1.PeekNextVtxEdgeEU();// EU rooted at Vtx1 if (pEU1->GetLEDSOtherVtx() == pVtx2) { #ifndef NDEBUG fprintf(stdout, "Merge will create zero-length edge.\n"); #endif if (pEU1 == pEU1->GetLEDSNCEdgeUse()->GetLEDSNCEdgeUse()->GetLEDSNCEdgeUse()){ pEU1->GetLEDSFace()->Delete(); } else { #ifndef NDEBUG fprintf(stdout, "Non-triangular face.\n"); #endif pEU1->Delete(); } } } } // This is a helper function for the MergeVtx function. It figures // out which of the EUs that use pVtx1 but aren't rooted at it // will become siblings of EUs rooted at pVtx2, and chains their sibling // pointers together. Need to call it twice, with both orders of // the vertices being merged, to match up all the EUs' siblings. VOID CLEDSliteVertex::MatchSiblingEdgeUses(CLEDSliteVertex *pVtx1, CLEDSliteVertex *pVtx2) { CLEDSliteVtxEdgeIter VtxEdgeIter1, VtxEdgeIter2; CLEDSliteEdgeUse *pFirstEU1, *pEU1, *pPrevEU1, *pPrevEU1Sib; CLEDSliteEdgeUse *pFirstEU2, *pEU2, *pEU2Sib; VtxEdgeIter1.Init(pVtx1); pFirstEU1 = VtxEdgeIter1.PeekFirstVtxEdgeEU(); pEU1 = NULL; while (pEU1 != pFirstEU1) { pEU1 = VtxEdgeIter1.PeekNextVtxEdgeEU();// EU rooted at Vtx1 pPrevEU1 = pEU1->GetLEDSPrevCEdgeUse(); // EU terminating at Vtx1 VtxEdgeIter2.Init(pVtx2); pFirstEU2 = VtxEdgeIter2.PeekFirstVtxEdgeEU(); pEU2 = NULL; while (pEU2 != pFirstEU2) { pEU2 = VtxEdgeIter2.PeekNextVtxEdgeEU(); //EU rooted at Vtx2 if (pPrevEU1->GetLEDSRootVtx() == pEU2->GetLEDSOtherVtx()) { pEU2Sib = pEU2->GetLEDSSiblingEdgeUse(); pPrevEU1Sib = pPrevEU1->GetLEDSSiblingEdgeUse(); #ifndef NDEBUG fprintf(stdout, "Removing edge from global list.\n"); #endif // remove the pEU2 and its siblings from the global list of edges // BUG: need to remove all siblings if more than one. // Write a separate LEDSGeometry method, RemoveEdge. // NEW BUG?? I don't know if Remove will work here!!! Not tested!!! pEU2->GetLEDSGeometry()->GetCListEdges()-> Remove(pEU2); // RemoveForward((INT_32)pEU2); pEU2->GetLEDSGeometry()->GetCListEdges()-> Remove(pEU2Sib); // RemoveForward((INT_32)pEU2Sib); // combine the two sets of sibling pointers // (common case each set has only one EU, but this code works // for any number, since if no sibs sibling ptr pts to self) pPrevEU1->SetLEDSSiblingEdgeUse(pEU2Sib); pEU2->SetLEDSSiblingEdgeUse(pPrevEU1Sib); } } // VtxEdgeIter2.Uninit(); } } VOID CLEDSliteVertex::MergeVtx(CLEDSliteVertex *pNewVtx) { CLEDSliteEdgeUse *pFirstEU, *pEU, *pEU2ndOld, *pEU2ndNew; CLEDSliteVtxEdgeIter VtxEdgeIter; RemoveZeroLengthEdges(this, pNewVtx); RemoveZeroLengthEdges(pNewVtx, this); MatchSiblingEdgeUses(this, pNewVtx); MatchSiblingEdgeUses(pNewVtx, this); // update all of the new vertices EU's Root Vertex fields // to point to the old one VtxEdgeIter.Init(pNewVtx); pFirstEU = VtxEdgeIter.PeekFirstVtxEdgeEU(); pEU = NULL; while (pEU != pFirstEU) { pEU = VtxEdgeIter.PeekNextVtxEdgeEU(); pEU->SetLEDSRootVtx(this); } // combine the two sets of EUs for the two vertices pEU2ndOld = m_pledsFirstEU->GetLEDSNVEdgeUse(); pEU2ndNew = pNewVtx->GetLEDSFirstEU()->GetLEDSNVEdgeUse(); m_pledsFirstEU->SetLEDSNVEdgeUse(pEU2ndNew); pNewVtx->GetLEDSFirstEU()->SetLEDSNVEdgeUse(pEU2ndOld); // NEW BUG?? I don't know if Remove will work here!!! Not tested!!! pNewVtx->GetLEDSGeometry()->GetCListVertices()-> Remove(pNewVtx); // RemoveForward((INT_32)pNewVtx); } VOID CLEDSliteVertex::CalculateBound(CBound *pCBound) { ASSERT( pCBound != NULL ); pCBound->Insert(m_pt); } VOID CLEDSliteVertex::CalculateBoundOffset(CBound *pCBound, FLOAT fDir, FLOAT fOffset) { Point pt; Vector vNormal; ASSERT( pCBound != NULL ); ASSERT( fDir == 1.0 || fDir == -1.0f ); vNormal = m_vNormal * (fDir * fOffset); pt = m_pt + vNormal; pCBound->Insert(pt); } VOID CLEDSliteVertex::CalculateNormal(const Point &pt0, const Point &pt1, const Point &pt2, const Point &pt3) { UINT_32 i; Vector v[4]; Vector vNorm[4]; v[0] = pt0 - m_pt; v[1] = pt1 - m_pt; v[2] = pt2 - m_pt; v[3] = pt3 - m_pt; vNorm[0] = v[0] * v[1]; vNorm[1] = v[1] * v[2]; vNorm[2] = v[2] * v[3]; vNorm[3] = v[3] * v[0]; m_vNormal.Null(); for ( i = 0; i < 4; i++ ) { m_vNormal = m_vNormal + vNorm[i]; } m_vNormal.Normalize(); } VOID CLEDSliteVertex::Null() { m_pt.Null(); } BOOL CLEDSliteVertex::Homogenize() { return m_pt.Homogenize(); } VOID CLEDSliteVertex::Display() const { fprintf(stdout, "Vertex:\tPoint = "); m_pt.Display(8); } #ifdef WRITE_VERTEX_OUTPUT VOID CLEDSliteVertex::WriteSIF(UINT_32 uiLevel) const { WriteIndent(uiLevel); fprintf(gfpOutputFile, "(%s %ld ", gcppcSIFReservedWords[sifrwtVertex], m_lid); WriteSIFPoint(m_pt); fprintf(gfpOutputFile, ")\n"); } VOID CLEDSliteVertex::WriteSTLRef(UINT_32 /*uiLevel*/, const Matrix &m) const { Point pt; fprintf(gfpOutputFile, " %s ", gcppcSTLReservedWords[stlrwtVertex]); pt = m * m_pt; WriteSTLPoint(m_pt); fprintf(gfpOutputFile, "\n"); } VOID CLEDSliteVertex::WriteDSG(UINT_32 uiLevel) const { WriteSIF(uiLevel); } #endif // WRITE_VERTEX_OUTPUT /************************************************************************ Functions for constructing ordered list(s) of face-connected edges around a vertex. Puts each ordered list in a contour (ordered CW when viewed from "outside" the part) and makes these the contours in a componentList. These functions really aren't general purpose because they muck around with the Extra fields. ************************************************************************/ // Where should these go? Need declarations, too. // As well as real functions, of course. BOOL inContour(CLEDSliteEdgeUse *pEUEdge) { if (pEUEdge->GetExtra() != NULL) return TRUE; else return FALSE; } VOID setExtraInContour(CLEDSliteEdgeUse *pEUEdge) { int foo; pEUEdge->SetExtra(&foo); } // Construct the ordered list(s) of face-connected edges around vertex // Has been tested with a vertex with two disk cycles. CListInt *CLEDSliteVertex::MakeVtxEUCyclesList() { CLEDSliteEdgeUse *pEUedge, *pEUfirstEdge; CListInt *newComponentList = NULL; CListInt *newContour; CLEDSliteVtxEdgeIter *VtxEdgeIter = new CLEDSliteVtxEdgeIter; VtxEdgeIter->Init(this); pEUfirstEdge = pEUedge = VtxEdgeIter->PeekFirstVtxEdgeEU(); newComponentList = new CListInt; newComponentList->Init(); do { // need to define inContour function if (pEUedge != NULL && !inContour(pEUedge)) { newContour = new CListInt; newContour->Init(); newComponentList->InsertLast(newContour, 0); newContour = MakeVtxEUList(pEUedge, newContour); } pEUedge = VtxEdgeIter->PeekNextVtxEdgeEU(); } while (pEUedge && (pEUedge != pEUfirstEdge)); delete VtxEdgeIter; return (newComponentList); } CListInt *CLEDSliteVertex::MakeVtxEUList(CLEDSliteEdgeUse *pEUedge, CListInt *newContour) { CLEDSliteEdgeUse *pEUfirstEdge, *pEUcurEdge; pEUcurEdge = pEUfirstEdge = pEUedge; do { newContour->InsertLast(pEUcurEdge, 0); setExtraInContour(pEUcurEdge); pEUcurEdge = GetNextEdge(pEUcurEdge); } while (pEUcurEdge != pEUfirstEdge); return (newContour); } CLEDSliteEdgeUse *CLEDSliteVertex::GetNextEdge(CLEDSliteEdgeUse *pEUcurEdge) { CLEDSliteEdgeUse *pEUsiblingEdge, *pEUnextEdge; ASSERT (pEUcurEdge != NULL); pEUsiblingEdge = pEUcurEdge->GetLEDSSiblingEdgeUse(); // Check that object has had edges grouped into pairs if pseudo-2-manifold ASSERT(pEUsiblingEdge->GetLEDSSiblingEdgeUse() == pEUcurEdge); pEUnextEdge = pEUsiblingEdge->GetLEDSNCEdgeUse(); ASSERT(pEUnextEdge->GetLEDSRootVtx() == pEUcurEdge->GetLEDSRootVtx()); return pEUnextEdge; // Do I need to figure out how to do this in LEDS? // It's for that case of all new begin edges where the face is old. /* if (!faceContour->extra) { initExtra(faceContour); (*(SLstmt *)(faceContour->extra)).contour = sliceContour; } */ } ////////////////////////////////////////////////////////////////////////////// // CLEDSVertex Class // CLEDSVertex::CLEDSVertex() { m_lidLID = NON_LID; m_lidFirstEU = NON_LID; } CLEDSVertex::~CLEDSVertex() { // Uninit(); } VOID CLEDSVertex::Init(LID lidLID, LID lidFirstEU, Point pt, CLEDSGeometry *pCLEDSGeometry, UINT_32 uiOrigName) { CVertex::Init(); m_lidLID = lidLID; m_pt = pt; m_lidFirstEU = lidFirstEU; m_uiID = uiOrigName; m_pCLEDSGeometry = pCLEDSGeometry; } VOID CLEDSVertex::Uninit() { m_lidLID = NON_LID; m_lidFirstEU = NON_LID; CLEDSliteVertex::Uninit(); } VOID CLEDSVertex::Display() const { fprintf(stdout, "Vertex:\tPoint = "); m_pt.Display(); cout << " LID " << m_lidLID << " 1st EU lid " << m_lidFirstEU << endl; if (m_pledsFirstEU != NULL) { cout << " 1st EU :"; m_pledsFirstEU->Display(); } } CLEDSEdgeUse *CLEDSVertex::GetSafeLEDSFirstEU() const { if (m_pCLEDSGeometry->GetPtrsUpdated() == TRUE) return ((CLEDSEdgeUse *)m_pledsFirstEU); else return ((CLEDSEdgeUse *)m_pCLEDSGeometry->GetLIDmapEU()-> GetPtr(m_lidFirstEU)); } /************************************************************************ Functions for constructing ordered list(s) of face-connected edges around a vertex. Puts each ordered list in a contour (ordered CW when viewed from "outside" the part) and makes these the contours in a componentList. These functions really aren't general purpose because they muck around with the Extra fields. ************************************************************************/ /* // Where should these go? Need declarations, too. // As well as real functions, of course. BOOL inContour(CLEDSEdgeUse *pEUEdge) { if (pEUEdge->GetExtra() != NULL) return TRUE; else return FALSE; } VOID setExtraInContour(CLEDSEdgeUse *pEUEdge) { int foo; pEUEdge->SetExtra(&foo); } // Construct the ordered list(s) of face-connected edges around vertex // Has been tested with a vertex with two disk cycles. CListInt *CLEDSVertex::MakeVtxEUCyclesList() { CLEDSEdgeUse *pEUedge, *pEUfirstEdge; CListInt *newComponentList = NULL; CListInt *newContour; CLEDSVtxEdgeIter *VtxEdgeIter = new CLEDSVtxEdgeIter; VtxEdgeIter->Init(this); pEUfirstEdge = pEUedge = VtxEdgeIter->PeekFirstVtxEdgeEU(); newComponentList = new CListInt; newComponentList->Init(); do { // need to define inContour function if (pEUedge != NULL && !inContour(pEUedge)) { newContour = new CListInt; newContour->Init(); newComponentList->InsertLast(newContour, 0); newContour = MakeVtxEUList(pEUedge, newContour); } pEUedge = VtxEdgeIter->PeekNextVtxEdgeEU(); } while (pEUedge && (pEUedge != pEUfirstEdge)); delete VtxEdgeIter; return (newComponentList); } CListInt *CLEDSVertex::MakeVtxEUList(CLEDSEdgeUse *pEUedge, CListInt *newContour) { CLEDSEdgeUse *pEUfirstEdge, *pEUcurEdge; pEUcurEdge = pEUfirstEdge = pEUedge; do { newContour->InsertLast(pEUcurEdge, 0); setExtraInContour(pEUcurEdge); pEUcurEdge = GetNextEdge(pEUcurEdge); } while (pEUcurEdge != pEUfirstEdge); return (newContour); } CLEDSEdgeUse *CLEDSVertex::GetNextEdge(CLEDSEdgeUse *pEUcurEdge) { CLEDSEdgeUse *pEUsiblingEdge, *pEUnextEdge; ASSERT (pEUcurEdge != NULL); pEUsiblingEdge = pEUcurEdge->GetLEDSSiblingEdgeUse(); // Check that object has had edges grouped into pairs if pseudo-2-manifold ASSERT(pEUsiblingEdge->GetLEDSSiblingEdgeUse() == pEUcurEdge); pEUnextEdge = pEUsiblingEdge->GetLEDSNCEdgeUse(); ASSERT(pEUnextEdge->GetLEDSRootVtx() == pEUcurEdge->GetLEDSRootVtx()); return pEUnextEdge; // Do I need to figure out how to do this in LEDS? // It's for that case of all new begin edges where the face is old. // if (!faceContour->extra) // { // initExtra(faceContour); // (*(SLstmt *)(faceContour->extra)).contour = sliceContour; // } } */ ////////////////////////////////////////////////////////////////////////////// // CLEDSliteVtxEdgeIter Class // CLEDSliteVtxEdgeIter::CLEDSliteVtxEdgeIter() { m_pledsEdgeIter = NULL; m_pCGeometry = NULL; } CLEDSliteVtxEdgeIter::~CLEDSliteVtxEdgeIter() { } VOID CLEDSliteVtxEdgeIter::Init(CLEDSliteVertex *pCLEDSVertex) { m_pCGeometry = pCLEDSVertex; } VOID CLEDSliteVtxEdgeIter::Uninit() { m_pCGeometry = NULL; } BOOL CLEDSliteVtxEdgeIter::Valid() { return (m_pledsEdgeIter != NULL); } CLEDSliteEdgeUse *CLEDSliteVtxEdgeIter::PeekFirstVtxEdgeEU() { m_pledsEdgeIter = ((CLEDSliteVertex*)m_pCGeometry)->GetLEDSFirstEU(); return (m_pledsEdgeIter); } CLEDSliteEdgeUse *CLEDSliteVtxEdgeIter::PeekNextVtxEdgeEU() { /* if (m_pledsEdgeIter == NULL) m_pledsEdgeIter = ((CLEDSVertex*)m_pCGeometry)->GetLEDSFirstEU(); else */ m_pledsEdgeIter = m_pledsEdgeIter->GetLEDSNVEdgeUse(); return (m_pledsEdgeIter); } ////////////////////////////////////////////////////////////////////////////// // CLEDSVtxEdgeIter Class // CLEDSVtxEdgeIter::CLEDSVtxEdgeIter() { } CLEDSVtxEdgeIter::~CLEDSVtxEdgeIter() { } VOID CLEDSVtxEdgeIter::Uninit() { } CLEDSliteEdgeUse *CLEDSVtxEdgeIter::PeekFirstVtxEdgeEU() { m_pledsEdgeIter = ((CLEDSVertex*)m_pCGeometry)->GetSafeLEDSFirstEU(); return ((CLEDSEdgeUse *)m_pledsEdgeIter); } CLEDSliteEdgeUse *CLEDSVtxEdgeIter::PeekNextVtxEdgeEU() { /* if (m_pledsEdgeIter == NULL) m_pledsEdgeIter = ((CLEDSVertex*)m_pCGeometry)->GetSafeLEDSFirstEU(); else */ m_pledsEdgeIter = ((CLEDSEdgeUse *)m_pledsEdgeIter)->GetSafeLEDSNVEdgeUse(); return ((CLEDSEdgeUse *)m_pledsEdgeIter); } // Auxilliary function int ZVertexCompare(const void *arg1, const void *arg2) { CLEDSVertex *pCLEDSVertex1 = * (CLEDSVertex **) arg1; CLEDSVertex *pCLEDSVertex2 = * (CLEDSVertex **) arg2; FLOAT fz1 = (pCLEDSVertex1->GetPoint())(Z); FLOAT fz2 = (pCLEDSVertex2->GetPoint())(Z); // Assumes normalized points if (fz1 < fz2) { return (-1); } else if (fz1 > fz2) { return (1); } else { return (0); } }