c93adf402b
- aggiunta funzione SurfTriMesh::GeneralizedCut per taglio TriMesh con curva che rappresenta sezione di cilindro infinito.
912 lines
47 KiB
C++
912 lines
47 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2019-2019
|
|
//----------------------------------------------------------------------------
|
|
// File : SurfTriMeshBooleans.cpp Data : 27.05.19 Versione : 2.1e5
|
|
// Contenuto : Implementazione delle funzioni booleane per SurfFTrimesh.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 10.05.19 LM Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include "SurfTriMesh.h"
|
|
#include "CurveLine.h"
|
|
#include "CurveComposite.h"
|
|
#include "SurfFlatRegion.h"
|
|
#include "DistPointLine.h"
|
|
#include "Triangulate.h"
|
|
#include "GeoConst.h"
|
|
#include "/EgtDev/Include/EgkCurve.h"
|
|
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
|
#include "/EgtDev/Include/EgkIntersLineTria.h"
|
|
#include "/EgtDev/Include/EgkIntersTriaTria.h"
|
|
#include "/EgtDev/Include/EGkChainCurves.h"
|
|
#include <algorithm>
|
|
|
|
//----------------------------------------------------------------------------
|
|
struct TriaInOut {
|
|
Triangle3d trTria ;
|
|
bool bTriaInside ;
|
|
} ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
FindRectangleTriangleIntersectionSegment(const Point3d ptP1, const Point3d ptP2, const Point3d ptP3, const Point3d ptP4,
|
|
const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg)
|
|
{
|
|
// Definisco i due triangoli formanti il rettangolo
|
|
Triangle3d trTria1, trTria2 ;
|
|
trTria1.Set( ptP1, ptP2, ptP4) ;
|
|
trTria2.Set( ptP2, ptP3, ptP4) ;
|
|
trTria1.Validate() ;
|
|
trTria2.Validate() ;
|
|
Vector3d vtSeg = ptP2 - ptP1 ;
|
|
vtSeg.Normalize() ;
|
|
// Interseco il triangolo corrente col primo dei due triangoli del rettangolo
|
|
Point3d ptIntA1, ptIntB1 ;
|
|
TRIA3DVECTOR vTria1 ;
|
|
int nIntType1 = IntersTriaTria( trTria1, trTria, ptIntA1, ptIntB1, vTria1) ;
|
|
if ( nIntType1 == ITTT_YES) {
|
|
if ( ( ptIntB1 - ptIntA1) * vtSeg < 0.)
|
|
std::swap( ptIntA1, ptIntB1) ;
|
|
ptStSeg = ptIntA1 ;
|
|
ptEnSeg = ptIntB1 ;
|
|
}
|
|
// Interseco il triangolo corrente con il secondo dei due triangoli del rettangolo
|
|
Point3d ptIntA2, ptIntB2 ;
|
|
TRIA3DVECTOR vTria2 ;
|
|
int nIntType2 = IntersTriaTria( trTria2, trTria, ptIntA2, ptIntB2, vTria2) ;
|
|
if ( nIntType2 == ITTT_YES) {
|
|
if ( ( ptIntB2 - ptIntA2) * vtSeg < 0.)
|
|
std::swap( ptIntA2, ptIntB2) ;
|
|
ptEnSeg = ptIntB2 ;
|
|
if ( ! ( nIntType1 == ITTT_YES))
|
|
ptStSeg = ptIntA2 ;
|
|
}
|
|
return ( nIntType1 == ITTT_YES || nIntType2 == ITTT_YES) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
FindRectangleTriangleIntersectionSegment2( const Point3d ptP1, const Point3d ptP2, const Point3d ptP3, const Point3d ptP4,
|
|
const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg)
|
|
{
|
|
// Definisco i due triangoli formanti il rettangolo
|
|
Triangle3d trTria1, trTria2;
|
|
trTria1.Set(ptP1, ptP2, ptP4);
|
|
trTria2.Set(ptP2, ptP3, ptP4);
|
|
trTria1.Validate();
|
|
trTria2.Validate();
|
|
Vector3d vtSeg = ptP3 - ptP1;
|
|
vtSeg.Normalize();
|
|
// Interseco il triangolo corrente col primo dei due triangoli del rettangolo
|
|
Point3d ptIntA1, ptIntB1;
|
|
TRIA3DVECTOR vTria1;
|
|
int nIntType1 = IntersTriaTria(trTria1, trTria, ptIntA1, ptIntB1, vTria1);
|
|
if ( nIntType1 == ITTT_YES) {
|
|
if ((ptIntB1 - ptIntA1) * vtSeg < 0.)
|
|
std::swap(ptIntA1, ptIntB1);
|
|
ptStSeg = ptIntA1;
|
|
ptEnSeg = ptIntB1;
|
|
}
|
|
// Interseco il triangolo corrente con il secondo dei due triangoli del rettangolo
|
|
Point3d ptIntA2, ptIntB2;
|
|
TRIA3DVECTOR vTria2;
|
|
int nIntType2 = IntersTriaTria(trTria2, trTria, ptIntA2, ptIntB2, vTria2);
|
|
if ( nIntType2 == ITTT_YES) {
|
|
if ((ptIntB2 - ptIntA2) * vtSeg < 0.)
|
|
std::swap(ptIntA2, ptIntB2);
|
|
ptEnSeg = ptIntB2;
|
|
if ( !( nIntType1 == ITTT_YES))
|
|
ptStSeg = ptIntA2;
|
|
}
|
|
return ( nIntType1 == ITTT_YES || nIntType2 == ITTT_YES);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
|
{
|
|
// La superficie deve essere valida
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// La curva deve essere valida e chiusa; il vettore estrusione deve essere non nullo
|
|
Vector3d vtExtr ;
|
|
if ( ( ! cvCurve.GetExtrusion( vtExtr)) || ( ! cvCurve.IsClosed()) || vtExtr.IsSmall())
|
|
return false ;
|
|
// Approssimo la curva con segmenti
|
|
PolyLine plLine ;
|
|
cvCurve.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, plLine) ;
|
|
// Appiattisco la polilinea nel piano perpendicolare all'estrusione
|
|
Frame3d frCurve ;
|
|
Point3d ptStart ; cvCurve.GetStartPoint( ptStart) ;
|
|
frCurve.Set( ptStart, vtExtr) ;
|
|
plLine.ToLoc( frCurve) ;
|
|
plLine.Flatten() ;
|
|
double dArea ;
|
|
plLine.GetAreaXY( dArea) ;
|
|
BBox3d b3Crv ;
|
|
plLine.GetLocalBBox( b3Crv) ;
|
|
plLine.ToGlob( frCurve) ;
|
|
// Assegno il senso di rotazione della curva (visto dalla punta del vettore estrusione)
|
|
bool bCCW = ( dArea > 0) ;
|
|
// Recupero Bounding-box della trimesh
|
|
BBox3d b3SurfBox ;
|
|
GetLocalBBox( b3SurfBox) ;
|
|
// Trovo minima e massima distanza dei vertici del bounding-box della TriMesh dal piano della curva
|
|
b3SurfBox.ToLoc( frCurve) ;
|
|
Point3d ptMin, ptMax ;
|
|
b3SurfBox.GetMinMax( ptMin, ptMax) ;
|
|
Vector3d vtMax = ( ptMax.z + 10) * vtExtr ;
|
|
Vector3d vtMin = ( ptMin.z - 10) * vtExtr ;
|
|
// Ciclo sui triangoli
|
|
bool bModif = false ;
|
|
int nNumTria = GetTriangleSize() ;
|
|
for ( int nT = 0 ; nT < nNumTria ; ++ nT) {
|
|
// Recupero il triangolo
|
|
Triangle3d trTria ;
|
|
GetTriangle( nT, trTria) ;
|
|
// Box del triangolo nel riferimento locale della curva
|
|
BBox3d b3Tria ;
|
|
trTria.GetLocalBBox( b3Tria) ;
|
|
b3Tria.ToLoc( frCurve) ;
|
|
// Se il box del triangolo non interseca quello della curva
|
|
if ( ! b3Crv.OverlapsXY( b3Tria)) {
|
|
if ( bCCW) {
|
|
RemoveTriangle( nT) ;
|
|
bModif = true ;
|
|
}
|
|
continue ;
|
|
}
|
|
// Determino il numero di vertici che cadono nella curva
|
|
int nVertInside = 0 ;
|
|
// Ciclo sui vertici del triangolo
|
|
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
|
// Vertice del triangolo e sua proiezione sul piano della curva
|
|
Point3d ptVert ;
|
|
if ( ! GetVertex( m_vTria[nT].nIdVert[nV], ptVert))
|
|
continue ;
|
|
double dDistVertPlane = ( ptVert - ptStart) * vtExtr ;
|
|
Point3d ptVertOnPlane = ptVert - dDistVertPlane * vtExtr ;
|
|
// Ciclo sui segmenti della curva, per determinare se la proiezione sulla curva di almeno un vertice
|
|
// del triangolo è all'interno del loop oppure un punto della curva, spostandosi lungo una
|
|
// retta parallela al versore di estrusione, interseca il triangolo.
|
|
double dSqDistVertCurve = DBL_MAX ;
|
|
Point3d ptStMin, ptEnMin ;
|
|
Point3d ptSt, ptEn ;
|
|
bool bContinue = plLine.GetFirstLine( ptSt, ptEn) ;
|
|
while ( bContinue) {
|
|
CurveLine cvLine ;
|
|
cvLine.Set( ptSt, ptEn) ;
|
|
// Calcolo della distanza del vertice proiettato sul piano della curva
|
|
// dal segmento corrente
|
|
DistPointLine dCurDistCalc( ptVertOnPlane, cvLine) ;
|
|
double dCurSqDist ;
|
|
// Se tale distanza è minore della minima distanza attuale, la aggiorno insieme con gli estremi
|
|
// del segmento a distanza minima
|
|
if ( dCurDistCalc.GetSqDist( dCurSqDist) && dCurSqDist < dSqDistVertCurve) {
|
|
dSqDistVertCurve = dCurSqDist ;
|
|
ptStMin = ptSt ;
|
|
ptEnMin = ptEn ;
|
|
}
|
|
bContinue = plLine.GetNextLine( ptSt, ptEn) ;
|
|
}
|
|
// Direzione del segmento a minima distanza dal vertice corrente proiettato sul piano della curva
|
|
Vector3d vtTan = ptEnMin - ptStMin ;
|
|
vtTan.Normalize() ;
|
|
// Se punto proiettato nella curva aumentiamo il numero di punti interni
|
|
if ( ( ptVertOnPlane - ptStMin) * ( vtTan ^ vtExtr) < EPS_SMALL)
|
|
++ nVertInside ;
|
|
}
|
|
|
|
// Casi in cui l'orientamento della curva stabilisce la parti interne ed esterne del triangolo
|
|
if ( abs( trTria.GetN() * vtExtr) > EPS_ZERO) {
|
|
// Vettore di segmenti
|
|
std::vector<CurveLine> vLine ;
|
|
// Ciclo sui segmenti
|
|
Point3d ptSt, ptEn ;
|
|
bool bContinue = plLine.GetFirstLine( ptSt, ptEn) ;
|
|
while ( bContinue) {
|
|
Point3d ptSegSt, ptSegEn ;
|
|
// C'è interferenza fra il rettangolo, ottenuto dall'estrusione del segmento corrente, e il triangolo
|
|
if ( FindRectangleTriangleIntersectionSegment( ptSt + vtMin, ptEn + vtMin, ptEn + vtMax, ptSt + vtMax,
|
|
trTria, ptSegSt, ptSegEn)) {
|
|
// Costruisco il tratto di curva
|
|
CurveLine cvLine ;
|
|
if ( cvLine.Set( ptSegSt, ptSegEn))
|
|
vLine.emplace_back( cvLine) ;
|
|
}
|
|
bContinue = plLine.GetNextLine( ptSt, ptEn) ;
|
|
}
|
|
// Creo i loop
|
|
ChainCurves LoopCreator ;
|
|
LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ;
|
|
// Carico le curve per concatenarle
|
|
for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) {
|
|
Point3d ptSt = vLine[nCv].GetStart() ;
|
|
Point3d ptEn = vLine[nCv].GetEnd() ;
|
|
Vector3d vtDir; vLine[nCv].GetStartDir( vtDir) ;
|
|
LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ;
|
|
}
|
|
// Recupero i concatenamenti
|
|
INTVECTOR vIds ;
|
|
Point3d ptNearStart ;
|
|
std::vector<CurveComposite> cvLoopVec ;
|
|
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
|
|
CurveComposite cvLoop ;
|
|
for ( auto i : vIds) {
|
|
// Aggiungo la linea alla curva composta.
|
|
if ( ! cvLoop.AddCurve( vLine[i - 1], true, 10 * EPS_SMALL))
|
|
return false ;
|
|
}
|
|
cvLoop.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
|
cvLoopVec.emplace_back( cvLoop) ;
|
|
}
|
|
|
|
// Fra i loop trovati separo gli aperti dai chiusi
|
|
std::vector<CurveComposite> cvInnerClosedLoopVec ;
|
|
std::vector<CurveComposite> cvOpenLoopVec ;
|
|
for ( int nL = 0 ; nL < int( cvLoopVec.size()) ; ++ nL) {
|
|
if ( cvLoopVec[nL].IsClosed())
|
|
cvInnerClosedLoopVec.emplace_back( cvLoopVec[nL]) ;
|
|
else
|
|
cvOpenLoopVec.emplace_back( cvLoopVec[nL]) ;
|
|
}
|
|
|
|
// Se contemporaneamente c'è almeno un loop chiuso e almeno uno aperto,
|
|
// oppure c'è più di un loop chiuso, vi è un errore.
|
|
if ( ( cvInnerClosedLoopVec.size() > 0 && cvOpenLoopVec.size() > 0.) ||
|
|
cvInnerClosedLoopVec.size() > 1)
|
|
return false ;
|
|
// Se c'è un loop chiuso
|
|
if ( cvInnerClosedLoopVec.size() == 1) {
|
|
// Passo da curva composita a PolyLine
|
|
PolyLine plInnerLoop ;
|
|
const ICurve* pCv = cvInnerClosedLoopVec[0].GetFirstCurve() ;
|
|
while ( pCv != nullptr) {
|
|
// Estremi del segmento corrente del loop chiuso corrente
|
|
Point3d ptSegSt, ptSegEn ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
plInnerLoop.AddUPoint( 0., ptSegSt) ;
|
|
plInnerLoop.AddUPoint( 0., ptSegEn) ;
|
|
pCv = cvInnerClosedLoopVec[0].GetNextCurve() ;
|
|
}
|
|
// Se necessario inverto il loop trovato
|
|
if ( trTria.GetN() * vtExtr < - EPS_ZERO)
|
|
plInnerLoop.Invert() ;
|
|
// Tre vertici dentro la curva
|
|
if ( nVertInside == 3) {
|
|
// Accedo agli indici del triangolo
|
|
int nTriaVertId[3] ;
|
|
GetTriangle( nT, nTriaVertId) ;
|
|
PolyLine plExternalLoop ;
|
|
Point3d ptTriaVert0, ptTriaVert1, ptTriaVert2 ;
|
|
GetVertex( nTriaVertId[0], ptTriaVert0) ;
|
|
GetVertex( nTriaVertId[1], ptTriaVert1) ;
|
|
GetVertex( nTriaVertId[2], ptTriaVert2) ;
|
|
// Rimuovo il triangolo corrente
|
|
RemoveTriangle( nT) ;
|
|
plExternalLoop.AddUPoint( 0., ptTriaVert0) ;
|
|
plExternalLoop.AddUPoint( 0., ptTriaVert1) ;
|
|
plExternalLoop.AddUPoint( 0., ptTriaVert2) ;
|
|
plExternalLoop.AddUPoint( 0., ptTriaVert0) ;
|
|
// Poligonalizzo il loop
|
|
Triangulate CreateTriangulation ;
|
|
PNTVECTOR vPt ;
|
|
INTVECTOR vTr ;
|
|
POLYLINEVECTOR vPL ;
|
|
vPL.emplace_back( plExternalLoop) ;
|
|
vPL.emplace_back( plInnerLoop) ;
|
|
CreateTriangulation.Make( vPL, vPt, vTr) ;
|
|
// Aggiungo i triangoli
|
|
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
|
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
|
int nNewId[3] = { AddVertex( vPt[nNewTriaVertId[0]]),
|
|
AddVertex( vPt[nNewTriaVertId[1]]),
|
|
AddVertex( vPt[nNewTriaVertId[2]]) } ;
|
|
AddTriangle( nNewId) ;
|
|
bModif = true ;
|
|
}
|
|
}
|
|
// Se nessun vertice dentro (Con un loop chiuso o ci sono tre vertici dentro alla curva o nessuno)
|
|
else {
|
|
// Rimuovo il triangolo corrente
|
|
RemoveTriangle( nT) ;
|
|
// Poligonalizzo il loop
|
|
Triangulate CreateTriangulation ;
|
|
PNTVECTOR vPt ;
|
|
INTVECTOR vTr ;
|
|
CreateTriangulation.Make( plInnerLoop, vPt, vTr) ;
|
|
// Aggiungo i triangoli
|
|
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
|
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
|
int nNewId[3] = { AddVertex(vPt[nNewTriaVertId[0]]),
|
|
AddVertex(vPt[nNewTriaVertId[1]]),
|
|
AddVertex(vPt[nNewTriaVertId[2]]) } ;
|
|
AddTriangle( nNewId) ;
|
|
bModif = true ;
|
|
}
|
|
}
|
|
}
|
|
// Loop aperti, devo chiuderli
|
|
else if ( cvOpenLoopVec.size() > 0) {
|
|
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
|
|
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
|
|
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
|
|
// chiusi di cui è formato il perimetro.
|
|
std::vector<CurveComposite> cvBoundClosedLoopVec ;
|
|
CurveComposite cvFirstLoop ;
|
|
CurveLine cvEdge ;
|
|
cvEdge.Set( trTria.GetP( 0), trTria.GetP( 1)) ;
|
|
cvFirstLoop.AddCurve( cvEdge, true, 10 * EPS_SMALL) ;
|
|
cvEdge.Set( trTria.GetP( 1), trTria.GetP( 2)) ;
|
|
cvFirstLoop.AddCurve( cvEdge, true, 10 * EPS_SMALL) ;
|
|
cvEdge.Set( trTria.GetP( 2), trTria.GetP( 0)) ;
|
|
cvFirstLoop.AddCurve( cvEdge, true, 10 * EPS_SMALL) ;
|
|
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
|
|
std::vector<bool> vbInOut ;
|
|
vbInOut.push_back( true) ;
|
|
// Divido il loop di partenza in sotto-loop
|
|
while ( cvOpenLoopVec.size() > 0) {
|
|
int nLastOpenLoopN = int( cvOpenLoopVec.size()) - 1 ;
|
|
for ( int nL = 0 ; nL < int( cvBoundClosedLoopVec.size()) ; ++ nL) {
|
|
// Estremi del loop aperto
|
|
Point3d ptOpenLoopStP, ptOpenLoopEnP ;
|
|
cvOpenLoopVec[nLastOpenLoopN].GetStartPoint( ptOpenLoopStP) ;
|
|
cvOpenLoopVec[nLastOpenLoopN].GetEndPoint( ptOpenLoopEnP) ;
|
|
// Cerco se esistono dei tratti del loop chiuso corrente che sono
|
|
// toccati dagli estremi del loop aperto corrente
|
|
const ICurve* pCvSt = nullptr ;
|
|
const ICurve* pCvEn = nullptr ;
|
|
const ICurve* pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != nullptr && ( pCvSt == nullptr || pCvEn == nullptr)) {
|
|
// Estremi del segmento corrente del loop chiuso corrente
|
|
Point3d ptSegSt, ptSegEn ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
// Vedo se gli estremi del loop aperto stanno su un segmento del chiuso
|
|
DistPointLine dStDistCalc( ptOpenLoopStP, ptSegSt, ptSegEn) ;
|
|
DistPointLine dEnDistCalc( ptOpenLoopEnP, ptSegSt, ptSegEn) ;
|
|
double dSqDistSt ;
|
|
dStDistCalc.GetSqDist( dSqDistSt) ;
|
|
if ( SqDist( ptOpenLoopStP, ptSegSt) < EPS_SMALL * EPS_SMALL ||
|
|
SqDist( ptOpenLoopStP, ptSegEn) < EPS_SMALL * EPS_SMALL)
|
|
dSqDistSt = 1. ;
|
|
if ( dSqDistSt < EPS_SMALL * EPS_SMALL)
|
|
pCvSt = pCv ;
|
|
double dSqDistEn ;
|
|
dEnDistCalc.GetSqDist( dSqDistEn) ;
|
|
if ( SqDist( ptOpenLoopEnP, ptSegSt) < EPS_SMALL * EPS_SMALL ||
|
|
SqDist( ptOpenLoopEnP, ptSegEn) < EPS_SMALL * EPS_SMALL)
|
|
dSqDistEn = 1. ;
|
|
if ( dSqDistEn < EPS_SMALL * EPS_SMALL)
|
|
pCvEn = pCv ;
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
}
|
|
// Se entrambi gli estremi del loop aperto sono su un segmento del loop chiuso devo dividere il loop in due
|
|
if ( pCvSt != nullptr && pCvEn != nullptr) {
|
|
// Entrambi gli estremi del loop aperto sono su uno stesso segmento del loop chiuso
|
|
if ( pCvSt == pCvEn) {
|
|
bool bFirstInside ;
|
|
bool bFirstSt ;
|
|
CurveComposite cvSplitLoop1, cvSplitLoop2 ;
|
|
// Creo primo loop
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != nullptr) {
|
|
// Segmenti loop chiuso
|
|
if ( pCv != pCvSt && pCv != pCvEn) {
|
|
Point3d ptSegSt, ptSegEn ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
}
|
|
// Dal chiuso all'aperto
|
|
else if ( pCv == pCvSt) {
|
|
// Distanze degli estremi del loop aperto dal punto iniziale del segmento corrente
|
|
Point3d ptSegSt, ptSegEn ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
double dDistStSt = SqDist( ptSegSt, ptOpenLoopStP) ;
|
|
double dDistStEn = SqDist( ptSegSt, ptOpenLoopEnP) ;
|
|
// Devo percorrere il loop aperto nel suo verso
|
|
if ( dDistStSt < dDistStEn) {
|
|
// Dall'inizio del segmento corrente fino all'inizio del loop aperto
|
|
ptSegEn = ptOpenLoopStP ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpenStart = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve() ;
|
|
const ICurve* pOpen = pOpenStart ;
|
|
while ( pOpen != nullptr) {
|
|
Point3d ptOpenSt, ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt) ;
|
|
pOpen->GetEndPoint( ptOpenEn) ;
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenSt, ptOpenEn) ;
|
|
cvSplitLoop1.AddCurve( cvOpenSeg) ;
|
|
if ( pOpen == pOpenStart) {
|
|
Vector3d vtLast = ptSegSt - ptSegEn ;
|
|
vtLast.Normalize() ;
|
|
Vector3d vtFirst = ptOpenEn - ptOpenSt ;
|
|
vtFirst.Normalize() ;
|
|
bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ;
|
|
}
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ;
|
|
}
|
|
// Dalla fine del loop aperto alla fine del segmento corrente
|
|
ptSegSt = ptOpenLoopEnP ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
bFirstSt = true ;
|
|
}
|
|
// Devo percorrere il loop aperto contro il suo verso
|
|
else {
|
|
// Dall'inizio del segmento corrente fino alla fine del loop aperto
|
|
ptSegEn = ptOpenLoopEnP ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpenLast = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve() ;
|
|
const ICurve* pOpen = pOpenLast ;
|
|
while ( pOpen != nullptr) {
|
|
Point3d ptOpenSt, ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt) ;
|
|
pOpen->GetEndPoint( ptOpenEn) ;
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenEn, ptOpenSt) ;
|
|
cvSplitLoop1.AddCurve( cvOpenSeg) ;
|
|
if ( pOpen == pOpenLast) {
|
|
Vector3d vtLast = ptSegSt - ptSegEn ;
|
|
vtLast.Normalize() ;
|
|
Vector3d vtFirst = ptOpenEn - ptOpenSt ;
|
|
vtFirst.Normalize() ;
|
|
bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ;
|
|
}
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve() ;
|
|
}
|
|
// Dall'inizio del loop aperto fino alla fine del segmento corrente
|
|
ptSegSt = ptOpenLoopStP ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
bFirstSt = false ;
|
|
}
|
|
}
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
}
|
|
// Creo secondo loop
|
|
if ( bFirstSt) {
|
|
// Tratto segmento ove cadono gli estremi del loop aperto
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptOpenLoopStP, ptOpenLoopEnP) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve();
|
|
while (pOpen != nullptr) {
|
|
Point3d ptOpenSt, ptOpenEn;
|
|
pOpen->GetStartPoint(ptOpenSt);
|
|
pOpen->GetEndPoint(ptOpenEn);
|
|
CurveLine cvOpenSeg;
|
|
cvOpenSeg.Set(ptOpenEn, ptOpenSt);
|
|
cvSplitLoop2.AddCurve(cvOpenSeg);
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve();
|
|
}
|
|
}
|
|
else {
|
|
// Tratto segmento ove cadono gli estremi del loop aperto
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptOpenLoopEnP, ptOpenLoopStP) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve() ;
|
|
while ( pOpen != nullptr) {
|
|
Point3d ptOpenSt, ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt) ;
|
|
pOpen->GetEndPoint( ptOpenEn) ;
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenSt, ptOpenEn) ;
|
|
cvSplitLoop2.AddCurve( cvOpenSeg);
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ;
|
|
}
|
|
}
|
|
// Aggiungo i nuovi loop nel vettore
|
|
cvBoundClosedLoopVec[nL] = cvSplitLoop1 ;
|
|
cvBoundClosedLoopVec.emplace_back( cvSplitLoop2) ;
|
|
vbInOut[nL] = bFirstInside ;
|
|
vbInOut.push_back( ! bFirstInside) ;
|
|
}
|
|
// Estremi dell'aperto su due diversi segmenti del chiuso
|
|
else {
|
|
bool bFirstInside ;
|
|
bool bFirstSt ;
|
|
CurveComposite cvSplitLoop1, cvSplitLoop2 ;
|
|
// Creo primo loop
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != nullptr) {
|
|
// Segmento su cui non incide nessun estremo del loop aperto
|
|
if ( pCv != pCvSt && pCv != pCvEn) {
|
|
Point3d ptSegSt, ptSegEn ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
}
|
|
// Segmento su cui incide l'estremo iniziale del loop aperto
|
|
else if ( pCv == pCvSt) {
|
|
// Dall'inizio del segmento corrente fino all'inizio del loop aperto
|
|
Point3d ptSegSt ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptOpenLoopStP) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpenFirst = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve();
|
|
const ICurve* pOpen = pOpenFirst ;
|
|
while ( pOpen != nullptr) {
|
|
// Valuto se cvSplitLoop1 è interno o esterno
|
|
Point3d ptOpenSt, ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt) ;
|
|
pOpen->GetEndPoint( ptOpenEn) ;
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenSt, ptOpenEn) ;
|
|
cvSplitLoop1.AddCurve( cvOpenSeg) ;
|
|
if ( pOpen == pOpenFirst) {
|
|
Vector3d vtLast = ptSegSt - ptOpenLoopStP ;
|
|
vtLast.Normalize() ;
|
|
Vector3d vtFirst = ptOpenEn - ptOpenSt ;
|
|
vtFirst.Normalize() ;
|
|
bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ;
|
|
}
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ;
|
|
}
|
|
// Dalla fine del loop aperto fino alla fine del segmento ove arriva il loop aperto
|
|
while ( pCv != pCvEn)
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
Point3d ptSegEn ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
cvSeg ;
|
|
cvSeg.Set( ptOpenLoopEnP, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
bFirstSt = true ;
|
|
}
|
|
// Segmento su cui incide l'estremo finale del loop aperto
|
|
else {
|
|
// Dall'inizio del segmento corrente fino alla fine del loop aperto
|
|
Point3d ptSegSt ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptOpenLoopEnP) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpenLast = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve() ;
|
|
const ICurve* pOpen = pOpenLast ;
|
|
while ( pOpen != nullptr) {
|
|
Point3d ptOpenSt , ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt) ;
|
|
pOpen->GetEndPoint( ptOpenEn) ;
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenEn, ptOpenSt) ;
|
|
cvSplitLoop1.AddCurve( cvOpenSeg) ;
|
|
if ( pOpen == pOpenLast) {
|
|
Vector3d vtLast = ptSegSt - ptOpenLoopEnP ;
|
|
vtLast.Normalize() ;
|
|
Vector3d vtFirst = ptOpenEn - ptOpenSt ;
|
|
vtFirst.Normalize() ;
|
|
bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ;
|
|
}
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve() ;
|
|
}
|
|
// Dalla fine del loop aperto fino alla fine del segmento ove arriva il loop aperto
|
|
while ( pCv != pCvSt)
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
Point3d ptSegEn ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
cvSeg.Set( ptOpenLoopStP, ptSegEn) ;
|
|
cvSplitLoop1.AddCurve( cvSeg) ;
|
|
bFirstSt = false ;
|
|
}
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
}
|
|
// Creo secondo loop
|
|
if ( bFirstSt) {
|
|
// Individuo il segmento ove incide l'estremo iniziale del loop aperto
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != pCvSt)
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
// Dall'estremo finale del loop aperto alla fine del segmento su cui giace
|
|
Point3d ptSegSt, ptSegEn ;
|
|
ptSegSt = ptOpenLoopStP ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
// Loop chiuso fino a segmento ove cade l'estremo finale dell'aperto
|
|
const ICurve* pCvStop = pCvEn ;
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
if ( pCv == nullptr)
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != pCvStop) {
|
|
if ( pCv == nullptr)
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
}
|
|
// Dall'inizio del segmento del loop chiuso ove cade l'estremo finale del loop aperto
|
|
// a quest'ultimo
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
ptSegEn = ptOpenLoopEnP ;
|
|
cvSeg.Set( ptSegSt, ptOpenLoopEnP) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve() ;
|
|
while ( pOpen != nullptr) {
|
|
Point3d ptOpenSt, ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt) ;
|
|
pOpen->GetEndPoint( ptOpenEn) ;
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenEn, ptOpenSt) ;
|
|
cvSplitLoop2.AddCurve( cvOpenSeg) ;
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve() ;
|
|
}
|
|
}
|
|
else {
|
|
// Individuo il segmento ove incide l'estremo finale del loop aperto
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != pCvEn)
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
// Dall'estremo finale del loop aperto alla fine del segmento su cui giace
|
|
Point3d ptSegSt, ptSegEn ;
|
|
ptSegSt = ptOpenLoopEnP ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
// Loop chiuso fino al segmento ove cade l'inizio del loop aperto
|
|
const ICurve* pCvStop = pCvSt ;
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
if ( pCv == nullptr)
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != pCvStop) {
|
|
if ( pCv == nullptr)
|
|
pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
CurveLine cvSeg ;
|
|
cvSeg.Set( ptSegSt, ptSegEn) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
}
|
|
// Dall'inizio del segmento del loop chiuso ove cade l'estremo iniziale del loop aperto
|
|
// a quest'ultimo
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
ptSegEn = ptOpenLoopStP ;
|
|
cvSeg.Set( ptSegSt, ptOpenLoopStP) ;
|
|
cvSplitLoop2.AddCurve( cvSeg) ;
|
|
// Loop aperto
|
|
const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve() ;
|
|
while ( pOpen != nullptr) {
|
|
Point3d ptOpenSt, ptOpenEn ;
|
|
pOpen->GetStartPoint( ptOpenSt);
|
|
pOpen->GetEndPoint( ptOpenEn);
|
|
CurveLine cvOpenSeg ;
|
|
cvOpenSeg.Set( ptOpenSt, ptOpenEn) ;
|
|
cvSplitLoop2.AddCurve( cvOpenSeg) ;
|
|
pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ;
|
|
}
|
|
}
|
|
// Aggiungo i nuovi loop nel vettore
|
|
cvBoundClosedLoopVec[nL] = cvSplitLoop1 ;
|
|
cvBoundClosedLoopVec.emplace_back( cvSplitLoop2) ;
|
|
vbInOut[nL] = bFirstInside ;
|
|
vbInOut.push_back( ! bFirstInside) ;
|
|
}
|
|
}
|
|
}
|
|
cvOpenLoopVec.resize( nLastOpenLoopN) ;
|
|
}
|
|
RemoveTriangle( nT) ;
|
|
// Trasformo i loop compositi in loop polyline
|
|
std::vector<PolyLine> vplPolyVec ;
|
|
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
|
|
for ( int nL = 0 ; nL < int( vplPolyVec.size()) ; ++ nL) {
|
|
const ICurve* pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ;
|
|
while ( pCv != nullptr) {
|
|
// Estremi del segmento corrente del loop chiuso corrente
|
|
Point3d ptSegSt, ptSegEn ;
|
|
pCv->GetStartPoint( ptSegSt) ;
|
|
pCv->GetEndPoint( ptSegEn) ;
|
|
vplPolyVec[nL].AddUPoint( 0., ptSegSt) ;
|
|
vplPolyVec[nL].AddUPoint( 0., ptSegEn) ;
|
|
pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ;
|
|
}
|
|
if ( vbInOut[nL]) {
|
|
// Poligonalizzo il loop
|
|
Triangulate CreateTriangulation ;
|
|
PNTVECTOR vPt ;
|
|
INTVECTOR vTr ;
|
|
CreateTriangulation.Make( vplPolyVec[nL], vPt, vTr) ;
|
|
// Aggiungo i triangoli
|
|
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
|
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
|
int nNewId[3] = { AddVertex(vPt[nNewTriaVertId[0]]),
|
|
AddVertex(vPt[nNewTriaVertId[1]]),
|
|
AddVertex(vPt[nNewTriaVertId[2]]) } ;
|
|
AddTriangle( nNewId) ;
|
|
bModif = true ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( nVertInside == 0)
|
|
RemoveTriangle( nT) ;
|
|
}
|
|
// L'orientamento del loop non stabilise i vertici dentro e fuori
|
|
else {
|
|
std::vector<TriaInOut> vTriaVec ;
|
|
TriaInOut trStartTria ;
|
|
trStartTria.trTria = trTria ;
|
|
trStartTria.bTriaInside = true ;
|
|
vTriaVec.emplace_back( trStartTria) ;
|
|
vTriaVec.resize( 1) ;
|
|
// Ciclo sui segmenti
|
|
Point3d ptSt, ptEn ;
|
|
bool bContinue = plLine.GetFirstLine( ptSt, ptEn) ;
|
|
while ( bContinue) {
|
|
for ( int nTr = 0 ; nTr < int( vTriaVec.size()) ; ++ nTr) {
|
|
Point3d ptSegSt, ptSegEn ;
|
|
// C'è interferenza fra il rettangolo, ottenuto dall'estrusione del segmento corrente, e il triangolo
|
|
if ( FindRectangleTriangleIntersectionSegment2( ptSt + vtMin, ptEn + vtMin, ptEn + vtMax, ptSt + vtMax,
|
|
vTriaVec[nTr].trTria, ptSegSt, ptSegEn)) {
|
|
// Stabilisco su quali lati del triangolo cadono gli estremi del segmento intersezione
|
|
int nStEdge = -1 ;
|
|
int nEnEdge = -1 ;
|
|
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
|
int nW = (nV + 1) % 3 ;
|
|
Point3d ptVertV = vTriaVec[nTr].trTria.GetP( nV) ;
|
|
Point3d ptVertW = vTriaVec[nTr].trTria.GetP( nW) ;
|
|
DistPointLine dStDistCalc( ptSegSt, ptVertV, ptVertW) ;
|
|
DistPointLine dEnDistCalc( ptSegEn, ptVertV, ptVertW) ;
|
|
double dSqDistSt ;
|
|
dStDistCalc.GetSqDist( dSqDistSt) ;
|
|
if ( dSqDistSt < EPS_SMALL * EPS_SMALL)
|
|
nStEdge = nV ;
|
|
double dSqDistEn ;
|
|
dEnDistCalc.GetSqDist( dSqDistEn) ;
|
|
if ( dSqDistEn < EPS_SMALL * EPS_SMALL)
|
|
nEnEdge = nV ;
|
|
}
|
|
int nMinInd, nMaxInd ;
|
|
Point3d ptMin, ptMax ;
|
|
if ( nStEdge < nEnEdge) {
|
|
nMinInd = nStEdge ;
|
|
nMaxInd = nEnEdge ;
|
|
ptMin = ptSegSt ;
|
|
ptMax = ptSegEn ;
|
|
}
|
|
else {
|
|
nMinInd = nEnEdge ;
|
|
nMaxInd = nStEdge ;
|
|
ptMin = ptSegEn ;
|
|
ptMax = ptSegSt ;
|
|
}
|
|
TriaInOut trSingleTria ;
|
|
PolyLine plInnerLoop ;
|
|
bool bLoopInside ;
|
|
if ( nMaxInd == ( nMinInd + 1) % 3) {
|
|
trSingleTria.trTria.SetP( 0, ptMin) ;
|
|
trSingleTria.trTria.SetP( 1, vTriaVec[nTr].trTria.GetP( ( nMinInd + 1) % 3)) ;
|
|
trSingleTria.trTria.SetP( 2, ptMax) ;
|
|
Vector3d vtTan = ptEn - ptSt ;
|
|
vtTan.Normalize() ;
|
|
if ( ( trSingleTria.trTria.GetP(1) - trSingleTria.trTria.GetP(0)) * ( vtTan ^ vtExtr) < 0.)
|
|
trSingleTria.bTriaInside = true ;
|
|
else
|
|
trSingleTria.bTriaInside = false ;
|
|
trSingleTria.trTria.Validate( true) ;
|
|
plInnerLoop.AddUPoint( 0., ptMin) ;
|
|
plInnerLoop.AddUPoint( 0., ptMax) ;
|
|
plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( ( nMinInd + 2) % 3)) ;
|
|
plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( nMinInd)) ;
|
|
plInnerLoop.AddUPoint( 0., ptMin) ;
|
|
if ( ( vTriaVec[nTr].trTria.GetP( nMinInd) - ptMin) * ( vtTan ^ vtExtr) < 0.)
|
|
bLoopInside = true ;
|
|
else
|
|
bLoopInside = false ;
|
|
}
|
|
else {
|
|
trSingleTria.trTria.SetP( 0, ptMin) ;
|
|
trSingleTria.trTria.SetP( 1, ptMax) ;
|
|
trSingleTria.trTria.SetP( 2, vTriaVec[nTr].trTria.GetP( nMinInd)) ;
|
|
Vector3d vtTan = ptEn - ptSt ;
|
|
vtTan.Normalize() ;
|
|
if ( ( trSingleTria.trTria.GetP( 2) - trSingleTria.trTria.GetP( 0)) * ( vtTan ^ vtExtr) < 0.)
|
|
trSingleTria.bTriaInside = true ;
|
|
else
|
|
trSingleTria.bTriaInside = false ;
|
|
trSingleTria.trTria.Validate( true) ;
|
|
plInnerLoop.AddUPoint( 0., ptMin) ;
|
|
plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( ( nMinInd + 1) % 3)) ;
|
|
plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( ( nMinInd + 2) % 3)) ;
|
|
plInnerLoop.AddUPoint( 0., ptMax) ;
|
|
plInnerLoop.AddUPoint( 0., ptMin) ;
|
|
if ( ( vTriaVec[nTr].trTria.GetP( ( nMinInd + 1) % 3) - ptMin) * ( vtTan ^ vtExtr) < 0.)
|
|
bLoopInside = true ;
|
|
else
|
|
bLoopInside = false ;
|
|
}
|
|
// Poligonalizzo il loop
|
|
Triangulate CreateTriangulation ;
|
|
PNTVECTOR vPt ;
|
|
INTVECTOR vTr ;
|
|
CreateTriangulation.Make( plInnerLoop, vPt, vTr) ;
|
|
// Aggiungo i triangoli al vettore
|
|
int nOldSize = int( vTriaVec.size()) ;
|
|
int nAddSize = int( vTr.size() / 3) ;
|
|
vTriaVec.resize( nOldSize + nAddSize) ;
|
|
for ( int m = nOldSize - 1 ; m > nTr ; -- m) {
|
|
vTriaVec[m + nAddSize] = vTriaVec[m] ;
|
|
}
|
|
vTriaVec[nTr] = trSingleTria ;
|
|
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
|
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
|
TriaInOut trNewTria ;
|
|
trNewTria.trTria.SetP( 0, vPt[nNewTriaVertId[0]]) ;
|
|
trNewTria.trTria.SetP( 1, vPt[nNewTriaVertId[1]]) ;
|
|
trNewTria.trTria.SetP( 2, vPt[nNewTriaVertId[2]]) ;
|
|
trNewTria.trTria.Validate( true) ;
|
|
trNewTria.bTriaInside = bLoopInside ;
|
|
vTriaVec[nTr + 1 + (n / 3)] = trNewTria ;
|
|
}
|
|
-- nTr ;
|
|
}
|
|
}
|
|
bContinue = plLine.GetNextLine( ptSt, ptEn) ;
|
|
}
|
|
// Se non sono state trovate intersezioni col triangolo
|
|
if ( vTriaVec.size() == 1) {
|
|
// Se almeno un punto interno (sotto l'ipotesi di nessuna intersezione
|
|
// equivale a tre punti interni) deve essere conservato così com'è.
|
|
if ( nVertInside > 0)
|
|
continue ;
|
|
// Altrimenti il triangolo deve essere eliminato
|
|
else {
|
|
RemoveTriangle( nT) ;
|
|
continue ;
|
|
}
|
|
}
|
|
RemoveTriangle( nT) ;
|
|
bModif = true ;
|
|
// Aggiungo i triangoli alla trimesh
|
|
for ( int n = 0 ; n < int( vTriaVec.size()) ; ++ n) {
|
|
if ( vTriaVec[n].bTriaInside) {
|
|
int nNewId[3] = { AddVertex(vTriaVec[n].trTria.GetP( 0)),
|
|
AddVertex(vTriaVec[n].trTria.GetP( 1)),
|
|
AddVertex(vTriaVec[n].trTria.GetP( 2)) } ;
|
|
AddTriangle( nNewId) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se avvenuta modifica, aggiorno tutto
|
|
if ( bModif)
|
|
return ( AdjustVertices() && DoCompacting()) ;
|
|
|
|
return true ;
|
|
}
|