Compare commits

...

114 Commits

Author SHA1 Message Date
Daniele Bariletti 83bd050868 EgtGeomKernel :
- piccoli aggiustamenti.
2025-09-04 15:06:28 +02:00
Daniele Bariletti 1ba1eb6a27 Merge remote-tracking branch 'origin/master' into FasterVMill5Axis 2025-09-04 13:02:46 +02:00
Daniele Bariletti 7e78f0d0e3 EgtGeomKernel :
- piccola correzione .
2025-08-28 15:25:38 +02:00
Riccardo Elitropi df828ab2ba EgtGeomKernel :
- in CalcPocketing piccola miglioria per Conformal.
2025-08-28 14:41:44 +02:00
Daniele Bariletti a4b66af304 EgtGeomKernel :
- piccola correzione.
2025-08-28 11:51:08 +02:00
Daniele Bariletti 0a5d655bfc EgtGeomKernel :
- correzione al precedente commit.
2025-08-28 11:37:35 +02:00
Daniele Bariletti 6393817f41 EgtGeomKernel :
- piccoli aggiustamenti.
2025-08-28 10:27:43 +02:00
Daniele Bariletti f871bfedc9 EgtGeomKernel :
- correzioni alla versione VM 5 assi con sup bilineari.
2025-08-28 10:10:53 +02:00
Daniele Bariletti e38b065357 EgtGeomKernel :
- VM 5 assi con sup. bilineari, aggiunta gestione delle intersezioni multiple.
2025-08-27 10:43:58 +02:00
Daniele Bariletti 704a977475 EgtGeomKernel :
- tolto l'uso di namespace std dagli header.
2025-08-27 10:42:11 +02:00
Daniele Bariletti 51fb1f4993 EgtGeomKernel :
- VM 5 assi con bilineari con un volume unico.
2025-08-26 10:30:34 +02:00
Daniele Bariletti dbb751a441 EgtGeomKernel :
- VM 5 assi con bilineari, riorganizzato.
2025-08-25 16:53:44 +02:00
Dario Sassi 371ff54d9c EgtGeomKernel :
- aggiunte funzioni GetSurfBezierAuxSurfTol e GetSurfBezierAuxSurfRefinedTol.
2025-08-24 19:13:18 +02:00
Daniele Bariletti 6a4b4feff5 EgtGeomKernel :
- aggiunta funzione per restituire tutti i punti di controllo di una surf di bezier.

(cherry picked from commit 574041cf18)
2025-08-22 15:44:27 +02:00
Daniele Bariletti 6f1f3441ea EgtGeomKernel :
- uniformazione delle funzioni per l'approssimazione curve con bezier.

(cherry picked from commit 05c0b0a18b)
2025-08-22 15:44:17 +02:00
Daniele Bariletti b955b12f38 EgtGeomKernel :
- aggiunta e miglioramento funzioni per la gesitone di curve bezier.

(cherry picked from commit 8ee5bc74d5)
2025-08-22 15:43:53 +02:00
Dario Sassi f22ea484db EgtGeomKernel :
- modifiche e migliorie calcoli per approssimazione di superfici di Bezier con trimesh
- aggiunte funzioni globali per impostare tolleranze di approssimazione delle superfici di Bezier
- eliminazione dell'uso della funzione pow (inefficiente) dove non necessaria
- utilizzo di Pow (efficiente) per potenze con esponente intero.
2025-08-22 11:44:56 +02:00
Riccardo Elitropi 1b9738eace EgtGeomKernel :
- In CalcPocketing piccola correzione per lavorazione Conformal
- In IntersParLinesSurfTm aggiunta estensione per intersezione con vettore di superfici TriMesh e aggiunto indice di superficie in IntLinStmInfo.
2025-08-04 14:40:43 +02:00
Dario Sassi 0a8cc414a5 EgtGeomKernel 2.7h1 :
- ricompilazione con cambio versione.
2025-08-03 13:39:03 +02:00
Riccardo Elitropi 7a682653cd EgtGeomKernel :
- in CAvParSilhouettesSurfTm corretta estensione XY della griglia per utensili a cui è applicato un Offset Radiale.
2025-08-01 16:34:46 +02:00
Daniele Bariletti 9286ab6535 EgtGeomKernel :
- correzioni e miglioramenti al VM 5assi.
2025-08-01 10:29:01 +02:00
Riccardo Elitropi 85736ab03f Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-07-30 13:22:57 +02:00
Riccardo Elitropi 673f5c7a9b EgtGeomKernel :
- In CalcPocketing corretto punto di ingresso per caso ottimizzato a Spirale con curve di Bordo Open.
2025-07-30 13:21:38 +02:00
Dario Sassi 34d0bcbdfe EgtGeomKernel :
- in FromPolyLine di CurveComposite conservo i parametri degli estremi.
2025-07-28 08:34:44 +02:00
Riccardo Elitropi 7abf3027d4 EgtGeomKernel :
- in CalcPocketing corretta gestione superficie limite per Conformal.
2025-07-24 11:21:22 +02:00
Daniele Bariletti ffe3d44cac EgtGeomKernel :
- correzioni al VM 5 assi con bilineari.
2025-07-23 14:56:20 +02:00
Daniele Bariletti dd23b848ac Merge branch 'master' into FasterVMill5Axis 2025-07-22 14:40:30 +02:00
Daniele Bariletti 33cca03698 EgtGeomKernel :
- piccole migliorie tecniche.
2025-07-22 13:13:49 +02:00
Daniele Bariletti d4d14dd866 EgtGeomKernel :
- correzioni alla funzione IsClosed per le surf Bezier.
2025-07-22 11:33:51 +02:00
Daniele Bariletti d6f0fdac50 EgtGeomKernel :
- correzioni VM 5 assi.
2025-07-22 09:12:34 +02:00
Dario Sassi 080605510c EgtGeomKernel :
- prime modifiche e correzioni a creazione di superfici di Bezier.
2025-07-22 08:30:27 +02:00
Daniele Bariletti 1a7b789ef3 EgtGeomKernel :
- aggiornata funzione IsClosed per le superfici di Bezier.
2025-07-21 12:33:42 +02:00
Daniele Bariletti cc4183a677 Merge branch 'master' into FasterVMill5Axis 2025-07-21 09:03:18 +02:00
Daniele Bariletti c2bae56656 EgtGeomKernel :
- versione completa VM 5 assi con bilineari e volumi chiusi.
2025-07-21 08:27:47 +02:00
Dario Sassi 38a5c0cbb3 EgtGeomKernel :
- correzione nell'aggiunta di curve a CurveComposite (gestito caso di altra curva che va trasformata in segmento di retta).
2025-07-15 19:25:36 +02:00
SaraP 81a8eb698e EgtGeomKernel :
- correzione del test per archi degeneri nell'offset con Voronoi.
2025-07-15 15:07:50 +02:00
SaraP ee4bb7d7c4 EgtGeomKernel :
- correzione nell'offset con Voronoi per archi piccoli.
2025-07-15 11:52:23 +02:00
Riccardo Elitropi 8b0d5bddbf EgtGeomKernel :
- In CalcPocketing piccola miglioria per il calcolo delle regioni non svuotate.
2025-07-14 17:46:36 +02:00
Daniele Bariletti ba75033f0a EgtGeomKernel :
- VM 5 assi con volumi chiusi, con bilineari.
2025-07-14 17:30:03 +02:00
Riccardo Elitropi eb2b90c6f2 EgtGeomKernel :
- In CalcPocketing aggiunto flag per calcolo delle regioni non svuotate.
2025-07-14 10:14:04 +02:00
Riccardo Elitropi 3b5c34cb05 EgtGeomKernel :
- in CalcPocketing migliorati i collegamenti per lavorazioni Conformal e migliorato l'orientamento delle curve per lavorazioni Spiral.
2025-07-11 15:38:55 +02:00
Dario Sassi 2fe22a62c2 EgtGeomKernel :
- in svuotature SpiralOut non si eliminano le passate iniziali adiacenti.
2025-07-09 15:36:36 +02:00
Dario Sassi ff6307fcca EgtGeomKernel :
- prime sistemazioni per offset superfici trimesh tramite Zmap.
2025-07-07 14:59:06 +02:00
Daniele Bariletti c6e80a0b6a EgtGeomKernel :
- accorpamento del codice VM 5 assi.
2025-07-04 17:14:04 +02:00
Riccardo Elitropi b957cc75be EgtGeomKernel :
- aggiunte funzioni per calcolo di Zmap e TriMesh di Offset Fillet Thickening.
2025-07-04 12:59:43 +02:00
Daniele Bariletti fc18539472 EgtGeomKernel :
- correzioni a VM 5assi.
2025-07-04 12:37:06 +02:00
Daniele Bariletti de7229aee7 EgtGeomKernel :
- correzioni a VM 5 assi con casi ottimizzati.
2025-07-02 17:14:08 +02:00
Riccardo Elitropi 53e66032a0 EgtGeomKernel 2.7g1 :
- migliorata e corretta la classe di calcolo delle Silhouette (l'Offset viene eseguito su tutte le curve e non singolarmente e l'estensione XY del Box locale tiene conto del raggio utensile per utensili non standard)
- in SurfTriMesh aggiunte le funzioni per il calcolo dei Box delle Parts
- in Offset delle superfici, ripristinata la funzione di somma di intervalli senza media delle normali e rimozione di memoryLeaks.
2025-07-02 11:44:10 +02:00
Daniele Bariletti 2fc6c30c8f EgtGeomKernel :
- imbastimento versione VM 5 assi con gestione casi diversi.
2025-06-27 15:53:24 +02:00
Riccardo Elitropi f05c5f1261 EgtGeomKernel :
- aggiunte funzioni per Offset e FatOffset per un insieme di curve
- in VolZmapOffset migliorata la gestione delle normali per l'addizione di intervalli.
2025-06-25 15:51:19 +02:00
Daniele Bariletti 6af5591cf6 EgtGeomKernel :
- estensione del VM 5 assi e 3 assi ai casi con utensili diversi dal cilindro.
2025-06-20 16:20:12 +02:00
Daniele Bariletti 41cbe862e5 EgtGeomKernel :
- versione corretta del VM a 5 assi per lama e 3 assi.
2025-06-19 16:26:31 +02:00
Riccardo Elitropi 057b8273e2 EgtGeomKernel :
- in VolZmap::CreateFromTriMesh() corretta espansione per caso Box in attesa di correzione in marching Cubes.
2025-06-19 12:47:35 +02:00
SaraP 6421c12408 EgtGeomKernel :
- piccola modifica.
2025-06-17 08:24:47 +02:00
Daniele Bariletti 0aca5aeb07 Merge branch 'master' into FasterVMill5Axis 2025-06-16 15:12:20 +02:00
Daniele Bariletti bdbd3583b8 EgtGeomKernel :
- versione temporanea per VM5assi per caso lama e 3 assi.
2025-06-16 15:10:10 +02:00
Riccardo Elitropi 626d5b0e51 EgtGeomKernel 2.7f2 :
- Aggiunte funzioni per calcolo di Offset per superfici chiuse TriMesh
- Piccola miglioria alla triangolazione (con SaraP)
- Migliorie per rimozioni TJunction, calcolo delle normali dei triangoli e creazione di una TriMesh a partire da uno ZMap (con SaraP)
- Aggiunte funzioni di SubtractMap e piccole modifiche per estensione dei Box di creazione per gli Zmap.
2025-06-16 11:34:23 +02:00
SaraP 0bffa0039c EgtGeomKernel 2.7f1 :
- migliorie e piccole correzioni varie nelle trimesh ( booleane, chiusura).
2025-06-09 15:47:11 +02:00
Riccardo Elitropi 9819c8cee8 EgtGeomKernel :
- In CalcPocketing piccola modifica sui nomi dei parametri della funzione.
2025-06-09 12:13:56 +02:00
Riccardo Elitropi 53ab676750 EgtGeomKernel :
- In CalcPocketing correzione piccolo errore.
2025-06-09 11:38:46 +02:00
Riccardo Elitropi afa4872c97 EgtGeomKernel :
- In CalcPocketing piccola modifica per smussi sui raccordi speciali.
2025-06-06 16:51:25 +02:00
Riccardo Elitropi bf56d53faf EgtGeomKernel :
- In CalcPocketing sistemate le tolleranze di merge per le curve e migliorati i controlli per raccordi a circonferenza.
- In CurveComposite aggiunto controllo su Archi con angolo al centro circa a giro seguiti/precedeuti da curve di lunghezza sotto alla tolleranza lineare.
2025-06-04 16:26:33 +02:00
Daniele Bariletti f03adb9206 EgtGeomKernel :
- nuova versione VM 5 assi per caso lama e 3 assi.
2025-06-03 15:48:37 +02:00
Daniele Bariletti 529fa2e4a0 EgtGeomKernel :
- correzioni a VMill 5 assi e tentaivo di miglioramento per caso lama e 3 assi.
2025-06-03 09:30:48 +02:00
Dario Sassi 6df1b90e95 EgtGeomKernel 2.7e3 :
- in CurveComposite AddPoint comprende le funzionalità di FromPoint che è stata eliminata
- modifiche conseguenti in altre parti.
2025-05-31 11:54:21 +02:00
Riccardo Elitropi 9cba0e6d15 EgtGeomKernel :
- piccoli miglioramenti in CalcPocketing.
2025-05-30 17:04:19 +02:00
Riccardo Elitropi f16de3a20c EgtGeomKernel :
- in CalcPocketing, corretta gestione aree non svuotate nel caso di assenza di smussi o di cambio tipo di lavorazione.
2025-05-30 13:28:10 +02:00
Riccardo Elitropi 8cfa41d09f EgtGeomKernel :
- piccola correzione in CalcPocketing.
2025-05-30 12:18:23 +02:00
Riccardo Elitropi b59b501366 EgtGeomKernel :
- piccola correnzione in CalcPocketing.
2025-05-30 12:15:19 +02:00
Riccardo Elitropi 504bb50b13 EgtGeomKernel :
- modifica prototipi
- piccola miglioria per casi ottimizzati a Spirale in CalcPocketing.
2025-05-30 11:46:37 +02:00
Dario Sassi 969f1266e7 EgtGeomKernel :
- correzione euristica su Vmill a 5assi, in attesa di soluzione definitiva in sviluppo
2025-05-30 10:59:40 +02:00
Riccardo Elitropi fa680b7799 EgtGeomKernel :
- Aggiunto controllo sulla scalatura nella funzione GetSilhouette in SurfTriMesh
- In CalcPocketing, aggiunte funzioni ausiliarie per Debug.
2025-05-29 11:52:19 +02:00
Dario Sassi e185c85d5e EgtGeomKernel :
- piccola correzione provvisoria su Vmill a 5assi, in attesa di soluzione definitiva in sviluppo.
2025-05-29 08:30:50 +02:00
Daniele Bariletti acb0a5bd5e EgtGeomKernel :
- correzione e miglioramento del VM 5 assi per il caso lama e lavorazione 3 assi.
2025-05-28 17:57:03 +02:00
Riccardo Elitropi 62ce576d4d Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-05-28 17:22:55 +02:00
Riccardo Elitropi 161d3d9b17 EgtGeomKernel :
- In CalcPocketing aggiunte correzioni e migliorie per raccordi tra offset, per calcolo e rimozione delle regioni non svuotate e scelta degli offset per i percorsi.
2025-05-28 17:22:49 +02:00
Dario Sassi d88baa070f EgtGeomKernel 2.7e2 :
- ricompilazione con cambio versione.
2025-05-27 16:00:17 +02:00
Riccardo Elitropi 2b087dde51 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-05-27 14:27:25 +02:00
Riccardo Elitropi 7894a8fdc8 EgtGeomKernel :
- In CalcPocketing aggiunto riconoscimento per curve SpiralCirle.
2025-05-27 14:27:20 +02:00
SaraP 0f14e8335a EgtGeomKernel :
- aggiornata funzione CalcZigZagInfill per modifiche a CalcZigZag.
2025-05-27 12:05:04 +02:00
Riccardo Elitropi 7edf4bced8 EgtGeomKernel :
- Aggiunto parametro alle funzioni per creare la FatCurve.
2025-05-27 08:28:56 +02:00
Riccardo Elitropi 4a5639780b EgtGeomKernel :
- In CalcPocketing aggiunto controllo di MaxOptSize anche sulle curve singole di lavorazione.
2025-05-22 12:02:53 +02:00
Riccardo Elitropi 0a21a582be EgtGeomKernel :
- correzione scelta basi e tempProps per le curve a trapezio.
2025-05-22 10:32:36 +02:00
Dario Sassi 0e663c02c4 EgtGeomKernel :
- piccola miglioria suggeritra da compilatore 64bit.
2025-05-21 09:34:18 +02:00
Riccardo Elitropi 21afe8165c EgtGeomKernel :
- In CalcPocketing aggiunto controllo su Feed per lati aperti
- In CalcPocketing inizio stesura funzioni per Biarchi.
2025-05-20 17:28:05 +02:00
Daniele Bariletti 0247fe5e7c Merge branch 'master' into FasterVMill5Axis 2025-05-20 11:06:49 +02:00
Daniele Bariletti 50bad83fba EgtGeomKernel :
- accorpamento del codice per Virtual milling 5assi.
2025-05-20 11:06:21 +02:00
Daniele Bariletti 9c93d6c2f3 EgtGeomKernel :
- aggiunte funzioni per le lavorazioni generiche a 5 assi.
2025-05-20 10:14:39 +02:00
Riccardo Elitropi 4d9a50cf94 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-05-20 09:11:46 +02:00
Riccardo Elitropi bbdaac5d8d EgtGeomKernel :
- In CalcPocketing aggiunto controllo per angoli per segmento di entrata da fuori e aggiunto controllo con superficie limite da Offset Conformal.
2025-05-20 09:11:40 +02:00
Dario Sassi 0417c43bcf EgtGeomKernel :
- correzione a Pocketing per calcolo punto di inizio con lati aperti.
2025-05-19 17:39:26 +02:00
Riccardo Elitropi 15585b8f11 EgtGeomKernel :
- in PolygonElevation aggiunto controllo sul punto centrale della PolyLinea.
2025-05-16 15:48:41 +02:00
Daniele Bariletti 59755ec8a5 EgtGeomKernel :
- piccole correzioni.
2025-05-15 16:34:01 +02:00
Riccardo Elitropi b16dd260d8 EgtGEomKernel :
- In CalcPocketing aggiunto controllo lunghezza dei lati aperti,  aggiunto parametro MaxOptSize e aggiunte migliorie a percorsi Conformal.
2025-05-15 16:23:53 +02:00
SaraP d37a5a37b7 EgtGeomKernel :
- piccola correzione in GetSideAtMinDistPoint in un caso particolare di punto minimo nello start di curva chiusa.
2025-05-15 14:40:34 +02:00
Daniele Bariletti 79dfb4ae87 EgtGeomKernel :
- aggiunta di una funzione per  la VirtualMilling a 5 assi usando le bilineari.
2025-05-15 12:13:55 +02:00
Riccardo Elitropi 8b75b6e4c3 EgtGeomKernel :
- In CalcPocketing piccola miglioria per contorni ZigZag.
2025-05-13 11:41:08 +02:00
Riccardo Elitropi bcaad08b61 EgtGeomKernel :
- In CalcPocketing migliorata la gestione delle curve di svuotatura singole.
2025-05-09 16:08:34 +02:00
Riccardo Elitropi cbdeffd93a EgtGeomKernel :
- In CalcPocketing aggiunto merge dei percorsi nel caso di intersezione delle estensioni presso le uscite libere.
2025-05-07 15:00:04 +02:00
Riccardo Elitropi 0ce477a3e7 EgtGeomKernel :
- In CalcPocketing migliorata la gesitone delle lavorazioni Conformal
- In CalcPocketing migliorate le curve di bordo per lavorazioni OneWay e ZigZag.
2025-05-06 17:07:56 +02:00
Riccardo Elitropi 44eb4d1834 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-05-05 16:57:24 +02:00
Riccardo Elitropi 2e26b73208 EgtGeomKernel :
- in CalcPocketing piccola modifica per la creazione delle curve a ricciolo per aree non svuotate.
2025-05-05 16:57:20 +02:00
Dario Sassi de3fa3201e EgtGeomKernel 2.7e1 :
- ricompilazione con cambio versione.
2025-05-05 13:25:12 +02:00
Riccardo Elitropi f068aafbb5 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-05-05 12:25:16 +02:00
Riccardo Elitropi daedb07135 EgtGeomKernel :
- in CalcPocketing, aggiunta inversione del percorso per spirali in lavorazione SPIRAL_OUT.
2025-05-05 12:25:12 +02:00
SaraP 702e1e446d EgtGeomKernel :
- piccole correzioni nelle approssimazioni delle curve.
2025-04-28 15:14:05 +02:00
SaraP ea87db1ae1 EgtGeomKernel :
- negli offset gestite autointersezioni per raccordi chamfer ed extend.
2025-04-24 14:12:34 +02:00
Dario Sassi b65800843a EgtGeomKernel :
- proiezione curve su superficie ora accetta più superfici.
2025-04-23 12:18:16 +02:00
Dario Sassi e4c5d8645d Merge commit '85b06c29b4bf9af0f6c54bfa74ff2dd38c1103bd' 2025-04-22 18:01:34 +02:00
Daniele Bariletti 85b06c29b4 Merge branch 'FasterBezier_NoMultiThread' 2025-04-22 14:56:42 +02:00
Daniele Bariletti 5254d0c5ca EgtGeomKernel :
- rimosso header di debug.
2025-04-22 14:56:18 +02:00
Dario Sassi 9d038142a8 Merge remote-tracking branch 'origin/master' 2025-04-21 10:03:06 +02:00
Dario Sassi c5573e438b EgtGeomKernel 2.7d2 :
- in VolZmap migliorato calcolo step per Vmill 4assi.
2025-04-21 10:01:41 +02:00
Daniele Bariletti 8c7a0ac026 Merge branch 'FasterBezier_NoMultiThread' 2025-04-14 11:23:11 +02:00
41 changed files with 6843 additions and 3606 deletions
+152 -109
View File
@@ -311,7 +311,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol, const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol,
bool bAdvCorners) bool bAdvCorners)
{ {
// se non ho polylinee, allora esco // se non ho polylinee, allora esco
if ( vPL.empty()) if ( vPL.empty())
return true ; return true ;
@@ -341,10 +340,45 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
if ( ! CalcRegionPolyLines( vPL, vtN, mIndMat, vbInv)) if ( ! CalcRegionPolyLines( vPL, vtN, mIndMat, vbInv))
return false ; return false ;
#if ENABLE_SHARPED_EDGES_DEBUG
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
// ombra del tool
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
// 1° gruppo, griglia di punti
for ( int j = 0 ; j <= nStepY ; ++ j) {
for ( int i = 0 ; i <= nStepX ; ++ i) {
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
myPtGrid->Set( ptP) ;
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
vvCol[0].emplace_back( BLUE) ;
}
}
// 2° gruppo, superfici
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
if ( ! IsNull( pMyStm)) {
pMyStm->ToLoc( frGrid) ;
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
}
}
#endif
// vettore delle polyline visitate ( viste però come curve composite)
ICRVCOMPOPOVECTOR vPL_AsCompo ; vPL_AsCompo.reserve( vPL.size()) ;
// scorro i Chunk della matrice di interi, quindi le righe // scorro i Chunk della matrice di interi, quindi le righe
for ( int nChunk = 0 ; nChunk < int( mIndMat.size()) ; ++ nChunk) { for ( int nChunk = 0 ; nChunk < int( mIndMat.size()) ; ++ nChunk) {
// scorro le PolyLinee presenti nel Chunk // scorro le PolyLinee presenti nel Chunk
for ( int nPol = 0 ; nPol < int( vPL.size()) ; ++ nPol) { for ( int nLoop = 0 ; nLoop < int( mIndMat[nChunk].size()) ; ++ nLoop) {
// recupero l'indice della PolyLine di riferimento
int nPol = mIndMat[nChunk][nLoop] ;
if ( nPol < 0 || nPol >= int( vPL.size()))
return false ;
// essendo chiusa, se presenti meno di 4 punti, non faccio nulla // essendo chiusa, se presenti meno di 4 punti, non faccio nulla
int nPts = vPL[nPol].GetPointNbr() ; int nPts = vPL[nPol].GetPointNbr() ;
if ( nPts < 4) if ( nPts < 4)
@@ -380,33 +414,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ; vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ;
#if ENABLE_SHARPED_EDGES_DEBUG #if ENABLE_SHARPED_EDGES_DEBUG
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
// ombra del tool
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
// 1° gruppo, griglia di punti
for ( int j = 0 ; j <= nStepY ; ++ j) {
for ( int i = 0 ; i <= nStepX ; ++ i) {
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
myPtGrid->Set( ptP) ;
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
vvCol[0].emplace_back( BLUE) ;
break ;
}
break ;
}
// 2° gruppo, superfici
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
if ( ! IsNull( pMyStm)) {
pMyStm->ToLoc( frGrid) ;
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
}
}
// 3° gruppo, punti della PolyLine // 3° gruppo, punti della PolyLine
for ( int i = 0 ; i < int( vAdvPt.size()) ; ++ i) { for ( int i = 0 ; i < int( vAdvPt.size()) ; ++ i) {
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ; PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
@@ -416,23 +423,23 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
} }
#endif #endif
// modifico la posizione dei punti // modifico la posizione dei punti
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen)) if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
return false ; return false ;
// ricostrusico la polyLine // ricostrusico la polyLine a partire da una vuota
vPL[nPol].Clear() ; PolyLine PL_New ;
double dPar = -1 ; double dPar = -1 ;
for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) { for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) {
// se punto valido o sharped di angolo interno, lo aggiungo // se punto valido o sharped di angolo interno, lo aggiungo
if ( j == 0 || j == int( vAdvPt.size() - 1) || if ( j == 0 || j == int( vAdvPt.size() - 1) ||
vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT) vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT)
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ; PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
// se è un punto sharped di un angolo esterno // se è un punto sharped di un angolo esterno
else if ( vAdvPt[j].second == PointType::SHARPED_EXT) { else if ( vAdvPt[j].second == PointType::SHARPED_EXT) {
// se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto // se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto
if ( ! bAdvCorners) if ( ! bAdvCorners)
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ; PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
else { else {
// ricavo il punto a minima distanza dal materiale mediante metodo di bisezione // ricavo il punto a minima distanza dal materiale mediante metodo di bisezione
Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ; Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ;
@@ -463,51 +470,29 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ; DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ;
distPtLPrev.GetMinDistPoint( ptMinDistA) ; distPtLPrev.GetMinDistPoint( ptMinDistA) ;
distPtLSucc.GetMinDistPoint( ptMinDistB) ; distPtLSucc.GetMinDistPoint( ptMinDistB) ;
vPL[nPol].AddUPoint( ++ dPar, ptMinDistA) ; PL_New.AddUPoint( ++ dPar, ptMinDistA) ;
vPL[nPol].AddUPoint( ++ dPar, ptTest) ; PL_New.AddUPoint( ++ dPar, ptTest) ;
vPL[nPol].AddUPoint( ++ dPar, ptMinDistB) ; PL_New.AddUPoint( ++ dPar, ptMinDistB) ;
}
#if ENABLE_SHARPED_EDGES_DEBUG #if ENABLE_SHARPED_EDGES_DEBUG
// 5° gruppo, punti minDist A e B e ptMid // 5° gruppo, punti minDist A e B e ptMid
/*PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ; PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
myPtA->Set( ptMinDistA) ; myPtA->Set( ptMinDistA) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ; vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
vvCol[4].emplace_back( BROWN) ; vvCol[4].emplace_back( BROWN) ;
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ; PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
myPtB->Set( ptMinDistB) ; myPtB->Set( ptMinDistB) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ; vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
vvCol[4].emplace_back( BROWN) ; vvCol[4].emplace_back( BROWN) ;
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ; PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
myPtMid->Set( ptTest) ; myPtMid->Set( ptTest) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ; vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
vvCol[4].emplace_back( BROWN) ;*/ vvCol[4].emplace_back( BROWN) ;
#endif #endif
}
} }
} }
// riposiziono la polyLine
#if ENABLE_SHARPED_EDGES_DEBUG
// 6° gruppo, curve composita derivante dalla polyline
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
pCrvCompoPoly->FromPolyLine( vPL[nPol]) ;
//pCrvCompoPoly->SetExtrusion( frGrid.VersZ()) ;
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
vvCol[5].emplace_back( RED) ;
// 7° gruppo, controOffset
OffsetCurve offsCrv ;
offsCrv.Make( pCrvCompoPoly, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
pCrvCompoPoly.Set( ConvertCurveToComposite( offsCrv.GetLongerCurve())) ;
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( Release( pCrvCompoPoly))) ;
vvCol[6].emplace_back( WHITE) ;
string myName = Sharped_Edges_Debug_File_Name +
to_string( nChunk) + "_" +
to_string( nPol) + "_" +
to_string( dLevel) + "_" +
to_string( dAngTol) + ".nge" ;
SaveGeoObj( vvpGObj, vvCol, myName) ;
#endif
// se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla // se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla
// trimesh rischio di evere Chunk distinti uniti in un unico Chunk // trimesh rischio di evere Chunk distinti uniti in un unico Chunk
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ; PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
@@ -515,11 +500,53 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
return false ; return false ;
pCompo->FromPolyLine( vPL[nPol]) ; pCompo->FromPolyLine( vPL[nPol]) ;
SelfIntersCurve SIC( *pCompo) ; SelfIntersCurve SIC( *pCompo) ;
if ( SIC.GetCrossOrOverlapIntersCount() > 0) bool bDiscard = ( SIC.GetCrossOrOverlapIntersCount() > 0) ;
continue ; if ( ! bDiscard) {
// se la polyLine interseca una delle PolyLine precedenti, non la modifico
for ( auto& pCompoPL_Prev : vPL_AsCompo) {
IntersCurveCurve ICC( *pCompo, *pCompoPL_Prev) ;
if ( ICC.GetCrossOrOverlapIntersCount() > 0) {
bDiscard = true ;
break ;
}
}
}
// se nuova approssimazione da conservare, memorizzo i risultati
if ( ! bDiscard) {
vPL[nPol] = PL_New ;
vPL_AsCompo.emplace_back( Release( pCompo)) ;
}
} }
} }
#if ENABLE_SHARPED_EDGES_DEBUG
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
for ( const auto& PL : vPL) {
// 6° gruppo, curve composita derivante dalla polyline
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
pCrvCompoPoly->FromPolyLine( PL) ;
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
vvCol[5].emplace_back( RED) ;
vpCrv.emplace_back( Release( pCrvCompoPoly)) ;
}
// 7° gruppo, controOffset
ICURVEPOVECTOR vCrvCompoOffs ;
if ( ! CalcOffsetCurves( vpCrv, vCrvCompoOffs, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND)) {
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
return false ;
}
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
for ( const auto& pCvrOffs : vCrvCompoOffs) {
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCvrOffs))) ;
vvCol[6].emplace_back( WHITE) ;
}
string myName = Sharped_Edges_Debug_File_Name +
to_string( dLevel) + "_" +
to_string( dAngTol) + ".nge" ;
SaveGeoObj( vvpGObj, vvCol, myName) ;
#endif
return true ; return true ;
} }
@@ -785,21 +812,31 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false)) if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false))
swap( vPL_Sharped, vPL) ; swap( vPL_Sharped, vPL) ;
// se vettore di PolyLine vuoto, non faccio nulla
if ( vPL.empty())
return true ;
// se non ho impostato un utensile, devo effettuare un contro-offset // se non ho impostato un utensile, devo effettuare un contro-offset
if ( ! bTool) { if ( ! bTool) {
POLYLINEVECTOR vPL_Offs ; ICURVEPOVECTOR vpOwCrv ; vpOwCrv.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
CurveComposite crvCompo ; for ( const auto& PL : vPL) {
if ( ! crvCompo.FromPolyLine( vPL[i])) PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
return false ; pCrvCompoPoly->FromPolyLine( PL) ;
OffsetCurve offsCompo ; vpOwCrv.emplace_back( Release( pCrvCompoPoly)) ;
offsCompo.Make( &crvCompo, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ; vpCrv.emplace_back( vpOwCrv.back()) ;
PtrOwner<ICurve> pCrvOffset( offsCompo.GetLongerCurve()) ; }
while ( ! IsNull( pCrvOffset)) { // calcolo l'Offset
ICURVEPOVECTOR vpCrvOffs ;
if ( ! CalcOffsetCurves( vpCrv, vpCrvOffs, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND))
return false ;
// resituisco le PolyLine
POLYLINEVECTOR vPL_Offs ; vPL_Offs.reserve( vpCrvOffs.size()) ;
for ( auto& pCrv : vpCrvOffs) {
if ( pCrv != nullptr && pCrv->IsValid()) {
PolyLine myPolyLine ; PolyLine myPolyLine ;
pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ; pCrv->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
vPL_Offs.emplace_back( myPolyLine) ; vPL_Offs.emplace_back( myPolyLine) ;
pCrvOffset.Set( offsCompo.GetLongerCurve()) ;
} }
} }
swap( vPL_Offs, vPL) ; swap( vPL_Offs, vPL) ;
@@ -976,28 +1013,13 @@ CAvParSilhouettesSurfTm::Prepare( void)
return false ; return false ;
b3All.Add( b3Surf) ; b3All.Add( b3Surf) ;
} }
// espansione in Z del Box
// calcolo dati della griglia
const double EXTRA_XY = ( m_bTool ? m_dRad + 2 : 1.5 * m_dTol) ;
const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ; const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ;
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ; b3All.Expand( 0., 0., EXTRA_Z) ;
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
m_dDimZ = b3All.GetDimZ() ; m_dDimZ = b3All.GetDimZ() ;
m_dLevelOffs = - b3All.GetMin().z ;
// calcolo dei punti della griglia (sul top del cilindro) // set utensile corrente per calcolo delle collisioni
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ; double dExtraXY = m_dRad + m_dOffsR ;
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
int nInd = i + j * ( m_nStepX + 1) ;
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
vPntM[nInd] = { ptP, 0.} ;
}
}
// esecuzione della verifica
if ( m_dSideAng < EPS_ANG_SMALL) if ( m_dSideAng < EPS_ANG_SMALL)
m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ; m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
else { else {
@@ -1015,8 +1037,29 @@ CAvParSilhouettesSurfTm::Prepare( void)
double dStemRad = m_dRad + dDeltaRad ; double dStemRad = m_dRad + dDeltaRad ;
double dTipRad = m_dRad ; double dTipRad = m_dRad ;
dExtraXY = dStemRad + m_dOffsR ;
m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ; m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
} }
// calcolo dati della griglia
const double EXTRA_XY = ( m_bTool ? dExtraXY + 2. : 1.5 * m_dTol) ;
b3All.Expand( EXTRA_XY, EXTRA_XY, 0.) ;
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
m_dLevelOffs = - b3All.GetMin().z ;
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
// calcolo dei punti della griglia (sul top del cilindro)
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
int nInd = i + j * ( m_nStepX + 1) ;
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
vPntM[nInd] = { ptP, 0.} ;
}
}
// esecuzione verifica della collisione
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0]))) if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
return false ; return false ;
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k) for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
+1470 -1104
View File
File diff suppressed because it is too large Load Diff
+91 -13
View File
@@ -513,8 +513,13 @@ CurveToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurveBezier* ICurveBezier*
LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot) LineToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
{ {
// verifico sia una linea
const CurveLine* pCrvLine = GetBasicCurveLine( pCrv) ;
if ( pCrvLine == nullptr)
return nullptr ;
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ; PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali // rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
pCrvBezier->Init( nDeg, true) ; pCrvBezier->Init( nDeg, true) ;
@@ -560,7 +565,7 @@ ArcToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
nParts = max( nParts, 2) ; nParts = max( nParts, 2) ;
for ( int i = 0 ; i < nParts ; ++ i) { for ( int i = 0 ; i < nParts ; ++ i) {
// copio l'arco originale // copio l'arco originale
CurveArc cArc = *pArc ; CurveArc cArc = *GetBasicCurveArc(pArc->Clone()) ;
// lo limito alla parte di interesse // lo limito alla parte di interesse
cArc.TrimStartEndAtParam( i / double( nParts), ( i + 1) / double( nParts)) ; cArc.TrimStartEndAtParam( i / double( nParts), ( i + 1) / double( nParts)) ;
// creo la curva di Bezier equivalente // creo la curva di Bezier equivalente
@@ -584,8 +589,13 @@ ArcToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
CompositeToBezierCurve( const ICurveComposite* pCC, int nDeg, bool bMakeRatOrNot) CompositeToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
{ {
// verifico sia una composita
const CurveComposite* pCC = GetBasicCurveComposite( pCrv) ;
if ( pCC == nullptr)
return nullptr ;
// converto tutte le curve in bezier razionali di grado 2 // converto tutte le curve in bezier razionali di grado 2
PtrOwner<ICurveComposite> pCCBezier( CreateCurveComposite()) ; PtrOwner<ICurveComposite> pCCBezier( CreateCurveComposite()) ;
for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) {
@@ -620,10 +630,15 @@ CompositeToBezierCurve( const ICurveComposite* pCC, int nDeg, bool bMakeRatOrNot
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, double dTol) EditBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot, double dTol)
{ {
// se nDeg == -1 allora viene mantenuto il grado della curva originale // se nDeg == -1 allora viene mantenuto il grado della curva originale
// verifico sia una bezier
const CurveBezier* pCrvBezier = GetBasicCurveBezier( pCrv) ;
if ( pCrvBezier == nullptr)
return nullptr ;
if( nDeg == 2 || nDeg == 1) if( nDeg == 2 || nDeg == 1)
return nullptr ; return nullptr ;
@@ -889,8 +904,13 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol) ApproxBezierWithCubics(const ICurve* pCrv, double dTol)
{ {
// verifico sia una bezier
const CurveBezier* pCrvBezier = GetBasicCurveBezier( pCrv) ;
if ( pCrvBezier == nullptr)
return nullptr ;
// cerco di stimare quanti cambi di concavità ho // cerco di stimare quanti cambi di concavità ho
// tiro una linea tra il primo punto di controllo e l'ultimo e poi scorro gli altri punti di controllo // tiro una linea tra il primo punto di controllo e l'ultimo e poi scorro gli altri punti di controllo
// controllando quante volte salto da un lato all'altro della linea // controllando quante volte salto da un lato all'altro della linea
@@ -1012,8 +1032,13 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurveBezier* ICurveBezier*
ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez) ApproxCurveBezierWithSingleCubic( const ICurve* pCrv)
{ {
// verifico sia una bezier
const CurveBezier* pCrvBez = GetBasicCurveBezier( pCrv) ;
if ( pCrvBez == nullptr)
return nullptr ;
Point3d ptStart, ptEnd ; Point3d ptStart, ptEnd ;
pCrvBez->GetStartPoint( ptStart) ; pCrvBez->GetStartPoint( ptStart) ;
pCrvBez->GetEndPoint( ptEnd) ; pCrvBez->GetEndPoint( ptEnd) ;
@@ -1042,8 +1067,13 @@ ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurveBezier* ICurveBezier*
ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d& ptCen) ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen)
{ {
// verifico sia una bezier
const CurveBezier* pCrvBez = GetBasicCurveBezier( pCrv) ;
if ( pCrvBez == nullptr)
return nullptr ;
// converto una curva di bezier che definisce un arco perfetto di circonferenza // converto una curva di bezier che definisce un arco perfetto di circonferenza
// dato il centro( della circonferenza), inizio e fine // dato il centro( della circonferenza), inizio e fine
// N.B. : per archi con angolo al centro < 90 // N.B. : per archi con angolo al centro < 90
@@ -1068,9 +1098,9 @@ ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d&
double ay = ptStart.y - ptCen.y ; double ay = ptStart.y - ptCen.y ;
double bx = ptEnd.x - ptCen.x ; double bx = ptEnd.x - ptCen.x ;
double by = ptEnd.y - ptCen.y ; double by = ptEnd.y - ptCen.y ;
double q1 = pow( ax, 2) + pow( ay, 2) ; double q1 = ax * ax + ay * ay ;
double q2 = q1 + ax * bx + ay * by ; double q2 = q1 + ax * bx + ay * by ;
double k2 = 4./3 * ( sqrt( 2 * q1 * q2) - q2) / ( ax * by - ay * bx) ; double k2 = 4. / 3 * ( sqrt( 2 * q1 * q2) - q2) / ( ax * by - ay * bx) ;
Point3d ptCtrl1, ptCtrl2 ; Point3d ptCtrl1, ptCtrl2 ;
ptCtrl1.x = ptStart.x - k2 * ay ; ptCtrl1.x = ptStart.x - k2 * ay ;
ptCtrl1.y = ptStart.y + k2 * ax ; ptCtrl1.y = ptStart.y + k2 * ax ;
@@ -1086,7 +1116,9 @@ ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d&
ICurve* ICurve*
ApproxCurveWithBezier( const ICurve*, double dTol) ApproxCurveWithBezier( const ICurve*, double dTol)
{ {
// interpolazione di punti con una curva bezier // campiono punti lungo la curva e poi li interpolo
// oppure faccio la fat curve e poi calcolo una bezier che stia all'interno di quella regione
PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ; PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ;
return Release( pCC) ; return Release( pCC) ;
@@ -1262,7 +1294,7 @@ CurveToNoArcsCurve( const ICurve* pCrv)
return nullptr ; return nullptr ;
// se arco, devo trasformarlo in curva di Bezier (semplice o composta) // se arco, devo trasformarlo in curva di Bezier (semplice o composta)
if ( pCrv->GetType() == CRV_ARC) { if ( pCrv->GetType() == CRV_ARC) {
return ArcToBezierCurve( pCrv) ; return ArcToBezierCurve( GetCurveArc(pCrv)) ;
} }
// se curva composita, devo trasformarla in composita senza archi // se curva composita, devo trasformarla in composita senza archi
else if ( pCrv->GetType() == CRV_COMPO) { else if ( pCrv->GetType() == CRV_COMPO) {
@@ -2043,13 +2075,14 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids,
bool bMergeOnlySameProps)
{ {
Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ; Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids) ; return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids, bMergeOnlySameProps) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -2086,6 +2119,51 @@ CalcCurveSingleCurvesOffset( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double d
return pVoronoiObj->CalcSingleCurvesOffset( vCrvs, dOffs) ; return pVoronoiObj->CalcSingleCurvesOffset( vCrvs, dOffs) ;
} }
//----------------------------------------------------------------------------
bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs, int nType)
{
// creo oggetto Voronoi con le curve passate
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ;
}
return pVoronoiObj->CalcOffset( vCrvs, dOffs, nType) ;
}
//----------------------------------------------------------------------------
bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs,
bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps)
{
// controllo validità delle curve
for ( auto& pCrv : vpCrvs) {
if ( pCrv == nullptr)
return false ;
}
// se offset nullo restituisco direttamente le curve
if ( abs( dOffs) < EPS_SMALL) {
for ( auto& pCrv : vpCrvs) {
if ( ! vCrvs.emplace_back( pCrv->Clone()))
return false ;
}
return true ;
}
// creo oggetto Voronoi con le curve passate
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ;
}
return pVoronoiObj->CalcFatCurve( vCrvs, dOffs, bSquareEnds, bSquareMids, bMergeOnlySameProps) ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
ResetCurveVoronoi( const ICurve& crvC) ResetCurveVoronoi( const ICurve& crvC)
+1 -1
View File
@@ -33,5 +33,5 @@ bool CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) ;
bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ; bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ;
bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ; bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ; bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez) ; ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ; Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
+22 -14
View File
@@ -2274,17 +2274,17 @@ CurveBezier::MakeRationalStandardForm( void)
{ {
if ( ! m_bRat) if ( ! m_bRat)
return false ; return false ;
double dW0 = m_vWeCtrl[0] ; double dW0 = m_vWeCtrl.front() ;
double dWn = m_vWeCtrl.back() ; double dWn = m_vWeCtrl.back() ;
if( dW0 > 1- EPS_ZERO && dWn > 1 - EPS_ZERO) if ( dW0 > 1 - EPS_ZERO && dWn > 1 - EPS_ZERO)
return true ; return true ;
if( dW0 < EPS_ZERO || dWn < EPS_ZERO) if ( dW0 < EPS_ZERO || dWn < EPS_ZERO)
return false ; return false ;
// formula del Farin // formula del Farin
double dCoeff = pow( dW0 / dWn, 1. / m_nDeg) ; double dCoeff = pow( dW0 / dWn, 1. / m_nDeg) ;
for ( int i = 0 ; i < m_nDeg + 1 ; ++i) for ( int i = 0 ; i < m_nDeg + 1 ; ++i)
m_vWeCtrl[i] *= pow( dCoeff, i) / dW0 ; m_vWeCtrl[i] *= Pow( dCoeff, i) / dW0 ;
return true ; return true ;
} }
@@ -2293,13 +2293,13 @@ CurveBezier::MakeRationalStandardForm( void)
bool bool
CurveBezier::MakeNonRational( double dTol) CurveBezier::MakeNonRational( double dTol)
{ {
if( ! m_bRat) if ( ! m_bRat)
return true ; return true ;
// controllo se i pesi sono tutti == 1 allora è una finta razionale e mi basta fare una copia dei punti di controllo // controllo se i pesi sono tutti == 1 allora è una finta razionale e mi basta fare una copia dei punti di controllo
bool bIsActualRat = false ; bool bIsActualRat = false ;
for ( int i = 0 ; i < m_nDeg ; ++i) { for ( int i = 0 ; i < m_nDeg ; ++i) {
if ( abs(m_vWeCtrl[i] - 1) > EPS_SMALL) { if ( abs( m_vWeCtrl[i] - 1) > EPS_SMALL) {
bIsActualRat = true ; bIsActualRat = true ;
break ; break ;
} }
@@ -2323,8 +2323,8 @@ CurveBezier::MakeNonRational( double dTol)
pNewBez->Init( nDeg, false) ; pNewBez->Init( nDeg, false) ;
PNTVECTOR vPntCtrl ; PNTVECTOR vPntCtrl ;
PNTVECTOR vPntSampling ; PNTVECTOR vPntSampling ;
for ( int p = 0 ; p < nDeg + 1; ++p) { for ( int p = 0 ; p < nDeg + 1 ; ++p) {
Point3d pt ; GetPointD1D2( double(p) / nDeg, pt) ; Point3d pt ; GetPointD1D2( double( p) / nDeg, pt) ;
pNewBez->SetControlPoint( p, pt) ; pNewBez->SetControlPoint( p, pt) ;
vPntCtrl.push_back( pt) ; vPntCtrl.push_back( pt) ;
} }
@@ -2334,8 +2334,8 @@ CurveBezier::MakeNonRational( double dTol)
while ( dErr > dTol && c < 100) { while ( dErr > dTol && c < 100) {
double dErrMax = 0 ; double dErrMax = 0 ;
// calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale // calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale
for ( int p = 0 ; p < nDeg + 1; ++p) { for ( int p = 0 ; p < nDeg + 1 ; ++p) {
Point3d pt ; pNewBez->GetPointD1D2( double(p) / nDeg, pt) ; Point3d pt ; pNewBez->GetPointD1D2( double( p) / nDeg, pt) ;
Vector3d vDiff = vPntSampling[p] - pt ; Vector3d vDiff = vPntSampling[p] - pt ;
double dErrLoc = vDiff.Len() ; double dErrLoc = vDiff.Len() ;
if( dErrLoc > dErrMax) if( dErrLoc > dErrMax)
@@ -2353,15 +2353,15 @@ CurveBezier::MakeNonRational( double dTol)
// calcolo l'errore di approssimazione sulla curva // calcolo l'errore di approssimazione sulla curva
CalcBezierApproxError( this, pNewBez, dErr) ; CalcBezierApproxError( this, pNewBez, dErr) ;
bOk = dErr < dTol ; bOk = dErr < dTol ;
if( bOk) { if ( bOk) {
// aggiorno la curva di bezier originale con quella approssimata // aggiorno la curva di bezier originale con quella approssimata
Init( nDeg, false) ; Init( nDeg, false) ;
for( int i = 0 ; i < nDeg + 1 ; ++i) { for ( int i = 0 ; i < nDeg + 1 ; ++i) {
SetControlPoint( i, pNewBez->GetControlPoint( i)) ; SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
SetControlWeight( i, pNewBez->GetControlWeight( i)) ; SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
} }
} }
else if( nDeg < m_nDeg + 4) else if ( nDeg < m_nDeg + 4)
goto retry ; goto retry ;
} }
@@ -2383,3 +2383,11 @@ CurveBezier::IsALine( void) const
} }
return true ; return true ;
} }
//----------------------------------------------------------------------------
PNTVECTOR
CurveBezier::GetAllControlPoints( void) const
{
PNTVECTOR vPntCtrl = m_vPtCtrl ;
return vPntCtrl ;
}
+1
View File
@@ -153,6 +153,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
bool MakeRationalStandardForm( void) override ; bool MakeRationalStandardForm( void) override ;
bool MakeNonRational( double dTol) override ; bool MakeNonRational( double dTol) override ;
bool IsALine( void) const override ; bool IsALine( void) const override ;
PNTVECTOR GetAllControlPoints( void) const ; // non aggiunta in interfaccia
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
+5 -2
View File
@@ -502,8 +502,9 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
m_vPrevDer[nI].ToSpherical( nullptr, nullptr, &dDir1Deg) ; m_vPrevDer[nI].ToSpherical( nullptr, nullptr, &dDir1Deg) ;
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir) // costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ; pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
// forzo la spezzatura della curva
if ( IsNull( pCrv)) if ( IsNull( pCrv))
return false ; dMaxDist = 2 * dLinTol ;
} }
// se la polilinea è formata da 2 punti // se la polilinea è formata da 2 punti
else if ( PL.GetPointNbr() == 2) { else if ( PL.GetPointNbr() == 2) {
@@ -524,13 +525,15 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
// se raggiunto il massimo livello di recursione, forzo l'accettazione del biarco // se raggiunto il massimo livello di recursione, forzo l'accettazione del biarco
if ( nLev >= MAX_LEV) { if ( nLev >= MAX_LEV) {
if ( IsNull( pCrv))
return false ;
dMaxDist = 0 ; dMaxDist = 0 ;
// segnalo situazione per debug // segnalo situazione per debug
if ( GetEGkDebugLev() >= 5) if ( GetEGkDebugLev() >= 5)
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions")
} }
// se lunghezza abbastanza picccola, forzo l'accettazione della curva // se lunghezza abbastanza piccola, forzo l'accettazione della curva
double dLen ; double dLen ;
if ( PL.GetApproxLength( dLen) && dLen < 10 * EPS_SMALL) if ( PL.GetApproxLength( dLen) && dLen < 10 * EPS_SMALL)
dMaxDist = 0 ; dMaxDist = 0 ;
+64 -31
View File
@@ -192,7 +192,7 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
return false ; return false ;
// verifico lo stato // verifico lo stato
if ( m_nStatus != OK && ! ( m_CrvSmplS.empty() && m_nStatus == TO_VERIFY)) if ( m_nStatus != OK && ! ( m_CrvSmplS.empty() && ( m_nStatus == TO_VERIFY || m_nStatus == IS_A_POINT)))
return false ; return false ;
// controllo la tolleranza // controllo la tolleranza
@@ -224,8 +224,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
// lunghezza della curva originale // lunghezza della curva originale
double dOldLen ; pCrv->GetLength( dOldLen) ; double dOldLen ; pCrv->GetLength( dOldLen) ;
// eseguo modifica // eseguo modifica
if ( ! pCrv->ModifyStart( ptEnd)) if ( ! pCrv->ModifyStart( ptEnd)) {
return false ; CurveLine crvLine ;
if ( ! crvLine.Set( ptEnd, ptCrvEnd) || ! pCrv.Set( crvLine.Clone()))
return false ;
}
// verifico che la lunghezza non sia variata troppo // verifico che la lunghezza non sia variata troppo
double dNewLen ; pCrv->GetLength( dNewLen) ; double dNewLen ; pCrv->GetLength( dNewLen) ;
if ( abs( dNewLen - dOldLen) > 10 * dLinTol) if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
@@ -246,8 +249,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
// lunghezza della curva originale // lunghezza della curva originale
double dOldLen ; pCrv->GetLength( dOldLen) ; double dOldLen ; pCrv->GetLength( dOldLen) ;
// eseguo modifica // eseguo modifica
if ( ! pCrv->ModifyEnd( ptStart)) if ( ! pCrv->ModifyEnd( ptStart)) {
return false ; CurveLine crvLine ;
if ( ! crvLine.Set( ptCrvStart, ptStart) || ! pCrv.Set( crvLine.Clone()))
return false ;
}
// verifico che la lunghezza non sia variata troppo // verifico che la lunghezza non sia variata troppo
double dNewLen ; pCrv->GetLength( dNewLen) ; double dNewLen ; pCrv->GetLength( dNewLen) ;
if ( abs( dNewLen - dOldLen) > 10 * dLinTol) if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
@@ -375,9 +381,10 @@ CurveComposite::FromPolyLine( const PolyLine& PL)
return false ; return false ;
// ciclo di inserimento dei segmenti che uniscono i punti // ciclo di inserimento dei segmenti che uniscono i punti
double dParIni, dParFin ;
Point3d ptIni, ptFin ; Point3d ptIni, ptFin ;
PL.GetFirstPoint( ptIni) ; PL.GetFirstUPoint( &dParIni, &ptIni) ;
while ( PL.GetNextPoint( ptFin)) { while ( PL.GetNextUPoint( &dParFin, &ptFin)) {
// se i punti della coppia coincidono, passo alla coppia successiva // se i punti della coppia coincidono, passo alla coppia successiva
if ( AreSamePointApprox( ptIni, ptFin)) if ( AreSamePointApprox( ptIni, ptFin))
continue ; continue ;
@@ -388,10 +395,14 @@ CurveComposite::FromPolyLine( const PolyLine& PL)
// assegno i punti estremi // assegno i punti estremi
if ( ! pCrvLine->Set( ptIni, ptFin)) if ( ! pCrvLine->Set( ptIni, ptFin))
return false ; return false ;
// assegno i parametri degli estremi
pCrvLine->SetTempParam( dParIni, 0) ;
pCrvLine->SetTempParam( dParFin, 1) ;
// aggiungo la retta alla curva composita // aggiungo la retta alla curva composita
if ( ! AddSimpleCurve( Release( pCrvLine))) if ( ! AddSimpleCurve( Release( pCrvLine)))
return false ; return false ;
// aggiorno dati prossimo punto iniziale // aggiorno dati prossimo punto iniziale
dParIni = dParFin ;
ptIni = ptFin ; ptIni = ptFin ;
} }
@@ -1778,10 +1789,11 @@ bool
CurveComposite::AddPoint( const Point3d& ptStart) CurveComposite::AddPoint( const Point3d& ptStart)
{ {
// verifico lo stato // verifico lo stato
if ( m_nStatus != TO_VERIFY) if ( m_nStatus != TO_VERIFY && m_nStatus != IS_A_POINT)
return false ; return false ;
// assegno il punto // assegno il punto e setto lo stato
m_ptStart = ptStart ; m_ptStart = ptStart ;
m_nStatus = IS_A_POINT ;
return true ; return true ;
} }
@@ -1825,7 +1837,7 @@ bool
CurveComposite::AddLine( const Point3d& ptNew, bool bEndOrStart) CurveComposite::AddLine( const Point3d& ptNew, bool bEndOrStart)
{ {
// verifico lo stato // verifico lo stato
if ( m_nStatus != OK && m_nStatus != TO_VERIFY) if ( m_nStatus != OK && m_nStatus != IS_A_POINT)
return false ; return false ;
// costruisco la linea // costruisco la linea
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ; PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
@@ -3168,11 +3180,26 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
// se precedente molto corta // se precedente molto corta
double dLenP ; double dLenP ;
if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) { if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) {
// se abbastanza allineata alla successiva // se abbastanza allineata alla successiva
Vector3d vtDirP, vtDirC ; Vector3d vtDirP, vtDirC ;
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) { if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
Point3d ptStart ; bool bModifStart = ( pCrvC->GetType() != CRV_ARC) ;
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ; if ( ! bModifStart) {
/* nel caso in cui la curva corrente sia un arco, bisogna controllare che la somma tra
l'angolo al centro e l'angolo sotteso dalla curva precedente non superi l'angolo giro; in
caso positivo, la modifica del punto inziale dell'arco ( curva corrente) rimoverebbe
tutti gli angoli superiori a 360deg [curve a ricciolo per regioni non svuotate in Pocketing] */
Point3d ptS ; pCrvP->GetStartPoint( ptS) ;
Point3d ptE ; pCrvC->GetStartPoint( ptE) ;
const ICurveArc* pArcC = GetBasicCurveArc( pCrvC) ;
double dAngRef = ( Dist( ptS, ptE) / pArcC->GetRadius()) * RADTODEG ;
bModifStart = ( abs( pArcC->GetAngCenter()) + dAngRef < ANG_FULL - 10 * EPS_ANG_SMALL) ;
}
if ( bModifStart) {
Point3d ptStart ;
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ;
}
} }
} }
// se corrente molto corta // se corrente molto corta
@@ -3181,10 +3208,24 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
// se abbastanza allineata alla precedente // se abbastanza allineata alla precedente
Vector3d vtDirP, vtDirC ; Vector3d vtDirP, vtDirC ;
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) { if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
Point3d ptEnd ; bool bModifEnd = ( pCrvP->GetType() != CRV_ARC) ;
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ; if ( ! bModifEnd) {
/* nel caso in cui la curva predecente sia un arco, bisogna controllare che la somma tra
l'angolo al centro e l'angolo sotteso dalla curva corrente non superi l'angolo giro; in
caso positivo, la modifica del punto finale dell'arco ( curva precedente) rimoverebbe
tutti gli angoli superiori a 360deg [curve a ricciolo per regioni non svuotate in Pocketing] */
Point3d ptS ; pCrvP->GetEndPoint( ptS) ;
Point3d ptE ; pCrvC->GetEndPoint( ptE) ;
const CurveArc* pArcP = GetBasicCurveArc( pCrvP) ;
double dAngRef = ( Dist( ptS, ptE) / pArcP->GetRadius()) * RADTODEG ;
bModifEnd = ( abs( pArcP->GetAngCenter()) + dAngRef < ANG_FULL - 10. * EPS_ANG_SMALL) ;
}
if ( bModifEnd) {
Point3d ptEnd ;
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ;
}
} }
} }
// coefficiente deduzione tolleranza // coefficiente deduzione tolleranza
const double COEFF_TOL = 0.7 ; const double COEFF_TOL = 0.7 ;
// se entrambe rette // se entrambe rette
@@ -3264,11 +3305,12 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
if ( ! bPlaneArcs) { if ( ! bPlaneArcs) {
ptP1.Scale( frRef, 1, 1, 0) ; ptP1.Scale( frRef, 1, 1, 0) ;
ptP2.Scale( frRef, 1, 1, 0) ; ptP2.Scale( frRef, 1, 1, 0) ;
ptP3.Scale( frRef, 1, 1, 0) ; ptP3.Scale( frRef, 1, 1, 0) ;
ptC1Fin.Scale( frRef, 1, 1, 0) ;
} }
// verifico se circonferenza completa // verifico se circonferenza completa
bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ; bool bCirc = ( AreSamePointEpsilon( ptP1, ptP3, dCurrLinTol)) ;
if ( bCirc) { if ( bCirc) {
pArcC->GetMidPoint( ptP3) ; pArcC->GetMidPoint( ptP3) ;
if ( ! bPlaneArcs) if ( ! bPlaneArcs)
@@ -3277,6 +3319,10 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
CurveArc NewArc ; CurveArc NewArc ;
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) { if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
// se vicino a circonferenza arco per 3 punti potrebbe non dare il risultato desiderato quindi faccio controllo su raggio e centro
if ( Dist( NewArc.GetCenter(), ptC1Fin) > 2 * dCurrLinTol || abs( NewArc.GetRadius() - pArcP->GetRadius()) > 2 * dCurrLinTol)
return 0 ;
// verifico normale al piano dell'arco // verifico normale al piano dell'arco
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0) if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
NewArc.InvertN() ; NewArc.InvertN() ;
@@ -3794,19 +3840,6 @@ CurveComposite::ResetVoronoiObject() const
m_pVoronoiObj = nullptr ; m_pVoronoiObj = nullptr ;
} }
//----------------------------------------------------------------------------
bool
CurveComposite::FromPoint(Point3d& ptStart)
{
// verifico lo stato
if ( m_nStatus != TO_VERIFY)
return false ;
// assegno il punto e setto lo stato
m_ptStart = ptStart ;
m_nStatus = IS_A_POINT ;
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CurveComposite::GetOnlyPoint(Point3d& ptStart) const CurveComposite::GetOnlyPoint(Point3d& ptStart) const
+1 -2
View File
@@ -177,8 +177,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ; bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ;
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ; bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ; bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
bool FromPoint( Point3d& ptStart) override ; // funzione per settare la curva ad un unico punto bool GetOnlyPoint( Point3d& ptStart) const override ;
bool GetOnlyPoint( Point3d& ptStart) const override ; // funzione per recuperare l'unico punto da cui è composta la curva ( degenere)
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
+17 -6
View File
@@ -152,7 +152,7 @@ DistPointCurve::GetMinDistPoint( double dNearParam, Point3d& ptMinDist, int& nFl
} }
} }
// cerco punto discreto più vicino (anche estremi di zone continue) // cerco punto discreto più vicino (anche estremi di zone continue)
double dParam ; double dParam ;
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) { for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
if ( i == 0 || if ( i == 0 ||
@@ -197,7 +197,7 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
} }
} }
// cerco punto discreto più vicino (anche estremi di zone continue) // cerco punto discreto più vicino (anche estremi di zone continue)
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) { for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
if ( i == 0 || if ( i == 0 ||
abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) { abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) {
@@ -232,9 +232,20 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
Vector3d vtTg = 0.5 * ( vtPreTg + vtPostTg) ; Vector3d vtTg = 0.5 * ( vtPreTg + vtPostTg) ;
// se tangenti opposte, si deve ricalcolare spostandosi un poco // se tangenti opposte, si deve ricalcolare spostandosi un poco
if ( ! vtTg.Normalize()) { if ( ! vtTg.Normalize()) {
double dDeltaU = 1000 * EPS_PARAM ; double dDeltaU = 1000 * EPS_PARAM ;
if ( ! m_pCurve->GetPointTang( m_Info[nInd].dPar - dDeltaU, ICurve::FROM_MINUS, ptQ, vtPreTg) || double dParPre = m_Info[nInd].dPar - dDeltaU ;
! m_pCurve->GetPointTang( m_Info[nInd].dPar + dDeltaU, ICurve::FROM_PLUS, ptQ, vtPostTg)) double dParPost = m_Info[nInd].dPar + dDeltaU ;
// verifico se il parametro deve essere modificato per adattarsi a curva chiusa
if ( m_pCurve->IsClosed()) {
double dParS, dParE ;
m_pCurve->GetDomain( dParS, dParE) ;
if ( dParPre < dParS)
dParPre = dParE - dDeltaU ;
if ( dParPost > dParE)
dParPost = dParS + dDeltaU ;
}
if ( ! m_pCurve->GetPointTang( dParPre, ICurve::FROM_MINUS, ptQ, vtPreTg) ||
! m_pCurve->GetPointTang( dParPost, ICurve::FROM_PLUS, ptQ, vtPostTg))
return false ; return false ;
vtTg = 0.5 * ( vtPreTg + vtPostTg) ; vtTg = 0.5 * ( vtPreTg + vtPostTg) ;
if ( ! vtTg.Normalize( EPS_ZERO)) if ( ! vtTg.Normalize( EPS_ZERO))
@@ -264,7 +275,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
if ( m_dDist < 0 || m_Info.empty()) if ( m_dDist < 0 || m_Info.empty())
return false ; return false ;
// cerco punto discreto più vicino (anche estremi di zone continue) // cerco punto discreto più vicino (anche estremi di zone continue)
int nInd ; int nInd ;
double dParam ; double dParam ;
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) { for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
BIN
View File
Binary file not shown.
+3
View File
@@ -320,6 +320,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersLineVolZmap.cpp" /> <ClCompile Include="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" /> <ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" /> <ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="SurfTriMeshOffset.cpp" />
<ClCompile Include="VolZmapOffset.cpp" />
<ClCompile Include="PolygonElevation.cpp" /> <ClCompile Include="PolygonElevation.cpp" />
<ClCompile Include="Quaternion.cpp" /> <ClCompile Include="Quaternion.cpp" />
<ClCompile Include="RotationMinimizingFrame.cpp" /> <ClCompile Include="RotationMinimizingFrame.cpp" />
@@ -343,6 +345,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" /> <ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" /> <ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" /> <ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
<ClInclude Include="CAvSilhouetteSurfTm.h" /> <ClInclude Include="CAvSilhouetteSurfTm.h" />
<ClInclude Include="CDeBoxTria.h" /> <ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" /> <ClInclude Include="CDeCapsTria.h" />
+9
View File
@@ -546,6 +546,12 @@
<ClCompile Include="DistPointSurfFr.cpp"> <ClCompile Include="DistPointSurfFr.cpp">
<Filter>File di origine\GeoDist</Filter> <Filter>File di origine\GeoDist</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="VolZmapOffset.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshOffset.cpp">
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
@@ -1226,6 +1232,9 @@
<ClInclude Include="CAvSilhouetteSurfTm.h"> <ClInclude Include="CAvSilhouetteSurfTm.h">
<Filter>File di intestazione</Filter> <Filter>File di intestazione</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc"> <ResourceCompile Include="EgtGeomKernel.rc">
+106 -21
View File
@@ -23,20 +23,20 @@ using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static void static void
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen, UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite) int nStm, int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
{ {
Point3d ptInt, ptInt2 ; Point3d ptInt, ptInt2 ;
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, bFinite) ; int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, bFinite) ;
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) { if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
double dU = ( ptInt - ptL) * vtDir ; double dU = ( ptInt - ptL) * vtDir ;
double dCosDN = vtDir * Tria.GetN() ; double dCosDN = vtDir * Tria.GetN() ;
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ; vInfo.emplace_back( nRes, dU, nStm, nT, dCosDN, ptInt) ;
} }
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) { else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
double dU = ( ptInt - ptL) * vtDir ; double dU = ( ptInt - ptL) * vtDir ;
double dU2 = ( ptInt2 - ptL) * vtDir ; double dU2 = ( ptInt2 - ptL) * vtDir ;
double dCosDN = vtDir * Tria.GetN() ; double dCosDN = vtDir * Tria.GetN() ;
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ; vInfo.emplace_back( nRes, dU, dU2, nStm, nT, dCosDN, ptInt, ptInt2) ;
} }
} }
@@ -48,7 +48,7 @@ OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
if ( vInfo.empty()) if ( vInfo.empty())
return ; return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea // ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(), sort( vInfo.begin(), vInfo.end(),
[]( const IntLinStmInfo& a, const IntLinStmInfo& b) []( const IntLinStmInfo& a, const IntLinStmInfo& b)
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ; { double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ; double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
@@ -108,7 +108,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
Triangle3d Tria ; Triangle3d Tria ;
Stm.GetTriangle( nT, Tria) ; Stm.GetTriangle( nT, Tria) ;
// aggiorno info con intersezione // aggiorno info con intersezione
UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, 0, nT, Tria, vInfo, bFinite) ;
} }
} }
} }
@@ -124,19 +124,23 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
// Intersezione di molte linee parallele con una superficie TriMesh // Intersezione di molte linee parallele con una superficie TriMesh
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfTriMesh& Stm) IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfTriMesh& Stm)
: m_bOk( false), m_frLines( frLines), m_pSTm( &Stm) : m_bOk( false), m_frLines( frLines), m_vpSTm( {&Stm})
{ {
// verifico esistenza superficie // verifico esistenza superficie
if ( m_pSTm == nullptr || ! m_pSTm->IsValid()) if ( m_vpSTm[0] == nullptr || ! m_vpSTm[0]->IsValid())
return ; return ;
// creo HashGrid 2d // aggiorno il vettore degli indici di base per mappare i triangoli con le rispettivi superfici
const int LIM_HG_TRIA = 127 ; // ( in questo caso la superficie è unica, quindi ho solo due elementi)
m_HGrids.SetActivationGrid( m_pSTm->GetTriangleCount() > LIM_HG_TRIA) ; m_vBaseInd = { 0, m_vpSTm[0]->GetTriangleCount()} ;
// riempio HashGrid // creo HashGrid 2d ed eventualmente attivo la griglia
const int LIM_HG_TRIA = 127 ;
m_HGrids.SetActivationGrid( m_vBaseInd.back() > LIM_HG_TRIA) ;
// riempio HashGrid
Triangle3d Tria ; Triangle3d Tria ;
int nT = Stm.GetFirstTriangle( Tria) ; int nT = m_vpSTm[0]->GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) { while ( nT != SVT_NULL) {
// calcolo il BBox del triangolo nel riferimento scelto // calcolo il BBox del triangolo nel riferimento scelto
Tria.ToLoc( m_frLines) ; Tria.ToLoc( m_frLines) ;
@@ -145,10 +149,55 @@ IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfT
b3Tria.Add( Tria.GetP( 1)) ; b3Tria.Add( Tria.GetP( 1)) ;
b3Tria.Add( Tria.GetP( 2)) ; b3Tria.Add( Tria.GetP( 2)) ;
// inserisco nella griglia // inserisco nella griglia
if ( ! m_HGrids.Add( nT, b3Tria)) if ( ! m_HGrids.Add( nT, b3Tria)) // ( 0 + nT, Tria)
return ; return ;
// passo al prossimo triangolo // passo al prossimo triangolo
nT = Stm.GetNextTriangle( nT, Tria) ; nT = m_vpSTm[0]->GetNextTriangle( nT, Tria) ;
}
// aggiorno
m_bOk = m_HGrids.Update() ;
}
//----------------------------------------------------------------------------
// Intersezione di molte linee parallele con un vettore di superfici TriMesh
//----------------------------------------------------------------------------
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const CISURFTMPVECTOR& vStm)
: m_bOk( false), m_frLines( frLines), m_vpSTm( vStm), m_vBaseInd( {0})
{
// verifico esistenza superfici
if ( m_vpSTm.empty())
return ;
for ( const ISurfTriMesh* pStm : m_vpSTm) {
if ( pStm == nullptr || ! pStm->IsValid())
return ;
}
// aggiorno il vettore degli indici di base per mappare i triangoli con le rispettivi superfici
// NB. dal costruttore è già inizializzato a {0}
for ( int i = 0 ; i < int( m_vpSTm.size()) ; ++ i)
m_vBaseInd.emplace_back( m_vBaseInd.back() + m_vpSTm[i]->GetTriangleCount()) ;
// creo HashGrid 2d ed eventualmente attivo la griglia
const int LIM_HG_TRIA = 256 ;
m_HGrids.SetActivationGrid( m_vBaseInd.back() > LIM_HG_TRIA) ;
// riempio HashGrid
for ( int i = 0 ; i < int( m_vpSTm.size()) ; ++ i) {
Triangle3d Tria ;
int nT = m_vpSTm[i]->GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) {
// calcolo il BBox del triangolo nel riferimento scelto
Tria.ToLoc( m_frLines) ;
BBox3d b3Tria ;
b3Tria.Add( Tria.GetP( 0)) ;
b3Tria.Add( Tria.GetP( 1)) ;
b3Tria.Add( Tria.GetP( 2)) ;
// inserisco nella griglia ( aggiungo shift per indice del triangolo)
if ( ! m_HGrids.Add( m_vBaseInd[i] + nT, b3Tria))
return ;
// passo al prossimo triangolo
nT = m_vpSTm[i]->GetNextTriangle( nT, Tria) ;
}
} }
// aggiorno // aggiorno
m_bOk = m_HGrids.Update() ; m_bOk = m_HGrids.Update() ;
@@ -162,7 +211,7 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
if ( &vInfo == nullptr) if ( &vInfo == nullptr)
return false ; return false ;
vInfo.clear() ; vInfo.clear() ;
// verifico validità // verifico validità
if ( ! m_bOk) if ( ! m_bOk)
return false ; return false ;
@@ -174,15 +223,22 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
Point3d ptLL = ptL ; Point3d ptLL = ptL ;
ptLL.ToGlob( m_frLines) ; ptLL.ToGlob( m_frLines) ;
// recupero indici triangoli che intersecano box in 2d // recupero indici triangoli che intersecano box in 2d
INTVECTOR vnIds ; INTVECTOR vnIds ;
if ( m_HGrids.Find( b3Line, vnIds)) { if ( m_HGrids.Find( b3Line, vnIds)) {
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) { for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
int nT = vnIds[i] ; // recupero la superficie
int nInd = vnIds[i] ;
int nSurf = GetSurfInd( nInd) ;
if ( nSurf == -1)
return false ;
// recupero il triangolo
int nT = nInd - m_vBaseInd[nSurf] ;
Triangle3d Tria ; Triangle3d Tria ;
m_pSTm->GetTriangle( nT, Tria) ; if ( ! m_vpSTm[nSurf]->GetTriangle( nT, Tria))
return false ;
// aggiorno info con intersezione // aggiorno info con intersezione
UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nT, Tria, vInfo, bFinite) ; UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nSurf, nT, Tria, vInfo, bFinite) ;
} }
} }
@@ -192,6 +248,35 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
return true ; return true ;
} }
//----------------------------------------------------------------------------
int
IntersParLinesSurfTm::GetSurfInd( int nT) const
{
// verifico la presenza di almeno un intervallo
if ( m_vBaseInd.size() < 2)
return -1 ;
// se la superficie è unica, allora non devo cercarla
if ( int( m_vBaseInd.size()) == 2)
return 0 ;
// ricerca binaria dell'intervallo contenente la posizione del triangolo
int nS = 0 ;
int nE = int( m_vBaseInd.size()) - 1 ;
while ( true) {
if ( nT < m_vBaseInd[nS] || nT >= m_vBaseInd[nE])
return -1 ;
if ( nE - nS == 1)
return nS ;
int nM = ( nS + nE) / 2 ;
if ( nT == m_vBaseInd[nM])
return nM ;
if ( nT < m_vBaseInd[nM])
nE = nM ;
else
nS = nM ;
}
return -1 ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters) FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
@@ -217,7 +302,7 @@ FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
for ( size_t j = 1 ; j < vInters.size() ; ) { for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente // intersezione precedente
size_t i = j - 1 ; size_t i = j - 1 ;
// se hanno lo stesso parametro // se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) { if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se sono entrambe entranti o uscenti, elimino la seconda // se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) || if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
+149 -25
View File
@@ -16,9 +16,17 @@
#include "CurveArc.h" #include "CurveArc.h"
#include "CurveLine.h" #include "CurveLine.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkChainCurves.h"
using namespace std ; using namespace std ;
//----------------------------------------------------------------------------
static bool IsFillet( const ICurve* pCrv, double dDist) ;
static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
static bool AdjustIntersections( ICRVCOMPOPVECTOR& CrvList) ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IdentifyFillets( ICurveComposite* pCrvCo, double dDist) IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
@@ -52,36 +60,76 @@ IsFillet( const ICurve* pCrv, double dDist)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) AdjustCurveFillets( ICURVEPOVECTOR& vOffset, double dDist, int nType)
{ {
ICURVEPLIST CrvLst ; if ( vOffset.empty())
PtrOwner<ICurve> pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ; return true ;
while ( ! IsNull( pCrv)) {
// se identificato come fillet lo trasformo in smusso o estensione // suddivido le curve di offset individuando i fillet e isolandoli dagli altri tratti
if ( pCrv->GetTempParam() > EPS_SMALL) { ICRVCOMPOPVECTOR vCrvs ;
CurveComposite ccTemp ; for ( int i = 0 ; i < int( vOffset.size()) ; i ++) {
ModifyFillet( pCrv, dDist, nType, ccTemp) ; CurveComposite* pCompo = GetBasicCurveComposite( vOffset[i]) ;
// metto in lista le curve risultanti if ( pCompo == nullptr)
if ( ccTemp.GetCurveCount() > 0) { return false ;
PtrOwner<ICurve> pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ; bool bNewCrv = true ;
while ( ! IsNull( pCrv2)) { PtrOwner<ICurve> pCrv( pCompo->RemoveFirstOrLastCurve(false)) ;
CrvLst.push_back( Release( pCrv2)) ; while ( ! IsNull( pCrv)) {
pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; if ( pCrv->GetTempParam() > EPS_SMALL) {
} // se fillet calcolo il nuovo raccordo
CurveComposite* ccTemp = CreateBasicCurveComposite() ;
ModifyFillet( pCrv, dDist, nType, *ccTemp) ;
// assegno temp param per identificarlo nei conti successivi
ccTemp->SetTempParam( 1) ;
vCrvs.push_back( ccTemp) ;
bNewCrv = true ;
} }
else {
// aggiungo la curva
if ( bNewCrv) {
bNewCrv = false ;
CurveComposite* pCompo = ConvertCurveToBasicComposite( Release( pCrv)) ;
if ( pCompo == nullptr)
return false ;
vCrvs.push_back( pCompo) ;
}
else
vCrvs.back()->AddCurve( Release( pCrv)) ;
}
// passo alla curva successiva
pCrv.Set( pCompo->RemoveFirstOrLastCurve( false)) ;
} }
// altrimenti salvo in lista
else
CrvLst.push_back( Release( pCrv)) ;
// passo alla curva successiva
pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ;
} }
// rimetto le curve nella composita vOffset.clear() ;
for ( auto pCrv : CrvLst) {
pCrvCo->AddCurve( pCrv) ; // gestione delle intersezioni
if ( ! AdjustIntersections( vCrvs))
return false ;
// concateno i tratti ottenuti
ChainCurves ChainCrv ;
ChainCrv.Init( false, 2 * EPS_SMALL, vCrvs.size()) ;
for ( int i = 0 ; i < int( vCrvs.size()); ++ i) {
Point3d ptS, ptE ;
Vector3d vtS, vtE ;
vCrvs[i]->GetStartPoint( ptS) ;
vCrvs[i]->GetEndPoint( ptE) ;
vCrvs[i]->GetStartDir( vtS) ;
vCrvs[i]->GetEndDir( vtE) ;
ChainCrv.AddCurve( i + 1, ptS, vtS, ptE, vtE) ;
}
// recupero i concatenamenti
Point3d ptRef ; vCrvs[0]->GetStartPoint( ptRef) ;
INTVECTOR vIds ;
while ( ChainCrv.GetChainFromNear( ptRef, false, vIds)) {
PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCompo))
return false ;
for ( auto i : vIds)
pCompo->AddCurve( vCrvs[i-1]) ;
pCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
pCompo->GetEndPoint( ptRef) ;
vOffset.emplace_back( Release( pCompo)) ;
} }
// unisco tratti allineati
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
return true ; return true ;
} }
@@ -175,3 +223,79 @@ ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux)
} }
return false ; return false ;
} }
//----------------------------------------------------------------------------
bool
AdjustIntersections( ICRVCOMPOPVECTOR& vCrvs)
{
// sistema le curve nel vettore vCrvs eliminando le parti coinvolte nelle intersezioni
vector<Intervals> vIntervals( vCrvs.size()) ;
INTVECTOR vFillets ;
for ( int i = 0 ; i < int( vCrvs.size()) ; i ++) {
// salvo i parametri della curva
double dParS, dParE ;
vCrvs[i]->GetDomain( dParS, dParE) ;
vIntervals[i].Set( dParS, dParE) ;
// verifico se raccordo
if ( vCrvs[i]->GetTempParam() > EPS_SMALL)
vFillets.emplace_back( i) ;
}
// verifico se i raccordi intersecano le altre curve
bool bInters = false ;
for ( int i = 0 ; i < int( vFillets.size()) ; i ++) {
int nIdx = vFillets[i] ;
for ( int j = 0 ; j < int( vCrvs.size()) ; j ++) {
if ( j == nIdx)
continue ;
IntersCurveCurve intCC( *vCrvs[nIdx], *vCrvs[j]) ;
int nCnt = intCC.GetIntersCount() ;
if ( nCnt > 1) {
// aggiorno gli intervalli della curva sottraendo la parte coinvolta dall'intersezione
for ( int k = 0 ; k < nCnt - 1 ; k = k+2) {
IntCrvCrvInfo iccInfo1, iccInfo2 ;
intCC.GetIntCrvCrvInfo( k, iccInfo1) ;
// verifico non sia intersezione nell'estremo iniziale o sovrapposizione
if ( iccInfo1.IciA[0].dU < EPS_SMALL || iccInfo1.bOverlap) {
k-- ;
continue ;
}
intCC.GetIntCrvCrvInfo( k+1, iccInfo2) ;
vIntervals[nIdx].Subtract( iccInfo1.IciA[0].dU, iccInfo2.IciA[0].dU) ;
vIntervals[j].Subtract( iccInfo1.IciB[0].dU, iccInfo2.IciB[0].dU) ;
bInters = true ;
}
}
}
}
if ( ! bInters)
return true ;
// aggiorno le curve eliminando i tratti coinvolti nelle intersezioni
for ( int i = 0 ; i < int( vIntervals.size()) ; i++) {
if ( vIntervals[i].GetCount() > 1) {
PtrOwner<CurveComposite> pCompo( CloneBasicCurveComposite( vCrvs[i])) ;
if ( IsNull( pCompo))
return false ;
double dParS, dParE ;
vIntervals[i].GetFirst( dParS, dParE) ;
vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ;
while ( vIntervals[i].GetNext( dParS, dParE)) {
CurveComposite* pCrv = ConvertCurveToBasicComposite( pCompo->CopyParamRange( dParS, dParE)) ;
if ( pCrv == nullptr)
return false ;
vCrvs.emplace_back( pCrv) ;
}
}
else {
double dParS, dParE ;
vIntervals[i].GetFirst( dParS, dParE) ;
vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ;
}
}
return true ;
}
+1 -3
View File
@@ -16,6 +16,4 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ; bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ;
bool IsFillet( const ICurve* pCrv, double dDist) ; bool AdjustCurveFillets( ICURVEPOVECTOR& vCrvs, double dDist, int nType) ;
bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ;
bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
+13 -5
View File
@@ -674,12 +674,20 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
} }
// nono passo : se con smusso o estensione, sostituisco i fillet con questi // nono passo : se con smusso o estensione, sostituisco i fillet con questi
// NB questa parte non è gestita in modo efficiente perchè dovrebbe essere sempre disabilitata.
// Le funzioni sono state ottimizzate per lavorare con voronoi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { ICURVEPOVECTOR vCrvs ;
CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; vCrvs.reserve( m_CrvLst.size()) ;
IdentifyFillets( pCrvCo, dDist) ; for ( auto pCrv : m_CrvLst) {
AdjustCurveFillets( pCrvCo, dDist, nType) ; IdentifyFillets( GetCurveComposite( pCrv), dDist) ;
} vCrvs.emplace_back( pCrv) ;
}
if ( ! AdjustCurveFillets( vCrvs, dDist, nType))
return false ;
m_CrvLst.clear() ;
for ( int j = 0 ; j < int( vCrvs.size()) ; j ++)
m_CrvLst.emplace_back( Release( vCrvs[j])) ;
} }
} }
+7 -2
View File
@@ -150,12 +150,18 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
Vector3d vtN = pgFacet.GetVersN() ; Vector3d vtN = pgFacet.GetVersN() ;
PolyLine PL = pgFacet.GetPolyLine() ; PolyLine PL = pgFacet.GetPolyLine() ;
// calcolo elevazione massima del contorno della faccia // calcolo elevazione massima del contorno della faccia e nel suo centro
const double RAY_LEN = 100000 ; const double RAY_LEN = 100000 ;
dElev = 0 ; dElev = 0 ;
PNTVECTOR vptP ; vptP.reserve( PL.GetPointNbr()) ;
Point3d ptP ; Point3d ptP ;
bool bFound = PL.GetFirstPoint( ptP) ; bool bFound = PL.GetFirstPoint( ptP) ;
while ( bFound) { while ( bFound) {
vptP.push_back( ptP) ;
bFound = PL.GetNextPoint( ptP, true) ;
}
vptP.push_back( ptCen) ;
for ( const Point3d& ptP : vptP) {
ILSIVECTOR vInters ; ILSIVECTOR vInters ;
IntersLineSurfTm( ptP, vtN, RAY_LEN, CldStm, vInters, true) ; IntersLineSurfTm( ptP, vtN, RAY_LEN, CldStm, vInters, true) ;
for ( int i = 0 ; i < int( vInters.size()) ; ++ i) { for ( int i = 0 ; i < int( vInters.size()) ; ++ i) {
@@ -171,7 +177,6 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE) else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
dElev = max( dElev, Inters.dU2) ; dElev = max( dElev, Inters.dU2) ;
} }
bFound = PL.GetNextPoint( ptP, true) ;
} }
// calcolo elevazione massima degli eventuali spigoli (e vertici) della superficie chiusa dalla parte positiva della faccia e che cadono in essa // calcolo elevazione massima degli eventuali spigoli (e vertici) della superficie chiusa dalla parte positiva della faccia e che cadono in essa
int nEdgeCnt = CldStm.GetEdgeCount() ; int nEdgeCnt = CldStm.GetEdgeCount() ;
+5 -5
View File
@@ -19,10 +19,10 @@
void void
PolygonPlane::AddPoint( const Point3d& ptP) PolygonPlane::AddPoint( const Point3d& ptP)
{ {
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura) // se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
if ( m_nPntNbr == -1) { if ( m_nPntNbr == -1) {
// inizializzazioni // inizializzazioni
m_dLenN = 0 ; m_dLenN = -1 ;
m_vtN = V_NULL ; m_vtN = V_NULL ;
m_ptMid = ORIG ; m_ptMid = ORIG ;
m_dSXy = 0 ; m_dSXz = 0 ; m_dSXy = 0 ; m_dSXz = 0 ;
@@ -60,16 +60,16 @@ PolygonPlane::AddPoint( const Point3d& ptP)
bool bool
PolygonPlane::Finalize( void) PolygonPlane::Finalize( void)
{ {
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati) // almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
if ( m_nPntNbr + 1 < 3) if ( m_nPntNbr + 1 < 3)
return false ; return false ;
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato // se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
if ( ! AreSamePointExact( m_ptFirst, m_ptLast)) { if ( ! AreSamePointExact( m_ptFirst, m_ptLast)) {
// aggiungo il primo punto per far eseguire i conti sul lato di chiusura // aggiungo il primo punto per far eseguire i conti sul lato di chiusura
AddPoint( m_ptFirst) ; AddPoint( m_ptFirst) ;
} }
// se non effettuato, eseguo il calcolo finale // se non effettuato, eseguo il calcolo finale
if ( m_dLenN < EPS_SMALL) { if ( m_dLenN < 0) {
// lunghezza della normale (doppio dell'area del poligono) // lunghezza della normale (doppio dell'area del poligono)
m_dLenN = m_vtN.Len() ; m_dLenN = m_vtN.Len() ;
if ( m_dLenN < SQ_EPS_SMALL) if ( m_dLenN < SQ_EPS_SMALL)
+299 -191
View File
@@ -29,8 +29,6 @@ using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Angolo limite tra normale al triangolo e direzione di proiezione 89° // Angolo limite tra normale al triangolo e direzione di proiezione 89°
const double COS_ANG_LIM = 0.0175 ; const double COS_ANG_LIM = 0.0175 ;
// Massimo numero di triangoli per raffinare ricerca su spigoli
const int MAX_FACET_FOR_CORNER = 1000 ;
// Angolo massimo tra normali per effettuare bisezione su spigolo // Angolo massimo tra normali per effettuare bisezione su spigolo
const double COS_ANG_MAX_CORNER = 0.8660 ; const double COS_ANG_MAX_CORNER = 0.8660 ;
// Tipologia di punto // Tipologia di punto
@@ -156,30 +154,52 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
return true ; return true ;
} }
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ; // vettore di oggetti intersezione massiva rette parallele SurfTM
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3d& frRefLine, const IntersParLinesSurfTm& intPLSTM, ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
double dPar, Point5ax& Pt5ax) double dPar, Point5ax& Pt5ax)
{ {
// intersezione retta di proiezione con superficie // intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
Point3d ptL = GetToLoc( ptP, frRefLine) ; Point3d ptL = GetToLoc( ptP, frRefLine) ;
ILSIVECTOR vIntRes ; int nInd = -1 ;
intPLSTM.GetInters( ptL, 1, vIntRes, false) ; IntLinStmInfo IntRes ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) {
int nI = int( vIntRes.size()) - 1 ; ILSIVECTOR vIntRes ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
--nI ; // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = int( vIntRes.size()) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
// se trovata // se trovata
if ( nI >= 0) { if ( nInd >= 0) {
// calcolo il punto // calcolo il punto
Point3d ptInt ; Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ; ptInt = IntRes.ptI2 ;
else else
ptInt = vIntRes[nI].ptI ; ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ; Triangle3dEx trTria ;
if ( ! stmSurf.GetTriangle( vIntRes[nI].nT, trTria)) if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ; return false ;
Vector3d vtN ; Vector3d vtN ;
if ( ! CalcNormal( ptInt, trTria, vtN)) if ( ! CalcNormal( ptInt, trTria, vtN))
@@ -198,26 +218,30 @@ ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vtDir, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ; CISRFTMPVECTOR vpSurfTm ;
switch ( sfSurf.GetType()) { for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
case SRF_TRIMESH : const SurfTriMesh* pSurfTm = nullptr ;
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; switch ( vpSurf[i]->GetType()) {
break ; case SRF_TRIMESH :
case SRF_BEZIER : pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_BEZIER :
case SRF_FLATRGN : pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_FLATRGN :
default : pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ; break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
} }
if ( pSurfTm == nullptr)
return false ;
// controllo le tolleranze // controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ; dLinTol = max( dLinTol, LIN_TOL_MIN) ;
@@ -230,11 +254,20 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ; return false ;
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie // Oggetti per calcolo massivo intersezioni tra linee di proiezione e superfici
Frame3d frRefLine ; Frame3d frRefLine ;
if ( ! frRefLine.Set( ORIG, vtDir)) if ( ! frRefLine.Set( ORIG, vtDir))
return false ; return false ;
IntersParLinesSurfTm intPLSTM( frRefLine, *pSurfTm) ; INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) {
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
if ( pIntPLSTM == nullptr) {
for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j)
delete vpIntPLSTM[j] ;
return false ;
}
vpIntPLSTM.emplace_back( pIntPLSTM) ;
}
// Pulisco e riservo spazio nel vettore dei punti risultanti // Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ; vPt5ax.clear() ;
@@ -247,12 +280,16 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, frRefLine, intPLSTM, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
} }
// Libero oggetti per calcolo massivo
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i)
delete vpIntPLSTM[i] ;
// se richiesto, inserimento punti intermedi in presenza di spigoli // se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) { if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
@@ -325,72 +362,96 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax) ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
{ {
// punto di riferimento // punto di riferimento
Point3d ptMin = gpRef.GetPoint() ; Point3d ptMin = gpRef.GetPoint() ;
// intersezione della retta di minima distanza con la superficie // intersezione della retta di minima distanza con le superfici
Vector3d vtLine = ptP - ptMin ; Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ; double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) { if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ; vtLine /= dLineLen ;
ILSIVECTOR vIntRes ; // conservo l'intersezione più alta
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) { int nInd = -1 ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) IntLinStmInfo IntRes ;
int nI = int( vIntRes.size()) - 1 ; for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) ILSIVECTOR vIntRes ;
--nI ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se trovata // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
if ( nI >= 0) { int nI = int( vIntRes.size()) - 1 ;
// calcolo il punto while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
Point3d ptInt ; --nI ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) // se trovata
ptInt = vIntRes[nI].ptI2 ; if ( nI >= 0) {
else if ( nInd < 0) {
ptInt = vIntRes[nI].ptI ; IntRes = vIntRes[nI] ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) nInd = i ;
Triangle3dEx trTria ; }
if ( ! stmSurf.GetTriangle( vIntRes[nI].nT, trTria)) else {
return false ; double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
Vector3d vtN ; double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( ! CalcNormal( ptInt, trTria, vtN)) if ( dU > dUref) {
vtN = trTria.GetN() ; IntRes = vIntRes[nI] ;
// assegno valori al punto 5assi nInd = i ;
Pt5ax.ptP = ptInt ; }
Pt5ax.vtDir1 = vtN ; }
Pt5ax.vtDir2 = vtLine ; }
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
} }
} }
// se trovata
if ( nInd >= 0) {
// calcolo il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptInt, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
} }
return false ; return false ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& gpRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ; CISRFTMPVECTOR vpSurfTm ;
switch ( sfSurf.GetType()) { for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
case SRF_TRIMESH : const SurfTriMesh* pSurfTm = nullptr ;
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; switch ( vpSurf[i]->GetType()) {
break ; case SRF_TRIMESH :
case SRF_BEZIER : pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_BEZIER :
case SRF_FLATRGN : pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_FLATRGN :
default : pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ; break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
} }
if ( pSurfTm == nullptr)
return false ;
// controllo le tolleranze // controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ; dLinTol = max( dLinTol, LIN_TOL_MIN) ;
@@ -415,14 +476,14 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d&
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, gpRef, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
} }
// se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli // se richiesto, inserimento punti intermedi in presenza di spigoli
if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) { if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
// precedente // precedente
int j = i - 1 ; int j = i - 1 ;
@@ -434,7 +495,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d&
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptMid, *pSurfTm, gpRef, dMid, Pt5ax)) { if ( ProjectPointOnSurf( ptMid, vpSurfTm, gpRef, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ; -- i ;
} }
@@ -450,49 +511,69 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d&
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const ICurve& crRef, double dPar, Point5ax& Pt5ax) ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
{ {
// punto a minima distanza // punto a minima distanza
DistPointCurve dPC( ptP, crRef) ; DistPointCurve dPC( ptP, crRef) ;
Point3d ptMin ; Point3d ptMin ;
int nFlag ; int nFlag ;
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) { if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
// intersezione della retta di minima distanza con la superficie // intersezione della retta di minima distanza con le superfici
Vector3d vtLine = ptP - ptMin ; Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ; double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) { if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ; vtLine /= dLineLen ;
ILSIVECTOR vIntRes ; // conservo l'intersezione più alta
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) { int nInd = -1 ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) IntLinStmInfo IntRes ;
int nI = int( vIntRes.size()) - 1 ; for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) ILSIVECTOR vIntRes ;
--nI ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se trovata // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
if ( nI >= 0) { int nI = int( vIntRes.size()) - 1 ;
// calcolo il punto while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
Point3d ptInt ; --nI ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) // se trovata
ptInt = vIntRes[nI].ptI2 ; if ( nI >= 0) {
else if ( nInd < 0) {
ptInt = vIntRes[nI].ptI ; IntRes = vIntRes[nI] ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) nInd = i ;
Triangle3dEx trTria ; }
if ( ! stmSurf.GetTriangle( vIntRes[nI].nT, trTria)) else {
return false ; double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
Vector3d vtN ; double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( ! CalcNormal( ptInt, trTria, vtN)) if ( dU > dUref) {
vtN = trTria.GetN() ; IntRes = vIntRes[nI] ;
// assegno valori al punto 5assi nInd = i ;
Pt5ax.ptP = ptInt ; }
Pt5ax.vtDir1 = vtN ; }
Pt5ax.vtDir2 = vtLine ; }
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
} }
} }
// se trovata
if ( nInd >= 0) {
// assegno il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptInt, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
} }
} }
return false ; return false ;
@@ -500,26 +581,30 @@ ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const ICurve
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// Sistemazioni per tipo di superficie // Sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ; CISRFTMPVECTOR vpSurfTm ;
switch ( sfSurf.GetType()) { for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
case SRF_TRIMESH : const SurfTriMesh* pSurfTm = nullptr ;
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; switch ( vpSurf[i]->GetType()) {
break ; case SRF_TRIMESH :
case SRF_BEZIER : pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_BEZIER :
case SRF_FLATRGN : pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_FLATRGN :
default : pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ; break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
} }
if ( pSurfTm == nullptr)
return false ;
// Controllo le tolleranze // Controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ; dLinTol = max( dLinTol, LIN_TOL_MIN) ;
@@ -544,7 +629,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRe
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, crRef, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -622,7 +707,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRe
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax) ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
{ {
// punto sulla superficie guida a minima distanza // punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, stmRef) ; DistPointSurfTm dPS( ptP, stmRef) ;
@@ -643,71 +728,94 @@ ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const SurfTr
vtLine = trGuide.GetN() ; vtLine = trGuide.GetN() ;
dLineLen = 100 ; dLineLen = 100 ;
} }
// intersezione della retta con la superficie // intersezione della retta con le superfici (conservo l'intersezione più alta)
ILSIVECTOR vIntRes ; int nInd = -1 ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) { IntLinStmInfo IntRes ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
int nI = int( vIntRes.size()) - 1 ; ILSIVECTOR vIntRes ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
--nI ; // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
// se trovata int nI = int( vIntRes.size()) - 1 ;
if ( nI >= 0) { while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
// calcolo il punto --nI ;
Point3d ptInt ; // se trovata
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) if ( nI >= 0) {
ptInt = vIntRes[nI].ptI2 ; if ( nInd < 0) {
else IntRes = vIntRes[nI] ;
ptInt = vIntRes[nI].ptI ; nInd = i ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) }
Triangle3dEx trTria ; else {
if ( ! stmSurf.GetTriangle( vIntRes[nI].nT, trTria)) double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
return false ; double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
Vector3d vtN ; if ( dU > dUref) {
if ( ! CalcNormal( ptMin, trTria, vtN)) IntRes = vIntRes[nI] ;
vtN = trTria.GetN() ; nInd = i ;
// calcolo la normale della superficie guida }
Triangle3dEx trGuide ; }
if ( ! stmRef.GetTriangle( nTriaMin, trGuide)) }
return false ;
Vector3d vtN2 ;
if ( ! CalcNormal( ptMin, trGuide, vtN2))
vtN2 = trGuide.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
} }
} }
// se trovata
if ( nInd >= 0) {
// calcolo il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN))
vtN = trTria.GetN() ;
// calcolo la normale della superficie guida
Triangle3dEx trGuide ;
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
return false ;
Vector3d vtN2 ;
if ( ! CalcNormal( ptMin, trGuide, vtN2))
vtN2 = trGuide.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
} }
return false ; return false ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ; CISRFTMPVECTOR vpSurfTm ;
switch ( sfSurf.GetType()) { for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
case SRF_TRIMESH : const SurfTriMesh* pSurfTm = nullptr ;
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; switch ( vpSurf[i]->GetType()) {
break ; case SRF_TRIMESH :
case SRF_BEZIER : pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_BEZIER :
case SRF_FLATRGN : pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ;
break ; case SRF_FLATRGN :
default : pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ; break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
} }
if ( pSurfTm == nullptr)
return false ;
// sistemazioni per tipo di superficie di riferimento // sistemazioni per tipo di superficie di riferimento
const SurfTriMesh* pRefTm = nullptr ; const SurfTriMesh* pRefTm = nullptr ;
@@ -750,14 +858,14 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, *pRefTm, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
} }
// se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli // se richiesto, inserimento punti intermedi in presenza di spigoli
if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) { if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
// precedente // precedente
int j = i - 1 ; int j = i - 1 ;
@@ -769,7 +877,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptMid, *pSurfTm, *pRefTm, dMid, Pt5ax)) { if ( ProjectPointOnSurf( ptMid, vpSurfTm, *pRefTm, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ; -- i ;
} }
+32 -667
View File
@@ -95,56 +95,17 @@ ISurfBezier*
GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
bool bCapEnds, double dLinTol) bool bCapEnds, double dLinTol)
{ {
// verifica parametri // verifica parametri
if ( pCurve == nullptr || &vtExtr == nullptr) if ( pCurve == nullptr || &vtExtr == nullptr)
return nullptr ; return nullptr ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return nullptr ;
//// se richiesta chiusura agli estremi
//bool bDoCapEnds = false ;
//if ( bCapEnds) {
// // verifico che la curva sia chiusa e piatta
// Plane3d plPlane ;
// double dArea ;
// if ( PL.IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) {
// // componente dell'estrusione perpendicolare al piano della curva
// double dOrthoExtr = plPlane.GetVersN() * vtExtr ;
// if ( ( abs( dOrthoExtr) > EPS_SMALL)) {
// bDoCapEnds = true ;
// // se negativa, inverto il senso del contorno
// if ( dOrthoExtr < 0)
// PL.Invert() ;
// }
// }
//}
PtrOwner<const ICurve> pBezierForm( CurveToBezierCurve( pCurve)) ; PtrOwner<const ICurve> pBezierForm( CurveToBezierCurve( pCurve)) ;
// creo e setto la superficie trimesh // creo e setto la superficie di Bezier
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr)) if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr))
return nullptr ; return nullptr ;
//// se da fare, metto i tappi sulle estremità // restituisco la superficie
//if ( bDoCapEnds) {
// // creo la prima superficie di estremità
// SurfTriMesh STM1 ;
// if ( ! STM1.CreateByFlatContour( PL))
// return nullptr ;
// // la copio
// SurfTriMesh STM2 = STM1 ;
// // inverto la prima superficie
// STM1.Invert() ;
// // traslo la seconda
// STM2.Translate( vtExtr) ;
// ////// SurfCompo?
// //// le unisco alla superficie del fianco
// //if ( ! pSbz->DoSewing( STM1) || ! pSTM->DoSewing( STM2))
// // return nullptr ;
//}
// restituisco la superficie
return Release( pSbz) ; return Release( pSbz) ;
} }
@@ -201,45 +162,6 @@ GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3
return nullptr ; return nullptr ;
// limite minimo su tolleranza // limite minimo su tolleranza
dLinTol = max( dLinTol, EPS_SMALL) ; dLinTol = max( dLinTol, EPS_SMALL) ;
//// calcolo la polilinea che approssima la curva
//PolyLine PL ;
//if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
// return nullptr ;
//// se richiesta chiusura degli estremi
//if ( bCapEnds && ! PL.IsClosed()) { // serve la SURFCOMPO
// Vector3d vtAxN = vtAx ;
// vtAxN.Normalize() ;
// double dPosIni = 0, dPosFin = 0 ;
// Point3d ptP ;
// // proietto l'ultimo punto sull'asse di rotazione
// if ( PL.GetLastPoint( ptP)) {
// dPosFin = ( ptP - ptAx) * vtAxN ;
// Point3d ptPOnAx = ptAx + dPosFin * vtAxN ;
// // se non giace sull'asse, aggiungo il punto proiettato
// if ( ! AreSamePointApprox( ptP, ptPOnAx)) {
// double dU ;
// PL.GetLastU( dU) ;
// PL.AddUPoint( ( dU + 1), ptPOnAx) ;
// }
// }
// // inverto la polilinea
// PL.Invert() ;
// // proietto l'ultimo punto (era il primo) sull'asse di rotazione
// if ( PL.GetLastPoint( ptP)) {
// dPosIni = ( ptP - ptAx) * vtAxN ;
// Point3d ptPOnAx = ptAx + dPosIni * vtAxN ;
// // se non giace sull'asse, aggiungo il punto proiettato
// if ( ! AreSamePointApprox( ptP, ptPOnAx)) {
// double dU ;
// PL.GetLastU( dU) ;
// PL.AddUPoint( ( dU + 1), ptPOnAx) ;
// }
// }
// // decido se reinvertire la polilinea
// if ( dPosFin > dPosIni)
// PL.Invert() ;
//}
// creo e setto la superficie trimesh // creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
@@ -259,392 +181,31 @@ ISurfBezier*
GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol) double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol)
{ {
// verifica parametri // verifica parametri
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr) if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
return nullptr ; return nullptr ;
// limite minimo su tolleranza // limite minimo su tolleranza
dLinTol = max( dLinTol, EPS_SMALL) ; dLinTol = max( dLinTol, EPS_SMALL) ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return nullptr ;
// creo e setto la superficie bezier // creo e setto la superficie bezier
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove)) if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove))
return nullptr ; return nullptr ;
//// se richiesti caps /// richiede la SurfCompo
//if ( bCapEnds) { // se superficie risultante chiusa, verifico che la normale sia verso l'esterno
// // determino se la sezione è chiusa e piatta
// Plane3d plPlane ; double dArea ;
// bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ;
// // determino non sia una semplice rivoluzione
// bool bRevolved = ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL && abs( dMove) < EPS_SMALL) ;
// // se sezione chiusa e piatta e non rivoluzione, posso aggiungere i tappi
// if ( bSectClosedFlat && ! bRevolved) {
// // aggiungo il cap sull'inizio
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
// return nullptr ;
// pSTM->DoSewing( *pSci) ;
// // aggiungo il cap sulla fine
// Vector3d vtMove = vtAx ;
// vtMove.Normalize() ;
// vtMove *= dMove ;
// PL.Translate( vtMove) ;
// PL.Rotate( ptAx, vtAx, dAngRotDeg) ;
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
// return nullptr ;
// pSce->Invert() ;
// pSTM->DoSewing( *pSce) ;
// }
//}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ; double dVol ;
if ( pSbz->GetVolume( dVol) && dVol < 0) if ( pSbz->GetVolume( dVol) && dVol < 0)
pSbz->Invert() ; pSbz->Invert() ;
// restituisco la superficie // restituisco la superficie
return Release( pSbz) ; return Release( pSbz) ;
} }
//
////-------------------------------------------------------------------------------
//static ISurfBezier*
//GetSurfBezierSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // verifico che la linea guida sia piana
// Plane3d plGuide ;
// if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
// return nullptr ;
// Vector3d vtNorm = plGuide.GetVersN() ;
// // determino se la guida è chiusa
// bool bGuideClosed = pGuide->IsClosed() ;
// // curve di offset
// OffsetCurve OffsCrvR ;
// if ( ! OffsCrvR.Make( pGuide, dDimH / 2, ICurve::OFF_FILLET) || OffsCrvR.GetCurveCount() == 0)
// return nullptr ;
// PtrOwner<ICurve> pCrvR( OffsCrvR.GetLongerCurve()) ;
// if ( IsNull( pCrvR))
// return nullptr ;
// OffsetCurve OffsCrvL ;
// if ( ! OffsCrvL.Make( pGuide, -dDimH / 2, ICurve::OFF_FILLET) || OffsCrvL.GetCurveCount() == 0)
// return nullptr ;
// PtrOwner<ICurve> pCrvL( OffsCrvL.GetLongerCurve()) ;
// if ( IsNull( pCrvL))
// return nullptr ;
// // costruisco le parti di superficie
// PtrOwner<ISurfTriMesh> pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
// if ( IsNull( pSrfTop))
// return nullptr ;
// PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
// if ( IsNull( pSrfBot))
// return nullptr ;
// pSrfBot->Translate( -dDimV * vtNorm) ;
// pSrfBot->Invert() ;
// PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ;
// if ( IsNull( pSrfRgt))
// return nullptr ;
// pSrfRgt->Invert() ;
// PtrOwner<ISurfTriMesh> pSrfLft( GetSurfTriMeshByExtrusion( pCrvL, -dDimV * vtNorm, false, dLinTol)) ;
// if ( IsNull( pSrfLft))
// return nullptr ;
// // unisco le parti
// PtrOwner<ISurfTriMesh> pSTM( Release( pSrfTop)) ;
// pSTM->DoSewing( *pSrfRgt) ;
// pSTM->DoSewing( *pSrfLft) ;
// pSTM->DoSewing( *pSrfBot) ;
// // salvo tolleranza lineare usata e imposto angolo per smooth
// pSTM->SetLinearTolerance( dLinTol) ;
// pSTM->SetSmoothAngle( 20) ;
// // se guida aperta e tappi piatti
// if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
// // verifico che le due estremità siano chiuse e piatte
// POLYLINEVECTOR vPL ;
// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
// return nullptr ;
// Plane3d plEnds ; double dArea ;
// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
// return nullptr ;
// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
// return nullptr ;
// // aggiungo il cap sull'inizio
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
// return nullptr ;
// pSci->Invert() ;
// pSTM->DoSewing( *pSci) ;
// // aggiungo il cap sulla fine
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
// return nullptr ;
// pSce->Invert() ;
// pSTM->DoSewing( *pSce) ;
// }
// // se altrimenti guida aperta e tappi arrotondati
// if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
// // step di rotazione per rispettare la tolleranza
// double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ;
// // aggiungo il cap sull'inizio
// Point3d ptStart ;
// pGuide->GetStartPoint( ptStart) ;
// Vector3d vtStart ;
// pGuide->GetStartDir( vtStart) ;
// vtStart.Rotate( vtNorm, 0, 1) ;
// PolyLine PLStart ;
// PLStart.AddUPoint( 0, ptStart) ;
// PLStart.AddUPoint( 1, ptStart + dDimH / 2 * vtStart) ;
// PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dDimV * vtNorm) ;
// PLStart.AddUPoint( 3, ptStart - dDimV * vtNorm) ;
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
// return nullptr ;
// pSci->Invert() ;
// pSTM->DoSewing( *pSci) ;
// // aggiungo il cap sulla fine
// Point3d ptEnd ;
// pGuide->GetEndPoint( ptEnd) ;
// Vector3d vtEnd ;
// pGuide->GetEndDir( vtEnd) ;
// vtEnd.Rotate( vtNorm, 0, -1) ;
// PolyLine PLEnd ;
// PLEnd.AddUPoint( 0, ptEnd) ;
// PLEnd.AddUPoint( 1, ptEnd + dDimH / 2 * vtEnd) ;
// PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dDimV * vtNorm) ;
// PLEnd.AddUPoint( 3, ptEnd - dDimV * vtNorm) ;
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
// return nullptr ;
// pSce->Invert() ;
// pSTM->DoSewing( *pSce) ;
// }
// // restituisco la superficie
// return Release( pSTM) ;
//}
//
////-------------------------------------------------------------------------------
//static ISurfBezier*
//GetSurfBezierBeveledRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // metodo di calcolo impostato da USE_VORONOI
//
// // verifico che la linea guida sia piana
// Plane3d plGuide ;
// if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
// return nullptr ;
// // assegno la normale del piano
// Vector3d vtNorm = plGuide.GetVersN() ;
// // determino il punto centrale della sezione
// Point3d ptCen ;
// pGuide->GetStartPoint( ptCen) ;
// ptCen -= dDimV / 2 * vtNorm ;
// // determino se la guida è chiusa
// bool bGuideClosed = pGuide->IsClosed() ;
// // curve di offset
// const int NUM_OFFS = 4 ;
// OffsetCurve vOffsCrv[NUM_OFFS] ;
// double vDist[NUM_OFFS] = { dDimH / 2 - dBevelH, -dDimH / 2 + dBevelH, dDimH / 2, -dDimH / 2} ;
// bool bOk = true ;
// if ( ! USE_VORONOI) {
// future<bool> vRes[NUM_OFFS] ;
// for ( int i = 0 ; i < NUM_OFFS ; ++ i)
// vRes[i] = async( launch::async, &OffsetCurve::Make, &vOffsCrv[i], pGuide, vDist[i], ICurve::OFF_FILLET) ;
// bool bOk = true ;
// int nFin = 0 ;
// while ( nFin < NUM_OFFS) {
// for ( int i = 0 ; i < NUM_OFFS ; ++ i) {
// if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
// bOk = vRes[i].get() && bOk ;
// ++ nFin ;
// }
// }
// }
// }
// else {
// // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo
// for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i)
// bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ;
// }
//
// if ( ! bOk ||
// vOffsCrv[0].GetCurveCount() == 0 || vOffsCrv[1].GetCurveCount() == 0 ||
// vOffsCrv[2].GetCurveCount() == 0 || vOffsCrv[3].GetCurveCount() == 0)
// return nullptr ;
// PtrOwner<ICurve> pCrvR( vOffsCrv[0].GetLongerCurve()) ;
// if ( IsNull( pCrvR))
// return nullptr ;
// PtrOwner<ICurve> pCrvL( vOffsCrv[1].GetLongerCurve()) ;
// if ( IsNull( pCrvL))
// return nullptr ;
// PtrOwner<ICurve> pCrvRb( vOffsCrv[2].GetLongerCurve()) ;
// if ( IsNull( pCrvRb))
// return nullptr ;
// pCrvRb->Translate( - dBevelV * vtNorm) ;
// PtrOwner<ICurve> pCrvLb( vOffsCrv[3].GetLongerCurve()) ;
// if ( IsNull( pCrvLb))
// return nullptr ;
// pCrvLb->Translate( - dBevelV * vtNorm) ;
// // costruisco le parti di superficie
// PtrOwner<ISurfTriMesh> pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
// if ( IsNull( pSrfTop))
// return nullptr ;
// PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
// if ( IsNull( pSrfBot))
// return nullptr ;
// pSrfBot->Translate( -dDimV * vtNorm) ;
// pSrfBot->Invert() ;
// PtrOwner<ISurfTriMesh> pSrfTopR( GetSurfTriMeshRuled( pCrvRb, pCrvR, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
// if ( IsNull( pSrfTopR))
// return nullptr ;
// PtrOwner<ISurfTriMesh> pSrfBotR( pSrfTopR->Clone()) ;
// if ( IsNull( pSrfBotR))
// return nullptr ;
// pSrfBotR->Mirror( ptCen, vtNorm) ;
// PtrOwner<ISurfTriMesh> pSrfTopL( GetSurfTriMeshRuled( pCrvL, pCrvLb, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
// if ( IsNull( pSrfTopL))
// return nullptr ;
// PtrOwner<ISurfTriMesh> pSrfBotL( pSrfTopL->Clone()) ;
// if ( IsNull( pSrfBotL))
// return nullptr ;
// pSrfBotL->Mirror( ptCen, vtNorm) ;
// PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvRb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ;
// if ( IsNull( pSrfRgt))
// return nullptr ;
// pSrfRgt->Invert() ;
// PtrOwner<ISurfTriMesh> pSrfLft( GetSurfTriMeshByExtrusion( pCrvLb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ;
// if ( IsNull( pSrfLft))
// return nullptr ;
// // unisco le parti
// int nBuckets = max( 4 * ( pSrfRgt->GetVertexSize() + pSrfLft->GetVertexSize()), 1000) ;
// StmFromTriangleSoup stmSoup ;
// if ( ! stmSoup.Start( nBuckets))
// return nullptr ;
// stmSoup.AddSurfTriMesh( *pSrfTop) ;
// stmSoup.AddSurfTriMesh( *pSrfTopR) ;
// stmSoup.AddSurfTriMesh( *pSrfTopL) ;
// stmSoup.AddSurfTriMesh( *pSrfRgt) ;
// stmSoup.AddSurfTriMesh( *pSrfLft) ;
// stmSoup.AddSurfTriMesh( *pSrfBotR) ;
// stmSoup.AddSurfTriMesh( *pSrfBotL) ;
// stmSoup.AddSurfTriMesh( *pSrfBot) ;
// PtrOwner<ISurfTriMesh> pSTM ;
// // se guida aperta e tappi piatti
// if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
// // completo unione e recupero la superficie risultante
// if ( ! stmSoup.End())
// return nullptr ;
// pSTM.Set( stmSoup.GetSurf()) ;
// // preparo seconda zuppa di triangoli per inserire i tappi
// StmFromTriangleSoup stmCapSoup ;
// if ( ! stmCapSoup.Start( nBuckets))
// return nullptr ;
// // verifico che le due estremità siano chiuse e piatte
// POLYLINEVECTOR vPL ;
// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
// return nullptr ;
// Plane3d plEnds ; double dArea ;
// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
// return nullptr ;
// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
// return nullptr ;
// // calcolo il cap sull'inizio
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
// return nullptr ;
// pSci->Invert() ;
// // calcolo il cap sulla fine
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
// return nullptr ;
// pSce->Invert() ;
// // cucio i tappi all'estrusione
// if ( ! pSTM->DoSewing( *pSci) || ! pSTM->DoSewing( *pSce))
// return nullptr ;
// }
// // se altrimenti guida aperta e tappi arrotondati
// else if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
// // step di rotazione per rispettare il tipo o la tolleranza
// double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ;
// // aggiungo il cap sull'inizio
// Point3d ptStart ;
// pGuide->GetStartPoint( ptStart) ;
// Vector3d vtStart ;
// pGuide->GetStartDir( vtStart) ;
// vtStart.Rotate( vtNorm, 0, 1) ;
// PolyLine PLStart ;
// PLStart.AddUPoint( 0, ptStart) ;
// PLStart.AddUPoint( 1, ptStart + ( dDimH / 2 - dBevelH) * vtStart) ;
// PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dBevelV * vtNorm) ;
// PLStart.AddUPoint( 3, ptStart + dDimH / 2 * vtStart - ( dDimV - dBevelV) * vtNorm) ;
// PLStart.AddUPoint( 4, ptStart + ( dDimH / 2 - dBevelH) * vtStart - dDimV * vtNorm) ;
// PLStart.AddUPoint( 5, ptStart - dDimV * vtNorm) ;
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
// return nullptr ;
// pSci->Invert() ;
// stmSoup.AddSurfTriMesh( *pSci) ;
// // aggiungo il cap sulla fine
// Point3d ptEnd ;
// pGuide->GetEndPoint( ptEnd) ;
// Vector3d vtEnd ;
// pGuide->GetEndDir( vtEnd) ;
// vtEnd.Rotate( vtNorm, 0, -1) ;
// PolyLine PLEnd ;
// PLEnd.AddUPoint( 0, ptEnd) ;
// PLEnd.AddUPoint( 1, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd) ;
// PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dBevelV * vtNorm) ;
// PLEnd.AddUPoint( 3, ptEnd + dDimH / 2 * vtEnd - ( dDimV - dBevelV) * vtNorm) ;
// PLEnd.AddUPoint( 4, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd - dDimV * vtNorm) ;
// PLEnd.AddUPoint( 5, ptEnd - dDimV * vtNorm) ;
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
// return nullptr ;
// pSce->Invert() ;
// stmSoup.AddSurfTriMesh( *pSce) ;
// // completo unione e recupero la superficie risultante
// if ( ! stmSoup.End())
// return nullptr ;
// pSTM.Set( stmSoup.GetSurf()) ;
// }
// else {
// // completo unione e recupero la superficie risultante
// if ( ! stmSoup.End())
// return nullptr ;
// pSTM.Set( stmSoup.GetSurf()) ;
// }
// // salvo tolleranza lineare usata e imposto angolo per smooth
// pSTM->SetLinearTolerance( dLinTol) ;
// pSTM->SetSmoothAngle( 20) ;
// // restituisco la superficie
// return Release( pSTM) ;
//}
//
////-------------------------------------------------------------------------------
//ISurfBezier*
//GetSurfBezierRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // verifica parametri
// if ( pGuide == nullptr || dBevelH > 0.4 * dDimH || dBevelV > 0.4 * dDimV)
// return nullptr ;
// // determino se sezione squadrata o con smusso
// bool bSharp = ( dBevelH < 100 * EPS_SMALL || dBevelV < 100 * EPS_SMALL) ;
// // eseguo
// if ( bSharp)
// return GetSurfBezierSharpRectSwept( dDimH, dDimV, pGuide, nCapType, dLinTol) ;
// else
// return GetSurfBezierBeveledRectSwept( dDimH, dDimV, dBevelH, dBevelV, pGuide, nCapType, dLinTol) ;
//}
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfBezier* ISurfBezier*
GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol) GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
{ {
//// determino se la sezione è chiusa // riferimento all'inizio della linea guida
//bool bSectClosed = pSect->IsClosed() ;
//// determino se la guida è chiusa
//bool bGuideClosed = pGuide->IsClosed() ;
// riferimento all'inizio della linea guida
Frame3d frStart ; Frame3d frStart ;
Point3d ptStart ; Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ; pGuide->GetStartPoint( ptStart) ;
@@ -654,7 +215,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
// capisco se la guida è una linea spezzata o una curva // capisco se la guida è una linea spezzata o una curva
bool bGuideIsPolyLine = false ; bool bGuideIsPolyLine = false ;
switch( pGuide->GetType()) { switch ( pGuide->GetType()) {
case CRV_COMPO : { case CRV_COMPO : {
bGuideIsPolyLine = true ; bGuideIsPolyLine = true ;
const ICurveComposite* pCC = GetCurveComposite( pGuide) ; const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
@@ -925,14 +486,10 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
ISurfBezier* ISurfBezier*
GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
{ {
//// determino se la sezione è chiusa // determino algoritmo da usare per calcolare i riferimenti lungo la curva
//bool bSectClosed = pSect->IsClosed() ;
//// determino se la guida è chiusa
//bool bGuideClosed = pGuide->IsClosed() ;
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
bool bRMF = vtAx.IsSmall() ; bool bRMF = vtAx.IsSmall() ;
// riferimento all'inizio della linea guida // riferimento all'inizio della linea guida
Point3d ptStart ; Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ; pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ; Vector3d vtStart ;
@@ -952,7 +509,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
return nullptr ; return nullptr ;
} }
// capisco se la guida è una linea spezzata o una curva // capisco se la guida è una linea spezzata o una curva
bool bGuideIsPolyLine = false ; bool bGuideIsPolyLine = false ;
switch( pGuide->GetType()) { switch( pGuide->GetType()) {
case CRV_COMPO : { case CRV_COMPO : {
@@ -960,7 +517,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
const ICurveComposite* pCC = GetCurveComposite( pGuide) ; const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) { for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
const ICurve* pCrv = pCC->GetCurve( i) ; const ICurve* pCrv = pCC->GetCurve( i) ;
if( pCrv->GetType() != CRV_LINE) { if ( pCrv->GetType() != CRV_LINE) {
if ( pCrv->GetType() == CRV_BEZIER) { if ( pCrv->GetType() == CRV_BEZIER) {
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ; const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
bGuideIsPolyLine = pCrvBez->IsALine() ; bGuideIsPolyLine = pCrvBez->IsALine() ;
@@ -988,18 +545,18 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
int nSpanV = 0 ; int nSpanV = 0 ;
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ; PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
if ( bGuideIsPolyLine) { if ( bGuideIsPolyLine) {
if( pGuide->GetType() == CRV_LINE) if ( pGuide->GetType() == CRV_LINE)
nSpanV = 1 ; nSpanV = 1 ;
else if ( pGuide->GetType() == CRV_COMPO) else if ( pGuide->GetType() == CRV_COMPO)
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ; nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
} }
else { else {
//converto in bezier la guida ( grado 3, non razionale) // converto in bezier la guida ( grado 3, non razionale)
if ( pGuide->GetType() != CRV_BEZIER) if ( pGuide->GetType() != CRV_BEZIER)
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ; pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
else { else {
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ; const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
if( ! pGuideBez->IsRational()) if ( ! pGuideBez->IsRational())
pCrvV->AddCurve( pGuide->Clone()) ; pCrvV->AddCurve( pGuide->Clone()) ;
else else
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ; pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
@@ -1009,7 +566,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
nSpanV = pCrvV->GetCurveCount() ; nSpanV = pCrvV->GetCurveCount() ;
} }
// converto in bezier la sezione ( grado 3, non razionale) // converto in bezier la sezione ( grado 3, non razionale)
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ; PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
if ( pSect->GetType() != CRV_BEZIER) if ( pSect->GetType() != CRV_BEZIER)
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ; pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
@@ -1023,46 +580,44 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
if ( IsNull( pCrvU) || ! pCrvU->IsValid()) if ( IsNull( pCrvU) || ! pCrvU->IsValid())
return nullptr ; return nullptr ;
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita // calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
FRAME3DVECTOR vFrames ; FRAME3DVECTOR vFrames ;
if ( bRMF) { if ( bRMF) {
RotationMinimizingFrame RMF ; RotationMinimizingFrame RMF ;
if( bGuideIsPolyLine) { if ( bGuideIsPolyLine) {
if ( ! RMF.Set( pGuide, frStart) || if ( ! RMF.Set( pGuide, frStart) ||
! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty()) ! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
return nullptr ; return nullptr ;
} }
else { else {
if ( ! RMF.Set( pGuide, frStart) || if ( ! RMF.Set( pGuide, frStart) ||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty()) ! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
return nullptr ; return nullptr ;
} }
} }
else { else {
RotationXplaneFrame RXF ; RotationXplaneFrame RXF ;
if( bGuideIsPolyLine) { if ( bGuideIsPolyLine) {
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) || if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty()) ! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
return nullptr ; return nullptr ;
} }
else { else {
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) || if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty()) ! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
return nullptr ; return nullptr ;
} }
} }
//// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida // per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
int nSpanU = int( pCrvU->GetCurveCount()) ; int nSpanU = int( pCrvU->GetCurveCount()) ;
int nDegU = 9 ; // debug int nDegU = 9 ; // debug
int nDegV = 3 ; int nDegV = 3 ;
if ( bGuideIsPolyLine){ if ( bGuideIsPolyLine){
nDegV = 1 ; nDegV = 1 ;
// superficie swept // superficie swept
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ; PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; pSurfBez->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
pCrvU->ToLoc( frStart) ; pCrvU->ToLoc( frStart) ;
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) { for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
PtrOwner<ICurveComposite> pNewSect( pCrvU->Clone()) ; PtrOwner<ICurveComposite> pNewSect( pCrvU->Clone()) ;
@@ -1125,191 +680,6 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
return nullptr ; return nullptr ;
} }
////-------------------------------------------------------------------------------
//ISurfBezier*
//GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx,
// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // verifica parametri
// if ( pSect == nullptr || pGuide == nullptr)
// return nullptr ;
//
// bool bIsLine = false ;
// if ( pGuide->GetType() == CRV_LINE)
// bIsLine = true ;
// else {
// const CurveComposite* pCompo = GetBasicCurveComposite( pGuide) ;
// Point3d ptStart, ptEnd ;
// if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
// bIsLine = true ;
// }
// // se la guida è piana
// Plane3d plGuide ;
// if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL))
// return GetSurfBezierSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ;
//
// // altrimenti swept 3d
// return GetSurfBezierSwept3d( pSect, pGuide, vtAx, bCapEnds, dLinTol) ;
//}
//
////-------------------------------------------------------------------------------
//ISurfBezier*
//GetSurfBezierSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, const Vector3d& vtAx,
// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // verifica dei parametri
// if ( pSfrSect == nullptr || pGuide == nullptr)
// return nullptr ;
//
// // predispongo collettore superfici componenti
// StmFromTriangleSoup StmSoup ;
// StmSoup.Start() ;
//
// // per ogni loop della superficie, creo una Swept
// for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
// for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
// // recupero il loop
// PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( nC, nL)) ;
// if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
// return nullptr ;
// // creo la Trimesh Swept
// PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, vtAx, false, dLinTol)) ;
// if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid())
// return nullptr ;
// // aggiungo la Swept ricavata al risultato finale ( come triangoli )
// StmSoup.AddSurfTriMesh( *pStmLoopSwept) ;
// }
// }
//
// // Recupero la superficie
// if ( ! StmSoup.End())
// return nullptr ;
// PtrOwner<ISurfTriMesh> pStmSwept( StmSoup.GetSurf()) ;
// if ( IsNull( pStmSwept))
// return nullptr ;
//
// // se rischiesta chiusura...
// // Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa
// if ( bCapEnds && ! pGuide->IsClosed()) {
// // recupero i loop all'inizio (dalla regione e apportunamente approssimati)
// POLYLINEVECTOR vPLi ;
// for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
// for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
// vPLi.emplace_back() ;
// if ( ! pSfrSect->ApproxLoopWithLines( nC, nL, dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLi.back()))
// return nullptr ;
// }
// }
// // creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
// PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
// if ( ! pSci->CreateByRegion( vPLi))
// return nullptr ;
// pStmSwept->DoSewing( *pSci) ;
// // recupero i loops alla fine
// POLYLINEVECTOR vPLe ;
// if ( ! pStmSwept->GetLoops( vPLe))
// return nullptr ;
// // creo la superficie alla fine e la attacco
// PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
// if ( ! pSce->CreateByRegion( vPLe))
// return nullptr ;
// // attacco la superficie finale alla swept
// pSce->Invert() ;
// pStmSwept->DoSewing( *pSce) ;
// }
// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno
// double dVol ;
// if ( pStmSwept->GetVolume( dVol) && dVol < 0)
// pStmSwept->Invert() ;
//
// return Release( pStmSwept) ;
//}
//
////-------------------------------------------------------------------------------
//ISurfBezier*
//GetSurfBezierTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // verifica parametri
// if ( pSect == nullptr || pGuide == nullptr)
// return nullptr ;
// // determino se la sezione è chiusa
// bool bSectClosed = pSect->IsClosed() ;
// // punto iniziale della sezione e vettore a inizio guida
// Point3d ptStart ;
// if ( ! pSect->GetStartPoint( ptStart))
// return nullptr ;
// Point3d ptGuide ;
// if ( ! pGuide->GetStartPoint( ptGuide))
// return nullptr ;
// Vector3d vtDelta = ptStart - ptGuide ;
// // calcolo la polilinea che approssima la guida
// PolyLine PLG ;
// if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG))
// return nullptr ;
// // determino se la guida è chiusa
// bool bGuideClosed = PLG.IsClosed() ;
// // calcolo la superficie
// PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSTM))
// return nullptr ;
// // salvo tolleranza lineare usata
// pSTM->SetLinearTolerance( dLinTol) ;
// // superficie swept
// PtrOwner<ICurve> pPrevCrv ;
// Point3d ptP ;
// bool bPoint = PLG.GetFirstPoint( ptP) ;
// while ( bPoint) {
// // nuova curva
// PtrOwner<ICurve> pCurrCrv( pSect->Clone()) ;
// if ( IsNull( pCurrCrv))
// return nullptr ;
// pCurrCrv->Translate( ptP - ptStart + vtDelta) ;
// // se esiste la curva precedente, costruisco la rigata (di tipo minima distanza)
// if ( ! IsNull( pPrevCrv)) {
// PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_ISOPAR, dLinTol)) ;
// if ( IsNull( pSr))
// return nullptr ;
// pSTM->DoSewing( *pSr) ;
// }
// // salvo la curva come prossima precedente
// pPrevCrv.Set( pCurrCrv) ;
// // prossimo punto
// bPoint = PLG.GetNextPoint( ptP) ;
// }
// // se richiesti caps e sezione chiusa e guida aperta
// if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// // calcolo la polilinea che approssima la sezione
// PolyLine PLS ;
// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLS))
// return nullptr ;
// // verifico che la sezione sia chiusa e piatta
// Plane3d plSect ; double dArea ;
// if ( PLS.IsClosedAndFlat( plSect, dArea, 100 * EPS_SMALL)) {
// // aggiungo il cap sull'inizio
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PLS))
// return nullptr ;
// pSci->Invert() ;
// Point3d ptGi ; PLG.GetFirstPoint( ptGi) ;
// pSci->Translate( ptGi - ptStart + vtDelta) ;
// pSTM->DoSewing( *pSci) ;
// // aggiungo il cap sulla fine
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PLS))
// return nullptr ;
// Point3d ptGe ; PLG.GetLastPoint( ptGe) ;
// pSce->Translate( ptGe - ptStart + vtDelta) ;
// pSTM->DoSewing( *pSce) ;
// }
// }
// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno
// double dVol ;
// if ( pSTM->GetVolume( dVol) && dVol < 0)
// pSTM->Invert() ;
// // restituisco la superficie
// return Release( pSTM) ;
//}
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfBezier* ISurfBezier*
GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol) GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
@@ -1317,16 +687,12 @@ GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
// verifica parametri // verifica parametri
if ( &ptP == nullptr || pCurve == nullptr) if ( &ptP == nullptr || pCurve == nullptr)
return nullptr ; return nullptr ;
//// calcolo la polilinea che approssima la curva
//PolyLine PL ;
//if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
// return nullptr ;
// creo e setto la superficie trimesh // creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve)) if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve))
return nullptr ; return nullptr ;
//// salvo tolleranza lineare usata
//pSbz->SetLinearTolerance( dLinTol) ;
// restituisco la superficie // restituisco la superficie
return Release( pSbz) ; return Release( pSbz) ;
} }
@@ -1362,8 +728,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType)) if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType))
return nullptr ; return nullptr ;
//// salvo tolleranza lineare usata
//pSbz->SetLinearTolerance( dLinTol) ;
// restituisco la superficie // restituisco la superficie
return Release( pSbz) ; return Release( pSbz) ;
} }
@@ -1404,4 +769,4 @@ GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
return nullptr ; return nullptr ;
// restituisco la superficie // restituisco la superficie
return Release( pSbz) ; return Release( pSbz) ;
} }
+3 -2
View File
@@ -115,7 +115,8 @@ GetSurfFlatRegionDisk( double dRadius)
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfFlatRegion* ISurfFlatRegion*
GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, double dOffsLinTol) GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, double dOffsLinTol,
bool bMergeOnlySameProps)
{ {
// metodo di calcolo impostato da USE_VORONOI // metodo di calcolo impostato da USE_VORONOI
@@ -330,7 +331,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
else { else {
// calcolo la fat curve con Voronoi // calcolo la fat curve con Voronoi
ICURVEPOVECTOR vFatCurves ; ICURVEPOVECTOR vFatCurves ;
if ( ! CalcCurveFatCurve( *pCurve, vFatCurves, dRadius, bSquareEnds, bSquareMids)) if ( ! CalcCurveFatCurve( *pCurve, vFatCurves, dRadius, bSquareEnds, bSquareMids, bMergeOnlySameProps))
return nullptr ; return nullptr ;
// costruisco la superficie a partire dalle curve // costruisco la superficie a partire dalle curve
+401 -277
View File
File diff suppressed because it is too large Load Diff
+25 -26
View File
@@ -22,7 +22,6 @@
#include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkGeoCollection.h" #include "/EgtDev/Include/EGkGeoCollection.h"
using namespace std ;
class Tree ; class Tree ;
struct PairHashIntInt { struct PairHashIntInt {
@@ -77,16 +76,15 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
public : // ISurf public : // ISurf
bool IsSimple( void) const override bool IsSimple( void) const override
{ return true ; } { return true ; }
bool IsClosed( void) const override bool IsClosed( void) const override ;
{ return false ; }
bool GetArea( double& dArea) const override ; bool GetArea( double& dArea) const override ;
bool GetVolume( double& dVolume) const override bool GetVolume( double& dVolume) const override
{ if ( &dVolume == nullptr) { if ( &dVolume == nullptr)
return false ; return false ;
if( m_pSTM == nullptr) if ( m_pSTM == nullptr)
GetAuxSurf() ; GetAuxSurf() ;
dVolume = 0 ; dVolume = 0 ;
if( m_pSTM != nullptr) if ( m_pSTM != nullptr)
m_pSTM->GetVolume( dVolume) ; m_pSTM->GetVolume( dVolume) ;
return true ; } return true ; }
bool GetCentroid( Point3d& ptCen) const override ; bool GetCentroid( Point3d& ptCen) const override ;
@@ -158,6 +156,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ; bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ; bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ; bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
PNTVECTOR GetAllControlPoints( void) const ;
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
@@ -169,7 +168,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
public : public :
SurfBezier( void) ; SurfBezier( void) ;
SurfBezier( const SurfBezier& sbSrc) SurfBezier( const SurfBezier& sbSrc) : m_pSTM( nullptr), m_pSTMRefined( nullptr), m_pTrimReg(nullptr)
{ if ( ! CopyFrom( sbSrc)) { if ( ! CopyFrom( sbSrc))
LOG_ERROR( GetEGkLogger(), "SurfBezier : copy constructor error") } LOG_ERROR( GetEGkLogger(), "SurfBezier : copy constructor error") }
SurfBezier& operator =( const SurfBezier& sbSrc) SurfBezier& operator =( const SurfBezier& sbSrc)
@@ -221,27 +220,27 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetBernstein( double dU, int nDegU, DBLVECTOR& vBernU) const ; bool GetBernstein( double dU, int nDegU, DBLVECTOR& vBernU) const ;
private : private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria per la visualizzazione mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria per la visualizzazione
mutable SurfTriMesh* m_pSTMRefined ; // superficie trimesh ausiliaria raffinata per i calcoli mutable SurfTriMesh* m_pSTMRefined ; // superficie trimesh ausiliaria raffinata per i calcoli
Status m_nStatus ; // stato Status m_nStatus ; // stato
int m_nDegU ; // grado in U int m_nDegU ; // grado in U
int m_nDegV ; // grado in V int m_nDegV ; // grado in V
int m_nSpanU ; // numero di pezze in U int m_nSpanU ; // numero di pezze in U
int m_nSpanV ; // numero di pezze in V int m_nSpanV ; // numero di pezze in V
bool m_bRat ; // flag di razionale/polinomiale bool m_bRat ; // flag di razionale/polinomiale
bool m_bTrimmed ; // flag per presenza regione di trim bool m_bTrimmed ; // flag per presenza regione di trim
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
int m_nTempProp[2] ; // vettore proprietà temporanee int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei double m_dTempParam[2] ; // vettore parametri temporanei
mutable vector<ICRVCOMPOPOVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D mutable std::vector<ICRVCOMPOPOVECTOR> m_mCCEdge ; // vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato) mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
mutable DBLVECTOR m_vBernU ; mutable DBLVECTOR m_vBernU ;
mutable PNTVECTOR m_ptTemp ; mutable PNTVECTOR m_ptTemp ;
mutable DBLVECTOR m_vBernV ; mutable DBLVECTOR m_vBernV ;
+214 -36
View File
@@ -234,9 +234,13 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
m_vPart.clear() ; m_vPart.clear() ;
m_OGrMgr.Reset() ; m_OGrMgr.Reset() ;
ResetHashGrids3d() ; ResetHashGrids3d() ;
if ( ! vtN.Normalize( EPS_ZERO))
return SVT_DEL ;
// inserisco il triangolo // inserisco il triangolo
try { m_vTria.emplace_back( nIdVert, nTFlag) ;} try { m_vTria.emplace_back( nIdVert, nTFlag) ;}
catch(...) { return SVT_NULL ;} catch(...) { return SVT_NULL ;}
// aggiorno la sua normale
m_vTria.back().vtN = vtN ;
// aggiorno massimo TFlag // aggiorno massimo TFlag
m_nMaxTFlag = max( m_nMaxTFlag, nTFlag) ; m_nMaxTFlag = max( m_nMaxTFlag, nTFlag) ;
// ne determino l'indice // ne determino l'indice
@@ -1220,16 +1224,17 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
// se rimasto qualcosa // se rimasto qualcosa
if ( pgTria.GetSideCount() > 0) { if ( pgTria.GetSideCount() > 0) {
// lo proietto sul piano e creo la regione // lo proietto sul piano e creo la regione
pgTria.Scale( frOCS, 1, 1, 0) ; if ( pgTria.Scale( frOCS, 1, 1, 0)) {
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ; PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
if ( ! IsNull( pSfrTria)) { if ( ! IsNull( pSfrTria)) {
if ( bAllTria && Tria.GetN() * vtVers < 0) if ( bAllTria && Tria.GetN() * vtVers < 0)
pSfrTria->Invert() ; pSfrTria->Invert() ;
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ; pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr)) if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ; pSfr.Set( pSfrTria) ;
else else
pSfr->Add( *pSfrTria) ; pSfr->Add( *pSfrTria) ;
}
} }
} }
} }
@@ -1687,11 +1692,13 @@ SurfTriMesh::AdjustVertices( void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfTriMesh::AdjustAdjacencies( void) SurfTriMesh::AdjustAdjacencies( bool AdjustVert)
{ {
// sistemo le relazioni tra triangoli e vertici // sistemo le relazioni tra triangoli e vertici
if ( ! AdjustVertices()) if ( AdjustVert) {
return false ; if ( ! AdjustVertices())
return false ;
}
// matrice di incidenza vertici-triangoli // matrice di incidenza vertici-triangoli
INTMATRIX mVertTria( GetVertexSize()) ; INTMATRIX mVertTria( GetVertexSize()) ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
@@ -1874,7 +1881,7 @@ SurfTriMesh::TestSealing( void)
m_vTria[i].nIdAdjac[1] == SVT_NULL || m_vTria[i].nIdAdjac[1] == SVT_NULL ||
m_vTria[i].nIdAdjac[2] == SVT_NULL) { m_vTria[i].nIdAdjac[2] == SVT_NULL) {
bClosed = false ; bClosed = false ;
break ; break ;
} }
} }
} }
@@ -1936,7 +1943,7 @@ SurfTriMesh::PackVertices( void)
++ nFirstFree ; ++ nFirstFree ;
} }
else else
vVId.push_back( nId) ; vVId.push_back( nId) ;
} }
else { else {
if ( nFirstFree == SVT_NULL) if ( nFirstFree == SVT_NULL)
@@ -3043,7 +3050,7 @@ SurfTriMesh::AddBiTriangle( const int nIdVert[4])
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfTriMesh::DoCompacting( double dTol) SurfTriMesh::DoCompacting( double dTol)
{ {
// imposto ricalcolo // imposto ricalcolo
m_nStatus = ERR ; m_nStatus = ERR ;
m_OGrMgr.Reset() ; m_OGrMgr.Reset() ;
@@ -3084,6 +3091,7 @@ SurfTriMesh::DoCompacting( double dTol)
int nVIdSize = int( vVId.size()) ; int nVIdSize = int( vVId.size()) ;
// sistemo gli indici dei vertici nei triangoli // sistemo gli indici dei vertici nei triangoli
INTVECTOR vInvalidIds ;
for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) { for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) {
// salto i triangoli cancellati // salto i triangoli cancellati
if ( m_vTria[nId].nIdVert[0] == SVT_DEL) if ( m_vTria[nId].nIdVert[0] == SVT_DEL)
@@ -3100,15 +3108,51 @@ SurfTriMesh::DoCompacting( double dTol)
// aggiorno il triangolo // aggiorno il triangolo
m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ; m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ;
m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ; m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ;
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ; m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
// se due vertici coincidono o la normale non è calcolabile, cancello il triangolo
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] || // verifico se triangolo da rimuovere per vertici coincidenti
m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] || bool bRemove = false ;
m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] || int nTAdj1 = SVT_NULL, nTAdj2 = SVT_NULL ;
! CalcTriangleNormal( nId)) if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1]) {
RemoveTriangle( nId) ; nTAdj1 = m_vTria[nId].nIdAdjac[1] ;
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
bRemove = true ;
}
else if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2]) {
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
nTAdj2 = m_vTria[nId].nIdAdjac[1] ;
bRemove = true ;
}
else if ( m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) {
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
bRemove = true ;
}
if ( bRemove) {
// sistemo le contro adiacenze
if ( nTAdj1 != SVT_NULL) {
for ( int j = 0 ; j < 3 ; ++ j)
if ( m_vTria[nTAdj1].nIdAdjac[j] == nId)
m_vTria[nTAdj1].nIdAdjac[j] = nTAdj2 ;
}
if ( nTAdj2 != SVT_NULL) {
for ( int j = 0 ; j < 3 ; ++ j)
if ( m_vTria[nTAdj2].nIdAdjac[j] == nId)
m_vTria[nTAdj2].nIdAdjac[j] = nTAdj1 ;
}
// rimuovo il triangolo
RemoveTriangle( nId) ;
}
// verifico se il triangolo va rimosso per normale non calcolabile
else if ( ! CalcTriangleNormal( nId))
vInvalidIds.emplace_back( nId) ;
} }
// elimino triangoli invalidi ( con gestione speciale per evitare T-junctions)
if ( ! vInvalidIds.empty())
RemoveInvalidTriangles( vInvalidIds) ;
// compatto il vettore dei vertici // compatto il vettore dei vertici
if ( ! PackVertices()) if ( ! PackVertices())
return false ; return false ;
@@ -3345,22 +3389,23 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ; bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ; bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
// aggiorno le facce // se c'è mirror, devo invertire le facce
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { if ( bMirror) {
if ( m_vTria[i].nIdVert[0] != SVT_DEL) { for ( int i = 0 ; i < GetTriangleSize() ; ++ i)
// se c'è mirror, devo invertire la faccia if ( m_vTria[i].nIdVert[0] != SVT_DEL)
if ( bMirror) InvertTriangle( i) ;
InvertTriangle( i) ;
// aggiorno la normale
if ( ! CalcTriangleNormal( i)) {
// elimino il triangolo
RemoveTriangle( i) ;
}
}
} }
// rimuovo i triangoli resi invalidi dalla scalatura
bool bOk = DoCompacting() ;
return DoCompacting() ; // rimuovo i triangoli doppi
bool bModified = false ;
bOk = bOk && RemoveDoubleTriangles( bModified) ;
if ( bModified)
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
return bOk ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -3984,6 +4029,56 @@ SurfTriMesh::CloneShell( int nShell) const
return Release( pSurfTM) ; return Release( pSurfTM) ;
} }
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartLocalBBox( int nP, BBox3d& b3Loc) const
{
// verifico esistenza della parte
if ( nP < 0 || nP >= GetPartCount())
return false ;
// assegno il box in locale
b3Loc.Reset() ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// recupero il vettore delle Shell della parte corrente
const auto& vShell = m_vPart[nP].vShell ;
// scorro i triangoli validi contenuti nella Shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
// ciclo sui tre vertici
for ( int j = 0 ; j < 3 ; ++ j)
b3Loc.Add( m_vVert[m_vTria[i].nIdVert[j]].ptP) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const
{
// verifico esistenza della parte
if ( nP < 0 || nP >= GetPartCount())
return false ;
// assegno il box in locale
b3Ref.Reset() ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// recupero il vettore delle Shell della parte corrente
const auto& vShell = m_vPart[nP].vShell ;
// scorro i triangoli validi contenuti nella Shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
// ciclo sui tre vertici
for ( int j = 0 ; j < 3 ; ++ j)
b3Ref.Add( GetToGlob( m_vVert[m_vTria[i].nIdVert[j]].ptP, frRef)) ;
}
}
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int int
SurfTriMesh::GetPartCount( void) const SurfTriMesh::GetPartCount( void) const
@@ -4322,3 +4417,86 @@ SurfTriMesh::SetTempInt( int nId, int nTempInt) const
m_vTria[nId].nTemp = nTempInt ; m_vTria[nId].nTemp = nTempInt ;
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
SurfTriMesh::AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol)
{
// scorro i triangoli
for ( const Triangle3dEx& Tria : vTria) {
// ciclo sui tre vertici
int nIdV[3]{} ;
for ( int nV = 0 ; nV < 3 ; ++ nV) {
// verifico se vertice già presente
int nId ;
if ( ! VertGrid.Find( Tria.GetP( nV), dVertexTol, nId)) {
// se non presente, lo aggiugo
nIdV[nV] = AddVertex( Tria.GetP( nV)) ;
if ( nIdV[nV] == SVT_NULL)
return false ;
VertGrid.InsertPoint( Tria.GetP( nV), nIdV[nV]) ;
}
else
nIdV[nV] = nId ;
}
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) {
int nT = AddTriangle( nIdV, Tria.GetGrade()) ;
if ( nT != SVT_NULL && nT != SVT_DEL) {
// associo relazione vertice-triangolo
for ( int i = 0 ; i < 3 ; ++ i)
m_vVert[nIdV[i]].nIdTria = nT ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::AdjustTopologyFromZMap( void)
{
// cancello tutti i vertici che puntano a triangoli cancellati
bool bPack = false ;
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
if ( m_vVert[i].nIdTria == SVT_NULL) {
m_vVert[i].nIdTria = SVT_DEL ;
bPack = true ;
}
}
if ( bPack)
PackVertices() ;
m_nStatus = SurfTriMesh::OK ;
// calcolo le adiacenze
if ( ! AdjustAdjacencies())
return false ;
// verifico l'orientamento ( TODO -- Da migliorare...)
// Ora per funzionare è necessario che il ciclo sui triangoli parta da un triangolo orientato
// correttamente e che i triangoli invertiti siano "circondati" da triangoli tutti orientati correttamente
if ( ! AdjustOrientations())
return false ;
// calcolo le facce
if ( ! VerifyFaceting())
return false ;
// rimozione delle TJunction
bool bModified = false ;
if ( ! RemoveTJunctions( bModified, SQ_EPS_SMALL))
return false ;
if ( bModified) {
if ( ! AdjustVertices() || ! DoCompacting())
return false ;
}
else
TestSealing() ;
// semplifico le facce ( anche più piccola)
if ( ! SimplifyFacets( MAX_EDGE_LEN_STD, false, 5. * EPS_SMALL))
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::AdjustTopologyFromZMap")
return true ;
}
+19 -5
View File
@@ -18,6 +18,7 @@
#include "GeoObjRW.h" #include "GeoObjRW.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "/EgtDev/Include/EGkHashGrids3d.h" #include "/EgtDev/Include/EGkHashGrids3d.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
#include <deque> #include <deque>
#include <set> #include <set>
@@ -327,7 +328,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool Intersect( const ISurfTriMesh& Other) override ; bool Intersect( const ISurfTriMesh& Other) override ;
bool Subtract( const ISurfTriMesh& Other) override ; bool Subtract( const ISurfTriMesh& Other) override ;
bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf, bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ; INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
bool CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bool bSaveOnEq) override ; bool CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bool bSaveOnEq) override ;
bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ; bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ;
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ; bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
@@ -336,6 +337,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetShellArea( int nShell, double& dArea) const override ; bool GetShellArea( int nShell, double& dArea) const override ;
bool RemoveShell( int nShell) override ; bool RemoveShell( int nShell) override ;
SurfTriMesh* CloneShell( int nShell) const override ; SurfTriMesh* CloneShell( int nShell) const override ;
bool GetPartLocalBBox( int nP, BBox3d& b3Loc) const override ;
bool GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const override ;
int GetPartCount( void) const override ; int GetPartCount( void) const override ;
bool RemovePart( int nPart) override ; bool RemovePart( int nPart) override ;
bool GetPartArea( int nPart, double& dArea) const override ; bool GetPartArea( int nPart, double& dArea) const override ;
@@ -373,6 +376,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetTempInt( int nId, int& nTempInt) const ; bool GetTempInt( int nId, int& nTempInt) const ;
bool ResetTempInts( void) const ; bool ResetTempInts( void) const ;
bool SetTempInt( int nId, int nTempInt) const ; bool SetTempInt( int nId, int nTempInt) const ;
bool AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol = 2 * EPS_SMALL) ;
bool AdjustTopologyFromZMap( void) ;
private : private :
typedef std::vector<StmVert> VERTVECTOR ; typedef std::vector<StmVert> VERTVECTOR ;
@@ -388,7 +393,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool CopyFrom( const SurfTriMesh& clSrc) ; bool CopyFrom( const SurfTriMesh& clSrc) ;
bool Validate( bool bCorrect = false) ; bool Validate( bool bCorrect = false) ;
bool AdjustVertices( void) ; bool AdjustVertices( void) ;
bool AdjustAdjacencies( void) ; bool AdjustAdjacencies( bool AdjustVert = true) ;
bool AdjustOrientations( void) ; bool AdjustOrientations( void) ;
bool AdjustTriaOrientation( TRINTDEQUE& S3iQ) ; bool AdjustTriaOrientation( TRINTDEQUE& S3iQ) ;
bool TestSealing( void) ; bool TestSealing( void) ;
@@ -433,14 +438,16 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ; bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
bool IdentifyShells( void) const ; bool IdentifyShells( void) const ;
bool RemoveDoubleTriangles( bool& bModified) ; bool RemoveDoubleTriangles( bool& bModified) ;
bool RemoveTJunctions( bool& bModified) ; bool RemoveTJunctions( bool& bModified, double dMinSqDist = SQ_EPS_TRIA_H) ;
bool FlipTriangles( int nTA, int nTB) ; bool FlipTriangles( int nTA, int nTB) ;
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ; bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true, double dTolAlign = 50 * EPS_SMALL) ;
bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ; bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ;
bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ; bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ;
bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ; bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ;
bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ; bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ;
bool AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, double dTolAlign, bool& bModif) const ;
bool RemoveInvalidTriangles( const INTVECTOR& vIds) ;
bool FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const ;
private : private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Status m_nStatus ; // stato Status m_nStatus ; // stato
@@ -483,3 +490,10 @@ inline SurfTriMesh* GetBasicSurfTriMesh( IGeoObj* pGObj)
{ if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH) { if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH)
return nullptr ; return nullptr ;
return ( static_cast<SurfTriMesh*>( pGObj)) ; } return ( static_cast<SurfTriMesh*>( pGObj)) ; }
//----------------------------------------------------------------------------
// Raccolte di puntatori a SurfTriMesh
typedef std::vector<const SurfTriMesh*> CISRFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh
typedef std::vector<SurfTriMesh*> ISRFTMPVECTOR ; // vettore di puntatori a SurfTriMesh
typedef std::list<SurfTriMesh*> ISRFTMPLIST ; // lista di puntatori a SurfTriMesh
typedef std::vector<PtrOwner<SurfTriMesh>> ISRFTMPOVECTOR ; // vettore di puntatori esclusivi a SurfTriMesh
+42 -83
View File
@@ -502,9 +502,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
} }
} }
} }
// -------------------------------------------------------------------------------------------
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. Questo viene diviso in sotto-loop // 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 // chiusi mediante quelli aperti. I loop chiusi trovati precedentemente sono interni a uno dei
// sotto-loop chiusi di cui è formato il perimetro. // sotto-loop chiusi di cui è formato il perimetro.
@@ -704,16 +702,18 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
} }
} }
} }
// Elimino loop interni non validi // Verifico se i loop interni sono validi
bool bDouble = true ; bool bAllInvalid = true ;
for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) { for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) {
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 2) { // se chain formata da tre segmenti significa che si tratta di due linee sovrapposte ( il terzo tratto è quello aggiunto
bDouble = false ; // per forzare la chiusura)
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 3) {
bAllInvalid = false ;
break ; break ;
} }
} }
if ( vInnerLoop.empty() || bDouble) { if ( vInnerLoop.empty() || bAllInvalid) {
// Eseguo triangolazione // Eseguo triangolazione
PNTVECTOR vPt ; PNTVECTOR vPt ;
INTVECTOR vTr ; INTVECTOR vTr ;
@@ -753,63 +753,20 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
vPolygons.emplace_back( CurLoop) ; vPolygons.emplace_back( CurLoop) ;
} }
// poligono // controllo la direzione della normale del triangolo con quella del poligono di area maggiore
Polygon3d pgPol ; // ( per gestire eventuali inscatolamenti)
pgPol.FromPolyLine( vPolygons[1]) ; Vector3d vtPoly = V_NULL ;
double dMaxArea = -1 ;
// controllo direzioni delle normali for ( int i = 1 ; i < int( vPolygons.size()) ; i ++) {
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ; Plane3d plPoly ;
double dAreaPoly ;
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso vPolygons[i].IsClosedAndFlat( plPoly, dAreaPoly) ;
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ; if ( dAreaPoly > dMaxArea) {
// Ciclo sui segmenti del loop esterno vtPoly = plPoly.GetVersN() ;
auto itSt = ExternLoopList.begin() ; dMaxArea = dAreaPoly ;
auto itEn = itSt ; }
++ itEn ;
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
Point3d ptSt = itSt->first ;
Point3d ptEn = itEn->first ;
Vector3d vtSeg = ptEn - ptSt ;
double dSegLen = vtSeg.Len() ;
vtSeg /= dSegLen ;
// Vettore dei punti dei loop interni che stanno sul segmento del loop esterno
PNTUVECTOR vPointWithOrder ;
// Ciclo sui loop interni
for ( int nInnPoly = 1 ; nInnPoly < int( vPolygons.size()) ; ++ nInnPoly) {
// Ciclo sui punti dei loop interni
Point3d ptInnPoint ;
bool bIsFirst = true ;
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
while ( bContinue) {
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
double dDist ;
DistCalculator.GetDist( dDist) ;
double dLongPos = ( ptInnPoint - ptSt) * vtSeg ;
if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) {
POINTU NewPointU ;
NewPointU.first = ptInnPoint ;
NewPointU.second = dLongPos ;
if ( ! bIsFirst)
vPointWithOrder.emplace_back( NewPointU) ;
}
bIsFirst = false ;
bContinue = vPolygons[nInnPoly].GetNextPoint( ptInnPoint) ;
}
}
// Riordino i punti interni sul segmento esterno in funzione della distanza dall'origine di esso
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) - 1 ; ++ nPi) {
for ( int nPj = nPi + 1 ; nPj < int( vPointWithOrder.size()) ; ++ nPj) {
if ( vPointWithOrder[nPi].second > vPointWithOrder[nPj].second) {
swap( vPointWithOrder[nPi], vPointWithOrder[nPj]) ;
}
}
}
// Aggiungo i punti al loop esterno
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
}
} }
bool bCodirectedNormals = trTria.GetN() * vtPoly > 0. ;
PNTVECTOR vPt ; PNTVECTOR vPt ;
INTVECTOR vTr ; INTVECTOR vTr ;
@@ -836,6 +793,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
} }
// Divido i loop che si autointercettano // Divido i loop che si autointercettano
// TO DO : da verificare. Questa porzione di codice non dovrebbe andare prima della triangolazione?
int nInitialLoopNum = int( vPolygons.size()) ; int nInitialLoopNum = int( vPolygons.size()) ;
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) { for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
// Lista dei punti della PolyLine Loop corrente // Lista dei punti della PolyLine Loop corrente
@@ -883,11 +841,11 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
itSt2 = LoopPointList.emplace( itEn2, vAddingPointWithOrder[nPi]) ; itSt2 = LoopPointList.emplace( itEn2, vAddingPointWithOrder[nPi]) ;
} }
} }
// Spezzo i loop autointersecantesi // Spezzo i loop autointersecantesi
POLYLINEVECTOR vAuxPolygons ; POLYLINEVECTOR vAuxPolygons ;
vAuxPolygons.emplace_back( vPolygons[nL]) ; vAuxPolygons.emplace_back( vPolygons[nL]) ;
bool bSplitted = true ; bool bSplitted = true ;
while ( bSplitted) { while ( bSplitted) {
bSplitted = false ; bSplitted = false ;
@@ -956,16 +914,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
vPolygons.erase( vPolygons.begin() + i) ; vPolygons.erase( vPolygons.begin() + i) ;
else else
++ i ; ++ i ;
} }
// eventuale inversione della prima curva ( che determina il verso della triangolazione) per averla orientata
bool bCordirectedNormals_intLoop = bCodirectedNormals ; // come il triangolo
if ( ! vPolygons.empty()) { if ( ! vPolygons.empty()) {
Polygon3d pgPol ; Polygon3d pgPol ;
pgPol.FromPolyLine( vPolygons[0]) ; pgPol.FromPolyLine( vPolygons[0]) ;
// controllo direzioni delle normali if ( trTria.GetN() * pgPol.GetVersN() < 0.)
bCordirectedNormals_intLoop = trTria.GetN() * pgPol.GetVersN() > 0. ;
if ( ! bCordirectedNormals_intLoop)
vPolygons[0].Invert() ; vPolygons[0].Invert() ;
} }
@@ -981,7 +936,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ; Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ; Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ; Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCordirectedNormals_intLoop) if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ; Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
else else
Surf.m_vTria[nNewTriaNum].nTempShell = -1 ; Surf.m_vTria[nNewTriaNum].nTempShell = -1 ;
@@ -1123,7 +1078,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
{ {
bool bModif = false ; bool bModif = false ;
SurfTriMesh& SurfB = Other ; SurfTriMesh& SurfB = Other ;
@@ -1176,7 +1131,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
INTVECTOR vNearTria ; INTVECTOR vNearTria ;
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
// I scorro tutti i triangoli di B che intersecano il box di A // Scorro tutti i triangoli di B che intersecano il box di A
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) { for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
// Se il triangolo B non è valido, continuo // Se il triangolo B non è valido, continuo
@@ -1365,7 +1320,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Triangoli sovrapposti // Triangoli sovrapposti
if ( bContinue) { if ( bContinue) {
int nTriaNum2A = GetTriangleSize() ; int nTriaNum2A = GetTriangleSize() ;
// Resetto e ricalcolo la HashGrid della superficie B // Resetto e ricalcolo la HashGrid della superficie B
SurfB.ResetHashGrids3d() ; SurfB.ResetHashGrids3d() ;
for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) { for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) {
// Se il triangolo A non è valido, continuo // Se il triangolo A non è valido, continuo
@@ -1375,15 +1330,19 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Box del triangolo A // Box del triangolo A
BBox3d b3dTriaA ; BBox3d b3dTriaA ;
trTriaA.GetLocalBBox( b3dTriaA) ; trTriaA.GetLocalBBox( b3dTriaA) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A // Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; INTVECTOR vNearTria ;
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) { for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
// Se il triangolo B non è valido, continuo // Se il triangolo B non è valido, continuo
Triangle3d trTriaB ; Triangle3d trTriaB ;
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true)) if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
continue ; continue ;
// Se i triangoli sono sovrapposti // Se sono già stati classificati entrambi come sovrapposti continuo
if ( abs( m_vTria[nTA].nTempShell) == 2 && abs( SurfB.m_vTria[vNearTria[nTB]].nTempShell) == 2)
continue ;
// Se i triangoli sono sovrapposti
TRIA3DVECTOR vTriaAB ; TRIA3DVECTOR vTriaAB ;
Point3d ptTempA, ptTempB ; Point3d ptTempA, ptTempB ;
int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ; int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ;
@@ -1475,7 +1434,7 @@ SurfTriMesh::Add( const ISurfTriMesh& Other)
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione ) // tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
SurfTriMesh SurfA_cl ; SurfTriMesh SurfA_cl ;
SurfA_cl.CopyFrom( this) ; SurfA_cl.CopyFrom( this) ;
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo // ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
IntersectTriMeshTriangle( SurfB) ; IntersectTriMeshTriangle( SurfB) ;
@@ -1625,12 +1584,12 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
AddTriangle( nNewVert, m_nMaxTFlag) ; AddTriangle( nNewVert, m_nMaxTFlag) ;
} }
} }
// sistemazioni varie // sistemazioni varie
bool bOk = ( AdjustVertices() && DoCompacting()) ; bool bOk = ( AdjustVertices() && DoCompacting()) ;
bool bModified = false ; bool bModified = false ;
bOk = bOk && RemoveDoubleTriangles( bModified) ; bOk = bOk && RemoveDoubleTriangles( bModified) ;
if ( bModified) if ( bModified)
bOk = bOk && ( AdjustVertices() && DoCompacting()) ; bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
bOk = bOk && RemoveTJunctions( bModified) ; bOk = bOk && RemoveTJunctions( bModified) ;
if ( bModified) if ( bModified)
+116
View File
@@ -0,0 +1,116 @@
//----------------------------------------------------------------------------
// EgalTech 2025
//----------------------------------------------------------------------------
// File : SurfTriMeshOffset.cpp Data : 07.07.25 Versione : 2.7g1
// Contenuto : Implementazione funzione per Offset di Superfici TriMesh.
//
//
//
// Modifiche : 10.06.25 RE Creazione modulo.
// 10.06.25 RE Offset di superfici chiuse.
// 04.07.25 RE Thickening Offset di superfici generiche.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
using namespace std ;
//----------------------------------------------------------------------------
static ISurfTriMesh*
SumStm( const CISURFTMPVECTOR& vStm)
{
// se vettore vuoto, non faccio nulla
if ( vStm.empty())
return nullptr ;
// definisco la superficie somma tra tutte ( la prima deve essere valida)
PtrOwner<ISurfTriMesh> pStmAdd( CreateSurfTriMesh()) ;
if ( IsNull( pStmAdd))
return nullptr ;
// scorro le superfici
for ( const ISurfTriMesh* pStm : vStm) {
if ( pStm == nullptr || ! pStm->IsValid() || pStm->GetTriangleCount() == 0)
continue ;
if ( ! pStmAdd->IsValid() || pStmAdd->GetTriangleCount() == 0) {
if ( ! pStmAdd->CopyFrom( pStm))
return nullptr ;
}
else
pStmAdd->Add( *pStm) ;
}
// restituisco la superficie ottenuta
return ( Release( pStmAdd)) ;
}
//----------------------------------------------------------------------------
// Funzione che crea l'Offset di una superficie TriMesh
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
{
return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dPrec, nType)) ;
}
//----------------------------------------------------------------------------
// Funzione che crea il Fat Offset di una superficie TriMesh
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
{
return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dPrec, nType)) ;
}
//----------------------------------------------------------------------------
// Funzione che crea l'Offset di un insieme di superfici
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
{
// se vettore delle superfici vuoto, non faccio nulla
if ( vStm.empty())
return nullptr ;
// controllo sul valore di tolleranza lineare
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
if ( abs( dOffs) < 10 * EPS_SMALL)
return SumStm( vStm) ;
// creo lo Zmap associato alle superfici TriMesh
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
return nullptr ;
// restituisco la superficie TriMesh
return ( pVolZmap->GetSurfTriMesh()) ;
}
//----------------------------------------------------------------------------
//* Funzione che crea il Fat Offset di un insieme di superfici
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
{
// se vettore delle superfici vuoto, non faccio nulla
if ( vStm.empty())
return nullptr ;
// controllo sul valore di tolleranza lineare
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
if ( abs( dOffs) < 10 * EPS_SMALL)
return SumStm( vStm) ;
// creo lo Zmap associato alle superfici TriMesh
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
return nullptr ;
// restituisco la superficie TriMesh
return ( pVolZmap->GetSurfTriMesh()) ;
}
+204 -31
View File
@@ -17,7 +17,6 @@
#include "Triangulate.h" #include "Triangulate.h"
#include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistLineLine.h" #include "/EgtDev/Include/EGkDistLineLine.h"
#include <unordered_map>
using namespace std ; using namespace std ;
@@ -35,6 +34,7 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
// recupero i vertici dei triangoli // recupero i vertici dei triangoli
int nIdV[3] ; int nIdV[3] ;
GetTriangle( nT, nIdV) ; GetTriangle( nT, nIdV) ;
bool bToRemove = false ;
// ciclo sui triangoli adiacenti // ciclo sui triangoli adiacenti
for ( int nE = 0 ; nE < 3 ; ++ nE) { for ( int nE = 0 ; nE < 3 ; ++ nE) {
// recupero triangolo adiacente, se non esiste passo al successivo // recupero triangolo adiacente, se non esiste passo al successivo
@@ -53,10 +53,14 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
} }
} }
if ( nCoinc == 3) { if ( nCoinc == 3) {
RemoveTriangle( nAdjT) ; // se i vertici coincidono rimuovo entrambi i triangoli
bToRemove = true ;
bModified = true ; bModified = true ;
RemoveTriangle( nAdjT) ;
} }
} }
if ( bToRemove)
RemoveTriangle( nT) ;
} }
return true ; return true ;
@@ -86,8 +90,8 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
// Recupero i vertici del triangolo A // Recupero i vertici del triangolo A
Point3d ptSegSt, ptSegEn, ptVertA ; Point3d ptSegSt, ptSegEn, ptVertA ;
if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) || if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) ||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) || ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA)) ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
return false ; return false ;
// Recupero il vertice opposto del triangolo B // Recupero il vertice opposto del triangolo B
Point3d ptVertB ; Point3d ptVertB ;
@@ -98,23 +102,43 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
if ( ! DiagDist.IsSmall()) if ( ! DiagDist.IsSmall())
return false ; return false ;
double dPos1, dPos2 ; double dPos1, dPos2 ;
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2) || if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2))
dPos1 < EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() - EPS_SMALL || return false ;
dPos2 < EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() - EPS_SMALL) if ( dPos1 < - EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() + EPS_SMALL ||
return false ; dPos2 < - EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() + EPS_SMALL)
return false ;
// Eseguo il flipping // Eseguo il flipping
m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ; m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ;
m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ; m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ;
m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ; m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ;
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ; m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ;
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ; m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ;
// sistemo anche le contro-adiacenze
int nTC = m_vTria[nTA].nIdAdjac[nEdgeA] ;
if ( nTC != SVT_NULL) {
for ( int i = 0 ; i < 3 ; i++)
if ( m_vTria[nTC].nIdAdjac[i] == nTB) {
m_vTria[nTC].nIdAdjac[i] = nTA ;
break ;
}
}
int nTD = m_vTria[nTB].nIdAdjac[nEdgeB] ;
if ( nTD != SVT_NULL) {
for ( int i = 0 ; i < 3 ; i++)
if ( m_vTria[nTD].nIdAdjac[i] == nTA) {
m_vTria[nTD].nIdAdjac[i] = nTB ;
break ;
}
}
return true ; return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfTriMesh::RemoveTJunctions( bool& bModified) SurfTriMesh::RemoveTJunctions( bool& bModified, double dMinSqDist)
{ {
bModified = false ; bModified = false ;
@@ -123,6 +147,11 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro // Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) { for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
// se adiacenze tutte valide, passo al successivo
if ( m_vTria[nT].nIdAdjac[0] != SVT_DEL && m_vTria[nT].nIdAdjac[0] != SVT_NULL &&
m_vTria[nT].nIdAdjac[1] != SVT_DEL && m_vTria[nT].nIdAdjac[1] != SVT_NULL &&
m_vTria[nT].nIdAdjac[2] != SVT_DEL && m_vTria[nT].nIdAdjac[2] != SVT_NULL)
continue ;
// Se il triangolo non è valido, passo al successivo // Se il triangolo non è valido, passo al successivo
Triangle3d trTria ; Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
@@ -150,6 +179,8 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
if ( dSegLen < EPS_SMALL) if ( dSegLen < EPS_SMALL)
continue ; continue ;
vtSeg /= dSegLen ; vtSeg /= dSegLen ;
int nV1 = m_vTria[nT].nIdVert[nSeg] ;
int nV2 = m_vTria[nT].nIdVert[Next( nSeg)] ;
// Ciclo sui triangoli vicini // Ciclo sui triangoli vicini
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) { for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
// Salto il triangolo se è quello di riferimento // Salto il triangolo se è quello di riferimento
@@ -157,13 +188,16 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
continue ; continue ;
// Cerco i vertici che stanno sul lato del triangolo // Cerco i vertici che stanno sul lato del triangolo
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) { for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
int nCurrVert = m_vTria[vNearTria[nI]].nIdVert[nVert] ;
if ( nCurrVert == nV1 || nCurrVert == nV2)
continue ;
Point3d ptVert ; Point3d ptVert ;
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert)) if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
continue ; continue ;
double dProj = ( ptVert - ptSegSt) * vtSeg ; double dProj = ( ptVert - ptSegSt) * vtSeg ;
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ; double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H) if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < dMinSqDist)
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ; vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
} }
} }
// Riordino i vertici sul segmento // Riordino i vertici sul segmento
@@ -307,16 +341,42 @@ ChooseGoodStartPoint( PNTULIST& PointList)
return false ; return false ;
} }
//---------------------------------------------------------------------------- // -------------------------------------------------------------
static bool bool
AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif) SurfTriMesh::AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, double dTolAlign, bool& bModif) const
{ {
// vettore dei loop della faccia adiacente
POLYLINEVECTOR LoopVec ;
// Ciclo sui punti del loop // Ciclo sui punti del loop
auto itLast = PointList.begin() ; auto itLast = PointList.begin() ;
for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) { for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) {
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia // bisogna fermarsi per analizzare il tratto corrente alla ricerca di punti allineati se dal punto corrente
if ( itLast->second != it->second) { // inizia un tratto adiacente ad un'altra faccia oppure se il punto corrente non verrà eliminato dal loop
// della faccia adiacente
bool bAnalyze = ( itLast->second != it->second) ;
if ( bAnalyze)
LoopVec.clear() ;
if ( ! bAnalyze && itLast->second != - 1) {
if ( LoopVec.empty())
GetFacetLoops( int( itLast->second), LoopVec) ;
for ( int i = 0 ; i < int( LoopVec.size()) && ! bAnalyze ; i ++) {
const PNTULIST& PointListAdj = LoopVec[i].GetUPointList() ;
int nSamePoints = 0 ;
for ( auto itAdj = PointListAdj.begin() ; itAdj != prev( PointListAdj.end()) ; ++ itAdj) {
// cerco il punto corrente sul loop della faccia adiacente
if ( AreSamePointApprox( it->first, itAdj->first))
++ nSamePoints ;
if ( ( nSamePoints == 1 && int( PointListAdj.size()) <= 4) || nSamePoints > 1) {
bAnalyze = true ;
break ;
}
}
}
}
if ( bAnalyze) {
// Raccolgo i punti in una polyline // Raccolgo i punti in una polyline
PolyLine PL ; PolyLine PL ;
int nPar = -1 ; int nPar = -1 ;
@@ -326,7 +386,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
} }
PL.AddUPoint( ++nPar, it->first) ; PL.AddUPoint( ++nPar, it->first) ;
// Provo ad eliminare i punti allineati // Provo ad eliminare i punti allineati
PL.RemoveAlignedPoints( 50 * EPS_SMALL) ; PL.RemoveAlignedPoints( dTolAlign) ;
if ( PL.GetPointNbr() < nPar + 1) { if ( PL.GetPointNbr() < nPar + 1) {
// rimuovo dalla lista dei punti gli eliminati (salto gli estremi) // rimuovo dalla lista dei punti gli eliminati (salto gli estremi)
int nUCurr = 1 ; int nUCurr = 1 ;
@@ -418,7 +478,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced) SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced, double dTolAlign)
{ {
// La trimesh deve essere valida // La trimesh deve essere valida
if ( ! IsValid()) if ( ! IsValid())
@@ -433,8 +493,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare // Ciclo sulle facce della mesh per trovare quelle da ritriangolare
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ; unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) { for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
// Recupero i loop della faccia (il parametro indica la faccia adiacente) // Recupero i loop della faccia ( il parametro indica la faccia adiacente)
POLYLINEVECTOR LoopVec ; POLYLINEVECTOR LoopVec ;
GetFacetLoops( nF, LoopVec) ; GetFacetLoops( nF, LoopVec) ;
@@ -445,13 +505,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
// Lista dei punti del loop // Lista dei punti del loop
PNTULIST& PointList = LoopVec[nL].GetUPointList() ; PNTULIST& PointList = LoopVec[nL].GetUPointList() ;
// Se il loop è un triangolo, non va modificato
if ( int( PointList.size()) <= 4)
continue ;
// Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento // Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento
if ( ! ChooseGoodStartPoint( PointList)) if ( ! ChooseGoodStartPoint( PointList))
continue ; continue ;
// Sistemo il loop // Sistemo il loop
bool bModif = false ; bool bModif = false ;
if ( ! AdjustLoop( PointList, dMaxEdgeLen, bModif)) if ( ! AdjustLoop( PointList, dMaxEdgeLen, dTolAlign, bModif))
return false ; return false ;
if ( bModif) if ( bModif)
bToRetriangulate = true ; bToRetriangulate = true ;
@@ -479,9 +543,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
// Eseguo la ritriangolazione della faccia // Eseguo la ritriangolazione della faccia
PNTVECTOR vPt ; PNTVECTOR vPt ;
INTVECTOR vTr ; INTVECTOR vTr ;
if ( Triangulate().Make( LoopVec, vPt, vTr)) { if ( Triangulate().Make( LoopVec, vPt, vTr) && ! vTr.empty())
FacetMap.emplace( nF, make_pair( vPt, vTr)) ; FacetMap.emplace( nF, make_pair( vPt, vTr)) ;
}
// Se non riesco a triangolare anche solo questa faccia, interrompo tutto // Se non riesco a triangolare anche solo questa faccia, interrompo tutto
else else
return false ; return false ;
@@ -502,17 +565,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
// Cancello i triangoli // Cancello i triangoli
for ( int nT : vDelTria) for ( int nT : vDelTria)
RemoveTriangle( nT) ; RemoveTriangle( nT) ;
// Applico le nuove triangolazioni delle facce // Applico le nuove triangolazioni delle facce
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) { for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
const PNTVECTOR& vPt = itF->second.first ; const PNTVECTOR& vPt = itF->second.first ;
const INTVECTOR& vTr = itF->second.second ; const INTVECTOR& vTr = itF->second.second ;
// Inserisco i nuovi triangoli // Inserisco i nuovi triangoli
bool bFirstTria = true ; bool bFirstTria = true ;
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewId[3] = { AddVertex( vPt[vTr[n]]), int nNewId[3] = { AddVertex( vPt[vTr[n]]),
AddVertex( vPt[vTr[n + 1]]), AddVertex( vPt[vTr[n + 1]]),
AddVertex( vPt[vTr[n + 2]])} ; AddVertex( vPt[vTr[n + 2]])} ;
auto itCol = ColorMap.find( itF->first) ; auto itCol = ColorMap.find( itF->first) ;
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ; int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
int nNewTriaId = AddTriangle( nNewId, nTFlag) ; int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
@@ -525,7 +588,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
} }
} }
} }
// dichiaro necessità ricalcolo della grafica e di hashgrids3d // dichiaro necessità ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ; m_OGrMgr.Reset() ;
ResetHashGrids3d() ; ResetHashGrids3d() ;
@@ -722,3 +785,113 @@ SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECT
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
SurfTriMesh::FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const
{
// recupero il lato più lungo del triangolo
double dLen0 = SqDist( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
double dLen1 = SqDist( m_vVert[m_vTria[nT].nIdVert[1]].ptP, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
double dLen2 = SqDist( m_vVert[m_vTria[nT].nIdVert[2]].ptP, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
nEdge = -1 ;
if ( dLen0 > dLen1 && dLen0 > dLen2)
nEdge = 0 ;
else if ( dLen1 > dLen2)
nEdge = 1 ;
else
nEdge = 2 ;
// recupero il triangolo adiacente sul lato più lungo
nAdjTrg = m_vTria[nT].nIdAdjac[nEdge] ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemoveInvalidTriangles( const INTVECTOR& vIds)
{
// al momento gestito solo per trimesh con adiacenze definite, eventualmente da estendere.
// Analoga a RemoveFistInvalidTrg in Triangulate.cpp
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
unordered_map<int, bool> InvalidMap ;
for ( auto nId : vIds)
InvalidMap[nId] = true ;
for ( int i = 0 ; i < int( vIds.size()) ; i++) {
int nTA = vIds[i] ;
if ( ! InvalidMap[nTA])
continue ;
// recupero il triangolo adiacente sul suo lato più lungo
int nTB, nEdgeA ;
FindAdjacentOnLongerEdge( nTA, nEdgeA, nTB) ;
// se adiacente è nullo posso rimuovere tranquillamente il triangolo senza creare TJunctions
if ( nTB == SVT_NULL) {
RemoveTriangle( nTA) ;
continue ;
}
// se adiacente è valido posso fare il flip per rendere valido nTA
else if ( ! InvalidMap[nTB]) {
FlipTriangles( nTA, nTB) ;
InvalidMap[nTA] = false ;
}
// se adiacente è invalido creo una catena da risolvere non appena si trova un triangolo valido
else {
INTVECTOR vChain = {nTA} ;
INTVECTOR vChainEdges = {nEdgeA} ;
int nTCurr = nTB ;
while ( nTCurr != SVT_NULL && InvalidMap[nTCurr]) {
// calcolo il successivo
int nTOther, nEdgeCurr ;
FindAdjacentOnLongerEdge( nTCurr, nEdgeCurr, nTOther) ;
if ( nTOther == vChain.back()) {
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
FlipTriangles( nTCurr, nTOther) ;
if ( vChain.size() > 1) {
vChain.pop_back() ;
vChainEdges.pop_back() ;
// individuo il nuovo adiacente all'ultimo triangolo della catena dopo aver fatto flip
nTOther = m_vTria[vChain.back()].nIdAdjac[vChainEdges.back()] ;
}
}
else {
vChain.emplace_back( nTCurr) ;
vChainEdges.emplace_back( nEdgeCurr) ;
}
// aggiorno per iterazione successiva
nTCurr = nTOther ;
}
// se la catena termina su triangolo nullo, posso rimuovere tutti i triangoli della catena
if ( nTCurr == SVT_NULL) {
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
RemoveTriangle( vChain[k]) ;
InvalidMap[vChain[k]] = false ;
}
}
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido trovato
else {
FlipTriangles( vChain.back(), nTCurr) ;
InvalidMap[vChain.back()] = false ;
for ( int i = int( vChain.size()) - 2 ; i >= 0 ; i--) {
int nTA = vChain[i] ;
if ( ! InvalidMap[nTA])
continue ;
// eseguo il flip con il triangolo adiacente sul suo lato più lungo
int nTOther = m_vTria[nTA].nIdAdjac[vChainEdges[i]] ;
FlipTriangles( nTA, nTOther) ;
InvalidMap[nTA] = false ;
}
}
}
}
return true ;
}
+260 -441
View File
File diff suppressed because it is too large Load Diff
+49 -53
View File
@@ -23,12 +23,12 @@
#include <utility> #include <utility>
struct PairHashInt64 { struct PairHashInt64 {
size_t operator()(const pair<int64_t, int64_t>& key) const { size_t operator()(const std::pair<int64_t, int64_t>& key) const {
size_t h1 = std::hash<int64_t>{}(key.first) ; size_t h1 = std::hash<int64_t>{}(key.first) ;
size_t h2 = std::hash<int64_t>{}(key.second) ; size_t h2 = std::hash<int64_t>{}(key.second) ;
return h1 ^ (h2 << 1); // Combine hashes return h1 ^ (h2 << 1); // Combine hashes
} }
}; } ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct Inters { struct Inters {
@@ -42,13 +42,13 @@ struct Inters {
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR // se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool operator < ( Inters& b) bool operator < ( Inters& b)
{ {
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici // trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ; const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
int nPos1 = std::distance( vEdges.begin(), iter1) ; int nPos1 = std::distance( vEdges.begin(), iter1) ;
const auto iter2 = find( vEdges.begin(), vEdges.end(), b.nIn) ; const auto iter2 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
int nPos2 = std::distance( vEdges.begin(), iter2) ; int nPos2 = std::distance( vEdges.begin(), iter2) ;
// se sono loop interni li ordino in modo decrescente rispetto all'area // se sono loop interni li ordino in modo decrescente rispetto all'area
bool bEqIn = ( nIn == b.nIn) ; bool bEqIn = ( nIn == b.nIn) ;
double dAreaA = 0 , dAreaB = 0 ; double dAreaA = 0 , dAreaB = 0 ;
if ( bEqIn && nIn == -1) { if ( bEqIn && nIn == -1) {
@@ -63,7 +63,7 @@ struct Inters {
pl.Close() ; pl.Close() ;
pl.GetAreaXY( dAreaB) ; pl.GetAreaXY( dAreaB) ;
} }
// se nIn è un vertice sistemo il valore // se nIn è un vertice sistemo il valore
int nEdgeIn = nIn ; int nEdgeIn = nIn ;
if ( nIn > 3) if ( nIn > 3)
nEdgeIn = nIn - 4 ; nEdgeIn = nIn - 4 ;
@@ -75,13 +75,13 @@ struct Inters {
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ; ( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
} }
static bool FirstEncounter ( Inters& a, Inters& b) static bool FirstEncounter( Inters& a, Inters& b)
{ {
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima. // riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso // ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita // nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
// trovo i lati di ingresso e uscita // trovo i lati di ingresso e uscita
const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ; const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ;
int nPos1 = std::distance( vEdges.begin(), iter1) ; int nPos1 = std::distance( vEdges.begin(), iter1) ;
const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ; const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ;
@@ -92,13 +92,13 @@ struct Inters {
int nPos4 = std::distance( vEdges.begin(), iter4) ; int nPos4 = std::distance( vEdges.begin(), iter4) ;
int nFirstA = 0 ; int nFirstA = 0 ;
int nFirstB = 0 ; int nFirstB = 0 ;
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR // salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
// salvo il lato che viene prima confrontando ingresso e uscita // salvo il lato che viene prima confrontando ingresso e uscita
if ( nPos2 < nPos1) { if ( nPos2 < nPos1) {
nPos1 = nPos2 ; nPos1 = nPos2 ;
nFirstA = int( a.vpt.size()) - 1 ; nFirstA = int( a.vpt.size()) - 1 ;
} }
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita // se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
else if ( nPos2 == nPos1 ) { else if ( nPos2 == nPos1 ) {
if ( nPos1 == 0 ) if ( nPos1 == 0 )
nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ; nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
@@ -125,11 +125,11 @@ struct Inters {
} }
a.bSortedbyStart = nFirstA == 0 ; a.bSortedbyStart = nFirstA == 0 ;
b.bSortedbyStart = nFirstB == 0 ; b.bSortedbyStart = nFirstB == 0 ;
// se sono diversi ritorno il confronto // se sono diversi ritorno il confronto
if ( nPos1 != nPos3) if ( nPos1 != nPos3)
return nPos1 < nPos3 ; return nPos1 < nPos3 ;
// se sono uguali devo valutare il punto di intersezione // se sono uguali devo valutare il punto di intersezione
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) || return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) || ( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) ||
( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) || ( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) ||
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ; ( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
@@ -163,17 +163,15 @@ class Cell
public : public :
~Cell( void) {} ~Cell( void) {}
Cell( void) Cell( void)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), : m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( false), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( false), m_nRightEdgeIn( -1),
m_ptPbl( ORIG), m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ORIG),
{ m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) {}
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
m_ptPtr = ptTr ;
}
Cell( const Point3d& ptBL, const Point3d& ptTR) Cell( const Point3d& ptBL, const Point3d& ptTR)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), : m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( 0), m_nRightEdgeIn( -1),
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {} m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ptBL),
m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
bool IsSame( const Cell& cOtherCell) const bool IsSame( const Cell& cOtherCell) const
{ return ( m_nId == cOtherCell.m_nId) ; } { return ( m_nId == cOtherCell.m_nId) ; }
void SetBottomLeft( const Point3d& ptBL) void SetBottomLeft( const Point3d& ptBL)
@@ -192,9 +190,11 @@ class Cell
{ return Point3d( m_ptPbl.x, m_ptPtr.y) ; } { return Point3d( m_ptPbl.x, m_ptPtr.y) ; }
Point3d GetBottomRight( void) const Point3d GetBottomRight( void) const
{ return Point3d( m_ptPtr.x, m_ptPbl.y); } { return Point3d( m_ptPtr.x, m_ptPbl.y); }
Point3d GetCenter( void) const
{ return ( m_ptPbl + m_ptPtr) / 2 ; }
double GetSplitValue( void) const double GetSplitValue( void) const
{ return m_dSplit ; } { return m_dSplit ; }
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, altrimenti orizzontalmente
{ return m_bSplitVert ; } { return m_bSplitVert ; }
bool IsLeaf( void) const // flag che indica se la cella ha figli o se è una foglia bool IsLeaf( void) const // flag che indica se la cella ha figli o se è una foglia
{ return ( m_nChild1 == -2 && m_nChild2 == -2) ; } { return ( m_nChild1 == -2 && m_nChild2 == -2) ; }
@@ -245,41 +245,41 @@ class Tree
public : public :
~Tree( void) ; ~Tree( void) ;
Tree( void) ; Tree( void) ;
//Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; Tree( const Point3d ptBl, const Point3d ptTr) ; // da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno bool SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
bool SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini) bool BuildTree( double dLinTol = LIN_TOL_STD,
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh double dSideMin = 1, // è la minima lunghezza del lato di una cella
// dSideMin è lunghezza minima del lato di una cella nello spazio reale double dSideMax = INFINITO) ; // è la massima dimensione di un triangolo della trimesh
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, std::vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops) ;
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
// ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico // ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
bool GetEdges3D ( vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline bool GetEdges3D ( std::vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline
bool GetSplitLoops( ICRVCOMPOPOVECTOR& vCCLoopSplit) const // funzione che restituisce i loop splitatti ai confini delle celle bool GetSplitLoops( ICRVCOMPOPOVECTOR& vCCLoopSplit) const // funzione che restituisce i loop splitatti ai confini delle celle
{ for ( int i = 0 ; i < int( m_vCCLoop2D.size()); ++i) vCCLoopSplit.emplace_back( m_vCCLoop2D[i]->Clone()) ; return true ; }; { for ( int i = 0 ; i < int( m_vCCLoop2D.size()); ++i) vCCLoopSplit.emplace_back( m_vCCLoop2D[i]->Clone()) ; return true ; };
void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico // funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli
bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U bool IsClosedU( void) const // restituisce flag di chiusara in U
bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V { return m_bClosedU ; }
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli bool IsClosedV( void) const // restituisce flag di chiusara in V
{ return m_bClosedV ; }
BOOLVECTOR GetPoles( void) // restituisce i flag che indicano se i lati sono collassati in dei poli
{ return m_vbPole ; }
private : private :
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondità di +- 1 int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId int GetDepth( int nId, int nRef) const ; // livello del nodo nId
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right
void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
@@ -307,28 +307,24 @@ class Tree
bool GetPoint(double dU, double dV, Point3d& pt) const ; bool GetPoint(double dU, double dV, Point3d& pt) const ;
bool SavePoint( double dU, double dV, Point3d& pt) ; bool SavePoint( double dU, double dV, Point3d& pt) ;
private : private :
const SurfBezier* m_pSrfBz ; // superficie di bezier const SurfBezier* m_pSrfBz ; // superficie di bezier
DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00
bool m_bTrimmed ; // superficie trimmata bool m_bTrimmed ; // superficie trimmata
unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
vector<tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
bool m_bBilinear ; // superficie bilineare bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch bool m_bMulti ; // superficie multi-patch
bool m_bClosedU ; // superficie chiusa lungo il parametro U bool m_bClosedU ; // superficie chiusa lungo il parametro U
bool m_bClosedV ; // superficie chiusa lungo il parametro V bool m_bClosedV ; // superficie chiusa lungo il parametro V
BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge) BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge)
bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero
int m_nDegU ; // grado della superficie nel parametro U int m_nDegU ; // grado della superficie nel parametro U
int m_nDegV ; // grado della superficie nel parametro V int m_nDegV ; // grado della superficie nel parametro V
int m_nSpanU ; // numero di span lungo il parametro U int m_nSpanU ; // numero di span lungo il parametro U
int m_nSpanV ; // numero di span lungo il parametro V int m_nSpanV ; // numero di span lungo il parametro V
unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
mutable unordered_map<pair<int64_t, int64_t>,Point3d, PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int) mutable std::unordered_map<std::pair<int64_t, int64_t>,Point3d, PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
INTVECTOR m_vnLeaves ; // vettore delle foglie INTVECTOR m_vnLeaves ; // vettore delle foglie
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
bool m_bTestMode ; // bool che indica se la test mode è attiva
ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle
vector<pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim. std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
} ; } ;
+53 -34
View File
@@ -818,7 +818,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
} }
} }
// If vertex k is inside the ear triangle, then this is not an ear // If vertex k is inside the ear triangle, then this is not an ear
else if ( TestPointInTriangle( vPt[vPol[k]], vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) { else if ( TestPointInOrOnTriangle( vPt[vPol[k]], vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) {
bIsEar = false ; bIsEar = false ;
break ; break ;
} }
@@ -978,6 +978,28 @@ Triangulate::TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const
return true ; return true ;
} }
//----------------------------------------------------------------------------
// test if point p is inside or on the border of triangle (a, b, c)
bool
Triangulate::TestPointInOrOnTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
{
// If P is on a vertex is considered inside
if ( AreSamePoint( ptP, ptA))
return true ;
if ( AreSamePoint( ptP, ptB))
return true ;
if ( AreSamePoint( ptP, ptC))
return true ;
// If P is on the right of at least one edge is outside
if ( TriangleIsCCW( ptA, ptP, ptB, EPS_SMALL))
return false ;
if ( TriangleIsCCW( ptB, ptP, ptC, EPS_SMALL))
return false ;
if ( TriangleIsCCW( ptC, ptP, ptA, EPS_SMALL))
return false ;
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Triangulate::SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd) Triangulate::SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd)
@@ -1385,6 +1407,7 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
// I triangoli cap se eliminati danno origine a T-junctions, quindi devono essere gestiti opportunamente con dei flip. // I triangoli cap se eliminati danno origine a T-junctions, quindi devono essere gestiti opportunamente con dei flip.
// I triangoli needle se eliminati non sono problematici, ma i loro vertici coincidenti vanno gestiti opportunamente nel // I triangoli needle se eliminati non sono problematici, ma i loro vertici coincidenti vanno gestiti opportunamente nel
// calcolo delle adiacenze dei triangoli cap. // calcolo delle adiacenze dei triangoli cap.
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
int nTria = int( vTr.size()) / 3 ; int nTria = int( vTr.size()) / 3 ;
INTVECTOR vCapTria ; INTVECTOR vCapTria ;
@@ -1482,46 +1505,40 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
INTVECTOR vChain, vChainEdges ; INTVECTOR vChain, vChainEdges ;
vChain.emplace_back( nTA) ; vChain.emplace_back( nTA) ;
vChainEdges.emplace_back( nEA) ; vChainEdges.emplace_back( nEA) ;
int nTCurr = nTB ;
while ( nTB != -1 && ! vbIsValidTria[nTB]) { int nEOther ;
// aggiungo alla catena while ( nTCurr != -1 && ! vbIsValidTria[nTCurr]) {
vChain.emplace_back( nTB) ;
// calcolo il successivo // calcolo il successivo
nTA = nTB ; int nTOther, nECurr ;
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ; FindAdjacentOnLongerEdge( vPt, vTr, nTCurr, nECurr, nTOther, nEOther) ;
vChainEdges.emplace_back( nEA) ;
// verifico di non aver trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi) if ( nTOther == vChain.back()) {
// e quindi di non essere entrato in un loop // se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
if ( nTB == vChain[vChain.size()-2]) {
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua // flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
FlipTrg( vTr, nTA, nTB, nEA, nEB) ; FlipTrg( vTr, nTCurr, nTOther, nECurr, nEOther) ;
// aggiorno per iterazione successiva if ( vChain.size() > 1) {
if ( vChain.size() == 2) {
vChain.pop_back() ; vChain.pop_back() ;
vChainEdges.pop_back() ; vChainEdges.pop_back() ;
FindAdjacentOnLongerEdge( vPt, vTr, vChain.back(), nEA, nTB, nEB) ; // individuo il nuovo adiacente all'ultimo triangolo della catena tra i due appena flippati
vChainEdges[0] = nEA ; TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTCurr, nTOther, nTB, nEB) ;
nTOther = nTB ;
} }
else {
// elimino gli ultimi due triangoli che sono appena stati flippati e ricalcolo adiacenza del triangolo
// precedente
vChain.pop_back() ;
vChain.pop_back() ;
vChainEdges.pop_back() ;
vChainEdges.pop_back() ;
int nTTest1 = nTA ;
int nTTest2 = nTB ;
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTTest1, nTTest2, nTB, nEB) ;
}
} }
else {
vChain.emplace_back( nTCurr) ;
vChainEdges.emplace_back( nECurr) ;
}
// aggiorno per iterazione successiva
nTCurr = nTOther ;
} }
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena // se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
if ( nTB == -1) { if ( nTCurr == -1) {
bRemovedTrg = true ; bRemovedTrg = true ;
for ( int k = 0 ; k < int( vChain.size()) ; k++) { for ( int k = 0 ; k < int( vChain.size()) ; k++) {
if ( vbIsValidTria[vChain[k]])
continue ;
vTr[3*vChain[k]] = -1 ; vTr[3*vChain[k]] = -1 ;
vTr[3*vChain[k] + 1] = -1 ; vTr[3*vChain[k] + 1] = -1 ;
vTr[3*vChain[k] + 2] = -1 ; vTr[3*vChain[k] + 2] = -1 ;
@@ -1530,14 +1547,16 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
} }
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido // se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido
else { else {
FlipTrg( vTr, vChain.back(), nTB, vChainEdges.back(), nEB) ; FlipTrg( vTr, vChain.back(), nTCurr, vChainEdges.back(), nEOther) ;
vbIsValidTria[vChain.back()] = true ; vbIsValidTria[vChain.back()] = true ;
int nTrgTest1 = vChain.back() ; int nTrgTest1 = vChain.back() ;
int nTrgTest2 = nTB ; int nTrgTest2 = nTCurr ;
for ( int i = int( vChain.size()-2) ; i >= 0 ; i--) { for ( int j = int( vChain.size()-2) ; j >= 0 ; j--) {
// triangolo corrente // triangolo corrente
int nTA = vChain[i] ; int nTA = vChain[j] ;
int nEA = vChainEdges[i] ; if ( vbIsValidTria[nTA])
continue ;
int nEA = vChainEdges[j] ;
// devo trovare il nuovo adiacente dopo il flip dei successivi nella catena // devo trovare il nuovo adiacente dopo il flip dei successivi nella catena
TestAdjacentOnEdge( vTr, nTA, nEA, nTrgTest1, nTrgTest2, nTB, nEB) ; TestAdjacentOnEdge( vTr, nTA, nEA, nTrgTest1, nTrgTest2, nTB, nEB) ;
// flip per rendere valido il triangolo corrente // flip per rendere valido il triangolo corrente
@@ -1608,7 +1627,7 @@ MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
vPt.reserve( fist.c_vertex.num_vertices) ; vPt.reserve( fist.c_vertex.num_vertices) ;
for ( int i = 0 ; i < fist.c_vertex.num_vertices ; i ++) for ( int i = 0 ; i < fist.c_vertex.num_vertices ; i ++)
vPt.emplace_back( fist.c_vertex.vertices[i].x, fist.c_vertex.vertices[i].y, fist.c_vertex.vertices[i].z) ; vPt.emplace_back( fist.c_vertex.vertices[i].x, fist.c_vertex.vertices[i].y, fist.c_vertex.vertices[i].z) ;
// recupero i triangoli da fist // recupero i triangoli da fist
vTr.reserve( 3 * fist.c_vertex.num_triangles) ; vTr.reserve( 3 * fist.c_vertex.num_triangles) ;
for ( int i = 0 ; i < fist.c_vertex.num_triangles ; i ++) { for ( int i = 0 ; i < fist.c_vertex.num_triangles ; i ++) {
+1
View File
@@ -45,6 +45,7 @@ class Triangulate
bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = 0.1 * EPS_SMALL) ; bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = 0.1 * EPS_SMALL) ;
bool TestIntersection( const Point3d& ptA1, const Point3d& ptA2, const Point3d& ptB1, const Point3d& ptB2) ; bool TestIntersection( const Point3d& ptA1, const Point3d& ptA2, const Point3d& ptB1, const Point3d& ptB2) ;
bool TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ; bool TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
bool TestPointInOrOnTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
bool SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd) ; bool SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd) ;
bool GetPntVectorFromPolyline( const PolyLine& PL, bool bXmaxStart, PNTVECTOR& vPi) ; bool GetPntVectorFromPolyline( const PolyLine& PL, bool bXmaxStart, PNTVECTOR& vPi) ;
bool GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& nI) ; bool GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& nI) ;
+103 -15
View File
@@ -1520,14 +1520,14 @@ VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
// ciclo sulle griglie // ciclo sulle griglie
bool bCompleted = true ; bool bCompleted = true ;
for ( int g = 0 ; g < m_nMapNum ; ++ g) { for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
// definisco dei sistemi di riferimento ausiliari // definisco dei sistemi di riferimento ausiliari
Frame3d frMapFrame ; Frame3d frMapFrame ;
if ( g == 0) if ( nG == 0)
frMapFrame = m_MapFrame ; frMapFrame = m_MapFrame ;
else if ( g == 1) else if ( nG == 1)
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ; frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
else if ( g == 2) else if ( nG == 2)
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ; frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
// oggetto per calcolo massivo intersezioni // oggetto per calcolo massivo intersezioni
@@ -1538,33 +1538,121 @@ VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
vector<future<bool>> vRes ; vector<future<bool>> vRes ;
vRes.resize( nThreadMax) ; vRes.resize( nThreadMax) ;
// se dimensione griglia in X maggiore di dimensione Y // se dimensione griglia in X maggiore di dimensione Y
if ( m_nNx[g] > m_nNy[g]) { if ( m_nNx[nG] > m_nNy[nG]) {
int nDexNum = m_nNx[g] / nThreadMax ; int nDexNum = m_nNx[nG] / nThreadMax ;
int nRemainder = m_nNx[g] % nThreadMax ; int nRemainder = m_nNx[nG] % nThreadMax ;
int nInfI = 0 ; int nInfI = 0 ;
int nSupI = 0 ; int nSupI = 0 ;
// aggiungo le parti interessate alla mappa // aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfI = nSupI ; nInfI = nSupI ;
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g, vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, nG,
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( m_MapFrame.Orig()), nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ; ref( *pStm), ref( intPLSTM)) ;
} }
} }
// se dimensione griglia in Y maggiore di dimensione X // se dimensione griglia in Y maggiore di dimensione X
else { else {
int nDexNum = m_nNy[g] / nThreadMax ; int nDexNum = m_nNy[nG] / nThreadMax ;
int nRemainder = m_nNy[g] % nThreadMax ; int nRemainder = m_nNy[nG] % nThreadMax ;
int nInfJ = 0 ; int nInfJ = 0 ;
int nSupJ = 0 ; int nSupJ = 0 ;
// aggiungo le parti interessate alla mappa // aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfJ = nSupJ ; nInfJ = nSupJ ;
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g, vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, nG,
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()), 0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ; ref( *pStm), ref( intPLSTM)) ;
}
}
// ciclo per attendere che tutti gli async abbiano terminato.
int nTerminated = 0 ;
while ( nTerminated < nThreadMax) {
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
// async terminato
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
++ nTerminated ;
bCompleted = bCompleted && vRes[nL].get() ;
}
}
}
if ( ! bCompleted)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SubtractSurfTm( const ISurfTriMesh* pStm)
{
// controllo sulla superficie
double dVol ;
if ( pStm == nullptr || ! pStm->IsValid() || ! pStm->IsClosed() ||
! pStm->GetVolume( dVol) || dVol < 0)
return false ;
// controllo se il Box3d della superficie si interseca con il Box3d dello Zmap corrente
BBox3d BBox_stm, BBox_curr ;
if ( ! pStm->GetLocalBBox( BBox_stm) || ! GetLocalBBox( BBox_curr))
return false ;
BBox3d BBox_inters ;
if ( BBox_stm.FindIntersection( BBox_curr, BBox_inters) && BBox_inters.IsEmpty())
return true ; // se non ci sono intersezioni, la superficie non influenza lo Zmap
Vector3d vtLen = BBox_curr.GetMax() - BBox_curr.GetMin() ; // dimensione massima dello spillone
// ciclo sulle griglie
bool bCompleted = true ;
for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
// definisco dei sistemi di riferimento ausiliari
Frame3d frMapFrame ;
if ( nG == 0)
frMapFrame = m_MapFrame ;
else if ( nG == 1)
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
else if ( nG == 2)
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
// oggetto per calcolo massivo intersezioni
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
// numero massimo di thread
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
vector<future<bool>> vRes ;
vRes.resize( nThreadMax) ;
// se dimensione griglia in X maggiore di dimensione Y
if ( m_nNx[nG] > m_nNy[nG]) {
int nDexNum = m_nNx[nG] / nThreadMax ;
int nRemainder = m_nNx[nG] % nThreadMax ;
int nInfI = 0 ;
int nSupI = 0 ;
// aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfI = nSupI ;
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::SubtractMapPart, this, nG,
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ;
}
}
// se dimensione griglia in Y maggiore di dimensione X
else {
int nDexNum = m_nNy[nG] / nThreadMax ;
int nRemainder = m_nNy[nG] % nThreadMax ;
int nInfJ = 0 ;
int nSupJ = 0 ;
// aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfJ = nSupJ ;
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::SubtractMapPart, this, nG,
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ;
} }
} }
+128 -11
View File
@@ -16,15 +16,23 @@
#include "ObjGraphicsMgr.h" #include "ObjGraphicsMgr.h"
#include "GeoObjRW.h" #include "GeoObjRW.h"
#include "Tool.h" #include "Tool.h"
#include "SurfBezier.h"
#include "/EgtDev/Include/EGkVolZmap.h" #include "/EgtDev/Include/EGkVolZmap.h"
#include "/EgtDev/Include/EGkIntersLineVolZmap.h" #include "/EgtDev/Include/EGkIntersLineVolZmap.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include <unordered_map> #include <unordered_map>
#include <stack> #include <stack>
#include <mutex> #include <mutex>
#include <atomic> #include <atomic>
#include <tuple>
typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
// ------------------------- FORWARD ------------------------------------------------------------- // ------------------------- FORWARD -------------------------------------------------------------
class IntersParLinesSurfTm ; class IntersParLinesSurfTm ;
class BBox3d ;
class Frame3d ;
// ------------------------- STRUTTURE ----------------------------------------------------------- // ------------------------- STRUTTURE -----------------------------------------------------------
struct AppliedVector { struct AppliedVector {
@@ -33,6 +41,55 @@ struct AppliedVector {
int nPropIndex ; int nPropIndex ;
} ; } ;
struct MachInfo {
int n5AxisType ;
int nSub ;
int nStepCnt ;
double dSide ;
Vector3d vtDirTipStartEx ;
Vector3d vtDirTipEndEx ;
Vector3d vtDirTopStartEx ;
Vector3d vtDirTopEndEx ;
VCT3DVECTOR vvtTipStartAux ;
VCT3DVECTOR vvtTipEndAux ;
VCT3DVECTOR vvtTopStartAux ;
VCT3DVECTOR vvtTopEndAux ;
Vector3d vtDirTip ;
Vector3d vtDirTop ;
MachInfo( int n5AxisType_, int nSub_, int nStepCnt_, double dSide_, Vector3d vtDirTipStartEx_, Vector3d vtDirTipEndEx_, Vector3d vtDirTopStartEx_, Vector3d vtDirTopEndEx_,
VCT3DVECTOR vvtTipStartAux_, VCT3DVECTOR vvtTipEndAux_, VCT3DVECTOR vvtTopStartAux_, VCT3DVECTOR vvtTopEndAux_, Vector3d vtDirTip_, Vector3d vtDirTop_) :
n5AxisType( n5AxisType_), nSub( nSub_), nStepCnt( nStepCnt_), dSide( dSide_), vtDirTipStartEx( vtDirTipStartEx_), vtDirTipEndEx( vtDirTipEndEx_), vtDirTopStartEx( vtDirTopStartEx_), vtDirTopEndEx( vtDirTopEndEx_),
vvtTipStartAux( vvtTipStartAux_), vvtTipEndAux( vvtTipEndAux_), vvtTopStartAux( vvtTopStartAux_), vvtTopEndAux( vvtTopEndAux_), vtDirTip( vtDirTip_), vtDirTop( vtDirTop_) {}
};
struct ToolInfo {
double dHeight ;
double dMaxRad ;
double dMinRad ;
double dTan ;
double dMaxH ;
double dMinH ;
double dMaxRadApprox ;
double dMinRadApprox ;
BBox3d bbStartCyl ;
BBox3d bbEndCyl ;
Frame3d frToolStart ;
Frame3d frToolEnd ;
//Vector3d vtDirTip ;
//Vector3d vtDirTop ;
ToolInfo( double dHeight_, double dMaxRad_, double dMinRad_, double dTan_, double dMaxH_, double dMinH_, double dMaxRadApprox_, double dMinRadApprox_,
BBox3d bbStartCyl_, BBox3d bbEndCyl_, Frame3d frToolStart_, Frame3d frToolEnd_) :
dHeight ( dHeight_), dMaxRad( dMaxRad_), dMinRad( dMinRad_), dTan( dTan_), dMaxH( dMaxH_), dMinH( dMinH_), dMaxRadApprox( dMaxRadApprox_), dMinRadApprox( dMinRadApprox_),
bbStartCyl( bbStartCyl_), bbEndCyl( bbEndCyl_), frToolStart( frToolStart_), frToolEnd( frToolEnd_) {}
};
struct SurfBezForInters {
SurfBezier sBez ;
BBox3d bbSurf ;
double A1, A2, B1, B2, C1, C2 ;
Vector3d d ;
};
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class VolZmap : public IVolZmap, public IGeoObjRW class VolZmap : public IVolZmap, public IGeoObjRW
{ {
@@ -80,10 +137,13 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ; bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ; bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ; bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ; bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0.) override ;
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
int GetBlockCount( void) const override ; int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ; int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ; bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
ISurfTriMesh* GetSurfTriMesh( void) const override ;
bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ; bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ;
bool GetVolume( double& dVol) const override ; bool GetVolume( double& dVol) const override ;
bool IsTriDexel( void) const override bool IsTriDexel( void) const override
@@ -93,7 +153,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
{ return m_nDexVoxRatio ; } { return m_nDexVoxRatio ; }
bool ChangeResolution( int nDexVoxRatio) override ; bool ChangeResolution( int nDexVoxRatio) override ;
void SetShowEdges( bool bShow) override void SetShowEdges( bool bShow) override
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica { m_bShowEdges = bShow ; // qui necessario far ricreare la grafica
m_OGrMgr.Clear() ; } m_OGrMgr.Clear() ; }
bool GetShowEdges( void) const override bool GetShowEdges( void) const override
{ return m_bShowEdges ; } { return m_bShowEdges ; }
@@ -144,6 +204,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool RemovePart( int nPart) override ; bool RemovePart( int nPart) override ;
int GetPartMinDistFromPoint( const Point3d& ptP) const override ; int GetPartMinDistFromPoint( const Point3d& ptP) const override ;
bool AddSurfTm( const ISurfTriMesh* pStm) override ; bool AddSurfTm( const ISurfTriMesh* pStm) override ;
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
bool MakeUniform( double dToler) override ; bool MakeUniform( double dToler) override ;
public : // IGeoObjRW public : // IGeoObjRW
@@ -258,9 +319,12 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ; bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ;
bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs, bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) ; const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) ;
bool SelectGeneralMotion( int nGrid, const PNTVECTOR& ptPs, const PNTVECTOR& ptPe, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int n5AxisType) ;
bool SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL) ; bool SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL) ;
bool InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs, bool InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs,
Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3]) ; Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3]) ;
bool InitializeAuxPoints( Point3d ptTop1s[3], Point3d ptTop1e[3], Point3d ptTop2s[3], Point3d ptTop2e[3],
Point3d ptBottom1s[3], Point3d ptBottom1e[3], Point3d ptBottom2s[3], Point3d ptBottom2e[3]) ;
// SOTTRAZIONI // SOTTRAZIONI
// UTENSILI // UTENSILI
// Asse di simmetria parallelo a Z // Asse di simmetria parallelo a Z
@@ -288,11 +352,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ; bool Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
bool Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ; bool Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
bool Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; bool Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt un Perp
bool Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; bool Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt un Perp
bool GenTool_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ; bool GenTool_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
bool GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ; bool GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
// lavorazioni a 5 assi
bool GenTool_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
bool Cyl_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, double dHeightCorr = 0, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
bool CylBall_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
bool Conus_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
// COMPONENTI // COMPONENTI
// Asse di simmetria diretto come l'asse Z // Asse di simmetria diretto come l'asse Z
@@ -311,7 +380,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ; const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
bool CompPar_ZMilling( int nGrid, double dLenX, double dLenY, double dLenZ, bool CompPar_ZMilling( int nGrid, double dLenX, double dLenY, double dLenZ,
const Point3d& ptS, const Point3d& ptE, const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realt MillingPerp
// Asse di simmetria con orientazione generica // Asse di simmetria con orientazione generica
bool CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, bool CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bTapB, bool bTapT, int nToolNum) ; double dHei, double dRad, bool bTapB, bool bTapT, int nToolNum) ;
@@ -327,7 +396,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ; const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
bool CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ, bool CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ,
const Point3d& ptS, const Point3d& ptE, const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
// lavorazioni a 5 assi
bool Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe,
double dHeight, double dMaxRad, double dMinRad, int nToolNum, int n5AxisType) ;
bool CompCyl_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe,
double dHeight, double dRadius, int nToolNum,int n5AxisType) ;
bool CompConus_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtToolDirS, const VCT3DVECTOR& vtToolDirE, double dHei, double dMaxRad, double dMinRad,
bool bTapB, bool bTapT,const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum, int n5AxisType) ;
// Generica traslazione sfera // Generica traslazione sfera
bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ; bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ;
// Additivi // Additivi
@@ -341,7 +418,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
// BBox per utensili e solidi semplici con movimenti di traslazione // BBox per utensili e solidi semplici con movimenti di traslazione
inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ; int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, const Vector3d& vtV2,
double dRad, double dTipRad, double dHei, double dRad, double dTipRad, double dHei,
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ; int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA, inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
@@ -372,6 +449,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool IntersLineTruncatedPyramid( const Point3d& ptLineSt, const Vector3d& vtLineDir, bool IntersLineTruncatedPyramid( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& frTruncPyramFrame, double dSegMin, double dSegMax, double dHeight, const Frame3d& frTruncPyramFrame, double dSegMin, double dSegMax, double dHeight,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ; Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersToolLine( const Point3d& ptLineStart, const Vector3d& vtLineDir, const MachInfo& mi, const ToolInfo& ti,
const std::vector<SurfBezForInters>& vSurfBez,PNTVEC3DVECTOR& vInters, INTVECTOR& vSurfInters) const ;
bool TestIntersPlaneZmapBBox( const Plane3d& plPlane) const ; bool TestIntersPlaneZmapBBox( const Plane3d& plPlane) const ;
// Voxel: esistenza e passaggio da N a ijk per i voxel // Voxel: esistenza e passaggio da N a ijk per i voxel
bool IsValidVoxel( int nN) const ; bool IsValidVoxel( int nN) const ;
@@ -432,17 +511,55 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
// Funzioni per Offset di superfici
bool InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
bool InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap = false) ;
bool AddIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap = false) ;
public :
// ------------------------- ENUM ----------------------------------------------------------------
enum MillingPhase {
COUNT_START_VOL = 0 ,
ONLY_LATERAL_SURF = 1 ,
COUNT_END_VOL = 2 ,
COUNT_START_END = 3
} ;
enum Move5Axis{
ALONG_CONVEX = 0 ,
ALONG_CONCAVE = 1 ,
ACROSS = 2 ,
NO_BASE_INTERS = 3
} ;
enum CuttingSurface {
NONE = -1,
TOOL = 0 ,
BZ = 1 ,
LATERAL = 2
} ;
private : private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
enum Shape { GENERIC = 0, BOX = 1, EXTRUSION = 2} ; enum Shape { GENERIC = 0, BOX = 1, EXTRUSION = 2, OFFSET = 3} ;
static const int N_MAPS = 3 ; static const int N_MAPS = 3 ;
static const int N_VOXBLOCK = 32 ; static const int N_VOXBLOCK = 32 ;
private : private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Status m_nStatus ; // stato Status m_nStatus ; // stato
int m_nTempProp[2] ; // vettore proprietà temporanee int m_nTempProp[2] ; // vettore propriet temporanee
double m_dTempParam[2] ; // vettore parametri temporanei double m_dTempParam[2] ; // vettore parametri temporanei
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
@@ -476,8 +593,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable BOOLVECTOR m_BlockToUpdate ; mutable BOOLVECTOR m_BlockToUpdate ;
mutable INTVECTOR m_BlockUpdatingCounter ; mutable INTVECTOR m_BlockUpdatingCounter ;
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non è noto int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non noto
// Se >= 0 è il numero di componenti connesse // Se >= 0 il numero di componenti connesse
mutable std::vector<VoxelContainer> m_InterBlockVox ; mutable std::vector<VoxelContainer> m_InterBlockVox ;
mutable SharpTriaMatrix m_InterBlockOriginalSharpTria ; mutable SharpTriaMatrix m_InterBlockOriginalSharpTria ;
+116 -20
View File
@@ -17,6 +17,7 @@
#include "CurveLine.h" #include "CurveLine.h"
#include "VolZmap.h" #include "VolZmap.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtNumUtils.h"
#include <future> #include <future>
@@ -597,6 +598,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool bool
VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
@@ -691,7 +693,100 @@ VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
{
// controllo sui parametri
if ( nMap < 0 || nMap > 2 ||
nInfI < 0 || nInfI > m_nNx[nMap] ||
nSupI < 0 || nSupI > m_nNx[nMap] ||
nInfJ < 0 || nInfJ > m_nNy[nMap] ||
nSupJ < 0 || nSupJ > m_nNy[nMap])
return false ;
// determinazione e ridimensionamento dei dexel interni alla trimesh
for ( int i = nInfI ; i < nSupI ; ++ i) {
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
// definisco la retta da intersecare con la trimesh
double dX = ( i + 0.5) * m_dStep ;
double dY = ( j + 0.5) * m_dStep ;
Point3d ptP0( dX, dY, 0) ;
// intersezioni della retta con la TriMesh
ILSIVECTOR IntersectionResults ;
intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ;
// rimuovo le intersezioni in eccesso
for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) {
int nJ = nI + 1 ; // prima successiva
int nK = nJ + 1 ; // seconda successiva
int nT = nK + 1 ; // terza successiva
// determino i segni delle 4 intersezioni tra la linea e il trangolo della TriMesh
int nSgnI = IntersectionResults[nI].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nI].dCosDN > -EPS_SMALL ? 0 : - 1 ;
int nSgnJ = IntersectionResults[nJ].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nJ].dCosDN > -EPS_SMALL ? 0 : - 1 ;
int nSgnK = IntersectionResults[nK].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nK].dCosDN > -EPS_SMALL ? 0 : - 1 ;
int nSgnT = IntersectionResults[nT].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nT].dCosDN > -EPS_SMALL ? 0 : - 1 ;
// parametri dell'intersezione sulla linea
double dUJ = IntersectionResults[nJ].dU ;
double dUK = IntersectionResults[nK].dU ;
// controllo coerenza con segni...
if ( nSgnI != 0 && nSgnI == nSgnJ &&
nSgnK != 0 && nSgnK == nSgnT &&
nSgnI == - nSgnT &&
abs( dUJ - dUK) < EPS_SMALL) {
// ... ed elimino le intersezioni in eccesso...
IntersectionResults.erase( IntersectionResults.begin() + nK) ;
IntersectionResults.erase( IntersectionResults.begin() + nJ) ;
}
}
int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide
bool bInside = false ; // Flag entrata/uscita per tratto di retta
Point3d ptIn ; Vector3d vtInN ;
// per ogni intersezione valida trovata...
for ( int k = 0 ; k < nInt ; ++ k) {
// ricavo il tipo di intersezione
int nIntType = IntersectionResults[k].nILTT ;
// se c'è intersezione
if ( nIntType != ILTT_NO) {
// ricavo il cos tra i vettori ( normale del triangolo e tangente alla retta)
double dCos = IntersectionResults[k].dCosDN ;
// se entro nella superficie trimesh...
if ( dCos < - EPS_SMALL) {
ptIn = IntersectionResults[k].ptI ; // punto di intersezione
int nT = IntersectionResults[k].nT ; // triangolo di interesse
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
Surf.GetFacetNormal( nF, vtInN) ;
bInside = true ; // entrata
}
// ...se esco dalla superficie trimesh ( prima sono per forza entrato)
else if ( dCos > EPS_SMALL && bInside) {
Point3d ptOut = IntersectionResults[k].ptI ; // punto di intersezione
int nT = IntersectionResults[k].nT ; // triangolo di interesse
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
Vector3d vtOutN ; Surf.GetFacetNormal( nF, vtOutN) ; // vettore d'uscita
// Aggiungo un tratto al dexel
SubtractIntervals( nMap, i, j,
ptIn.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
ptOut.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
- vtInN, - vtOutN, 0, true) ;
bInside = false ; // uscita
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox)
{ {
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare // Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
double dVol ; double dVol ;
@@ -704,14 +799,15 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
// Determino il bounding box della TriMesh // Determino il bounding box della TriMesh
BBox3d SurfBBox ; BBox3d SurfBBox ;
Surf.GetLocalBBox( SurfBBox) ; Surf.GetLocalBBox( SurfBBox) ;
// Determino i punti estremi del bounding box
Point3d ptMapOrig, ptMapEnd ;
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
// Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione, // Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione,
// quindi espandiamo il bounding box per ovviare al problema. // quindi espandiamo il bounding box per ovviare al problema.
SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ; if ( dExtraBox > EPS_ZERO)
SurfBBox.Expand( dExtraBox) ;
// Determino i punti estremi del bounding box
Point3d ptMapOrig, ptMapEnd ;
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
// Sistema di riferimento intrinseco dello Zmap // Sistema di riferimento intrinseco dello Zmap
m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ; m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ;
@@ -760,15 +856,15 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
// ciclo sulle griglie // ciclo sulle griglie
bool bCompleted = true ; bool bCompleted = true ;
for ( int g = 0 ; g < m_nMapNum ; ++ g) { for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
// Definisco dei sistemi di riferimento ausiliari // Definisco dei sistemi di riferimento ausiliari
Frame3d frMapFrame ; Frame3d frMapFrame ;
if ( g == 0) if ( nG == 0)
frMapFrame = m_MapFrame ; frMapFrame = m_MapFrame ;
else if ( g == 1) else if ( nG == 1)
frMapFrame.Set( ptMapOrig, Y_AX, Z_AX, X_AX) ; frMapFrame.Set( ptMapOrig, Y_AX, Z_AX, X_AX) ;
else if ( g == 2) else if ( nG == 2)
frMapFrame.Set( ptMapOrig, Z_AX, X_AX, Y_AX) ; frMapFrame.Set( ptMapOrig, Z_AX, X_AX, Y_AX) ;
// Oggetto per calcolo massivo intersezioni // Oggetto per calcolo massivo intersezioni
@@ -778,28 +874,28 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ; int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
vector< future<bool>> vRes ; vector< future<bool>> vRes ;
vRes.resize( nThreadMax) ; vRes.resize( nThreadMax) ;
if ( m_nNx[g] > m_nNy[g]) { if ( m_nNx[nG] > m_nNy[nG]) {
int nDexNum = m_nNx[g] / nThreadMax ; int nDexNum = m_nNx[nG] / nThreadMax ;
int nRemainder = m_nNx[g] % nThreadMax ; int nRemainder = m_nNx[nG] % nThreadMax ;
int nInfI = 0 ; int nInfI = 0 ;
int nSupI = 0 ; int nSupI = 0 ;
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfI = nSupI ; nInfI = nSupI ;
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g, vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ; nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
} }
} }
else { else {
int nDexNum = m_nNy[g] / nThreadMax ; int nDexNum = m_nNy[nG] / nThreadMax ;
int nRemainder = m_nNy[g] % nThreadMax ; int nRemainder = m_nNy[nG] % nThreadMax ;
int nInfJ = 0 ; int nInfJ = 0 ;
int nSupJ = 0 ; int nSupJ = 0 ;
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfJ = nSupJ ; nInfJ = nSupJ ;
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g, vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ; 0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
} }
} }
@@ -825,7 +921,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ; m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ;
// Tipologia // Tipologia
m_nShape = ( IsBox() ? BOX : GENERIC) ; m_nShape = ( dExtraBox > EPS_ZERO && IsBox() ? BOX : GENERIC) ;
// Aggiornamento dello stato // Aggiornamento dello stato
m_nStatus = OK ; m_nStatus = OK ;
+31 -1
View File
@@ -19,6 +19,7 @@
#include "MC_Tables.h" #include "MC_Tables.h"
#include "PolygonPlane.h" #include "PolygonPlane.h"
#include "IntersLineBox.h" #include "IntersLineBox.h"
#include "SurfTriMesh.h"
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkChainCurves.h" #include "/EgtDev/Include/EGkChainCurves.h"
@@ -571,6 +572,35 @@ VolZmap::GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const
} }
} }
//----------------------------------------------------------------------------
ISurfTriMesh*
VolZmap::GetSurfTriMesh( void) const
{
// controllo che lo Zmap sia valido
if ( ! IsValid())
return nullptr ;
// inizializzo la superficie
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->Init( 3, 1))
return nullptr ;
PointGrid3d VertGrid ; VertGrid.Init( 50000) ;
// ciclo lungo i blocchi dello Zmap
for ( int nB = 0 ; nB < GetBlockCount() ; ++ nB) {
TRIA3DEXVECTOR vTria ;
GetBlockTriangles( nB, vTria) ;
if ( ! pStm->AddTriaFromZMap( vTria, VertGrid))
return nullptr ;
}
// sistemo la topologia
if ( ! pStm->AdjustTopologyFromZMap())
return nullptr ;
return ( Release( pStm)) ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int int
VolZmap::GetBlockCount( void) const VolZmap::GetBlockCount( void) const
@@ -1142,7 +1172,7 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
} }
// Controllo se il voxel ha una sola faccia che giace in un piano canonico e quindi ha gestione speciale // Controllo se il voxel ha una sola faccia che giace in un piano canonico e quindi ha gestione speciale
if ( m_nShape != BOX) { if ( m_nShape != BOX && m_nShape != OFFSET) {
// Faccia XY normale Z+ // Faccia XY normale Z+
if ( nIndex == 15) { if ( nIndex == 15) {
int nTool ; double dPos ; int nTool ; double dPos ;
+568
View File
@@ -0,0 +1,568 @@
//----------------------------------------------------------------------------
// EgalTech 2025-2025
//----------------------------------------------------------------------------
// File : OffsetSurfTm.cpp Data : 09.06.25 Versione : 2.7e3
// Contenuto : Dichiarazione della funzione per calcolare l'offset di superfici TriMesh
// mediante Zmap
//
//
//
// Modifiche : 09.06.25 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "CurveLine.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include <future>
using namespace std ;
//----------------------------------------------------------------------------
// Funzione per sottrarre intervalli lungo un Dexel per l'offset di una superficie TriMesh
//----------------------------------------------------------------------------
bool
VolZmap::SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap)
{
// TODO -- Aggiustare eventuali tolleranze
return SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
}
//----------------------------------------------------------------------------
// Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh
//----------------------------------------------------------------------------
bool
VolZmap::AddIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap)
{
// TODO -- Aggiustare eventuali tolleranze
return AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
}
//----------------------------------------------------------------------------
// Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti
//----------------------------------------------------------------------------
bool
VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nTool)
{
// determino il Box della sfera posizionata su tale vertice
BBox3d BBoxSphere( ptV - dOffs * Vector3d( 1., 1., 1.),
ptV + dOffs * Vector3d( 1., 1., 1.)) ;
// determino gli intervalli di interesse mediante intersezione con Box della sfera
int nStartI = max( 0, int( BBoxSphere.GetMin().x / m_dStep)) ;
int nEndI = min( m_nNx[nGrid] - 1, int( BBoxSphere.GetMax().x / m_dStep)) ;
int nStartJ = max( 0, int( BBoxSphere.GetMin().y / m_dStep)) ;
int nEndJ = min( m_nNy[nGrid] - 1, int( BBoxSphere.GetMax().y / m_dStep)) ;
// aggiorno gli spilloni interessati
double dSqRad = dOffs * dOffs ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
double dX = ( i + 0.5) * m_dStep ;
double dY = ( j + 0.5) * m_dStep ;
Point3d ptC( dX, dY, 0.) ;
double dStSqDXY = SqDistXY( ptC, ptV) ;
if ( dStSqDXY < dSqRad) {
double dMin = ptV.z - sqrt( dSqRad - dStSqDXY) ;
Vector3d vtNmin = Point3d( dX, dY, dMin) - ptV ;
vtNmin.Normalize() ;
double dMax = ptV.z + sqrt( dSqRad - dStSqDXY) ;
Vector3d vtNmax = Point3d( dX, dY, dMax) - ptV ;
vtNmax.Normalize() ;
if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool) ;
else
SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, nTool) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti.
//----------------------------------------------------------------------------
bool
VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid,
int nTool)
{
// determino la lunghezza dello spigolo corrente
double dH = Dist( ptP1, ptP2) ;
// asse del cilindro
Vector3d vtV = ptP2 - ptP1 ; vtV.Normalize() ;
// calcolo box del cilindro
BBox3d BBoxCylinder ;
BBoxCylinder.Add( ptP1) ;
BBoxCylinder.Add( ptP2) ;
if ( AreSameOrOppositeVectorApprox( vtV, X_AX))
BBoxCylinder.Expand( 0., abs( dOffs), abs( dOffs)) ;
else if ( AreSameOrOppositeVectorApprox( vtV, Y_AX))
BBoxCylinder.Expand( abs( dOffs), 0., abs( dOffs)) ;
else if ( AreSameOrOppositeVectorApprox( vtV, Z_AX))
BBoxCylinder.Expand( abs( dOffs), abs( dOffs), 0.) ;
else {
double dExpandX = abs( dOffs) * sqrt( 1 - vtV.x * vtV.x) ;
double dExpandY = abs( dOffs) * sqrt( 1 - vtV.y * vtV.y) ;
double dExpandZ = abs( dOffs) * sqrt( 1 - vtV.z * vtV.z) ;
BBoxCylinder.Expand( dExpandX, dExpandY, dExpandZ) ;
}
// determino gli intervalli di interesse mediante intersezione
int nStartI = max( 0, int( BBoxCylinder.GetMin().x / m_dStep)) ;
int nEndI = min( m_nNx[nGrid] - 1, int( BBoxCylinder.GetMax().x / m_dStep)) ;
int nStartJ = max( 0, int( BBoxCylinder.GetMin().y / m_dStep)) ;
int nEndJ = min( m_nNy[nGrid] - 1, int( BBoxCylinder.GetMax().y / m_dStep)) ;
// aggiorno gli spilloni interessati
Frame3d CylFrame ;
if ( ! CylFrame.Set( ptP1, vtV))
return false ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
ptInt1, vtN1, ptInt2, vtN2)) {
if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
else
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
// L'idea è quella di creare uno ZMap a partire dal Box complessivo delle superfici TriMesh :
// - le superfici chiuse possono già inserire i rispettivi spilloni
// - le superfici aperte non danno contributo
//----------------------------------------------------------------------------
bool
VolZmap::InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
{
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
// --- se una sola superficie
if ( int( vSurf.size()) == 1) {
// controllo la validità della superficie
if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0)
return true ;
// --- se superficie chiusa posso direttamente creare lo Zmap iniziale
if ( vSurf[0]->IsClosed()) {
// definisco lo Zamp a partire dall'espansione del Box della superficie
if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion))
return false ;
}
// --- se superficie aperta, lo creo inizialmente vuoto a partire dal suo Box
BBox3d BBoxSurf ;
vSurf[0]->GetLocalBBox( BBoxSurf) ;
BBoxSurf.Expand( dBoxExpansion) ;
if ( ! CreateEmpty( BBoxSurf.GetMin(), BBoxSurf.GetDimX(), BBoxSurf.GetDimY(), BBoxSurf.GetDimZ(), dTol, true))
return false ;
}
// --- se più superfici
else {
// calcolo il Box complessivo
BBox3d BBoxGlob ;
for ( const ISurfTriMesh* Surf : vSurf) {
// controllo la validità della superficie
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// calcolo il Box della superficie
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
// aggiungo il Box a quello complessivo
BBoxGlob.Add( BBoxSurf) ;
}
// definisco uno Zmap vuoto a partire dal Box
BBoxGlob.Expand( dBoxExpansion) ;
if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true))
return false ;
// aggiungo tutte le superfici chiuse
for ( const ISurfTriMesh* Surf : vSurf) {
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0 || ! Surf->IsClosed())
continue ;
if ( ! AddSurfTm( Surf))
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
// L'idea è quella di creare uno ZMap vuoto a partire dal Box complessivo delle superfici TriMesh
//----------------------------------------------------------------------------
bool
VolZmap::InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
{
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
// calcolo il Box complessivo
BBox3d BBoxGlob ;
for ( const ISurfTriMesh* Surf : vSurf) {
// controllo la validità della superficie
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// calcolo il Box della superficie
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
// aggiungo il Box a quello complessivo
BBoxGlob.Add( BBoxSurf) ;
}
// definisco uno Zmap vuoto a partire dal Box
BBoxGlob.Expand( dBoxExpansion) ;
return ( CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true)) ;
}
//----------------------------------------------------------------------------
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
// mediante una superficie aperta
//----------------------------------------------------------------------------
bool
VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
{
// da studiare...
return false ;
}
//----------------------------------------------------------------------------
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
// mediante una superficie chiusa
//----------------------------------------------------------------------------
bool
VolZmap::UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
{
// controlli sulla superficie
if ( Surf == nullptr || ! Surf->IsClosed())
return false ;
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
return true ;
// Assunzioni :
// - Idea Generale di Offset
// - Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e
// centro il vertice corrente)
// - Su ogni lato viene definito un cilindro ( con raggio di base pari al valore di Offset
// e asse definito dall'edge stesso)
// - Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono
// definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale)
//
// - Segno dell'Offset :
// - Positivo ( si sommano gli intervalli corrisipondenti alle entità create)
// - Negativo ( si sottraggono gli intervalli corrispondenti alle enetità create)
//
// - Semplificazione entità :
// La creazione di Sfere e Cilindri potrebbe essere resa più "corretta" definitendo solo
// "spicchi 3d" di sfera e "spicchi 3d" di cilindri. Dato che le operazioni di somma, sottrazioni e
// calcolo delle normali per gli spilloni sono elementari su queste figure, si rischia di appesantire
// troppo i conti introducendo variabili angolari che non sommando tutte le parti.
//
// definisco vettore di frame Locali alle 3 griglie
FRAME3DVECTOR vFrGrid( 4) ;
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
// ----------------------- Cilindri e Sfere -----------------------
// scorro gli Edge della superficie
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
// recupero lo spigolo
int nV1, nV2, nF1, nF2 ; double dAng ;
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
// controllo se il cilindro serve
// NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici
// durante questa iterazione; non significa che questa sfera non verrà mai creata...
// Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti
if ( dAng * dOffs < 0)
continue ;
// recupero le coordinate dei vertici
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
// esprimo gli estremi nel riferimento della griglia
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
// aggiungo/sottraggo gli intervalli definiti dal cilindro
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid))
return false ;
// aggiungo/sottraggo gli intervalli definiti dalla sfera
if ( ! vbVert[nV1]) {
if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid))
return false ;
}
if ( ! vbVert[nV2]) {
if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid))
return false ;
}
}
vbVert[nV1] = true ;
vbVert[nV2] = true ;
}
// ----------------------- Facce -----------------------
// scorro tutte le facce definendo una superficie di estrusione
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
// recupero lo faccia
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
// recupero la normale della faccia
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
// definisco la superficie di estrusione
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vPL[i].Translate( - abs( dOffs) * vtN) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
vpCrvs.emplace_back( Release( pCrvCompo)) ;
}
// recupero la TriMesh di estrusione
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
// aggiorno gli spilloni
if ( dOffs > 0.)
AddSurfTm( pStmExtr) ;
else
SubtractSurfTm( pStmExtr) ;
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// [Fillet Thickening] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
// mediante una superficie generica (aperta o chiusa)
//----------------------------------------------------------------------------
bool
VolZmap::UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
{
// controlli sulla superficie
if ( Surf == nullptr)
return false ;
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
return true ;
// non inizializzo lo Zmap, semplicemente lavoro con facce, spigoli e vertici
// definisco vettore di frame Locali alle 3 griglie
FRAME3DVECTOR vFrGrid( 4) ;
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
// ----------------------- Cilindri e Sfere -----------------------
// scorro gli Edge della superficie
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
// recupero lo spigolo
int nV1, nV2, nF1, nF2 ; double dAng ;
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
// recupero le coordinate dei vertici
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
// esprimo gli estremi nel riferimento della griglia
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
// aggiungo/sottraggo gli intervalli definiti dal cilindro
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, abs( dOffs), nGrid))
return false ;
// aggiungo/sottraggo gli intervalli definiti dalla sfera
if ( ! vbVert[nV1]) {
if ( ! CreateOffsSphereOnVertex( ptP1, abs( dOffs), nGrid))
return false ;
}
if ( ! vbVert[nV2]) {
if ( ! CreateOffsSphereOnVertex( ptP2, abs( dOffs), nGrid))
return false ;
}
}
vbVert[nV1] = true ;
vbVert[nV2] = true ;
}
// ----------------------- Facce -----------------------
// scorro tutte le facce definendo una superficie di estrusione
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
// recupero lo faccia
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
// recupero la normale della faccia
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
// definisco la superficie di estrusione
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vPL[i].Translate( - abs( dOffs) * vtN) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
vpCrvs.emplace_back( Release( pCrvCompo)) ;
}
// recupero la TriMesh di estrusione
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
// aggiorno gli spilloni
AddSurfTm( pStmExtr) ;
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da un
// vettore di superfici TriMesh (aperte o chiuse).
// Definizione :
// - Lo Zmap di Offset ( positivo o negativo) di una superficie chiusa è automaticamente l'Offset stesso
// - Lo Zmap di Offset ( positivo o negativo) di una superficie aperta è ????? ( da capire...)
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
{
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// verifica sul parametro di Offset ( coerente con Curve e FlatRegion)
if ( abs( dOffs) < 10 * EPS_SMALL)
return true ;
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// inizializzo lo Zmap di Offset a partire dalle superfici
if ( ! InitVolZMapOffs( vSurf, dOffs, dTol))
return false ;
// scorro le superfici
for ( const ISurfTriMesh* Surf : vSurf) {
// se superficie non valida, passo alla successiva
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// aggiorno lo ZMap
if ( Surf->IsClosed()) {
if ( nType == STMOFF_FILLET) {
if ( ! UpdateVolZMapByClosedSurfFilletOffset( Surf, dOffs, dTol))
return false ;
}
}
else {
// --- LE SUPERFICI APERTE SONO PER ORA DISABILITATE ---
}
}
m_nShape = OFFSET ;
return true ;
}
//----------------------------------------------------------------------------
// Funzione per la creazine di uno Zmap di Fat Offset a partire da un
// vettore di superfici TriMesh (aperte o chiuse).
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
{
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// verifica sul parametro di Offset ( coerente con Curve e FlatRegion)
if ( abs( dOffs) < 10 * EPS_SMALL)
return true ;
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// inizializzo lo Zmap di Offset a partire dalle superfici
if ( ! InitVolZMapThickeningOffs( vSurf, dOffs, dTol))
return false ;
// scorro le superfici
for ( const ISurfTriMesh* Surf : vSurf) {
// se superficie non valida, passo alla successiva
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// aggiorno lo Zmap
if ( nType == STMOFF_FILLET) {
if ( ! UpdateVolZMapBySurfThickeningFilletOffset( Surf, dOffs, dTol))
return false ;
}
}
m_nShape = OFFSET ;
return true ;
}
+1874 -197
View File
File diff suppressed because it is too large Load Diff
+187 -172
View File
@@ -25,7 +25,7 @@
using namespace std ; using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd) Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
: m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true) : m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true)
{ {
// tento di aggiungere la curva // tento di aggiungere la curva
@@ -35,7 +35,7 @@ Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd) Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
: m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true) : m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true)
{ {
// tento di aggiungere la superficie // tento di aggiungere la superficie
@@ -45,16 +45,16 @@ Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
Voronoi::~Voronoi( void) Voronoi::~Voronoi( void)
{ {
Clear() ; Clear() ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::Clear( void) Voronoi::Clear( void)
{ {
// pulizia oggetto vroni // pulizia oggetto vroni
if ( m_vroni != nullptr) if ( m_vroni != nullptr)
delete m_vroni ; delete m_vroni ;
m_vroni = nullptr ; m_vroni = nullptr ;
@@ -72,7 +72,7 @@ Voronoi::Clear( void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::AddCurve( const ICurve* pCrv) Voronoi::AddCurve( const ICurve* pCrv)
{ {
if ( ! m_bAllowAdd) if ( ! m_bAllowAdd)
return false ; return false ;
@@ -99,21 +99,21 @@ Voronoi::AddCurve( const ICurve* pCrv)
if ( ! vtExtr.IsSmall()) if ( ! vtExtr.IsSmall())
plPlane.Set( ptS, vtExtr) ; plPlane.Set( ptS, vtExtr) ;
else else
plPlane.Set( ptS, Z_AX) ; plPlane.Set( ptS, Z_AX) ;
} }
else { else {
if ( ! pCrv->IsFlat( plPlane, false, 10 * EPS_SMALL)) if ( ! pCrv->IsFlat( plPlane, false, 10 * EPS_SMALL))
return false ; return false ;
} }
if ( m_vpCrvs.empty()) { if ( m_vpCrvs.empty()) {
// se prima curva considerata assegno il frame al Voronoi // se prima curva considerata assegno il frame al Voronoi
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ; m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
} }
else { else {
// altrimenti verifico sia complanare ad eventuali curve già presenti // altrimenti verifico sia complanare ad eventuali curve già presenti
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane)) if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ; return false ;
} }
// creo una copia della curva e la porto in locale // creo una copia della curva e la porto in locale
@@ -128,8 +128,8 @@ Voronoi::AddCurve( const ICurve* pCrv)
m_vroni = new( nothrow) vroniObject() ; m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr) if ( m_vroni == nullptr)
return false ; return false ;
m_vroni->apiInitializeProgram() ; m_vroni->apiInitializeProgram() ;
} }
// aggiungo la curva in locale all'oggetto vroni // aggiungo la curva in locale all'oggetto vroni
if ( ! AddCurveToVroni( pCrvLoc)) if ( ! AddCurveToVroni( pCrvLoc))
@@ -144,61 +144,61 @@ Voronoi::AddCurve( const ICurve* pCrv)
BBox3d bBox ; BBox3d bBox ;
pCrvLoc->GetLocalBBox( bBox) ; pCrvLoc->GetLocalBBox( bBox) ;
m_bBox.Add( bBox) ; m_bBox.Add( bBox) ;
return true ; return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr) Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
{ {
if ( ! m_bAllowAdd) if ( ! m_bAllowAdd)
return false ; return false ;
if ( pSfr == nullptr) if ( pSfr == nullptr)
return false ; return false ;
// recupero il piano // recupero il piano
Point3d ptCen ; pSfr->GetCentroid( ptCen) ; Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
Vector3d vtN = pSfr->GetNormVersor() ; Vector3d vtN = pSfr->GetNormVersor() ;
if ( m_vpCrvs.empty()) { if ( m_vpCrvs.empty()) {
// assegno il frame al Voronoi // assegno il frame al Voronoi
m_Frame.Set( ptCen, vtN) ; m_Frame.Set( ptCen, vtN) ;
} }
else { else {
// verifico sia complanare ad eventuali curve già presenti // verifico sia complanare ad eventuali curve già presenti
Plane3d plPlane ; Plane3d plPlane ;
plPlane.Set( ptCen, pSfr->GetNormVersor()) ; plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane)) if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ; return false ;
} }
try { try {
// verifico se oggetto vroni è stato inizializzato // verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) { if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ; m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr) if ( m_vroni == nullptr)
return false ; return false ;
m_vroni->apiInitializeProgram() ; m_vroni->apiInitializeProgram() ;
} }
// aggiungo le curve di loop // aggiungo le curve di loop
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) { for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) { for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ; PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
if ( IsNull( pCrvLoc)) if ( IsNull( pCrvLoc))
return false ; return false ;
pCrvLoc->ToLoc( m_Frame) ; pCrvLoc->ToLoc( m_Frame) ;
if ( ! AddCurveToVroni( pCrvLoc)) if ( ! AddCurveToVroni( pCrvLoc))
return false ; return false ;
} }
} }
} }
catch (...) { catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage())
return false ; return false ;
} }
// aggiorno il box complessivo // aggiorno il box complessivo
BBox3d bBox ; BBox3d bBox ;
Frame3d frSrf = m_Frame ; Frame3d frSrf = m_Frame ;
@@ -211,16 +211,16 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::AddCurveToVroni( const ICurve* pCrv) Voronoi::AddCurveToVroni( const ICurve* pCrv)
{ {
int nLoopId = m_vpCrvs.size() ; int nLoopId = m_vpCrvs.size() ;
// aggiungo il punto iniziale // aggiungo il punto iniziale
Point3d ptStart ; Point3d ptStart ;
if ( ! pCrv->GetStartPoint( ptStart)) if ( ! pCrv->GetStartPoint( ptStart))
return false ; return false ;
int nCrv = m_vroni->HandlePnt( ptStart.x, ptStart.y, {nLoopId, 0}) ; int nCrv = m_vroni->HandlePnt( ptStart.x, ptStart.y, {nLoopId, 0}) ;
// aggiungo la parte rimanente della curva // aggiungo la parte rimanente della curva
switch ( pCrv->GetType()) { switch ( pCrv->GetType()) {
case CRV_LINE : case CRV_LINE :
@@ -229,7 +229,7 @@ Voronoi::AddCurveToVroni( const ICurve* pCrv)
case CRV_ARC : case CRV_ARC :
m_vpCrvs.emplace_back( pCrv->Clone()) ; m_vpCrvs.emplace_back( pCrv->Clone()) ;
return AddArcToVroni( GetCurveArc( pCrv), nCrv, nLoopId) ; return AddArcToVroni( GetCurveArc( pCrv), nCrv, nLoopId) ;
case CRV_COMPO : case CRV_COMPO :
return AddCompoToVroni( GetCurveComposite( pCrv), nCrv, nLoopId) ; return AddCompoToVroni( GetCurveComposite( pCrv), nCrv, nLoopId) ;
case CRV_BEZIER : case CRV_BEZIER :
return AddBezierToVroni( GetCurveBezier( pCrv), nCrv, nLoopId) ; return AddBezierToVroni( GetCurveBezier( pCrv), nCrv, nLoopId) ;
@@ -242,7 +242,7 @@ Voronoi::AddCurveToVroni( const ICurve* pCrv)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd) Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
{ {
if ( pLine == nullptr) if ( pLine == nullptr)
return false ; return false ;
@@ -250,7 +250,7 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
// verifico se il punto finale viene forzato oppure deve essere ricavato dalla pLine // verifico se il punto finale viene forzato oppure deve essere ricavato dalla pLine
if ( ! ptEnd.IsValid()) { if ( ! ptEnd.IsValid()) {
if ( ! pLine->GetEndPoint( ptEnd)) if ( ! pLine->GetEndPoint( ptEnd))
return false ; return false ;
} }
m_vroni->AddSeg( &nVroniCrv, ptEnd.x, ptEnd.y, {nLoopId, nCrvId}) ; m_vroni->AddSeg( &nVroniCrv, ptEnd.x, ptEnd.y, {nLoopId, nCrvId}) ;
@@ -259,7 +259,7 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd) Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
{ {
if ( pArc == nullptr) if ( pArc == nullptr)
return false ; return false ;
@@ -285,7 +285,7 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
// verifico se il punto finale viene forzato oppure deve essere ricavato dal pArc // verifico se il punto finale viene forzato oppure deve essere ricavato dal pArc
if ( ! ptEnd.IsValid()) { if ( ! ptEnd.IsValid()) {
if ( ! pArc->GetEndPoint( ptEnd)) if ( ! pArc->GetEndPoint( ptEnd))
return false ; return false ;
} }
m_vroni->AddArc( &nVroniCrv, ptEnd.x, ptEnd.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ; m_vroni->AddArc( &nVroniCrv, ptEnd.x, ptEnd.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ;
} }
@@ -295,7 +295,7 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId) Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId)
{ {
if ( pCompo == nullptr) if ( pCompo == nullptr)
return false ; return false ;
@@ -315,18 +315,18 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
bool bClosed = pCopy->IsClosed() ; bool bClosed = pCopy->IsClosed() ;
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) { for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
Point3d ptForcedEnd = P_INVALID ; Point3d ptForcedEnd = P_INVALID ;
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni) // se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
if ( i == pCopy->GetCurveCount() - 1 && bClosed) if ( i == pCopy->GetCurveCount() - 1 && bClosed)
pCompo->GetStartPoint( ptForcedEnd) ; pCompo->GetStartPoint( ptForcedEnd) ;
// aggiungo // aggiungo
const ICurve* pCrv = pCopy->GetCurve( i) ; const ICurve* pCrv = pCopy->GetCurve( i) ;
int nType = pCrv->GetType() ; int nType = pCrv->GetType() ;
if ( nType == CRV_LINE) if ( nType == CRV_LINE)
AddLineToVroni( GetCurveLine( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ; AddLineToVroni( GetCurveLine( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
else if ( nType == CRV_ARC) else if ( nType == CRV_ARC)
AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ; AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
} }
// aggiungo al vettore di curve // aggiungo al vettore di curve
@@ -341,7 +341,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
{ {
if ( pBezier == nullptr) if ( pBezier == nullptr)
return false ; return false ;
// riconduco al caso di curva composita // riconduco al caso di curva composita
PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ; PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCompo)) if ( IsNull( pCompo))
@@ -352,28 +352,28 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
Vector3d vtExtr ; pBezier->GetExtrusion( vtExtr) ; Vector3d vtExtr ; pBezier->GetExtrusion( vtExtr) ;
pCompo->SetExtrusion( vtExtr) ; pCompo->SetExtrusion( vtExtr) ;
return AddCompoToVroni( pCompo, nVroniCrv, nLoopId) ; return AddCompoToVroni( pCompo, nVroniCrv, nLoopId) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
Voronoi::GetCurve( int nId) const Voronoi::GetCurve( int nId) const
{ {
// verifico validità indice // verifico validità indice
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1) if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
return nullptr ; return nullptr ;
// ne faccio una copia // ne faccio una copia
ICurve* pCrv = m_vpCrvs[nId]->Clone() ; ICurve* pCrv = m_vpCrvs[nId]->Clone() ;
if ( pCrv == nullptr) if ( pCrv == nullptr)
return nullptr ; return nullptr ;
// la porto nel riferimento globale // la porto nel riferimento globale
pCrv->ToGlob( m_Frame) ; pCrv->ToGlob( m_Frame) ;
return pCrv ; return pCrv ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::GetVroniPlane( Plane3d& plPlane) const Voronoi::GetVroniPlane( Plane3d& plPlane) const
{ {
if ( ! IsValid()) if ( ! IsValid())
@@ -383,13 +383,13 @@ Voronoi::GetVroniPlane( Plane3d& plPlane) const
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcVoronoi( int nBound) Voronoi::CalcVoronoi( int nBound)
{ {
// se già stato calcolato con lo stesso bound non devo fare nulla // se già stato calcolato con lo stesso bound non devo fare nulla
if ( m_bVDComputed && nBound == m_nBound) if ( m_bVDComputed && nBound == m_nBound)
return true ; return true ;
// se già stato calcolato reset dei dati // se già stato calcolato reset dei dati
if ( m_bVDComputed) if ( m_bVDComputed)
m_vroni->ResetVoronoiDiagram() ; m_vroni->ResetVoronoiDiagram() ;
@@ -398,9 +398,9 @@ Voronoi::CalcVoronoi( int nBound)
m_nBound = max( nBound, VORONOI_STD_BOUND) ; m_nBound = max( nBound, VORONOI_STD_BOUND) ;
// calcolo // calcolo
m_bVDComputed = true ; m_bVDComputed = true ;
string sTmp = "" ; string sTmp = "" ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ; m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
return true ; return true ;
} }
@@ -416,7 +416,7 @@ Voronoi::GetBisectorCurve( int i)
int nType = m_vroni->GetBisectorType( i) ; int nType = m_vroni->GetBisectorType( i) ;
// linea // linea
if ( nType == BisectorType::LINE) { if ( nType == BisectorType::LINE) {
// recupero i dati del bisettore da vroni // recupero i dati del bisettore da vroni
Point3d ptS, ptE ; Point3d ptS, ptE ;
double dParS, dParE ; double dParS, dParE ;
@@ -434,7 +434,7 @@ Voronoi::GetBisectorCurve( int i)
pLine->SetTempParam( dParS, 0) ; pLine->SetTempParam( dParS, 0) ;
pLine->SetTempParam( dParE, 1) ; pLine->SetTempParam( dParE, 1) ;
pLine->ToGlob( m_Frame) ; pLine->ToGlob( m_Frame) ;
return pLine ; return pLine ;
} }
// degenerate hyperellipse ( arco) // degenerate hyperellipse ( arco)
@@ -454,20 +454,20 @@ Voronoi::GetBisectorCurve( int i)
pArc->SetTempParam( dParS, 0) ; pArc->SetTempParam( dParS, 0) ;
pArc->SetTempParam( dParS, 1) ; // dParE = dParS pArc->SetTempParam( dParS, 1) ; // dParE = dParS
pArc->ToGlob( m_Frame) ; pArc->ToGlob( m_Frame) ;
return pArc ; return pArc ;
} }
// bisettore generico // bisettore generico
else if ( nType != BisectorType::NONE) { else if ( nType != BisectorType::NONE) {
// approssimo linearmente il bisettore // approssimo linearmente il bisettore
int nPoints = m_vroni->GetApproxedBisectorPointsNbr( i) ; int nPoints = m_vroni->GetApproxedBisectorPointsNbr( i) ;
if ( nPoints < 2) if ( nPoints < 2)
return nullptr ; return nullptr ;
CurveComposite* pCompo = CreateBasicCurveComposite() ; CurveComposite* pCompo = CreateBasicCurveComposite() ;
if ( pCompo == nullptr) if ( pCompo == nullptr)
return nullptr ; return nullptr ;
// verifico se devo leggere i punti del bisettore al contrario per averlo orientato dal parametro minore al maggiore // verifico se devo leggere i punti del bisettore al contrario per averlo orientato dal parametro minore al maggiore
bool bInvert = false ; bool bInvert = false ;
double dPar1, dPar2 ; double dPar1, dPar2 ;
@@ -481,13 +481,13 @@ Voronoi::GetBisectorCurve( int i)
m_vroni->GetApproxedBisectorPoint( i, bInvert ? nPoints - 1 : 0, pt.v, dParS) ; m_vroni->GetApproxedBisectorPoint( i, bInvert ? nPoints - 1 : 0, pt.v, dParS) ;
pCompo->AddPoint( pt) ; pCompo->AddPoint( pt) ;
int nCrvCount = 0 ; int nCrvCount = 0 ;
double dParPrev = dParS ; double dParPrev = dParS ;
int j = bInvert ? nPoints - 2 : 1 ; int j = bInvert ? nPoints - 2 : 1 ;
while ( ( bInvert && j >= 0) || ( ! bInvert && j < nPoints)) { while ( ( bInvert && j >= 0) || ( ! bInvert && j < nPoints)) {
double dPar ; double dPar ;
m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ; m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ;
if ( pCompo->AddLine( pt)) { if ( pCompo->AddLine( pt)) {
// setto i parametri sulla sottocurva // setto i parametri sulla sottocurva
pCompo->SetCurveTempParam( nCrvCount, dParPrev, 0) ; pCompo->SetCurveTempParam( nCrvCount, dParPrev, 0) ;
pCompo->SetCurveTempParam( nCrvCount, dPar, 1) ; pCompo->SetCurveTempParam( nCrvCount, dPar, 1) ;
@@ -501,7 +501,7 @@ Voronoi::GetBisectorCurve( int i)
else else
j ++ ; j ++ ;
} }
// setto parametri sulla curva // setto parametri sulla curva
pCompo->SetTempParam( dParS, 0) ; pCompo->SetTempParam( dParS, 0) ;
pCompo->SetTempParam( dParPrev, 1) ; pCompo->SetTempParam( dParPrev, 1) ;
@@ -521,12 +521,12 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;
try { try {
// verifico se necessario calcolo Voronoi // verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed || nBound != m_nBound) if ( ! m_bVDComputed || nBound != m_nBound)
CalcVoronoi( nBound) ; CalcVoronoi( nBound) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// recupero la curva del bisettore // recupero la curva del bisettore
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ; PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
@@ -546,7 +546,7 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
{ {
vCrvs.clear() ; vCrvs.clear() ;
@@ -561,21 +561,21 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
bRight = false ; bRight = false ;
else if ( nSide == WMAT_RIGHT) else if ( nSide == WMAT_RIGHT)
bLeft = false ; bLeft = false ;
try { try {
if ( ! m_bVDComputed) if ( ! m_bVDComputed)
CalcVoronoi() ; CalcVoronoi() ;
// calcolo medial axis // calcolo medial axis
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ; m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se il lato appartiene al medial axis // verifico se il lato appartiene al medial axis
if ( m_vroni->IsWMATEdge( i)) { if ( m_vroni->IsWMATEdge( i)) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ; PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid()) if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ; vCrvs.emplace_back( Release( pCrv)) ;
} }
} }
// libero la memoria di vroni utilizzata per calcolare bisettore // libero la memoria di vroni utilizzata per calcolare bisettore
@@ -590,7 +590,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
{ {
vOffs.clear() ; vOffs.clear() ;
@@ -603,38 +603,34 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
for ( auto pCrv : m_vpCrvs) for ( auto pCrv : m_vpCrvs)
vOffs.emplace_back( pCrv->Clone()) ; vOffs.emplace_back( pCrv->Clone()) ;
} }
// calcolo offset // calcolo offset
ICRVCOMPOPLIST OffsList ; ICRVCOMPOPLIST OffsList ;
if ( ! CalcVroniOffset( OffsList, abs( dOffs))) if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
return false ; return false ;
// sistemo le curve di offset calcolate con vroni // sistemo le curve di offset calcolate con vroni
for ( auto pCrv : OffsList) { for ( auto pCrv : OffsList) {
// seleziono le porzioni dell'offset che si trovano dal lato richiesto // seleziono le porzioni dell'offset che si trovano dal lato richiesto
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ; ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) { for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
// eventuale inversione // eventuale inversione
if ( dOffs > EPS_SMALL) if ( dOffs > EPS_SMALL)
vResult[i]->Invert() ; vResult[i]->Invert() ;
// sistemo il punto di inizio // sistemo il punto di inizio
if ( vResult[i]->IsClosed()) if ( vResult[i]->IsClosed())
AdjustOffsetStart( vResult[i]) ; AdjustOffsetStart( vResult[i]) ;
// sistemo i raccordi // identifico i raccordi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0)
IdentifyFillets( vResult[i], dOffs) ; IdentifyFillets( vResult[i], dOffs) ;
AdjustCurveFillets( vResult[i], dOffs, nType) ;
}
// porto nel frame globale
vResult[i]->ToGlob( m_Frame) ;
// unisco le parti allineate // unisco le parti allineate
vResult[i]->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; vResult[i]->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ;
// aggiungo al vettore finale // aggiungo al vettore finale
vOffs.emplace_back( Release( vResult[i])) ; vOffs.emplace_back( Release( vResult[i])) ;
} }
@@ -642,11 +638,22 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
delete( pCrv) ; delete( pCrv) ;
} }
// aggiusto i raccordi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0)
if ( ! AdjustCurveFillets( vOffs, dOffs, nType)) {
vOffs.clear() ;
return false ;
}
// porto nel frame globale
for ( int i = 0 ; i < int( vOffs.size()) ; i++)
vOffs[i]->ToGlob( m_Frame) ;
return true ; return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs) Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
{ {
// calcola, se possibile, le curve di offset del valore richiesto come curve singole, andando a recuperare i tratti del // calcola, se possibile, le curve di offset del valore richiesto come curve singole, andando a recuperare i tratti del
@@ -660,22 +667,22 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;
try { try {
if ( ! m_bVDComputed) if ( ! m_bVDComputed)
CalcVoronoi() ; CalcVoronoi() ;
// individuo il lato richiesto // individuo il lato richiesto
bool bLeft = ( dOffs < 0) ; bool bLeft = ( dOffs < 0) ;
bool bRight = ! bLeft ; bool bRight = ! bLeft ;
for ( int i = 0 ; i < int( m_vpCrvs.size()) ; i++) { for ( int i = 0 ; i < int( m_vpCrvs.size()) ; i++) {
if ( ! m_vpCrvs[i]->IsClosed()) { if ( ! m_vpCrvs[i]->IsClosed()) {
// se è presente una curva aperta il medial axis deve essere fatto sia a destra sia a sinistra // se è presente una curva aperta il medial axis deve essere fatto sia a destra sia a sinistra
bLeft = true ; bLeft = true ;
bRight = true ; bRight = true ;
break ; break ;
} }
} }
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ; int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
// seleziono le curve del medial axis aventi parametro costante pari all'offset richiesto // seleziono le curve del medial axis aventi parametro costante pari all'offset richiesto
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ; m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
@@ -688,7 +695,7 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
m_vroni->GetBisectorParams( i, dParS, dParE) ; m_vroni->GetBisectorParams( i, dParS, dParE) ;
if ( abs( dParS - abs( dOffs)) < EPS_SMALL && abs( dParE - abs( dOffs)) < EPS_SMALL) { if ( abs( dParS - abs( dOffs)) < EPS_SMALL && abs( dParE - abs( dOffs)) < EPS_SMALL) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ; PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid()) { if ( ! IsNull( pCrv) && pCrv->IsValid()) {
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento // se necessario verifico se dal lato corretto rispetto ai siti di riferimento
if ( bLeft && bRight) { if ( bLeft && bRight) {
// recupero i siti di riferimento // recupero i siti di riferimento
@@ -700,7 +707,7 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
pCrv->SetTempProp( nOrigCrv1, 1) ; pCrv->SetTempProp( nOrigCrv1, 1) ;
int nSide = GetOffsetCurveSide( pCrv) ; int nSide = GetOffsetCurveSide( pCrv) ;
if ( nSide != nSideRef) if ( nSide != nSideRef)
continue ; continue ;
} }
if ( nOrigCrv2 != -1) { if ( nOrigCrv2 != -1) {
// verifico il lato rispetto al secondo sito // verifico il lato rispetto al secondo sito
@@ -709,18 +716,18 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
int nSide = GetOffsetCurveSide( pCrv) ; int nSide = GetOffsetCurveSide( pCrv) ;
if ( nSide != nSideRef) if ( nSide != nSideRef)
continue ; continue ;
} }
} }
vCrvs.emplace_back( Release( pCrv)) ; vCrvs.emplace_back( Release( pCrv)) ;
} }
} }
} }
} }
// concateno le curve ottenute // concateno le curve ottenute
if ( vCrvs.size() == 1) if ( vCrvs.size() == 1)
vOffs.emplace_back( Release( vCrvs[0])) ; vOffs.emplace_back( Release( vCrvs[0])) ;
else if ( ! vCrvs.empty()) { else if ( ! vCrvs.empty()) {
ChainCurves chainC ; ChainCurves chainC ;
chainC.Init( true, 10 * EPS_SMALL, int( vCrvs.size())) ; chainC.Init( true, 10 * EPS_SMALL, int( vCrvs.size())) ;
for ( int i = 0 ; i < int( vCrvs.size()) ; ++ i) { for ( int i = 0 ; i < int( vCrvs.size()) ; ++ i) {
@@ -747,14 +754,14 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
vCrvs[nInd]->Invert() ; vCrvs[nInd]->Invert() ;
// aggiungo alla composita // aggiungo alla composita
if ( ! pCrvCompo->AddCurve( Release( vCrvs[nInd]))) if ( ! pCrvCompo->AddCurve( Release( vCrvs[nInd])))
return false ; return false ;
} }
if ( pCrvCompo->IsValid()) { if ( pCrvCompo->IsValid()) {
pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
vOffs.emplace_back( Release( pCrvCompo)) ; vOffs.emplace_back( Release( pCrvCompo)) ;
} }
} }
} }
// libero la memoria di vroni utilizzata per calcolare bisettore // libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ; m_vroni->apiFreeBisectorBuffer() ;
@@ -768,11 +775,11 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
{ {
// calcola i punti e le tangenti sui bisettori del medial axis in corrispondenza del valore di offset richiesto // calcola i punti e le tangenti sui bisettori del medial axis in corrispondenza del valore di offset richiesto
vResult.clear() ; vResult.clear() ;
if ( abs( dOffs) < EPS_SMALL) if ( abs( dOffs) < EPS_SMALL)
@@ -785,12 +792,12 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
// verifico se necessario ricalcolo Voronoi // verifico se necessario ricalcolo Voronoi
UpdateVoronoi( dOffs) ; UpdateVoronoi( dOffs) ;
// indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare // indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare
// la chiusura solo sulla prima curva. Eventualmente da estendere) // la chiusura solo sulla prima curva. Eventualmente da estendere)
bool bLeft = true, bRight = true ; bool bLeft = true, bRight = true ;
if ( m_vpCrvs[0]->IsClosed()) { if ( m_vpCrvs[0]->IsClosed()) {
bLeft = dOffs < 0 ; bLeft = dOffs < 0 ;
bRight = ! bLeft ; bRight = ! bLeft ;
} }
// calcolo medial axis // calcolo medial axis
@@ -819,12 +826,12 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
double dPar ; double dPar ;
Point3d ptTemp ; Point3d ptTemp ;
Vector3d vtDir ; Vector3d vtDir ;
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir)) if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
return false ; return false ;
vtDir.Normalize() ; vtDir.Normalize() ;
vResult.emplace_back( pt, vtDir) ; vResult.emplace_back( pt, vtDir) ;
} }
} }
// libero la memoria di vroni utilizzata per calcolare bisettori // libero la memoria di vroni utilizzata per calcolare bisettori
@@ -839,22 +846,23 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids) Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids,
bool bMergeOnlySameProps)
{ {
vCrvs.clear() ; vCrvs.clear() ;
if ( ! IsValid()) if ( ! IsValid())
return false ;
// se offset nullo errore
if ( abs( dOffs) < EPS_SMALL)
return false ; return false ;
ICRVCOMPOPLIST OffsList ; // se offset nullo errore
if ( abs( dOffs) < EPS_SMALL)
return false ;
ICRVCOMPOPLIST OffsList ;
if ( ! CalcVroniOffset( OffsList, abs( dOffs))) if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
return false ; return false ;
// sistemo le curve di offset calcolate con vroni // sistemo le curve di offset calcolate con vroni
bool bClosed = m_vpCrvs[0]->IsClosed() ; bool bClosed = m_vpCrvs[0]->IsClosed() ;
for ( auto pCrvOffs : OffsList) { for ( auto pCrvOffs : OffsList) {
@@ -863,11 +871,10 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
if ( dOffs > EPS_SMALL) if ( dOffs > EPS_SMALL)
pCrvOffs->Invert() ; pCrvOffs->Invert() ;
// sistemo i raccordi // identifico i raccordi da modificare
if ( bClosed && bSquareMids) { if ( bClosed && bSquareMids) {
// se curva è chiusa tutti i raccordi rispondono a bSquareMids // se curva è chiusa tutti i raccordi rispondono a bSquareMids
IdentifyFillets( pCrvOffs, dOffs) ; IdentifyFillets( pCrvOffs, dOffs) ;
AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ;
} }
else if ( ! bClosed && ( bSquareMids || bSquareEnds)) { else if ( ! bClosed && ( bSquareMids || bSquareEnds)) {
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e // se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
@@ -880,22 +887,30 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
else else
pCrvOffs->SetCurveTempParam( j, 0) ; pCrvOffs->SetCurveTempParam( j, 0) ;
} }
AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ;
} }
// porto nel frame globale
pCrvOffs->ToGlob( m_Frame) ;
// unisco le parti allineate // unisco le parti allineate
pCrvOffs->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; pCrvOffs->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, bMergeOnlySameProps) ;
// aggiungo al vettore finale // aggiungo al vettore finale
vCrvs.emplace_back( pCrvOffs) ; vCrvs.emplace_back( pCrvOffs) ;
} }
// sistemo i raccordi
if ( bSquareMids || bSquareEnds)
if ( ! AdjustCurveFillets( vCrvs, dOffs, ICurve::OFF_EXTEND)) {
vCrvs.clear() ;
return false ;
}
// porto nel frame globale
for ( int i = 0 ; i < int( vCrvs.size()) ; i++)
vCrvs[i]->ToGlob( m_Frame) ;
return true ; return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs) Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
{ {
OffsList.clear() ; OffsList.clear() ;
@@ -916,21 +931,21 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ; m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ;
// recupero le curve di offset da vroni // recupero le curve di offset da vroni
int nOffsCnt = m_vroni->GetOffsetCount() ; int nOffsCnt = m_vroni->GetOffsetCount() ;
for ( int i = 0 ; i < nOffsCnt ; i++) { for ( int i = 0 ; i < nOffsCnt ; i++) {
Point3d ptSChain = P_INVALID ; Point3d ptSChain = P_INVALID ;
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ; PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
for ( int j = 0 ; j < nCrvCnt ; j ++) { for ( int j = 0 ; j < nCrvCnt ; j ++) {
// recupero la sottocurva da vroni // recupero la sottocurva da vroni
Point3d ptS, ptE, ptC ; Point3d ptS, ptE, ptC ;
int nType ; int nType ;
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ; m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
if ( j == 0) if ( j == 0)
pCrvOffs->AddPoint( ptS) ; pCrvOffs->AddPoint( ptS) ;
// se estremi coincidenti la curva va ignorata ( da vroni non possono arrivare circonferenze) // se estremi coincidenti la curva va ignorata ( da vroni non possono arrivare circonferenze)
// ma controllo se appartiene ad una catena di tratti infinitesimi // ma controllo se appartiene ad una catena di tratti infinitesimi
@@ -939,7 +954,7 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
if ( ! AreSamePointApprox( ptSChain, ptE)) { if ( ! AreSamePointApprox( ptSChain, ptE)) {
if ( ! pCrvOffs->AddLine( ptE)) if ( ! pCrvOffs->AddLine( ptE))
return false ; return false ;
ptSChain = P_INVALID ; ptSChain = P_INVALID ;
} }
} }
else { else {
@@ -955,16 +970,16 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
if ( ! pCrvOffs->AddLine( ptE)) if ( ! pCrvOffs->AddLine( ptE))
return false ; return false ;
} }
else { else {
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ; PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
if ( ! pArc->SetC2P( ptC, ptS, ptE)) { if ( ! pArc->SetC2P( ptC, ptS, ptE)) {
// se raggio minore di EPS_SMALL approssimo con linea // se raggio minore di EPS_SMALL approssimo con linea
if ( AreSamePointApprox( ptC, ptS)) { if ( AreSamePointApprox( ptC, ptS)) {
if ( ! pCrvOffs->AddLine( ptE)) if ( ! pCrvOffs->AddLine( ptE))
return false ; return false ;
} }
else else
return false ; return false ;
} }
else { else {
// verifico orientamento // verifico orientamento
@@ -973,25 +988,25 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
pArc->ToExplementary() ; pArc->ToExplementary() ;
// aggiungo alla composita // aggiungo alla composita
if ( ! pCrvOffs->AddCurve( Release( pArc))) if ( ! pCrvOffs->AddCurve( Release( pArc)))
return false ; return false ;
} }
} }
// setto come info la sottocurva da cui si è generata // setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ; int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ; pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ; pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva // verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
// aperta e chiusa) // aperta e chiusa)
if ( nOrigCrv == -1) { if ( nOrigCrv == -1) {
int nOrigCrvCnt = 1 ; int nOrigCrvCnt = 1 ;
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO) if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ; nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) { if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ; double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ; pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
} }
} }
} }
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL // rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
@@ -999,8 +1014,8 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
// aggiungo la curva alla lista degli offset // aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
OffsList.push_back( Release( pCrvOffs)) ; OffsList.push_back( Release( pCrvOffs)) ;
} }
// libero la memoria di vroni dedicata agli offset // libero la memoria di vroni dedicata agli offset
m_vroni->apiFreeOffsetData() ; m_vroni->apiFreeOffsetData() ;
@@ -1014,11 +1029,11 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
Voronoi::UpdateVoronoi( double dOffs) Voronoi::UpdateVoronoi( double dOffs)
{ {
// calcolo il bound necessario per l'offset desiderato // calcolo il bound necessario per l'offset desiderato
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ; double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
if ( ! m_bVDComputed || dNeededBound > m_nBound) { if ( ! m_bVDComputed || dNeededBound > m_nBound) {
// aggiorno il valore del bound // aggiorno il valore del bound
int nBound = ( int)( ceil( dNeededBound) + 0.5) ; int nBound = ( int)( ceil( dNeededBound) + 0.5) ;
@@ -1030,9 +1045,9 @@ Voronoi::UpdateVoronoi( double dOffs)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICRVCOMPOPOVECTOR ICRVCOMPOPOVECTOR
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
{ {
ICRVCOMPOPOVECTOR vResult ; ICRVCOMPOPOVECTOR vResult ;
int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ; int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ;
@@ -1050,13 +1065,13 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
// controllo la curva complessiva // controllo la curva complessiva
int nSide = GetOffsetCurveSide( pCompo->GetCurve( 0)) ; int nSide = GetOffsetCurveSide( pCompo->GetCurve( 0)) ;
if ( nSide == nSideRef) if ( nSide == nSideRef)
vResult.emplace_back( pCompo->Clone()) ; vResult.emplace_back( pCompo->Clone()) ;
} }
else { else {
// scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato // scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato
PtrOwner<CurveComposite> pCompoCurr( CreateBasicCurveComposite()) ; PtrOwner<CurveComposite> pCompoCurr( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) { for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
bool bKeep = true ; bool bKeep = true ;
double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ; double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ;
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL) if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
bKeep = false ; bKeep = false ;
@@ -1072,8 +1087,8 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
if ( pCompoCurr->IsValid()) { if ( pCompoCurr->IsValid()) {
vResult.emplace_back( Release( pCompoCurr)) ; vResult.emplace_back( Release( pCompoCurr)) ;
pCompoCurr.Set( CreateBasicCurveComposite()) ; pCompoCurr.Set( CreateBasicCurveComposite()) ;
} }
} }
} }
// salvo eventuale ultima curva // salvo eventuale ultima curva
if ( pCompoCurr->IsValid()) if ( pCompoCurr->IsValid())
@@ -1087,17 +1102,17 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
vResult.pop_back() ; vResult.pop_back() ;
} }
} }
return vResult ; return vResult ;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int int
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
{ {
if ( pCrv == nullptr) if ( pCrv == nullptr)
return -1 ; return -1 ;
Point3d ptM ; pCrv->GetMidPoint( ptM) ; Point3d ptM ; pCrv->GetMidPoint( ptM) ;
// recupero curva e sottocurva di riferimento dalle temp prop // recupero curva e sottocurva di riferimento dalle temp prop
@@ -1106,8 +1121,8 @@ Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ; const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) { if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ; const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
if ( pCompoOrig != nullptr) if ( pCompoOrig != nullptr)
pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ; pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ;
} }
DistPointCurve distPC( ptM, *pCrvRef) ; DistPointCurve distPC( ptM, *pCrvRef) ;
@@ -1117,9 +1132,9 @@ Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
{ {
for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) { for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) {
// cerco il tratto associato alla prima sottocurva originale // cerco il tratto associato alla prima sottocurva originale
int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ; int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ;
@@ -1139,15 +1154,15 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::Translate( const Vector3d & vtMove) Voronoi::Translate( const Vector3d & vtMove)
{ {
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;
return m_Frame.Translate( vtMove) ; return m_Frame.Translate( vtMove) ;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
{ {
if ( ! IsValid()) if ( ! IsValid())
@@ -1156,7 +1171,7 @@ Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{ {
if ( ! IsValid()) if ( ! IsValid())
@@ -1165,7 +1180,7 @@ Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::ToGlob( const Frame3d& frRef) Voronoi::ToGlob( const Frame3d& frRef)
{ {
if ( ! IsValid()) if ( ! IsValid())
@@ -1174,7 +1189,7 @@ Voronoi::ToGlob( const Frame3d& frRef)
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::ToLoc( const Frame3d& frRef) Voronoi::ToLoc( const Frame3d& frRef)
{ {
if ( ! IsValid()) if ( ! IsValid())
@@ -1183,7 +1198,7 @@ Voronoi::ToLoc( const Frame3d& frRef)
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{ {
if ( ! IsValid()) if ( ! IsValid())
@@ -1192,7 +1207,7 @@ Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
{ {
if ( nCrv < 0 || nCrv > int( m_vpCrvs.size()) - 1) if ( nCrv < 0 || nCrv > int( m_vpCrvs.size()) - 1)
@@ -1206,14 +1221,14 @@ Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
// verifico se necessario calcolo Voronoi // verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed) if ( ! m_bVDComputed)
CalcVoronoi() ; CalcVoronoi() ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se è un bisettore relativo alla curva richiesta e dal lato opportuno // verifico se è un bisettore relativo alla curva richiesta e dal lato opportuno
if ( m_vroni->IsRelatedEdge( i, nCrv, bLeft)) { if ( m_vroni->IsRelatedEdge( i, nCrv, bLeft)) {
// calcolo i parametri del bisettore // calcolo i parametri del bisettore
double dParS, dParE ; double dParS, dParE ;
m_vroni->GetBisectorParams( i, dParS, dParE) ; m_vroni->GetBisectorParams( i, dParS, dParE) ;
dOffs = max( { dParS, dParE, dOffs}) ; dOffs = max( { dParS, dParE, dOffs}) ;
} }
} }
+1 -1
View File
@@ -57,7 +57,7 @@ class Voronoi
bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ; bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ;
bool CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs) ; bool CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs) ;
bool CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) ; bool CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) ;
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ; bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps = true) ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ; bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ; bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;