Compare commits

..

296 Commits

Author SHA1 Message Date
Daniele Bariletti 292c2bf87a EgtGeomKernel :
- piccola correzione.
2025-04-22 11:43:47 +02:00
Daniele Bariletti e45bbf2afd EgtGeomKernel:
- piccola correzione.
2025-04-14 11:22:56 +02:00
Daniele Bariletti fc6de68d83 Merge branch 'master' into FasterBezier_NoMultiThread 2025-04-14 09:01:39 +02:00
Daniele Bariletti a008c169ae EgtGeomKernel :
- aggiunta seconda trimesh alle bezier.
2025-04-14 09:01:15 +02:00
SaraP 3cd6c9299f EgtGeomKernel :
- correzione riferimenti in CalcSpecialPointOffset.
2025-04-11 16:41:13 +02:00
Daniele Bariletti 8e5801d656 Merge remote-tracking branch 'origin/HEAD' into FasterBezier_NoMultiThread 2025-04-11 16:02:12 +02:00
Daniele Bariletti 1691b7f84a EgtGeomKernel: - correzione al taglio di superfici di bezier con piani. 2025-04-11 16:01:14 +02:00
Daniele Bariletti 76e4197729 EgtGeomKernel:
- correzione errori nel taglio con piani di Surf di bezier.
2025-04-11 11:27:38 +02:00
Daniele Bariletti fb8bac8681 EgtGeomKernel:
- correzione di un errore di taglio con piani nelle surf Bezier.
2025-04-10 15:34:57 +02:00
Daniele Bariletti 55a9685add EgtGeomKernel:
- piccole correzioni.
2025-04-08 15:34:48 +02:00
Dario Sassi afa4be3717 EgtGeomKernel :
- modifiche solo estetiche.
2025-04-08 13:07:57 +02:00
Daniele Bariletti 57c03a54c9 Merge branch 'master' into FasterBezier_NoMultiThread 2025-04-08 12:56:30 +02:00
SaraP 91a9adaea4 EgtGeomKernel 2.4d1 :
- in OffsetCurve aggiunta funzione che restituisce punto di offset nel caso in cui non siano calcolabili curve
- correzione offset Voronoi nel caso di arco con raggio minore di EPS.
2025-04-08 08:37:20 +02:00
Daniele Bariletti 8657fa32c5 Merge remote-tracking branch 'origin/master' into FasterBezier_NoMultiThread 2025-04-07 10:21:23 +02:00
Dario Sassi b7a4f0bff3 EgtGeomKernel :
- a SurfTriMesh aggiunto metodo CreateByPolygonWithHoles.
2025-03-28 20:17:50 +01:00
Dario Sassi f0716e2727 EgtGeomKernel 2.7c4 :
- aggiunte funzioni GetSurfTriMeshPyramidFrustum e GetSurfTriMeshConeFrustum
- modificata funzione GetSurfTriMeshPyramid per origine ora in centro alla base.
2025-03-27 15:25:07 +01:00
Dario Sassi b1acf7f4f0 EgtGeomKernel :
- correzione a Inters3Planes (la linea deve essere infinita)
- modifiche varie e correzioni a ProjectCurveOnSurf per gestire spigoli e per far funzionare l'eliminazione dei punti superflui.
2025-03-26 11:26:36 +01:00
Daniele Bariletti 851c053f7c - pulizia del codice. 2025-03-25 12:37:13 +01:00
Daniele Bariletti 71276a8de3 - ottimizzazione del codice e gestione delle copie di polyline nel tree. 2025-03-25 12:17:06 +01:00
Daniele Bariletti b2e799e1d6 - ulteriore riduzione di copie di costruzione e copie di polyline in tree. 2025-03-24 12:42:56 +01:00
Daniele Bariletti eb9aaef53a - riduzione del numero di copie di polyline nel tree di una bezier. 2025-03-24 10:09:39 +01:00
Dario Sassi 49340d2629 EgtGeomKernel :
- in CollisionAvoid aumentato MAX_MOVE per calcoli con travi (elevazione su attacchi/uscite).
2025-03-17 15:11:34 +01:00
Daniele Bariletti 0b9c9f375c - aggiunta mappa per il calcolo dei punti 3d di una bezier. 2025-03-17 14:19:08 +01:00
Daniele Bariletti cd56f80790 - piccola modifica alla mappa dei polinomi di bernstein. 2025-03-17 14:19:03 +01:00
Riccardo Elitropi 65d826168b EgtGeomKernel :
- In ConformalZigZag piccola modifica sulla tolleranza della regione limite.
2025-03-17 09:55:22 +01:00
Riccardo Elitropi ea012988df EgtGeomKernel :
- aggiunto parametro in CalcPocketing.
2025-03-13 12:32:35 +01:00
Dario Sassi 67f3df353f EgtGeomKernel 2.7c2 :
- in CAvToolSurfTm caso singola posizione da controllare utilizzo HashGrid3d delle superfici tramite GetAllTriaOverlapBox.
2025-03-12 15:27:33 +01:00
Daniele Bariletti 9d34df708d - piccole correzioni
- passaggio da key int, double a int, int per la mappa di Bernstein per le bezier.
2025-03-12 12:43:10 +01:00
Daniele Bariletti 72947f1e36 Merge remote-tracking branch 'origin/HEAD' into FasterBezier 2025-03-12 09:41:01 +01:00
Daniele Bariletti 1cdae73b24 - aggiunta del membro statico per tenere in cache i polinomi di bernstein
- allocazione della memoria per il calcolo di bernstein fatto solo una volta per superficie.
2025-03-11 14:48:34 +01:00
Riccardo Elitropi a2825b2b6d EgtGeomKernel :
- migliorie MarchingSquares, semplificazione funzioni per CAv.
2025-03-11 11:17:30 +01:00
Daniele Bariletti 5bc7036e98 - miglioria per la copia di SurfBezier. 2025-03-10 12:40:36 +01:00
Daniele Bariletti 7e545aecd7 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-03-07 09:18:10 +01:00
Daniele Bariletti 0fc8291ef5 - piccola miglioria a test per concatenamento. 2025-03-07 09:17:38 +01:00
Dario Sassi 0d668c1a4a EgtGeomKernel :
- piccola miglioria a test per concatenamento.
2025-03-06 20:10:38 +01:00
Daniele Bariletti 4b1270f231 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-03-05 12:21:56 +01:00
Daniele Bariletti 9263dc0516 - modifica alla scelta del punto di start per le compo create come chain. 2025-03-05 12:21:50 +01:00
Riccardo Elitropi b0f7cb93fd EgtGeomKernel :
- Aggiunto parametro in CalcPocketing.
2025-03-04 17:42:53 +01:00
Riccardo Elitropi add3788db4 Merge commit '37c23faae3082033a87a89f1f7332ab5593356b6' 2025-03-04 17:24:09 +01:00
SaraP 37c23faae3 EgtGeomKernel 2.7c1 :
- aggiunta triangolazione con FIST.
2025-03-04 16:55:33 +01:00
Riccardo Elitropi fa6f12ba3b EgtGeomKernel :
- In CalcPocketing ConformalZigZag, piccola modifica alla tolleranza per riconoscimento lati Open/Close.
2025-03-03 12:04:30 +01:00
Riccardo Elitropi 730dd396f4 EgtGeomKernel :
- In CalcPocketing aggiunto parametro per ottimizzazione Offsets
- In CavToolSurfTm aggiunta funzione per Test griglia di punti con parametro di alzata dell'utensile e normali dei triangoli coinvolti
- In SurfTriMesh aggiunta funzione per calcolo dei Loop su una Part specifica.
2025-02-21 11:09:45 +01:00
Riccardo Elitropi 3b9f6773f2 EgtGeomKernel :
- in CalcPocketing piccola modifica nella creazione della superficie di incidenza.
2025-02-03 15:31:41 +01:00
Dario Sassi 97315f6ca4 EgtGeomKernel 2.7a3 :
- ricompilato con nuova libreria VRONI 7.8.
2025-01-29 16:47:07 +01:00
Riccardo Elitropi b2be420e36 EgtGeomKernel :
- in CalcPocketing Conformal migliorata la gestione delle entrate.
2025-01-28 08:35:09 +01:00
Riccardo Elitropi 4ee34b79f8 EgtGeomKernel :
- In CalcPocketing, piccola correzione nel calcolo dei Link per ConformalZigZag.
2025-01-27 10:24:43 +01:00
Riccardo Elitropi e4ee403d24 EgtGeomKernel :
- correzione tool avanzato per collisioni in calcolo di Silhouette.
2025-01-24 17:07:23 +01:00
Dario Sassi b709776f5f EgtGeomKernel :
- piccole mdofiche poco più che estetiche.
2025-01-20 08:30:39 +01:00
SaraP b5a2490fd4 EgtGeomKernel :
- piccola correzione triangolazione avanzata.
2025-01-17 12:21:25 +01:00
SaraP 7a18cd1c5c EgtGeomKernel :
- correzione offset con Voronoi nel caso di tratti infinitesimi consecutivi.
2025-01-17 09:03:55 +01:00
Dario Sassi 26e1448bbb EgtGeomKernel :
- unificata proiezione di curve su superfici trimesh e bezier.
2025-01-15 15:21:18 +01:00
Dario Sassi a1ebdb4eb6 EgtGeonKernel :
- piccola ulteriore miglioria in CalcAuxSurf di Region.
2025-01-14 18:52:56 +01:00
Dario Sassi 6603061f81 EgtGeomKernel :
- migliorato calcolo Trimesh associata a Region mediante eliminazione di isole piccole.
2025-01-14 18:22:15 +01:00
Dario Sassi 1c3d7bf2a6 EgtGeomKernel :
- piccole migliorie alle funzioni ProjectCurveOnSurfTm.
2025-01-14 08:45:26 +01:00
Riccardo Elitropi a4a030b776 EgtGeomKernel :
- In CalcPocketing migliorata la gestione dei lati aperti, migliorati i percorsi Conformal e di raccordo per gli smussi.
2025-01-10 16:42:42 +01:00
Dario Sassi 64a8294ea0 EgtGeomKernel :
- corretta intersezione tra segmenti di retta quasi paralleli
- aggiunte verifiche su Fillet e Chamfer.
2025-01-10 16:26:40 +01:00
Dario Sassi 847383d82d EgtGeomKernel 2.7a1 :
- cambio annuale di versione
- NurbsToBezierCurve ora aggiusta i valori dei nodi agli estremi (anzichè controllarli)
- compilazione 32bit senza più limiti per Windows XP.
2025-01-09 17:57:57 +01:00
Riccardo Elitropi c16d916a63 EgtGeomKernel :
- inizializzazione offset radiale per Silhouettes.
2025-01-07 13:25:21 +01:00
Riccardo Elitropi 91cae44533 EgtGeomKernel :
- in Silhouette, corretto offset radiale per altezze utensili.
2025-01-07 12:16:34 +01:00
Dario Sassi 56c3e28ac3 EGtGeomKernel :
- piccola modifica estetica.
2025-01-06 18:16:46 +01:00
Riccardo Elitropi 3238c86cec EgtGeomKernel :
- In CalcPocketing piccola correzione per estensione lati aperti e migliorie lavorazioni Conformal.
2024-12-31 12:01:36 +01:00
Riccardo Elitropi f050e682ef EgtGeomKernel :
- In CalcPocketing, piccola correzione per i casi a Trapezio.
2024-12-30 18:01:16 +01:00
Riccardo Elitropi 01c875b34f EgtGeomKernel :
- Semplificazione Silhouette con regioni piane.
2024-12-30 16:12:26 +01:00
Riccardo Elitropi 50b8a8aa94 in CalcPocketing :
- migliorati percorsi conformal ZigZag/OneWay
- migliorie varie.
2024-12-24 17:25:58 +01:00
SaraP 9f1aad5e49 EgtGeomKernel 2.6l3 :
- in CurveGetAreaXY aggiunto calcolo dell'area degli archi per eliminare approssimazione con polylines.
2024-12-18 16:47:02 +01:00
Riccardo Elitropi a38c50197b - In CalcPocketing migliorati i controlli per lavorazioni conformal
- In CAvSilhouette aggiunte funzioni per calcolo silhouette all'interno di una regione piana.
2024-12-12 11:48:40 +01:00
Dario Sassi fe54dde44e EgtGeomKernel :
- in Vmill corretti controlli per velocizzazione taglio dexel con cilindri.
2024-12-10 10:57:36 +01:00
Dario Sassi 62a3405d6a EgtGeomKernel 2.6l2 :
- tolta da interfaccia ISurfTriMesh il metodo CreateByRegion (usare al suo posto la funzione GetSurfTriMeshByRegion)
- aggiunta la funzione GetSurfTriMeshEmpty.
2024-12-04 15:04:26 +01:00
Dario Sassi cb9dd807ce EgtGeomKernel 2.6l1 :
- aggiunta funzione FlattenInAutoPlane per spianare la polilinea sul suo piano medio.
2024-11-29 18:52:42 +01:00
Dario Sassi d60d38a24b Revert "EgtGeomKernel 2.6i1 :"
This reverts commit e598e7986f.
2024-11-29 18:22:48 +01:00
Dario Sassi e598e7986f EgtGeomKernel 2.6i1 :
- aggiunta funzione FlattenAdv per spianare la polilinea sul suo piano medio.
2024-11-29 18:17:40 +01:00
Riccardo Elitropi 9bebd2f2ad Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-11-27 16:02:26 +01:00
Riccardo Elitropi 36d5c39094 EgtGeomKernel:
- in calcolo della Silhouette aggiunti casi ambigui, aggiunta funzione per controllo di sharpedEdges e migliorati i controlli di approssimazione.
2024-11-27 16:02:22 +01:00
Dario Sassi 1b08f4bbdd EgtGeomKernel :
- correzione calcolo PCA per punti (aumentata precisione).
2024-11-27 15:31:45 +01:00
SaraP 4a952b1c9b EgtGeomKernel :
- ulteriore correzione Voronoi.
2024-11-26 15:53:09 +01:00
SaraP 7a25927054 EgtGeomKernel 2.6k2 :
- in Voronoi migliorata la crezione di archi dervianti dall'offset
- in CurveArc::Set2PRS aggiunta normalizzazione vettore per gestire semicirconferenze con raggi piccoli.
2024-11-26 14:48:21 +01:00
SaraP cf022921a7 EgtGeomKernel 2.6k1 :
- in GetSilhouette ripristinato l'offset di tipo fillet ed extend per sistemare imprecisioni sugli spigoli.
2024-11-15 10:21:53 +01:00
Dario Sassi dc798aaaba EgtGeomKernel :
- in Vmill ulteriore velocizzazione nel taglio dexel con cilindri.
2024-10-29 18:39:52 +01:00
Dario Sassi eed89dab37 EgtGeomKernel 2.6j4 :
- in Vmill velocizzato taglio dexel con cilindri di grande diametro (come le lame).
2024-10-29 16:51:32 +01:00
Dario Sassi 990bc1a1e4 EgtGeomKernel :
- migliorato controllo precisione percorsi per proiezione curve su superfici.
2024-10-25 17:18:59 +02:00
Riccardo Elitropi 03433fe3af EgtGeomKernel :
- in CalcPocketing, aggiunto controllo sulla regione di incidenza.
2024-10-22 09:38:30 +02:00
Riccardo Elitropi e02611504b EgtGeomKernel :
- In CalcPocketing migliorato controllo per entrate da fuori
- corretta gestione delle curve singole di svuotatura.
2024-10-18 11:26:21 +02:00
SaraP a835433be4 EgtGeomKernel 2.6j3 :
- aggiunte funzioni per calcolare offset come curve singole con Voronoi.
2024-10-16 16:28:32 +02:00
Dario Sassi da8f40db17 EgtGeomKernel 2.6j1 :
- ricompilazione con cambio versione.
2024-10-10 15:43:05 +02:00
Riccardo Elitropi 5468e3f4fa EgtGeomKernel :
- in CalcPocketing rilassati i vincoli sulla regione di incidenza dei lati aperti e migliorata la gestione delle curve singole.
2024-10-10 13:02:42 +02:00
Daniele Bariletti 88684e305f Merge branch 'MoreBezier' 2024-10-04 15:40:24 +02:00
Daniele Bariletti f8ca8029d7 Merge remote-tracking branch 'origin/HEAD' into MoreBezier 2024-10-04 15:20:46 +02:00
Daniele Bariletti aa9c46cbb5 EgtGeomKernel :
- aggiunte la surfBz SweptInPlane e Swept3D.
2024-10-04 15:20:31 +02:00
Daniele Bariletti f0cf3c9559 EgtGeomKernel :
- rimozione memory leak
- corretto bug nella triangolazione bezier.
2024-10-04 14:57:23 +02:00
Riccardo Elitropi 9a638b9470 EgtGeomKernel :
- In CalcPocketing corretti errori per casi a trapezio
- migliorata la gestione delle curve singole di svuotatura.
2024-10-04 12:57:20 +02:00
Dario Sassi b07fbfc72e Merge commit 'a98b6bcc09a707b1c42a025b8e85a85801465f08' 2024-10-02 17:26:01 +02:00
Dario Sassi 0317c37557 EgtGeomKernel 2.6j1 :
- piccoli ritocchi a superfici di Bezier.
2024-10-02 17:25:24 +02:00
Riccardo Elitropi a98b6bcc09 EgtGeomKernel :
- in CalcPocketing estesi i percorsi OneWay
- piccole migliorie su selezione punto iniziale per curve singole.
2024-10-02 13:13:16 +02:00
Riccardo Elitropi c19861a911 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-10-01 12:41:19 +02:00
Riccardo Elitropi 8f8597d442 EgtGeomKernel :
- In CalcPocketing, piccola modifica in lavorazioni Conformal.
2024-10-01 12:41:15 +02:00
Dario Sassi 0c0eb9ef8f EgtGeomKernel 2.6i2 :
- ricompilazione con cambio versione.
2024-09-26 19:58:03 +02:00
Riccardo Elitropi 4ffb7087bd EgtGeomKernel :
- In CalcPocketing, migliorati i percorsi Conformal.
2024-09-26 12:22:51 +02:00
Dario Sassi dc070c4556 EgtgeomKernel :
- aggiunta funzione GetLoopCurveCount a FlatRegion.
2024-09-23 13:01:07 +02:00
Riccardo Elitropi 60729d5f39 EgtGeomKernel :
- Semplificazione codice in CalcPocketing.
2024-09-20 09:29:02 +02:00
SaraP da7e9dd6e2 EgtGeomKernel :
- aggiunte funzioni per calcolare Voronoi e medial axis di più curve.
2024-09-19 16:28:19 +02:00
Riccardo Elitropi aeff9fb418 EgtGeomKernel :
- in sgrossature, aggiunta modalità CONFORMAL_ZIGZAG e CONFORMAL_ONEWAY.
2024-09-19 09:06:40 +02:00
Daniele Bariletti e9e897593b EgtGeomKernel :
- modificata la CreateBySetOfCurves.
2024-09-17 17:27:31 +02:00
Daniele Bariletti bfc09d135c EgtGeomKernel :
- aggiunta la funzione IsLine per le bezier
- aggiunta funzione SurfBzSweptInPlane
- aggiunta la funzione InterpolatePointSetWithBezier.
2024-09-17 17:19:20 +02:00
SaraP 0998d0fffc EgtGeomKernel :
- correzione errore nel calcolo offset con Voronoi.
2024-09-10 16:17:50 +02:00
Daniele Bariletti 93c87ee720 EgtGeomKernel :
- correzione alla triangolazione delle bilineari bezier.
2024-09-10 12:30:01 +02:00
Daniele Bariletti a67a0502fa EgtGeomKernel :
- correzioni alla triangolazione di una surf di bezier (split iniziale).
2024-09-10 09:19:28 +02:00
Daniele Bariletti cec0a48be4 EgtGeomKernel :
- correzione alla SurfBzByScrewing.
2024-09-10 09:18:21 +02:00
Daniele Bariletti 0cc63d40eb EgtGeomKernel :
- piccole correzioni
- tolti commenti.
2024-09-10 09:17:59 +02:00
Dario Sassi 623eb6e630 EgtGeomKernel 2.6i1 :
- ricompilazione con cambio versione.
2024-09-05 17:37:54 +02:00
Dario Sassi 1f22299096 Merge commit '3f6c439983dee4957cb04a9b69dd01492ef38954' 2024-09-05 17:10:03 +02:00
Daniele Bariletti 3f6c439983 Merge branch 'MoreBezier' 2024-09-05 15:03:27 +02:00
Daniele Bariletti 8e22267476 EgtGeomKernel :
- piccole correzioni.
2024-09-05 12:13:28 +02:00
Daniele Bariletti aa2b6ccde5 EgtGeomKernel :
- modifica degli argomenti della funzione CalcRegionPolyLines.
2024-09-05 12:09:28 +02:00
Daniele Bariletti ec6cb79a8d EgtGeomKernel :
- correzione alla SurfTmByRegionExtrusion
- correzione alla SurfBzByScrewing.
2024-09-05 11:37:24 +02:00
Daniele Bariletti 76dceb4fc9 EgtGeomKernel :
- aggiunto un commento.
2024-09-05 08:53:15 +02:00
Daniele Bariletti b1564f7de0 EgtGeomKernel :
- aggiunto un commento.
2024-09-05 08:52:57 +02:00
Daniele Bariletti 21e4bd6d93 Merge branch 'master' into MoreBezier 2024-09-04 15:56:45 +02:00
Daniele Bariletti 2101d72abe Merge branch 'MoreBezier' 2024-09-04 15:50:24 +02:00
Daniele Bariletti 7a01f67c8b EgtGeomKernel :
- aggiunto un argomento alla CalcRegionPolyLines.
2024-09-04 15:50:01 +02:00
Daniele Bariletti 2267343afe EgtGeomKernel :
- correzione ai CopyFrom di CurveComposite e di SurfBezier.
2024-09-04 08:57:39 +02:00
Daniele Bariletti 9a5fe24781 EgtGeomKernel :
- correzione alle SbzByRegion.
2024-09-03 09:25:17 +02:00
Daniele Bariletti 4050aa11c5 EgtGeomKernel :
- aggiunto un limite di iterazioni per l'approssimazione con bezier cubiche
- correzione alla MakeNonRational.
2024-09-02 09:47:45 +02:00
Daniele Bariletti b75ddae396 Merge branch 'MoreBezier' 2024-08-30 16:16:25 +02:00
Daniele Bariletti 2d3f8487ee Merge remote-tracking branch 'origin/HEAD' into MoreBezier 2024-08-30 15:04:46 +02:00
SaraP 964647d7e6 EgtGeomKernel 2.6h3 :
- estensione del calcolo degli offset con Voronoi al caso di più curve scollegate tra loro.
2024-08-30 14:49:47 +02:00
Daniele Bariletti f78dd0fa83 EgtGewomKernel :
- correzione alle curve di bezier.
2024-08-30 14:46:59 +02:00
Daniele Bariletti 55ce22b06c EgtGeomKernel :
- piccoli aggiustamenti stilistici.
2024-08-29 10:05:45 +02:00
Daniele Bariletti 50df4f3503 Merge branch 'master' into MoreBezier 2024-08-29 09:23:08 +02:00
Daniele Bariletti 5c8f0c79f6 Merge commit '2b4090619bd13636d11a1684cd19a5b8a1ca4539' into MoreBezier 2024-08-29 09:21:42 +02:00
Daniele Bariletti de3f187ddf EgtGeomKernel :
- unificazione del codice per la CalcRegionPolyLines e modifiche collegate.
2024-08-29 09:20:00 +02:00
Daniele Bariletti f649954ee1 EgtGeomKernel :
- pulizia codice.
2024-08-28 09:35:27 +02:00
Daniele Bariletti 6e08f2a878 EgtGeomKernel :
- modifica alla MakeNonRational
- modifica alla EditCurveBezier ( si può scegliere liberamente il grado)
- aggiunte funzioni per uniformare le curve da usare per la creazione di sup di Beizer.
- piccola correzione alla triangolazione.
2024-08-26 17:07:51 +02:00
Dario Sassi 887922a715 EgtGeomKernel :
- migliorie a CalcAuxSurf di SurfFlatRegion (per casi di piccolissima dimensione).
2024-08-23 18:59:40 +02:00
Dario Sassi 640fef2e0a Merge commit '4f3fe68283f537bb933439a78ef909025408c904' 2024-08-23 09:21:22 +02:00
Daniele Bariletti 1a338a1a82 EgtGeomKernel :
- aggiunte le approssimazioni di bezier con bezier cubiche.
2024-08-22 15:57:53 +02:00
Riccardo Elitropi 4f3fe68283 EgtGeomKernel :
- aggiunta in CalcPocketing la gestione dei punti iniziali
- migliorie varie.
2024-08-22 12:54:25 +02:00
Dario Sassi 3908e11d18 EgtGeomKernel 2.6h2 :
- modifiche per permettere Mark di tipo 2.
2024-08-22 09:10:04 +02:00
Daniele Bariletti 4e6c5112e4 EgtGeomKernel :
- aggiunta di funzioni e modifica di funzioni per la gestione delle curve di bezier.
2024-08-09 17:35:47 +02:00
Daniele Bariletti e1ab88302f EgtGeomKernel :
- correzioni e miglioramenti alla triangolazione delle bezier.
2024-08-09 17:33:26 +02:00
Riccardo Elitropi 2b4090619b EgtGeomKernel :
- In CalcPocketing miglorate le Feed, le regioni non svuotate e le lavorazioni ConformalZigZag.
2024-08-06 15:11:11 +02:00
Dario Sassi b90289e42b EgtGeomKernel :
- piccole velocizzazioni per biarchi
- modifiche per unificazioni AreSamePoint***.
2024-08-06 14:42:25 +02:00
SaraP 5e84408685 EgtGeomKernel 2.6h1 :
- migliorato calcolo distanza nell'approssimazione con archi.
2024-08-05 16:50:35 +02:00
Daniele Bariletti b53c2f833a Merge branch 'MoreBezier' 2024-08-05 10:07:42 +02:00
Daniele Bariletti b5fcceaa75 Merge branch 'master' into MoreBezier 2024-08-05 08:46:27 +02:00
Daniele Bariletti f0bfbb6c85 EgtGeomKernel :
- correzioni e migliorie alla triangolazione con le bezier.
2024-08-02 15:12:35 +02:00
Daniele Bariletti 2710f735d1 EgtGeomKernel :
- correzioni e migliorie alla triangolazione delle bezier.
2024-08-01 16:24:16 +02:00
Daniele Bariletti ddffbd2c88 EgtGeomKernel :
- correzioni e migliorie alla triangolazione delle bezier.
2024-07-31 17:43:18 +02:00
SaraP fde952499d EgtGeomKernel :
- correzione in AssociatePolyLinesMinDistPoints.
2024-07-31 14:22:22 +02:00
Riccardo Elitropi b28102a8cc EgtGeomKernel :
In CalcPocketing per lavorazioni CONFORMAL_ZIGZAG aggiunta gestione aree non svuotate.
2024-07-30 18:34:37 +02:00
Daniele Bariletti f46db233dc EgtGeomKernel :
- ottimizzazione della triangolazione bezier.
2024-07-30 16:23:35 +02:00
Riccardo Elitropi df10b45c6b EgtGeomKernel :
- in CalcPocketing aggiunta lavorazione CONFORMAL_ZIGZAG
- migliorie varie.
2024-07-30 14:01:17 +02:00
Daniele Bariletti 1b13580340 EgtGeomKernel :
- correzioni alla triangolazione con le bezier.
2024-07-29 17:32:04 +02:00
Daniele Bariletti 742305b99b EgtGeomKernel :
- correzioni e miglioramenti alla triangolazione delle bezier.
2024-07-29 15:25:28 +02:00
Dario Sassi 1261de4dbb EgtGeomKernel 2.6g6 :
- ricompilazione con cambio versione.
2024-07-29 10:14:02 +02:00
Daniele Bariletti b50588f974 EgtGeomKernel :
- correzioni e migliorie alla triangolazione delle bezier.
2024-07-26 17:28:29 +02:00
Daniele Bariletti 9b87de9fa2 EgtGeomKernel :
- correzioni e migliorie alla triangolazione con le bezier.
2024-07-25 16:25:05 +02:00
Riccardo Elitropi 5bab4a9aa8 EgtGeomKernel :
- aggiunti percorsi di bordo In CalcPocketing per ZigZag e OneWay
- correzione punti per entrate
- migliorie varie.
2024-07-25 12:30:08 +02:00
Daniele Bariletti c3e7d3d8c7 EgtGeomKernel :
- miglioramenti alla triangolazione delle bezier.
2024-07-24 10:13:45 +02:00
Daniele Bariletti 89c22ffd06 EgtGeomKernel :
- correzioni e miglioramenti per la triangolazione bezier.
2024-07-24 09:27:38 +02:00
Riccardo Elitropi 5375752609 EgtGeomKernel :
- in CalcPocketing aggiunto un frame Locale XY per semplificazione conti e migliorata la gestione della svuotature a trapezio.
2024-07-23 11:52:43 +02:00
Daniele Bariletti 0a8f26c993 EgtGeomKernel :
- correzioni alla triangolazione delle bezier.
2024-07-23 09:47:19 +02:00
Riccardo Elitropi cba9c253e1 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-07-22 11:46:43 +02:00
Riccardo Elitropi 71f3bf8809 EgtMachKernel :
- in calcPocketing, migliorata la gestione di superfici con isole sia aperte che chiuse, gestito caso di circonferenza tutta aperta e modifica del parametro MinSafe.
2024-07-22 11:46:39 +02:00
Daniele Bariletti d491536eb4 EgtGeomKernel :
- piccola aggiunta al CopyFrom delle Surf Bezier.
2024-07-22 11:18:32 +02:00
Daniele Bariletti e68465c80b EgtGeomKernel :
- piccola aggiunta al CopyFrom delle Surf Bezier.
2024-07-22 11:18:01 +02:00
Daniele Bariletti dfb8fd2160 EgtGeomKernel :
- correzione bug nella triangolazione bezier.
2024-07-22 10:27:24 +02:00
Daniele Bariletti 746fa61e08 EgtGeomKernel :
- aggiunta dell'uniformazione delle curve in preparazione ad una superficie skinned.
2024-07-22 10:26:51 +02:00
Daniele Bariletti d0e0c46e2c EgtGeomKernel :
- correzione bug nella triangolazione bezier.
2024-07-22 10:22:36 +02:00
Daniele Bariletti 19c7f63303 EgtGeomKernel :
- generalizzazione della skinned con bezier.
2024-07-19 16:59:47 +02:00
Daniele Bariletti 87f6a29db3 EgtGeomKernel :
- aggiunte le skinned con le Bezier.
2024-07-19 13:13:45 +02:00
Riccardo Elitropi b04d1ed7a9 EgtGeomKernel :
- migliorie nella gestione dei lati Aperti/Chiusi in CalcPocketing.
2024-07-19 12:01:58 +02:00
Dario Sassi 54dba7ab41 EgtGeomKernel 2.6g5 :
- aggiunta classe DistPointSurfFr (distanza punto regione)
. a SurfFlatRegion aggiunte funzioni EraseChunk, GetChunkArea, GetChunkPerimeter, ResetAllCurveTempProps e ResetAllCurveTempParams
- piccoli adattamenti in CalcPocketing.
2024-07-18 20:18:18 +02:00
Daniele Bariletti 146c06d27f Merge branch 'master' into MoreBezier 2024-07-17 16:22:19 +02:00
Daniele Bariletti 7c45c1e287 EgtGeomKernel :
- aggiustamenti alla Bezier By Contour.
2024-07-17 16:18:18 +02:00
Daniele Bariletti d6dc5b8428 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2024-07-17 09:10:07 +02:00
Daniele Bariletti 28695f9138 EgtGeomKernel :
- piccola modifica alle funzioni per creare superfici di Bezier.
2024-07-17 09:10:03 +02:00
Dario Sassi 66cec4a872 EgtGeomKernel :
- ridotte tolleranze su tangenza in intersezione archi.
2024-07-17 09:00:33 +02:00
Dario Sassi 8d1d3f766a EgtGeomKernel :
- irrobustita funzione IsClosedAndFlat di PolyLine (facendo i conti rispetto al baricentro)
- per Regioni quando si aggiune il loop esterno, se risulta formato da più parti disgiunte (per autonitersezioni) si ignorano quelle molto piccole.
2024-07-16 08:38:40 +02:00
Dario Sassi befed079c8 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-07-15 18:51:13 +02:00
Daniele Bariletti b9138029db EgtGeomKernel 2.6g3 :
- aggionamento versione.
2024-07-15 17:34:11 +02:00
Daniele Bariletti 2246dbc284 Merge branch 'MoreBezier' 2024-07-15 17:30:17 +02:00
Dario Sassi 67180b3569 Merge commit '4748bd5ac888a0ae6b9381c40bad0aaf01df73aa' 2024-07-15 17:11:30 +02:00
Daniele Bariletti 3a2aa2c679 Merge branch 'master' into MoreBezier 2024-07-15 17:06:16 +02:00
Daniele Bariletti 9dd4e043d4 EgtGeomKernel :
- correzione bug nelle rigate con le Bezier.
2024-07-15 17:05:44 +02:00
Riccardo Elitropi 4748bd5ac8 EgtGeomKernel :
- In CalcPocketing corretta la gestione delle isole aperte mediante MaxOffset.
2024-07-15 13:28:14 +02:00
Daniele Bariletti 649f97e933 EgtGeomKernel :
- correzione bug di triangolazione bezier.
2024-07-15 10:04:48 +02:00
Dario Sassi 21feed172d EgtGeomKernel :
- in CollisionAvoid corretto assegnamento riferimento (da fare prima del calcolo di hashgrids)
- in CalcPocketing corretti i punti che lasciavano memory leaks e migliorie stilistiche varie.
2024-07-15 07:08:11 +02:00
Riccardo Elitropi e853ff7f13 Aggiunto parametro per evitare casi ottimizzati 2024-07-12 20:09:04 +02:00
Riccardo Elitropi 95ff8b21b9 EgtGeomKernel :
- In CalcPocketing aggiunta funzione per Chain delle curve singole di svuotatura
- Inversione dei percorsi per lavorazione utensile
- Migliorati i controlli per le entrate da fuori.
2024-07-12 16:29:53 +02:00
Dario Sassi a7be952e11 EgtGeomKernel :
- in Pocketing, alla fine di CalcSpiral aggiunto reset dei TempProp delle curve componenti i percorsi risultanti.
2024-07-12 13:49:20 +02:00
Daniele Bariletti 7a67ce9333 Merge branch 'master' into MoreBezier 2024-07-12 12:07:26 +02:00
Daniele Bariletti 695350d3f6 EgtGeomKernel :
- correzione per evitare errori di triangolazione in prossimità dei poli in sup di Bezier.
2024-07-12 12:04:41 +02:00
Dario Sassi aade1d19f1 EgtGeomKernel :
- correzioni alle HashGrids per evitare problemi con memoria
- ottimizzazione calcolo CollisionAvoid con TestSeries e TestPath fatti di seguito
- piccole milgiorie a Pocketing.
2024-07-12 08:46:00 +02:00
Dario Sassi fd4677d099 EgtGeomKernel :
- piccola modifica in svuotature (tolto controllo di offset negativo).
2024-07-11 09:00:21 +02:00
Daniele Bariletti f7a28447fb EgtGeomKernel :
- correzione alla triangolazione delle bezier.
2024-07-10 16:41:34 +02:00
Daniele Bariletti 79b470b18b EgtGeomKernel :
- correzione alle rigate con Bezier.
2024-07-10 16:41:07 +02:00
Riccardo Elitropi f6d3873ecb EgtGeomKernel :
- In CalcPocketing, aggiunta inversione dei percorsi.
2024-07-10 12:35:20 +02:00
Riccardo Elitropi 92a8cdad99 EgtGeomKernel :
- in CalcPocketing aggiunto calcolo della Feed per percorsi a curva singola.
2024-07-10 10:24:23 +02:00
Daniele Bariletti 0c346e2bc7 Merge branch 'master' into MoreBezier 2024-07-10 08:53:12 +02:00
Daniele Bariletti d54caf4ae3 EgtGeomKernel :
- pulizia codice.
2024-07-10 08:52:47 +02:00
Dario Sassi ff9ea34ae1 EgtGeomKernel :
- in TestPosition di CollisionAvoid possibilità di restituire normale alla superficie nell'ultimo punto di contatto.
2024-07-09 16:48:54 +02:00
Daniele Bariletti c7035305e2 EgtGeomKernel :
- correzione alle rigate Bezier nella modalità MinDist.
2024-07-09 15:47:47 +02:00
Daniele Bariletti bc3c1e377e EgtGeomKernel :
- corretta la ruled con bezier in modalità MinDistPlus.
2024-07-09 13:04:48 +02:00
Riccardo Elitropi 98eff1b0b9 EgtGeomKernel :
- in CalcPocketing pulizia del codice e migliorie varie.
2024-07-09 11:10:49 +02:00
SaraP 052cc9e841 EgtGeomKernel 2.6g2 :
- aggiornamento versione.
2024-07-09 10:30:51 +02:00
SaraP b6a7ce4eef EgtGeomKernel :
- aggiunte funzioni che restituiscono il valore di offset che fa sparire una curva chiusa, una flat region o un suo chunk.
2024-07-09 10:25:24 +02:00
Daniele Bariletti 7a66ad27d8 EgtGeomKernel :
- correzioni alle rigate con le bezier.
2024-07-08 15:20:09 +02:00
Daniele Bariletti b4878f1ac0 EgtGeomKernel :
- correzioni e migliorie alle rigate con le bezier MINDISTPLUS.
2024-07-05 17:12:08 +02:00
Riccardo Elitropi 447ebe11e5 EgtGeomKernel :
- in calcolo pocketing, semplificate le curve di Feed e migliorata la gestione della superficie limite.
2024-07-04 16:43:44 +02:00
Dario Sassi 8981057d29 EgtGeomKernel :
- in calcolo pocketing piccole sistemazioni a salvataggio coefficiente feed (sempre in CurveTempParam).
2024-07-03 17:07:35 +02:00
Riccardo Elitropi 3270b573a8 EgtGeomKernel :
- in CalcPocketing aggiunte funzioni di Feed e migliorati i controlli sui lati aperti.
2024-07-03 13:23:52 +02:00
Daniele Bariletti 6df0cf3203 Merge branch 'master' into MoreBezier 2024-07-03 11:15:39 +02:00
Daniele Bariletti d67cca385e EgtGeomKernel :
- correzioni alle rigate con le Bezier.
2024-07-03 11:15:10 +02:00
SaraP f9d67442d6 EgtGeomKernel 2.6g1 :
- correzione offset nel caso di archi molto piccoli.
2024-07-01 10:54:37 +02:00
Dario Sassi dea96ccbcc EgtGeomKernel :
- miglioramenti a calcolo silhouette con CollisionAvoid compresa parallelizzazione
- piccole migliorie a CollisionAvoid
- migliorie e correzioni a CalcPocketing.
2024-06-29 18:45:19 +02:00
Dario Sassi 0f4be10330 EgtGeomKernel :
- in SurfTrimesh i metodi RemoveShell e RemovePart ora annullano i dati su shell e part per ricalcolarli quando richiesti.
2024-06-26 17:41:23 +02:00
Dario Sassi 121abf5864 EgtGeomKernel 2.6f4 :
- miglioramenti alla gestione di shell e part nelle superfici Trimesh.
2024-06-26 08:41:57 +02:00
Dario Sassi 38e836de2b Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-06-25 19:13:49 +02:00
Riccardo Elitropi 376c4e3693 EgtGeomKernel :
- In calcPocketing migliorate e semplificate le gestioni dei lati aperti, sia di bordi che di isole, anche con la superficie limite.
2024-06-25 13:29:23 +02:00
Dario Sassi 48ffd52b16 Merge commit '3e924113d3cf8134e84c53cf3f6b1d88c6ed1a7a' 2024-06-24 16:28:05 +02:00
Daniele Bariletti 9a16259ff5 EgtGeomKernel :
- correzione al miglioramento sul tempo di triangolazione delle bezier.
2024-06-20 12:52:03 +02:00
Daniele Bariletti 10ae269882 Merge branch 'master' into MoreBezier 2024-06-19 10:16:14 +02:00
Daniele Bariletti 9d845179a4 EgtGeomKernel :
- migliormaneto della velocità di calcolo per la triangolazione di superfici di Bezier.
- irrobustimento della stessa triangolazione.
2024-06-19 10:07:03 +02:00
Riccardo Elitropi 88bf84cca1 EgtGeomKernel :
- Aggiunta possibilità di entrate da isole aperte per CalcPocketing ( SpiralIN).
2024-06-18 11:15:44 +02:00
Riccardo Elitropi 5ba8f1df36 EgtGeomKernel :
- aggiunta gestione isole aperte.
2024-06-17 11:51:01 +02:00
Dario Sassi c4a05bcb2f EgtGeomKernel :
- miglioramenti al calcolo silhouette con CollisionAvoid
- modifiche a CollisionAvoid per permettere accelerazione con HashGrid anche a TestPosition.
2024-06-17 07:10:27 +02:00
Riccardo Elitropi 5841c9cae0 EgtGeomKernel :
- migliorie a CalcPocketing.
2024-06-14 16:46:56 +02:00
Dario Sassi 4fd03a78de EgtGeomKernel :
- correzione a calcolo silhouette con CAv di superficie trimesh (Level va tenuto costante nelle diverse funzioni).
2024-06-14 12:07:37 +02:00
Dario Sassi 420c072670 EgtGeomKernel :
- migliorie e sistemazioni in calcolo silhouette con CollisionAvoid.
2024-06-14 08:13:03 +02:00
SaraP 36477623b8 EgtGeomKernel :
- nel calcolo degli offset con Voronoi viene sempre eseguito l'offset sia a destra sia a sinistra ( per evitare problemi classificazione di vroni nel caso di cruve chiuse con piccole autointersezioni).
2024-06-13 09:51:43 +02:00
Dario Sassi 84d859dfe2 EgtGeomKernel :
- aggiunte funzioni per impostare e leggere TempProp e tempParam sulle curve di contorno delle Regioni.
2024-06-13 07:58:23 +02:00
Daniele Bariletti 09220bfd68 EgtGeomKernel :
- correzione all'utlima modifica alla triangolazione delle bezier.
2024-06-12 15:18:27 +02:00
Dario Sassi 42aaf6f3eb Merge commit '619905d72006d93976eff22ad76dc261e59a2790' 2024-06-12 13:29:26 +02:00
Dario Sassi 3f1f365451 EgtGeomKernel 2.6f3 :
- migliorie e irrobustimenti a calcolo silhouette di trimesh con collisio avoid.
2024-06-12 13:28:41 +02:00
Daniele Bariletti 9a29ee0e27 EgtGeomKernel :
- pulizia codice.
2024-06-12 09:19:28 +02:00
Daniele Bariletti 619905d720 EgtGeomKernel :
- correzione alla conversione di nurbs periodiche.
2024-06-11 16:05:53 +02:00
Daniele Bariletti 36ce855ef3 EgtGeomKernel :
- correzione alla conversione di nurbs periodiche.
2024-06-11 15:55:56 +02:00
Dario Sassi 9b0f2c7f59 EgtGeomKernel :
- aggiunta funzione e classe per calcolo silhouette tramite campionamento con utensile cilindrico
- in CollisionAvoid aggiunta funzione per verifica di insieme di punti (senza verifiche su intermedi).
2024-06-11 09:28:59 +02:00
Daniele Bariletti c637ccec47 EgtGeomKernel :
- aggiunta commento per triangolazione bezier.
2024-06-10 14:57:58 +02:00
Daniele Bariletti 8f27154604 EgtGeomKernel :
- correzione alla conversione di nurbs periodiche in bezier.
2024-06-10 14:57:28 +02:00
Dario Sassi 5d02732db6 EgtGeomKernel :
- correzione a Collision Avoid per utensile cilindrico che tocca vertice triangolo sul bordo
- in CalcPocketing tolti riferimenti a SafeZ e assegnato valore default a OpenMinSafe e a bAboveHead .
2024-06-07 18:59:26 +02:00
Daniele Bariletti 36657e17c4 EgtGeomKernel :
- correzione alla funzione per tagliare una sup di bezier con un piano.
2024-06-07 17:42:19 +02:00
Daniele Bariletti e2008bd479 EgtGeomKernel :
- correzione ulteriore alla triangolazione delle superfici bezier con patch con lati collassati.
2024-06-07 17:41:39 +02:00
Daniele Bariletti e32b85bc2d EgtGeomKernel :
- correzione alla triangolazione di sup. di Bezier con patch con lati collassati in un polo.
2024-06-07 16:00:24 +02:00
Dario Sassi 6dfc50e630 EgtGeomKernel 2.6f2 :
- in CAvToolSurfTm tolleranza negativa in Path vuol dire non controllare punto intermedio.
2024-06-07 13:02:07 +02:00
Riccardo Elitropi b4820ff255 EgtGeomKernel :
- piccole modifiche e migliorie a CalcPocketing.
2024-06-07 10:21:01 +02:00
Dario Sassi 515247a394 EgtGeomKernel :
- modifica a DistPointSurfTm per controllo tolleranza più efficace.
2024-06-06 17:43:26 +02:00
Dario Sassi b5c649821f Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-06-06 16:55:08 +02:00
Dario Sassi 9ba0c6f4cc EgtGeomKernel :
- miglioria nel calcolo silhouette di Trimesh.
2024-06-06 16:49:19 +02:00
Daniele Bariletti 35fc94d8cb Merge branch 'master' into MoreBezier 2024-06-06 09:21:18 +02:00
Daniele Bariletti a0316e280c EgtGeomKernel :
- piccola correzione.
2024-06-06 09:20:56 +02:00
Daniele Bariletti 84bcc715a8 EgtGeomKernel :
- piccola correzione di una tolleranza.
2024-06-06 09:16:53 +02:00
Daniele Bariletti b34d31029b EgtGeomKernel :
- piccola correzione.
2024-06-06 09:13:57 +02:00
Daniele Bariletti f67865f9cc EgtGeomKernel :
- piccola correzione di una tolleranza.
2024-06-06 09:12:47 +02:00
SaraP f48053a541 EgtGeomKernel :
- nelle booleane delle trimesh piccola modifica a DecomposeLoop.
2024-06-05 16:14:39 +02:00
Daniele Bariletti 8e917aa6d2 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2024-06-05 09:11:18 +02:00
Daniele Bariletti f08dee836b EgtGeomKernel :
- correzioni alla conversione da nurbs a bezier per curve e superfici.
2024-06-05 09:11:00 +02:00
Daniele Bariletti 261e9ac0c8 EgtGeomKernel :
- correzioni alla conversione da nurbs a bezier per curve e superfici.
2024-06-05 09:10:22 +02:00
Dario Sassi b51d0c3e64 EgtGeomKernel :
- miglioramento a GetArc3P (ora riconosciuto come retta anche quando il punto intermedio coincide con uno dei due estremi).
2024-06-04 19:07:58 +02:00
Daniele Bariletti ac23938dd0 Merge branch 'master' into MoreBezier 2024-06-04 09:57:54 +02:00
Daniele Bariletti b9bac347e8 EgtGeomKernel :
- correzione alla gestione della conversione di curve nurbs periodiche.
2024-06-03 17:34:41 +02:00
Daniele Bariletti 980a1f62df EgtGeomKernel :
- correzione alla gestione di curve nurbs periodiche da convertire in bezier.
2024-06-03 17:32:14 +02:00
Daniele Bariletti 10c5d0fffe EgtGeomKernel :
- correzione alla rigata minDist con superficie Bezier.
2024-06-03 17:31:33 +02:00
Daniele Bariletti d7d36b670a EgtGeomKernel :
- correzione alla triangolazione di span bilineari in superfici di grado superiore all'uno.
2024-06-03 17:30:05 +02:00
Riccardo Elitropi 581551ee3e Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-06-03 12:06:48 +02:00
Riccardo Elitropi 487ce0c84b EgtGeomKernel :
- correzione percorsi tra più Chunk per SpiralIn/Out.
2024-06-03 12:06:44 +02:00
SaraP 5679733028 EgtGeomKernel :
- nelle operazioni booleane delle trimesh rilassata tolleranza per calcolo catene coincidenti durante la ritriangolazione.
2024-06-03 11:49:10 +02:00
Dario Sassi cd0fc4e449 EgtGeomKernel :
- piccole modifiche a Pocketing.
2024-06-03 09:10:04 +02:00
Dario Sassi e20b4b5b78 EgtGeomKernel 2.6f1 :
- modifiche a pocketing.
2024-06-03 08:15:38 +02:00
Dario Sassi b931582120 Merge commit 'bf14ab1332d4e190a3c3c8d8d802fd07b889b98b' 2024-05-31 14:48:33 +02:00
Riccardo Elitropi bf14ab1332 EgtGeomKernel :
Modifiche a CalcPocketing
- rimozione variabili statiche
- aggiunti casi ottimizzati Spiral
- estensione superfici sui lati aperti.
2024-05-31 13:10:15 +02:00
Daniele Bariletti 3b81a6b92e EgtGeomKernel :
- aggiunta la ruled bezier che aggiunge punti alla curva con meno punti ( da migliorare con la parametrizzazione sulla curva totale).
2024-05-30 16:53:37 +02:00
Dario Sassi 01bf44cf1e EgtGeomKernel :
- correzione a chiusura composita formata da un solo arco (il nuovo angolo giro al centro deve avere lo steso segno del precedente).
2024-05-30 16:45:38 +02:00
Dario Sassi b5d879cd3d EgtGeomKernel :
- in creazione regioni aggiunta chiusura loops di sicurezza dopo aggiustamenti
- in curve composite corretta chiusura per caso di un solo arco.
2024-05-30 11:20:45 +02:00
Dario Sassi 2b3c285190 EgtGeomKernel :
- modifiche stilistiche.
2024-05-30 08:45:43 +02:00
Dario Sassi 99bb83211c EgtGeomKernel 2.6e6 :
- a TestPath di CAvToolSurfTm passato un parametro in più per indicare la frazione di progress al completamento dell'operazione.
2024-05-29 18:57:12 +02:00
Daniele Bariletti b854c9588b EgtGeomKernel :
- implementata la versione ruled Bezier con la modalità isoparametrica.
2024-05-29 17:22:09 +02:00
Daniele Bariletti 2361225321 EgtGeomKernel :
- aggiunte le chiamate per la creazione di una rigata come superficie di Bezier
- aggiunta la funzione per la creazione del cono come Bezier ( ancora da implementare).
2024-05-28 16:29:10 +02:00
Daniele Bariletti eaf1138624 EgtGeomKernel :
- aggiunte le funzioni per creare rigate come superfici di Bezier
- piccole modifiche.
2024-05-28 16:25:43 +02:00
Daniele Bariletti ef5c67a4d5 EgtGeomKernel :
- aggiunti commenti
- aggiunte modifiche da implementare ulteriormente per la trinagolazione delle sup bilineari.
2024-05-28 16:23:58 +02:00
Daniele Bariletti ffd714d069 EgtGeomKernel :
- cambiato il nome ad una funzione.
2024-05-24 12:13:25 +02:00
Daniele Bariletti dc082d495e EgtGeomKernel :
- aggiunta limitazione alla creazione di una surf bezier tramite revolve nel caso in cui la curva attraversi l'asse di rivoluzione.
2024-05-24 11:30:04 +02:00
Daniele Bariletti e8e57ff793 Merge remote-tracking branch 'origin/master' into MoreBezier 2024-05-23 13:14:07 +02:00
Daniele Bariletti 3e16c4b56c EgtGeomKernel :
- aggiunti dei commenti.
2024-05-23 11:11:14 +02:00
Daniele Bariletti 77d3fcc7af EgtGeomKernel :
- aggiunta la funzione per il revolve con superfici di Bezier.
2024-05-22 12:13:15 +02:00
Daniele Bariletti 7322bf5034 EgtGeomKernel :
- correzioni alle funzioni per cambiare di grado le curve bezier.
2024-05-22 12:12:29 +02:00
Daniele Bariletti d340505593 Merge branch 'master' into MoreBezier 2024-05-21 15:49:54 +02:00
Daniele Bariletti 247849d112 EgtGeomKernel :
- aggiunta la funzione per modificare un singolo peso ad una curva di Bezier.
- aggiunta la funzione per lo screwing con una superficie di Bezier.
- aggiunto un commento.
2024-05-21 15:42:57 +02:00
Daniele Bariletti 1d4bccac4b EgtGeomKernel :
- aggiunte le funzioni per creare superfici di Bezier da Region e da Screwing.
2024-05-13 11:34:36 +02:00
Daniele Bariletti cc7aa66904 EgtGeomKernel :
- spostata la funzione CalcRegionPolyLines.
2024-05-13 10:30:24 +02:00
Daniele Bariletti 303a270359 EgtGeomKernel :
- gestione grado e razionalità delle curve convertite in Bezier.
2024-05-13 10:27:45 +02:00
Daniele Bariletti 5f56152a8b EgtGeomKernel :
- aggiunte le funzioni per creare SurfBez da estrusione e da FlatContour.
2024-05-09 15:13:25 +02:00
Daniele Bariletti d6567e94c4 EgtGeomKernel :
- aggiunta funzione MakeRational per curve di Bezier
- aggiunta funzione per la conversione in Bezier di una ICurve.
2024-05-08 17:49:31 +02:00
Daniele Bariletti a3f05c41fe Merge branch 'master' into MoreBezier 2024-05-08 08:52:20 +02:00
Daniele Bariletti 3143c00729 EgtGeomKernel :
- aggiunte le funzioni ProjectCurveOnSurfBez e la sua versione estesa.
2024-05-07 14:50:23 +02:00
Daniele Bariletti 621bf93ee9 Merge branch 'master' into MoreBezier 2024-05-07 10:32:08 +02:00
87 changed files with 19224 additions and 5441 deletions
+2
View File
@@ -317,6 +317,8 @@ AdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst, bool bNeedSameProp)
pCrvCo->RemoveSmallDefects( 2 * LIN_TOL_MIN, ANG_TOL_STD_DEG, true) ;
// unisco eventuali tratti allineati
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, bNeedSameProp) ;
// richiudo i loop per sicurezza
pCrvCo->Close() ;
}
}
+2 -1
View File
@@ -134,7 +134,8 @@ GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd,
// calcolo arco non riuscito, se i punti sono allineati nel giusto verso per essere una retta
// verifico se i punti sono allineati nel giusto verso
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) {
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO ||
AreSamePointApprox( ptOther, ptStart) || AreSamePointApprox( ptEnd, ptOther)) {
// creo l'oggetto retta
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
if ( IsNull( pLine))
+8 -8
View File
@@ -133,22 +133,22 @@ Attribs::Load( NgeReader& ngeIn)
unsigned char ucLev ;
if ( ! ngeIn.ReadUchar( ucLev, ","))
return false ;
m_Data[LEVEL] = CLIP( ucLev, GDB_LV_USER, GDB_LV_TEMP) ;
m_Data[LEVEL] = Clamp( ucLev, GDB_LV_USER, GDB_LV_TEMP) ;
// modo
unsigned char ucMode ;
if ( ! ngeIn.ReadUchar( ucMode, ","))
return false ;
m_Data[MODE] = CLIP( ucMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
m_Data[MODE] = Clamp( ucMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
// stato (se SEL è convertito in ON)
unsigned char ucStat ;
if ( ! ngeIn.ReadUchar( ucStat, ","))
return false ;
m_Data[STATUS] = CLIP( ucStat, GDB_ST_OFF, GDB_ST_ON) ;
m_Data[STATUS] = Clamp( ucStat, GDB_ST_OFF, GDB_ST_ON) ;
// marcatura (sempre OFF)
unsigned char ucMark ;
if ( ! ngeIn.ReadUchar( ucMark, ";"))
return false ;
m_Data[MARK] = CLIP( ucMark, GDB_MK_OFF, GDB_MK_OFF) ;
m_Data[MARK] = Clamp( ucMark, GDB_MK_OFF, GDB_MK_OFF) ;
// materiale
if ( ! ngeIn.ReadInt( m_Material, ";"))
return false ;
@@ -185,22 +185,22 @@ Attribs::DataFromString( const string& sParam)
int nLev ;
if ( ! FromString( vsParams[0], nLev))
return false ;
m_Data[LEVEL] = CLIP( nLev, GDB_LV_USER, GDB_LV_TEMP) ;
m_Data[LEVEL] = Clamp( nLev, GDB_LV_USER, GDB_LV_TEMP) ;
// modo
int nMode ;
if ( ! FromString( vsParams[1], nMode))
return false ;
m_Data[MODE] = CLIP( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
m_Data[MODE] = Clamp( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
// stato (ammessi solo OFF e ON)
int nStat ;
if ( ! FromString( vsParams[2], nStat))
return false ;
m_Data[STATUS] = CLIP( nStat, GDB_ST_OFF, GDB_ST_ON) ;
m_Data[STATUS] = Clamp( nStat, GDB_ST_OFF, GDB_ST_ON) ;
// marcatura (ammesso solo OFF)
int nMark ;
if ( ! FromString( vsParams[3], nMark))
return false ;
m_Data[MARK] = CLIP( nMark, GDB_MK_OFF, GDB_MK_OFF) ;
m_Data[MARK] = Clamp( nMark, GDB_MK_OFF, GDB_MK_OFF) ;
return true ;
}
+6 -8
View File
@@ -16,14 +16,12 @@
#include "/EgtDev/Include/EGkGdbConst.h"
#include "/EgtDev/Include/EGkColor.h"
#include "/EgtDev/Include/EgtStringBase.h"
#include "/EgtDev/Include/EgtNumUtils.h"
class NgeWriter ;
class NgeReader ;
class GeomDB ;
//----------------------------------------------------------------------------
#define CLIP( nV, nMIN, nMAX) (( nV < nMIN) ? nMIN : (( nV > nMAX) ? nMAX : nV))
//----------------------------------------------------------------------------
class Attribs
{
@@ -46,14 +44,14 @@ class Attribs
bool Load( NgeReader& ngeIn) ;
void SetLevel( int nLev)
{ m_OldData[LEVEL] = m_Data[LEVEL] ;
m_Data[LEVEL] = CLIP( nLev, GDB_LV_USER, GDB_LV_TEMP) ; }
m_Data[LEVEL] = Clamp( nLev, GDB_LV_USER, GDB_LV_TEMP) ; }
void RevertLevel( void)
{ std::swap( m_Data[LEVEL], m_OldData[LEVEL]) ; }
int GetLevel( void) const
{ return m_Data[LEVEL] ; }
void SetMode( int nMode)
{ m_OldData[MODE] = m_Data[MODE] ;
m_Data[MODE] = CLIP( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ; }
m_Data[MODE] = Clamp( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ; }
void RevertMode( void)
{ std::swap( m_Data[MODE], m_OldData[MODE]) ; }
int GetMode( void) const
@@ -61,13 +59,13 @@ class Attribs
void SetStatus( int nStat)
{ if ( m_Data[STATUS] != GDB_ST_SEL)
m_OldData[STATUS] = m_Data[STATUS] ;
m_Data[STATUS] = CLIP( nStat, GDB_ST_OFF, GDB_ST_SEL) ; }
m_Data[STATUS] = Clamp( nStat, GDB_ST_OFF, GDB_ST_SEL) ; }
void RevertStatus( void)
{ SetStatus( m_OldData[STATUS]) ; }
int GetStatus( void) const
{ return m_Data[STATUS] ; }
void SetMark( void)
{ m_Data[MARK] = GDB_MK_ON ; }
void SetMark( int nMark)
{ m_Data[MARK] = Clamp( nMark, GDB_MK_OFF, GDB_MK_ON_2) ; }
void ResetMark( void)
{ m_Data[MARK] = GDB_MK_OFF ; }
int GetMark( void) const
+9 -6
View File
@@ -83,7 +83,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
//----------------------------------------------------------------------------
ICurve*
GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
const PolyLine& PL, double& dDist)
const PolyLine& PL, double& dDist, double dTol)
{
// calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco
PtrOwner<ICurve> pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ;
@@ -122,7 +122,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
}
}
}
// non c'è intersezione, assegno valore medio
// non c'è intersezione, assegno valore medio
if ( dU < -0.5)
dU = 0.5 ;
// elimino casi vicino agli estremi, danno solo problemi
@@ -142,7 +142,10 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
Point3d ptPrev = ptCurr ;
while ( bPnt) {
double dLen = Dist( ptCurr, ptPrev) ;
int nStep = ( dLen < STEP ? 2 : 1) * int( dLen / STEP) + 1 ;
int nStep = int( dLen / STEP) + 1 ;
int nMinStep = ( dLen > 50 * dTol ? 3 : ( dLen > 10 * dTol ? 2 : 1)) ;
int nMaxStep = 10 ;
nStep = Clamp( nStep, nMinStep, nMaxStep) ;
for ( int i = 1 ; i <= nStep ; ++ i) {
double dCoeff = double( i) / nStep ;
Point3d ptP = Media( ptPrev, ptCurr, dCoeff) ;
@@ -163,7 +166,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
static ICurve*
CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg)
{
// se i due punti coincidono, non si può fare alcunché
// se i due punti coincidono, non si può fare alcunché
if ( AreSamePointApprox( ptP0, ptP1))
return nullptr ;
@@ -205,14 +208,14 @@ CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dD
double dDir0RelDeg = DiffAngle( dDir0Deg, dDirDiffDeg) ;
// direzione iniziale secondo arco limite rispetto a direzione P0->P1 (dalla finale simmetrico e invert)
double dDir1RelDeg = - DiffAngle( dDir1Deg, dDirDiffDeg) ;
// nel caso di direzioni a 180deg si sceglie la più compatta
// nel caso di direzioni a 180deg si sceglie la più compatta
if ( abs( abs( dDir1RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
dDir1RelDeg = ( dDir0RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
else if ( abs( abs( dDir0RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
dDir0RelDeg = ( dDir1RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
// intervallo angolare ammissibile a partire da direzione iniziale primo arco ammissibile ( == Dir0)
double dDeltaAngDeg = - dDir0RelDeg + dDir1RelDeg ;
// se non è nella regione, prendo l'altra parte di arco
// se non è nella regione, prendo l'altra parte di arco
if ( ! AngleInSpan( dDirStartRelDeg, dDir0RelDeg, dDeltaAngDeg))
pArc->ToExplementary() ;
// inverto per avere parametrizzazione crescente allontanandosi da Dir0 e avvicinandosi a Dir1
+1 -1
View File
@@ -17,5 +17,5 @@
//-----------------------------------------------------------------------------
ICurve* GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
const PolyLine& PL, double& dDist) ;
const PolyLine& PL, double& dDist, double dTol) ;
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : CAvSilhouetteSurfTm.h Data : 16.06.24 Versione : 2.6f2
// Contenuto : Dichiarazione della classe calcolo multi-silhouette.
//
//
//
// Modifiche : 10.06.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "CAvToolSurfTm.h"
#include "SurfFlatRegion.h"
#include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h"
//-----------------------------------------------------------------------------
class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm
{
public :
// generica
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol) override ;
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol,
double dSideAng, double dDiam, double dCornRad, double dMaxMat, double dOffsR,
double dMaxDepth) override ;
bool GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) override ;
public :
CAvParSilhouettesSurfTm( void) ;
private :
bool Prepare( void) ;
private :
CISURFTMPVECTOR m_vpStm ;
CAvToolSurfTm m_cavTstm ;
Frame3d m_frGrid ;
double m_dTol ;
double m_dSharpedTol ;
int m_nStepX ;
int m_nStepY ;
double m_dRad ;
double m_dCornRad ;
double m_dMaxMat ;
double m_dSideAng ;
double m_dOffsR ;
double m_dDimZ ;
double m_dLevelOffs ;
double m_dMaxDepth ;
bool m_bGridOk ;
bool m_bTool ;
DBLVECTOR m_vdGrid ;
} ;
+518 -54
View File
@@ -1,13 +1,13 @@
//----------------------------------------------------------------------------
// EgalTech 2018-2018
// EgalTech 2018-2024
//----------------------------------------------------------------------------
// File : CAvToolSurfTm.cpp Data : 08.05.18 Versione : 1.9e2
// File : CAvToolSurfTm.cpp Data : 07.06.24 Versione : 2.6f2
// Contenuto : Implementazione della classe CAvToolSurfTm.
//
//
//
// Modifiche : 27.04.18 DS Creazione modulo.
//
// 07.06.24 DS Con tolleranza lineare negativa non si controlla il punto medio.
//
//----------------------------------------------------------------------------
@@ -24,6 +24,7 @@ using namespace std ;
//----------------------------------------------------------------------------
const int STEP_PE = 50 ;
const double MAX_MOVE = 20000 ;
//----------------------------------------------------------------------------
ICAvToolSurfTm*
@@ -37,10 +38,29 @@ CreateCAvToolSurfTm( void)
// CAvToolSurfTm
//----------------------------------------------------------------------------
CAvToolSurfTm::CAvToolSurfTm( void)
: m_Tool( false)
: m_frMove( false), m_Tool( false)
{
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::Clear( void)
{
// pulisco la lista dei puntatori a Stm
m_vSTM.clear() ;
// pulisco e inizializzo la prima posizione della lista delle basi per gli indici dei triangoli
m_vBaseInd.clear() ;
m_vBaseInd.emplace_back( 0) ;
// pulisco HashGrid 2d
m_HGrids.Clear() ;
// reset utensile
m_Tool.Clear() ;
// reset riferimento
m_frMove.Reset( false) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
@@ -50,6 +70,9 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
// pulisco e inizializzo la prima posizione della lista delle basi per gli indici dei triangoli
m_vBaseInd.clear() ;
m_vBaseInd.emplace_back( 0) ;
// pulisco HashGrid 2d
m_HGrids.Clear() ;
// non tocco l'utensile
// aggiungo la superficie
return AddSurfTm( Stm) ;
}
@@ -58,7 +81,7 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
bool
CAvToolSurfTm::AddSurfTm( const ISurfTriMesh& Stm)
{
// verifico validità superficie
// verifico validità superficie
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &Stm) ;
if ( pStm == nullptr || ! pStm->IsValid())
return false ;
@@ -99,7 +122,8 @@ CAvToolSurfTm::SetGenTool( const ICurveComposite* pToolOutline)
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist)
CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
double& dTotDist, Vector3d* pvtTriaN) const
{
// Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF)
@@ -107,20 +131,78 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Imposto il riferimento di movimento
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
m_frMove.Set( ORIG, vtMove, vtDir) ;
else
m_frMove.Set( ORIG, vtMove) ;
// Eseguo controllo
// Se riferimento di movimento già presente
if ( m_frMove.IsValid()) {
// Calcolo nuovo riferimento di movimento
Frame3d frMove ;
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
frMove.Set( ORIG, vtMove, vtDir) ;
else
frMove.Set( ORIG, vtMove) ;
// Se riferimenti di movimento uguali, sfrutto HashGrid 2d
if ( AreSameFrame( frMove, m_frMove)) {
// Eseguo controllo
Point3d ptCurr = ptT ;
Vector3d vtTriaN ;
dTotDist = MyTestPositionHG( ptCurr, vtDir, vtTriaN) ;
if ( pvtTriaN != nullptr)
*pvtTriaN = vtTriaN ;
return ( dTotDist > - EPS_SMALL) ;
}
}
// Altrimenti eseguo controllo diretto
Point3d ptCurr = ptT ;
dTotDist = MyTestPosition( ptCurr, vtDir) ;
Vector3d vtTriaN ;
dTotDist = MyTestPosition( ptCurr, vtDir, vtMove, vtTriaN) ;
if ( pvtTriaN != nullptr)
*pvtTriaN = vtTriaN ;
return ( dTotDist > - EPS_SMALL) ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol)
CAvToolSurfTm::TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
double& dTotDist, VCT3DVECTOR& vVtN) const
{
// Funzione per calcolo collisione tra utensile e superfici ;
// dToTDist è la distanza di traslazione del punto ptT lungo vtDir per evitare la collisione,
// vVtN è la normale del triangolo che genera collsione ( NB. Nel caso di più triangoli concorrenti,
// vengono restituite tutte le normali trovate)
// Inizializzazione parametri
dTotDist = 0 ;
vVtN.clear() ;
// Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF)
return false ;
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Se riferimento di movimento già presente
if ( m_frMove.IsValid()) {
// Calcolo nuovo riferimento di movimento
Frame3d frMove ;
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
frMove.Set( ORIG, vtMove, vtDir) ;
else
frMove.Set( ORIG, vtMove) ;
// Se riferimenti di movimento uguali, sfrutto HashGrid 2d
if ( AreSameFrame( frMove, m_frMove)) {
// Eseguo controllo
Point3d ptCurr = ptT ;
dTotDist = MyTestPositionHGAdv( ptCurr, vtDir, vVtN) ;
return ( dTotDist > - EPS_SMALL) ;
}
}
// Altrimenti eseguo controllo diretto
Point3d ptCurr = ptT ;
dTotDist = MyTestPositionAdv( ptCurr, vtDir, vtMove, vVtN) ;
return ( dTotDist > - EPS_SMALL) ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
{
// Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF)
@@ -128,17 +210,139 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Se lista vuota, non devo fare alcunché
// Se vettore vuoto, non devo fare alcunché
if ( vPntM.empty())
return true ;
// Calcolo nuovo riferimento di movimento
Frame3d frMove ;
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
frMove.Set( ORIG, vtMove, vtDir) ;
else
frMove.Set( ORIG, vtMove) ;
// Se riferimento di movimento non presente o diverso dal calcolato
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
// Salvo nuovo riferimento
m_frMove = frMove ;
// Ricalcolo HashGrid
if ( ! PrepareHashGrid())
return false ;
}
// Determino il numero di punti dell'insieme
m_nTotPnt = int( vPntM.size()) ;
// Recupero il numero massimo di thread concorrenti
int nThreadMax = thread::hardware_concurrency() ;
bool bOk = true ;
// Se un solo thread o pochi punti
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
m_nCurrPnt = 0 ;
bOk = TestSubSeries( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ;
ProcessEvents( int( 100 * dProgCoeff), 0) ;
}
// altrimenti
else {
const int MAX_PARTS = 32 ;
INTINTVECTOR vFstLst( MAX_PARTS) ;
// calcolo le parti del vettore
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
int nPartDim = m_nTotPnt / nPartCnt + 1 ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
vFstLst[i].first = i * nPartDim ;
vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ;
}
// processo le parti
m_nCurrPnt = 0 ;
m_bBreak = false ;
future<bool> vRes[MAX_PARTS] ;
for ( int i = 0 ; i < nPartCnt ; ++ i)
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeries, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ;
// attendo i risultati
int nFin = 0 ;
int nNextPE = 0 ;
while ( nFin < nPartCnt) {
for ( int i = 0 ; i < nPartCnt ; ++ i) {
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
bOk = vRes[i].get() && bOk ;
++ nFin ;
}
}
if ( m_nCurrPnt > nNextPE) {
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
nNextPE += STEP_PE ;
if ( nRes == 1)
m_bBreak = true ;
}
}
ProcessEvents( int( 100 * dProgCoeff), 0) ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
{
// Se vettore vuoto, non devo fare alcunché
if ( vPntM.empty())
return true ;
// Ciclo sui punti da verificare
for ( int i = nFirst ; i <= nLast ; ++ i) {
// verifico il punto
Vector3d vtTriaN ;
double dMove = MyTestPositionHG( vPntM[i].first, vtDir, vtTriaN) ;
vPntM[i].second = dMove ;
if ( dMove < - EPS_SMALL)
return false ;
++ m_nCurrPnt ;
// se singolo thread
if ( nId == -1) {
// gestione eventi (ogni STEP_PE punti)
if (( m_nCurrPnt % STEP_PE) == 0) {
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
if ( nRes == 1)
return false ;
}
}
// altrimenti multithread
else {
if ( m_bBreak)
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff)
{
// Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF)
return false ;
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Se lista vuota, non devo fare alcunché
if ( lPntM.empty())
return true ;
// Imposto il riferimento di movimento
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
m_frMove.Set( ORIG, vtMove, vtDir) ;
// Controllo la tolleranza lineare (se negativa non vanno fatti controlli sui punti medi)
if ( dLinTol > -EPS_ZERO)
dLinTol = max( dLinTol, EPS_SMALL) ;
else
m_frMove.Set( ORIG, vtMove) ;
// Predispongo Hash Grid
if ( ! PrepareHashGrid())
return false ;
dLinTol = -1 ;
// Calcolo nuovo riferimento di movimento
Frame3d frMove ;
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
frMove.Set( ORIG, vtMove, vtDir) ;
else
frMove.Set( ORIG, vtMove) ;
// Se riferimento di movimento non presente o diverso dal calcolato
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
// Salvo nuovo riferimento
m_frMove = frMove ;
// Ricalcolo HashGrid
if ( ! PrepareHashGrid())
return false ;
}
// Determino il numero di punti del path
m_nTotPnt = int( lPntM.size()) ;
// Recupero il numero massimo di thread concorrenti
@@ -146,8 +350,9 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
bool bOk = true ;
// Se un solo thread o pochi punti
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
bOk = TestSubPath( -1, lPntM, vtDir, dLinTol) ;
ProcessEvents( 100, 0) ;
m_nCurrPnt = 0 ;
bOk = TestSubPath( -1, lPntM, vtDir, dLinTol, dProgCoeff) ;
ProcessEvents( int( 100 * dProgCoeff), 0) ;
}
// altrimenti
else {
@@ -167,7 +372,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
m_bBreak = false ;
future<bool> vRes[MAX_PARTS] ;
for ( int i = 0 ; i < nPartCnt ; ++ i)
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPath, this, i, ref( vlPntM[i]), cref( vtDir), dLinTol) ;
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPath, this, i, ref( vlPntM[i]), cref( vtDir), dLinTol, dProgCoeff) ;
// attendo i risultati
int nFin = 0 ;
int nNextPE = 0 ;
@@ -179,7 +384,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
}
}
if ( m_nCurrPnt > nNextPE) {
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt), 10) ;
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
nNextPE += STEP_PE ;
if ( nRes == 1)
m_bBreak = true ;
@@ -191,18 +396,98 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
lPntM.pop_back() ;
lPntM.splice( lPntM.end(), vlPntM[i]) ;
}
ProcessEvents( 100, 0) ;
ProcessEvents( int( 100 * dProgCoeff), 0) ;
}
// pulisco HashGrid 2d
m_HGrids.Clear() ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol)
CAvToolSurfTm::TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
{
// Se lista vuota, non devo fare alcunché
// NB. la posizione del punto non viene modificata :
// get<0> vPntM[i] è il punto su cui viene posizionata la testa dell'utensile ( const)
// get<1> vPntM[i] è il parametro di traslazione del punto lungo vtDir per evitare collisioni con i triangoli
// get<2> vPntM[i] è un vettore di Vector3d contenente tutte le normali di tangenza ( a meno di 10 * EPS_SMALL)
// Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF)
return false ;
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Se vettore vuoto, non devo fare alcunché
if ( vPntM.empty())
return true ;
// Calcolo nuovo riferimento di movimento
Frame3d frMove ;
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
frMove.Set( ORIG, vtMove, vtDir) ;
else
frMove.Set( ORIG, vtMove) ;
// Se riferimento di movimento non presente o diverso dal calcolato
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
// Salvo nuovo riferimento
m_frMove = frMove ;
// Ricalcolo HashGrid
if ( ! PrepareHashGrid())
return false ;
}
// Determino il numero di punti del path
m_nTotPnt = int( vPntM.size()) ;
// Recupero il numero massimo di thread concorrenti
int nThreadMax = thread::hardware_concurrency() ;
bool bOk = true ;
// Se un solo thread o pochi punti
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
m_nCurrPnt = 0 ;
bOk = TestSubSeriesAdv( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ;
ProcessEvents( int( 100 * dProgCoeff), 0) ;
}
// altrimenti
else {
const int MAX_PARTS = 32 ;
INTINTVECTOR vFstLst( MAX_PARTS) ;
// calcolo le parti del vettore
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
int nPartDim = m_nTotPnt / nPartCnt + 1 ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
vFstLst[i].first = i * nPartDim ;
vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ;
}
// processo le parti
m_nCurrPnt = 0 ;
m_bBreak = false ;
future<bool> vRes[MAX_PARTS] ;
for ( int i = 0 ; i < nPartCnt ; ++ i)
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeriesAdv, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ;
// attendo i risultati
int nFin = 0 ;
int nNextPE = 0 ;
while ( nFin < nPartCnt) {
for ( int i = 0 ; i < nPartCnt ; ++ i) {
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
bOk = vRes[i].get() && bOk ;
++ nFin ;
}
}
if ( m_nCurrPnt > nNextPE) {
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
nNextPE += STEP_PE ;
if ( nRes == 1)
m_bBreak = true ;
}
}
ProcessEvents( int( 100 * dProgCoeff), 0) ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff)
{
// Se lista vuota, non devo fare alcunché
if ( lPntM.empty())
return true ;
// Ciclo sui punti
@@ -212,12 +497,13 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
while ( itPntMCurr != lPntM.end()) {
// verifico il punto
ptCurr = itPntMCurr->first ;
double dMove = MyTestPositionHG( itPntMCurr->first, vtDir) ;
itPntMCurr->second = - dMove ;
Vector3d vtTriaN ;
double dMove = MyTestPositionHG( itPntMCurr->first, vtDir, vtTriaN) ;
itPntMCurr->second = dMove ;
if ( dMove < - EPS_SMALL)
return false ;
// se esiste il punto precedente devo verificare il medio
if ( itPntMPrev != lPntM.end()) {
// se esiste il punto precedente e richiesto devo verificare il medio
if ( itPntMPrev != lPntM.end() && dLinTol > 0) {
MyTestMidPointHG( lPntM, itPntMPrev, itPntMCurr, ptPrev, ptCurr, vtDir, dLinTol, 1) ;
}
// passo al successivo
@@ -229,7 +515,7 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
if ( nId == -1) {
// gestione eventi (ogni STEP_PE punti)
if (( m_nCurrPnt % STEP_PE) == 0) {
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt), 0) ;
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
if ( nRes == 1)
return false ;
}
@@ -243,10 +529,44 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
return true ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
{
// Se vettore vuoto, non devo fare alcunché
if ( vPntM.empty())
return true ;
// Ciclo sui punti da verificare
for ( int i = nFirst ; i <= nLast ; ++ i) {
// verifico il punto
Point3d ptCurr = get<0>( vPntM[i]) ;
get<1>( vPntM[i]) = MyTestPositionHGAdv( ptCurr, vtDir, get<2>( vPntM[i])) ;
if ( get<1>( vPntM[i]) < - EPS_SMALL)
return false ;
++ m_nCurrPnt ;
// se singolo thread
if ( nId == -1) {
// gestione eventi (ogni STEP_PE punti)
if (( m_nCurrPnt % STEP_PE) == 0) {
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
if ( nRes == 1)
return false ;
}
}
// altrimenti multithread
else {
if ( m_bBreak)
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev)
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const
{
// se superato limite di ricursione, esco
const int MAX_LEV = 10 ;
@@ -256,7 +576,8 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
Point3d ptMid = Media( ptPrev, ptCurr, 0.5) ;
// ne effettuo la correzione per evitare la collisione
Point3d ptNewMid = ptMid ;
double dMidMove = MyTestPositionHG( ptNewMid, vtDir) ;
Vector3d vtTriaN ;
double dMidMove = MyTestPositionHG( ptNewMid, vtDir, vtTriaN) ;
if ( dMidMove < - EPS_SMALL)
return false ;
// massima distanza ammissibile
@@ -265,7 +586,7 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
if ( abs(( Media( itPntMPrev->first, itPntMCurr->first, 0.5) - ptNewMid) * m_frMove.VersZ()) > 0.5 * dLinTol ||
SqDist( itPntMPrev->first, itPntMCurr->first) > dMaxSqDist) {
// aggiungo
lPntM.emplace( itPntMCurr, ptNewMid, - dMidMove) ;
lPntM.emplace( itPntMCurr, ptNewMid, dMidMove) ;
auto itPntMMid = itPntMCurr ;
-- itPntMMid ;
// verifico intervallo precedente
@@ -278,20 +599,48 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
//----------------------------------------------------------------------------
double
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir)
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const
{
// box dell'utensile con suo movimento
BBox3d b3Tool ;
// utensile
b3Tool.Add( ptT) ;
b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ;
if ( vtDir.IsX())
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
else if ( vtDir.IsY())
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
else if ( vtDir.IsZ())
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
else {
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ;
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ;
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ;
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
}
// aggiungo movimento
BBox3d b3Moved = b3Tool ;
b3Moved.Translate( MAX_MOVE * vtMove) ;
b3Tool.Add( b3Moved) ;
// determino movimento minimo per evitare collisione con superfici
double dTotDist = 0 ;
vtTriaN = V_NULL ;
for ( auto pStm : m_vSTM) {
Triangle3d Tria ;
for ( int nTria = pStm->GetFirstTriangle( Tria) ;
nTria != SVT_NULL ;
nTria = pStm->GetNextTriangle( nTria, Tria)) {
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ;
if ( dDist < - EPS_SMALL)
return -1 ;
if ( dDist > EPS_SMALL) {
dTotDist += dDist ;
ptT += dDist * m_frMove.VersZ() ;
INTVECTOR vTria ;
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
for ( int nTria : vTria) {
Triangle3d Tria ;
if ( pStm->GetTriangle( nTria, Tria)) {
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
if ( dDist < - EPS_SMALL)
return -1 ;
if ( dDist > EPS_SMALL) {
dTotDist += dDist ;
ptT += dDist * vtMove ;
vtTriaN = Tria.GetN() ;
}
}
}
}
}
@@ -300,7 +649,61 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir)
//----------------------------------------------------------------------------
double
CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
CAvToolSurfTm::MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const
{
// box dell'utensile con suo movimento
BBox3d b3Tool ;
// utensile
b3Tool.Add( ptT) ;
b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ;
if ( vtDir.IsX())
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
else if ( vtDir.IsY())
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
else if ( vtDir.IsZ())
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
else {
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ;
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ;
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ;
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
}
// aggiungo movimento
BBox3d b3Moved = b3Tool ;
b3Moved.Translate( MAX_MOVE * vtMove) ;
b3Tool.Add( b3Moved) ;
// determino movimento minimo per evitare collisione con superfici
double dTotDist = 0 ;
vVtTriaN.clear() ;
for ( auto pStm : m_vSTM) {
INTVECTOR vTria ;
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
for ( int nTria : vTria) {
Triangle3d Tria ;
if ( pStm->GetTriangle( nTria, Tria)) {
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
if ( dDist < - EPS_SMALL)
return -1 ;
// se devo traslare il punto, c'è collisione
if ( dDist > EPS_SMALL) {
if ( dDist > 10 * EPS_SMALL) {
vVtTriaN.clear() ;
dTotDist += dDist ;
ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ;
}
vVtTriaN.push_back( Tria.GetN()) ;
}
}
}
}
}
return dTotDist ;
}
//----------------------------------------------------------------------------
double
CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const
{
// calcolo box utensile nel riferimento di movimento
BBox3d b3Tool ;
@@ -320,8 +723,10 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
}
// ciclo sui triangoli che intersecano box in 2d
// ciclo sui triangoli che intersecano box in 2d
double dTotDist = 0 ;
vtTriaN = V_NULL ;
INTVECTOR vnIds ;
if ( m_HGrids.Find( b3Tool, vnIds)) {
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
@@ -337,11 +742,70 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
if ( dDist > EPS_SMALL) {
dTotDist += dDist ;
ptT += dDist * m_frMove.VersZ() ;
vtTriaN = Tria.GetN() ;
}
else if ( dDist < -EPS_SMALL)
return -1 ;
}
}
return dTotDist ;
}
//----------------------------------------------------------------------------
double
CAvToolSurfTm::MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const
{
// calcolo box utensile nel riferimento di movimento
BBox3d b3Tool ;
Point3d ptTL = ptT ; ptTL.ToLoc( m_frMove) ;
Vector3d vtDirL = vtDir ; vtDirL.ToLoc( m_frMove) ;
b3Tool.Add( ptTL) ;
b3Tool.Add( ptTL - vtDirL * m_Tool.GetHeigth()) ;
if ( vtDirL.IsX())
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
else if ( vtDirL.IsY())
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
else if ( vtDirL.IsZ())
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
else {
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDirL.x * vtDirL.x) ;
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDirL.y * vtDirL.y) ;
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
}
// ciclo sui triangoli che intersecano box in 2d
double dTotDist = 0. ;
INTVECTOR vnIds ;
if ( m_HGrids.Find( b3Tool, vnIds)) {
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
// recupero la superficie
int nInd = vnIds[i] ;
int nSurf = GetSurfInd( nInd) ;
if ( nSurf == -1)
return -1 ;
// recupero il triangolo
int nT = nInd - m_vBaseInd[nSurf] ;
Triangle3d Tria ;
if ( ! m_vSTM[nSurf]->GetTriangle( nT, Tria))
return -1 ;
// calcolo della collisione
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ;
if ( dDist < - EPS_SMALL)
return -1 ;
// se devo traslare il punto, c'è collisione
if ( dDist > EPS_SMALL) {
if ( dDist > 10 * EPS_SMALL) {
vVtTriaN.clear() ;
dTotDist += dDist ;
ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ;
}
vVtTriaN.push_back( Tria.GetN()) ;
}
}
}
return dTotDist ;
}
@@ -352,7 +816,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
// pulisco HashGrid 2d
m_HGrids.Clear() ;
// verifico esistenza superfici
if ( m_vSTM.size() == 0 || m_vBaseInd.size() < m_vSTM.size() + 1)
if ( m_vSTM.empty() || m_vBaseInd.size() < m_vSTM.size() + 1)
return false ;
// creo HashGrid 2d
const int LIM_HG_TRIA = 256 ;
@@ -379,7 +843,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
//----------------------------------------------------------------------------
int
CAvToolSurfTm::GetSurfInd( int nT)
CAvToolSurfTm::GetSurfInd( int nT) const
{
// verifico la presenza di almeno un intervallo
if ( m_vBaseInd.size() < 2)
+32 -7
View File
@@ -34,22 +34,47 @@ class CAvToolSurfTm : public ICAvToolSurfTm
{ return m_Tool.GetRadius() ; }
double GetToolHeight( void) const override
{ return m_Tool.GetHeigth() ; }
double GetToolTipHeight( void) const override
{ return m_Tool.GetTipHeigth() ; } ;
double GetToolTipRadius( void) const override
{ return m_Tool.GetTipRadius() ; } ;
double GetToolCornRadius( void) const override
{ return m_Tool.GetCornRadius() ; } ;
CISURFTMPVECTOR GetvStm( void) const {
CISURFTMPVECTOR vcStm ;
for ( int i = 0 ; i < int( m_vSTM.size()) ; ++ i)
vcStm.emplace_back( CloneSurfTriMesh( m_vSTM[i])) ;
return vcStm ;
}
const ICurveComposite& GetToolOutline( bool bApprox = false) const override
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist) override ;
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol) override ;
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
double& dTotDist, Vector3d* pvtTriaN = nullptr) const override ;
bool TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
double& dTotDist, VCT3DVECTOR& vVtN) const override ;
bool TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ;
bool TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ;
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff = 1) override ;
public :
CAvToolSurfTm( void) ;
bool Clear( void) ;
private :
bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol) ;
double MyTestPosition( Point3d& ptT, const Vector3d& vtDir) ;
double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) ;
bool TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
bool TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff) ;
double MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const ;
double MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const ;
double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const ;
double MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const ;
bool MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) ;
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const ;
bool PrepareHashGrid( void) ;
int GetSurfInd( int nT) ;
int GetSurfInd( int nT) const ;
private :
typedef std::vector<const SurfTriMesh*> CSURFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh
+1 -1
View File
@@ -2503,7 +2503,7 @@ DiskSegmentEscapeDistLongMot( const Point3d& ptDiskCen, double dDiskRad,
double dSegDist = 0. ;
for ( int nSol = 0 ; nSol < nRoot ; ++ nSol) {
// Soluzione interna al segmento
if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen) {
if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen + EPS_ZERO) {
Point3d ptC = ptSeg + vdRoots[nSol] * vtSeg ;
// Distanza del punto soluzione dal piano del disco nella posizione iniziale
double dCurDist = PointPlaneSignedDist( ptC, ptDiskCen, vtMove) ;
+7384 -1646
View File
File diff suppressed because it is too large Load Diff
+26 -23
View File
@@ -2,7 +2,7 @@
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : ChainCurves.cpp Data : 20.07.14 Versione : 1.5g3
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
// curve composite a partire dalle curve date.
//
//
@@ -43,10 +43,10 @@ bool
ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
const Point3d& ptEnd, const Vector3d& vtEnd)
{
// verifico validità Id
// verifico validità Id
if ( nId <= 0)
return false ;
// verifico non sia già stata aggiunta la stessa entità
// verifico non sia già stata aggiunta la stessa entità
if ( ! m_sCrvId.insert( nId).second)
return true ;
// inserisco i dati della curva nel vettore
@@ -68,7 +68,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
m_bIsFork = false ;
m_vFork.clear() ;
// recupero l'entità più vicina al punto di start
// recupero l'entità più vicina al punto di start
int nStart ;
INTVECTOR vStart ;
if ( ! m_PointGrid.FindNearest( ptStart, vStart) ||
@@ -82,7 +82,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
// tolgo dal grid
RemoveEntityFromGrid( nId) ;
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
bool bSkip = false ;
if ( bHaltOnFork) {
auto iIter = GetForkPoint( m_vCrvData[nId].ptEnd) ;
@@ -93,7 +93,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
}
}
// concateno dopo la fine dell'entità di partenza
// concateno dopo la fine dell'entità di partenza
INTVECTOR vIdsAfter ;
bool bClosed = false ;
if ( ! bSkip && ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd,
@@ -102,7 +102,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
return false ;
}
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
bool bRevSkip = false ;
if ( bHaltOnFork) {
auto iIter = GetForkPoint( m_vCrvData[nId].ptStart) ;
@@ -113,7 +113,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
}
}
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
INTVECTOR vIdsBefore ;
if ( ! bClosed) {
bool bRevClosed ;
@@ -258,7 +258,7 @@ ChainCurves::RemoveEntityFromGrid( int nId)
bool
ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& nStart)
{
// numero di entità candidate
// numero di entità candidate
int nSize = int( vStart.size()) ;
// se nessuna, errore
@@ -273,7 +273,7 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
// altrimenti, cerco la migliore
int nI = - 1 ;
double dSqDistMin = SQ_INFINITO ;
double dDistMin = INFINITO ;
for ( int i = 0 ; i < nSize ; ++ i) {
// recupero indice e verso
int nId = abs( vStart[i]) - 1 ;
@@ -281,9 +281,12 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
// calcolo un punto vicino all'estremo lungo la tangente
Point3d ptNear = ( bEquiv ? m_vCrvData[nId].ptStart + m_vCrvData[nId].vtStart :
m_vCrvData[nId].ptEnd - m_vCrvData[nId].vtEnd) ;
double dSqDist = SqDist( ptStart, ptNear) ;
if ( dSqDist < dSqDistMin) {
dSqDistMin = dSqDist ;
double dDist = Dist( ptStart, ptNear) ;
// tengo il segmento più vicino al punto
// favorendo eventualmente quello equiverso se entro EPS da un concorrente
if ( dDist < dDistMin - EPS_SMALL ||
((dDist < dDistMin + EPS_SMALL) && bEquiv && vStart[nI] < 0)) {
dDistMin = dDist ;
nI = i ;
}
}
@@ -302,7 +305,7 @@ bool
ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext)
{
INTVECTOR vMyNext = vNext ;
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
int nM = -1 ;
Point3d ptRef ;
double dSqMinDist = m_dToler * m_dToler ;
@@ -319,19 +322,19 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
}
}
for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) {
// salto l'entità più vicina
// salto l'entità più vicina
if ( i == nM)
continue ;
// recupero indice e verso
int nId = abs( vMyNext[i]) - 1 ;
bool bEquiv = ( vMyNext[i] > 0) ;
// verifico se più vicino al più vicino
// verifico se più vicino al più vicino
double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
if ( dRefSqDist < dCurrSqDist)
vMyNext[i] = 0 ;
}
// cerco la direzione più vicina
// cerco la direzione più vicina
int nI = -1 ;
int nF = 0 ;
INTVECTOR vFork ;
@@ -343,7 +346,7 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
// recupero indice e verso
int nId = abs( vMyNext[i]) - 1 ;
bool bEquiv = ( vMyNext[i] > 0) ;
// incremento contatore indice entità tra cui scegliere
// incremento contatore indice entità tra cui scegliere
++ nF ;
vFork.push_back( vMyNext[i]) ;
// se vietata inversione, salto se controverso
@@ -387,7 +390,7 @@ bool
ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev)
{
INTVECTOR vMyPrev = vPrev ;
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
int nM = -1 ;
Point3d ptRef ;
double dSqMinDist = m_dToler * m_dToler ;
@@ -404,19 +407,19 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
}
}
for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) {
// salto l'entità più vicina
// salto l'entità più vicina
if ( i == nM)
continue ;
// recupero indice e verso
int nId = abs( vMyPrev[i]) - 1 ;
bool bEquiv = ( vMyPrev[i] < 0) ;
// verifico se più vicino al più vicino
// verifico se più vicino al più vicino
double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
if ( dRefSqDist < dCurrSqDist)
vMyPrev[i] = 0 ;
}
// cerco la direzione più vicina
// cerco la direzione più vicina
int nI = - 1 ;
int nF = 0 ;
double dProScaMax = - 1.1 ;
@@ -428,7 +431,7 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
// recupero indice e verso
int nId = abs( vMyPrev[i]) - 1 ;
bool bEquiv = ( vMyPrev[i] < 0) ;
// incremento contatore indice entità tra cui scegliere
// incremento contatore indice entità tra cui scegliere
++ nF ;
vFork.push_back( vMyPrev[i]) ;
// se vietata inversione, salto se controverso
+2 -1
View File
@@ -398,7 +398,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
if ( dLenA > ( dRad - EPS_ZERO))
dLenH = 0 ;
else
dLenH= sqrt( dRad * dRad - dLenA * dLenA) ;
dLenH = sqrt( dRad * dRad - dLenA * dLenA) ;
// versore dal punto medio della corda al centro
Vector3d vtH = vtA / dLenA ;
vtH.Rotate( Z_AX, 0, ( bCCW ? 1 : -1)) ;
@@ -410,6 +410,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
m_dRad = dRad ;
// calcolo il versore di start
m_VtS = ( ptStart - m_PtCen) / m_dRad ;
m_VtS.Normalize() ;
// calcolo l'angolo al centro
bool bDet ;
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
+777 -119
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -33,4 +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 CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
+180 -5
View File
@@ -13,6 +13,7 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveAux.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
#include "DistPointCrvBezier.h"
@@ -141,6 +142,32 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::SetControlWeight( int nInd, double dW)
{
// verifico validità, razionalità e indice
if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg)
return false ;
// verifico che il peso non sia nullo o negativo
if ( dW < EPS_SMALL)
return false ;
// assegno il valore e il peso
m_vWeCtrl[nInd] = dW ;
// annullo analisi presenza singolarità
m_dParSing = - 2 ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::FromArc( const ICurveArc& crArc)
@@ -1542,7 +1569,7 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir1Deg) ;
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ;
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
if ( IsNull( pCrv))
return false ;
}
@@ -1779,12 +1806,24 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
// verifico che i trim non cancellino interamente la curva
if ( dUStartTrim > dUEndTrim - EPS_PARAM)
return false ;
// se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim
Point3d ptStart ;
if( m_bRat)
GetPointD1D2( dUStartTrim, ptStart) ;
// trim finale
if ( ! TrimEndAtParam( dUEndTrim))
return false ;
// trim iniziale con il parametro opportunamente ricalcolato
double dNewUStartTrim = dUStartTrim / dUEndTrim ;
return TrimStartAtParam( dNewUStartTrim) ;
double dNewUStartTrim ;
if( m_bRat)
GetParamAtPoint( ptStart, dNewUStartTrim) ;
else
dNewUStartTrim = dUStartTrim / dUEndTrim ;
//trim iniziale
if( ! TrimStartAtParam( dNewUStartTrim))
return false ;
return true ;
}
//----------------------------------------------------------------------------
@@ -1800,7 +1839,10 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
return false ;
// utilizzo il trim sui parametri
return TrimStartAtParam( dUTrim) ;
if( ! TrimStartAtParam( dUTrim))
return false ;
return true ;
}
//----------------------------------------------------------------------------
@@ -1816,7 +1858,10 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
return false ;
// utilizzo il trim sui parametri
return TrimEndAtParam( dUTrim) ;
if( ! TrimEndAtParam( dUTrim))
return false ;
return true ;
}
//----------------------------------------------------------------------------
@@ -2208,3 +2253,133 @@ CurveBezier::ResetVoronoiObject() const
delete m_pVoronoiObj ;
m_pVoronoiObj = nullptr ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::MakeRational( void)
{
if ( m_bRat)
return true ;
// creo il vettore dei pesi e li setto tutti a 1
m_vWeCtrl.assign( m_nDeg + 1, 1) ;
// aggiorno il flag rational
m_bRat = true ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::MakeRationalStandardForm( void)
{
if ( ! m_bRat)
return false ;
double dW0 = m_vWeCtrl[0] ;
double dWn = m_vWeCtrl.back() ;
if( dW0 > 1- EPS_ZERO && dWn > 1 - EPS_ZERO)
return true ;
if( dW0 < EPS_ZERO || dWn < EPS_ZERO)
return false ;
// formula del Farin
double dCoeff = pow( dW0 / dWn, 1. / m_nDeg) ;
for ( int i = 0 ; i < m_nDeg + 1 ; ++i)
m_vWeCtrl[i] *= pow( dCoeff, i) / dW0 ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::MakeNonRational( double dTol)
{
if( ! m_bRat)
return true ;
// controllo se i pesi sono tutti == 1 allora è una finta razionale e mi basta fare una copia dei punti di controllo
bool bIsActualRat = false ;
for ( int i = 0 ; i < m_nDeg ; ++i) {
if ( abs(m_vWeCtrl[i] - 1) > EPS_SMALL) {
bIsActualRat = true ;
break ;
}
}
bool bOk = true ;
if ( ! bIsActualRat) {
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
for ( int p = 0 ; p < m_nDeg ; ++p) {
Point3d pt = GetControlPoint( p) ;
pNewBez->SetControlPoint( p, pt) ;
}
}
else {
// provo ad approssimare la curva di bezier con una controparte non razionale
int nDeg = m_nDeg ;
// punto di rientro in caso fallisca il primo tentativo
retry :
nDeg += 2 ;
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
pNewBez->Init( nDeg, false) ;
PNTVECTOR vPntCtrl ;
PNTVECTOR vPntSampling ;
for ( int p = 0 ; p < nDeg + 1; ++p) {
Point3d pt ; GetPointD1D2( double(p) / nDeg, pt) ;
pNewBez->SetControlPoint( p, pt) ;
vPntCtrl.push_back( pt) ;
}
vPntSampling = vPntCtrl ;
int c = 0 ;
double dErr = INFINITO ;
while ( dErr > dTol && c < 100) {
double dErrMax = 0 ;
// calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale
for ( int p = 0 ; p < nDeg + 1; ++p) {
Point3d pt ; pNewBez->GetPointD1D2( double(p) / nDeg, pt) ;
Vector3d vDiff = vPntSampling[p] - pt ;
double dErrLoc = vDiff.Len() ;
if( dErrLoc > dErrMax)
dErrMax = dErrLoc ;
// aggiorno il vettore dei punti di controllo della nuova curva
vPntCtrl[p] += vDiff ;
}
dErr = dErrMax ;
// aggiorno i punti di controllo della nuova curva
for ( int i = 0 ; i < nDeg + 1 ; ++i)
pNewBez->SetControlPoint( i, vPntCtrl[i]) ;
++c ;
}
// calcolo l'errore di approssimazione sulla curva
CalcBezierApproxError( this, pNewBez, dErr) ;
bOk = dErr < dTol ;
if( bOk) {
// aggiorno la curva di bezier originale con quella approssimata
Init( nDeg, false) ;
for( int i = 0 ; i < nDeg + 1 ; ++i) {
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
}
}
else if( nDeg < m_nDeg + 4)
goto retry ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::IsALine( void) const
{
Point3d ptStart ; GetStartPoint( ptStart) ;
Point3d ptEnd ; GetEndPoint( ptEnd) ;
for ( int i = 1 ; i < m_nDeg ; ++i) {
Point3d ptCtrl = GetControlPoint( i) ;
DistPointLine dpl( ptCtrl, ptStart, ptEnd) ;
double dDist = 0 ; dpl.GetDist( dDist) ;
if( dDist > EPS_SMALL)
return false ;
}
return true ;
}
+5
View File
@@ -137,6 +137,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
bool Init( int nDeg, bool bIsRational) override ;
bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ;
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
bool SetControlWeight( int nInd, double dW) override ;
bool FromArc( const ICurveArc& crArc) override ;
bool FromLine( const ICurveLine& crLine) override ;
int GetDegree( void) const override
@@ -148,6 +149,10 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
double GetControlWeight( int nInd, bool* pbOk = NULL) const override ;
bool GetControlPolygonLength( double& dLen) const override ;
int GetSingularParam( double& dPar) const override ;
bool MakeRational( void) override ;
bool MakeRationalStandardForm( void) override ;
bool MakeNonRational( double dTol) override ;
bool IsALine( void) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+8 -8
View File
@@ -439,12 +439,12 @@ CurveByApprox::CalcSplitPoints( double dLinTol, double dAngTolDeg, double dLinFe
m_vSplits.push_back(i) ;
continue ;
}
// verifico linearità del tratto precedente
// verifico linearità del tratto precedente
bool bPrevLin = vtPrev.SqLen() > dSqLinFea &&
( m_vNextDer[i-1] * m_vPrevDer[i]) > dAngTolCos &&
( vtPrev ^ m_vNextDer[i-1]).SqLen() < dSqLinTol &&
( vtPrev ^ m_vPrevDer[i]).SqLen() < dSqLinTol ;
// verifico linearità del tratto successivo
// verifico linearità del tratto successivo
bool bNextLin = vtNext.SqLen() > dSqLinFea &&
( m_vNextDer[i] * m_vPrevDer[i+1]) > dAngTolCos &&
( vtNext ^ m_vNextDer[i]).SqLen() < dSqLinTol &&
@@ -483,7 +483,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
PtrOwner<ICurve> pCrv ;
double dMaxDist ;
// se la polilinea ha più di 2 punti
// se la polilinea ha più di 2 punti
if ( PL.GetPointNbr() > 2) {
// calcolo punti e direzioni agli estremi della polilinea usando la curva di Bezier
int nI ;
@@ -501,11 +501,11 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
ptP1 = m_vPnt[nI] ;
m_vPrevDer[nI].ToSpherical( nullptr, nullptr, &dDir1Deg) ;
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ;
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
if ( IsNull( pCrv))
return false ;
}
// se la polilinea è formata da 2 punti
// se la polilinea è formata da 2 punti
else if ( PL.GetPointNbr() == 2) {
// se molto vicini, esco
double dLen ;
@@ -561,7 +561,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
return false ;
}
// spezzo l'intervallo in due parti a metà
// spezzo l'intervallo in due parti a metà
double dParStart, dParEnd ;
if ( ! PL.GetFirstU( dParStart) || ! PL.GetLastU( dParEnd))
return false ;
@@ -569,9 +569,9 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
PolyLine PL2 ;
if ( ! PL.Split( dParMid, PL2))
return false ;
// prima metà
// prima metà
if ( ! BiArcOrSplit( nLev + 1, PL, dLinTol, dAngTolDeg, PA))
return false ;
// seconda metà
// seconda metà
return BiArcOrSplit( nLev + 1, PL2, dLinTol, dAngTolDeg, PA) ;
}
+20 -6
View File
@@ -291,9 +291,15 @@ CurveComposite::Close( void)
return true ;
// se molto vicini li modifico
if ( AreSamePointEpsilon( ptStart, ptEnd, 10 * EPS_SMALL)) {
// se un solo arco
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC) {
CurveArc* pArc = GetBasicCurveArc( m_CrvSmplS.front()) ;
return pArc->ChangeAngCenter( pArc->GetAngCenter() > 0 ? ANG_FULL : -ANG_FULL) ;
}
// caso generale
Point3d ptMid = Media( ptStart, ptEnd) ;
if ( ! ModifyStart( ptMid) ||
! ModifyEnd( ptMid))
if ( ! m_CrvSmplS.front()->ModifyStart( ptMid) ||
! m_CrvSmplS.back()->ModifyEnd( ptMid))
return false ;
}
// altrimenti aggiungo la linea di chiusura
@@ -598,6 +604,10 @@ CurveComposite::CopyFrom( const CurveComposite& ccSrc)
if ( ! AddCurve( *pCrv))
return false ;
}
if ( ccSrc.m_nStatus == IS_A_POINT) {
m_ptStart = ccSrc.m_ptStart ;
m_nStatus = IS_A_POINT ;
}
return true ;
}
@@ -656,7 +666,7 @@ CurveComposite::Dump( string& sOut, bool bMM, const char* szNewLine) const
while ( pCrvSmpl != nullptr && i < MAX_CRV) {
// assegno ed emetto nome e tipo della curva semplice
sOut += "#" + ToString( i) + " " + pCrvSmpl->GetTitle() + szNewLine ;
// salvataggio della curva semplice
// dati della curva semplice
if ( ! pCrvSmpl->Dump( sOut, bMM, szNewLine))
return false ;
// passo alla successiva
@@ -879,8 +889,10 @@ CurveComposite::TestClosure( void)
// se distanza superiore al limite ridotto forzo i punti a coincidere
if ( ! AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT)) {
// se un solo arco
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC)
return GetBasicCurveArc( m_CrvSmplS.front())->ChangeAngCenter( ANG_FULL) ;
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC) {
CurveArc* pArc = GetBasicCurveArc( m_CrvSmplS.front()) ;
return pArc->ChangeAngCenter( pArc->GetAngCenter() > 0 ? ANG_FULL : -ANG_FULL) ;
}
// caso generale
Point3d ptM = Media( ptStart, ptEnd) ;
return ( m_CrvSmplS.front()->ModifyStart( ptM) &&
@@ -940,6 +952,8 @@ CurveComposite::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) con
return false ;
}
} break ;
default :
return false ;
}
}
// recupero dati sulla planarità della polilinea
@@ -2975,7 +2989,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast)
m_CrvSmplS.pop_front() ;
}
// eseguo mini verifica
m_nStatus = ( m_CrvSmplS.size() > 0 ? OK : TO_VERIFY) ;
m_nStatus = ( ! m_CrvSmplS.empty() ? OK : TO_VERIFY) ;
// assegno estrusione e spessore della curva composita
pCrv->SetExtrusion( m_VtExtr) ;
pCrv->SetThickness( m_dThick) ;
+2 -2
View File
@@ -50,7 +50,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
}
// altrimenti, per curve successive
else {
// verifico se la distanza minima dal box è superiore al minimo già trovato
// verifico se la distanza minima dal box è superiore al minimo già trovato
BBox3d b3B ;
if ( pCrvSmpl->GetLocalBBox( b3B) &&
b3B.SqDistFromPoint( ptP) <= m_dDist * m_dDist) {
@@ -105,7 +105,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
++ i ;
}
}
// con minima distanza più bassa
// con minima distanza più bassa
else if ( dCurrDist < m_dDist) {
// aggiorno i minimi
m_dDist = dCurrDist ;
+2
View File
@@ -47,6 +47,8 @@ DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve, bool bI
case CRV_COMPO :
CrvCompositeCalculate( ptP, Curve) ;
break ;
default :
break ;
}
// salvo il punto
m_ptP = ptP ;
+156
View File
@@ -0,0 +1,156 @@
//----------------------------------------------------------------------------
// EgalTech 2018-2020
//----------------------------------------------------------------------------
// File : DistPointSurfTm.cpp Data : 19.12.20 Versione : 2.2l3
// Contenuto : Implementazione della classe distanza Punto da Trimesh.
//
//
//
// Modifiche : 07.12.18 LM Creazione modulo.
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "SurfFlatRegion.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfFr.h"
using namespace std ;
//----------------------------------------------------------------------------
DistPointSurfFr::DistPointSurfFr( const Point3d& ptP, const ISurfFlatRegion& frSurf)
: m_dDist( -1)
{
// FlatRegion non valida
if ( &frSurf == nullptr || ! frSurf.IsValid())
return ;
// Calcolo la distanza
Calculate( ptP, frSurf) ;
}
//----------------------------------------------------------------------------
void
DistPointSurfFr::Calculate( const Point3d& ptP, const ISurfFlatRegion& frSurf)
{
// Inizializzo distanza non calcolata
m_dDist = -1 ;
// Converto regione in classe base
const SurfFlatRegion* pSfr = GetBasicSurfFlatRegion( &frSurf) ;
if ( pSfr == nullptr)
return ;
// ciclo sulle parti della regione
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; nC ++) {
// ciclo sui loop della parte di regione
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; nL ++) {
PtrOwner<ICurve> pLoop( pSfr->GetLoop( nC, nL)) ;
if ( IsNull( pLoop)) {
m_dDist = -1 ;
return ;
}
DistPointCurve DPL( ptP, *pLoop) ;
double dDist ;
if ( DPL.GetDist( dDist) && ( m_dDist < -EPS_SMALL || dDist < m_dDist)) {
m_dDist = dDist ;
int nFlag ;
m_nMinChunk = nC ;
m_nMinLoop = nL ;
DPL.GetParamAtMinDistPoint( 0, m_dMinPar, nFlag) ;
DPL.GetMinDistPoint( 0, m_ptMinDistPoint, nFlag) ;
DPL.GetSideAtMinDistPoint( 0, pSfr->GetNormVersor(), m_nSide) ;
}
}
}
// se trovata, aggiorno minima distanza sul piano
if ( m_dDist > - EPS_SMALL) {
Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ;
m_dDistOnPlane = min( Dist( ptOn, m_ptMinDistPoint), m_dDist) ;
}
}
//----------------------------------------------------------------------------
bool
DistPointSurfFr::GetDist( double& dDist) const
{
if ( m_dDist < 0)
return false ;
dDist = m_dDist ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfFr::GetDistOnRegionPlane( double& dDist) const
{
if ( m_dDist < 0)
return false ;
dDist = m_dDistOnPlane ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfFr::GetPointAtMinDist( Point3d& ptMinDist) const
{
if ( m_dDist < 0)
return false ;
ptMinDist = m_ptMinDistPoint ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfFr::GetParamAtMinDist( int& nMinChunk, int& nMinLoop, double& dMinPar) const
{
if ( m_dDist < 0)
return false ;
nMinChunk = m_nMinChunk ;
nMinLoop = m_nMinLoop ;
dMinPar = m_dMinPar ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfFr::GetSideAtMinDist( int& nSide) const
{
if ( m_dDist < 0)
return false ;
nSide = m_nSide ;
return true ;
}
//----------------------------------------------------------------------------
bool
IsPointInsideSurfFr( const Point3d& ptP, const ISurfFlatRegion* pSfr, double dMinDist, bool& bInside, int& nChunk)
{
// default non include
bInside = false ;
nChunk = -1 ;
// verifica regione
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
// verifico se la proiezione del punto sul piano della regione sta nel suo box
Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ;
BBox3d b3Box ;
pSfr->GetLocalBBox( b3Box) ;
b3Box.Expand( dMinDist) ;
if ( ! b3Box.Encloses( ptOn))
return true ;
// determino dove sta il punto
DistPointSurfFr DPR( ptP, *pSfr) ;
double dDist ; int nMinCh, nMinL; double dMinPar ; int nSide ;
if ( DPR.GetDistOnRegionPlane( dDist) && DPR.GetParamAtMinDist( nMinCh, nMinL, dMinPar) && DPR.GetSideAtMinDist( nSide)) {
if ( abs( dMinDist) < EPS_SMALL)
bInside = ( nSide != PRS_OUT) ;
else if ( dMinDist < 0)
bInside = ( nSide == PRS_IN && dDist > abs( dMinDist) - EPS_SMALL) ;
else
bInside = ( nSide != PRS_OUT || dDist < dMinDist + EPS_SMALL) ;
if ( bInside)
nChunk = nMinCh ;
}
return true ;
}
+34 -32
View File
@@ -21,10 +21,10 @@ using namespace std ;
//----------------------------------------------------------------------------
// Calcola la differenza fra i bounding-box A e B.
// L'insieme differenza non è un bounding-box, ma è esprimibile come unione di al più sei bounding-box.
// L'insieme differenza non è un bounding-box, ma è esprimibile come unione di al più sei bounding-box.
// Se l'insieme differenza fra i box non ha misura nulla viene restituito true, false altrimenti.
// I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto
// nel box B; uno di questi si verifica se il box A è vuoto.
// I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto
// nel box B; uno di questi si verifica se il box A è vuoto.
// Nel vettore vBoxDiff vengono restituiti i box la cui unione costituisce la differenza fra A e B.
static bool
BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff)
@@ -34,7 +34,7 @@ BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDi
// Se box A vuoto, risultato vuoto
if ( boxA.IsEmpty())
return false ;
// Se box B vuoto o i box non si intersecano, risultato è ancora A
// Se box B vuoto o i box non si intersecano, risultato è ancora A
BBox3d boxInt ;
if ( boxB.IsSmall() || ! boxA.FindIntersection( boxB, boxInt)) {
vBoxDiff.emplace_back( boxA) ;
@@ -94,7 +94,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
{
// Inizializzo distanza non calcolata
m_dDist = - 1. ;
// Controllo se la superficie è chiusa
// Controllo se la superficie è chiusa
m_bIsSurfClosed = tmSurf.IsClosed() ;
// Lavoro con l'oggetto superficie trimesh di base
@@ -107,8 +107,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
if ( b3Stm.IsEmpty())
return ;
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
@@ -118,17 +118,17 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
BBox3d boxPPrev( ptP) ;
BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ;
// Variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima
double dMinSqDist = DBL_MAX ;
double dMinDist = DBL_MAX ;
int nMinDistTriaIndex = SVT_NULL ;
Point3d ptMinDistPoint ;
// Finché non si verifica la condizione di terminazione ingrandisco il box.
// Finché non si verifica la condizione di terminazione ingrandisco il box.
pStm->ResetTempInts() ;
bool bContinue = true ;
// creazione del vettore dei triangoli più vicini a ptP
// creazione del vettore dei triangoli più vicini a ptP
vector<pair<int, Triangle3d>> vTria ; // <indice triangolo, Triangolo>
while ( bContinue) {
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
BOXVECTOR vBox ;
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
// Ciclo sui box differenza
@@ -136,7 +136,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
for ( const auto& b3Box : vBox) {
// interseco il box con quello della superficie e ne verifico la distanza minima dal punto
BBox3d b3Int ;
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.SqDistFromPoint( ptP) > dMinSqDist)
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.DistFromPoint( ptP) > dMinDist)
continue ;
// ricerca sui triangoli nel box
bCollide = true ;
@@ -149,17 +149,22 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, trCurTria)) {
pStm->SetTempInt( nT, 1) ;
DistPointTriangle distPT( ptP, trCurTria) ;
double dCurSqDist ;
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
if ( distPT.GetSqDist( dCurSqDist)) {
if ( abs( dCurSqDist - dMinSqDist) < EPS_SMALL) // se distanze uguali...
vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo
else if ( dCurSqDist < dMinSqDist) { // se minore...
vTria.clear() ; // pulisco il vettore
dMinSqDist = dCurSqDist ;
double dCurrDist ;
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
if ( distPT.GetDist( dCurrDist)) {
// se distanze uguali...
if ( abs( dCurrDist - dMinDist) < EPS_SMALL)
// aggiungo il triangolo
vTria.emplace_back( make_pair( nT, trCurTria)) ;
// se minore...
else if ( dCurrDist < dMinDist) {
// pulisco il vettore
vTria.clear() ;
dMinDist = dCurrDist ;
nMinDistTriaIndex = nT ;
distPT.GetMinDistPoint( ptMinDistPoint) ;
vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo
// aggiungo il triangolo
vTria.emplace_back( make_pair( nT, trCurTria)) ;
}
}
}
@@ -167,7 +172,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
}
}
// Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
if ( ! bCollide || dMinSqDist < SQ_EPS_SMALL)
if ( ! bCollide || dMinDist < EPS_SMALL)
bContinue = false ;
else {
boxPPrev = boxP ;
@@ -180,10 +185,10 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
return ;
// salvo la distanza minima
m_dDist = sqrt( max( dMinSqDist, 0.)) ;
m_dDist = dMinDist ;
// salvo il punto a distanza minima
m_ptMinDistPoint = ptMinDistPoint ;
// se il punto è sulla TriMesh...
// se il punto è sulla TriMesh...
if ( m_dDist < EPS_SMALL) {
m_nMinDistTriaIndex = nMinDistTriaIndex ;
m_bIsInside = false ;
@@ -215,7 +220,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
// 1) calcolo i centroidi dei triangoli in questione
// 2) ottengo il punto medio di questi centroidi
// 3) controllo quale triangolo interseca il segmento che parte da ptP e arriva a tale punto
// 4) userò questo triangolo per classificare ptP
// 4) userò questo triangolo per classificare ptP
if ( bOutside == bInside) {
// calcolo il baricentro complessivo
Point3d ptBar_tot ;
@@ -236,9 +241,6 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
}
else // se informazioni coerenti
m_bIsInside = bInside ;
return ;
}
//----------------------------------------------------------------------------
@@ -291,8 +293,8 @@ GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
if ( b3Stm.IsEmpty())
return SVT_NULL ;
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
@@ -304,11 +306,11 @@ GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
// Variabili distanza minima
int nVert = SVT_NULL ;
double dMinSqDist = DBL_MAX ;
// Finché non si verifica la condizione di terminazione ingrandisco il box.
// Finché non si verifica la condizione di terminazione ingrandisco il box.
pStm->ResetTempInts() ;
bool bContinue = true ;
while ( bContinue) {
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
BOXVECTOR vBox ;
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
// Ciclo sui box differenza
BIN
View File
Binary file not shown.
+8 -4
View File
@@ -22,7 +22,7 @@
<ProjectGuid>{9A98A202-2853-454A-84CA-DCD1714176C9}</ProjectGuid>
<RootNamespace>EgtGeomKernel</RootNamespace>
<Keyword>MFCDLLProj</Keyword>
<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -30,7 +30,7 @@
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -46,7 +46,7 @@
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141_xp</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -281,6 +281,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="BBox3d.cpp" />
<ClCompile Include="BiArcs.cpp" />
<ClCompile Include="CalcPocketing.cpp" />
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
<ClCompile Include="CAvToolSurfTm.cpp" />
<ClCompile Include="CAvToolTriangle.cpp" />
@@ -309,6 +310,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="CurveByApprox.cpp" />
<ClCompile Include="CurveByInterp.cpp" />
<ClCompile Include="CurveCompositeOffset.cpp" />
<ClCompile Include="DistPointSurfFr.cpp" />
<ClCompile Include="IntersCurveSurfTm.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
@@ -322,6 +324,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="Quaternion.cpp" />
<ClCompile Include="RotationMinimizingFrame.cpp" />
<ClCompile Include="RotationXplaneFrame.cpp" />
<ClCompile Include="SbzFromCurves.cpp" />
<ClCompile Include="SbzStandard.cpp" />
<ClCompile Include="Voronoi.cpp" />
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
@@ -340,6 +343,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="CAvSilhouetteSurfTm.h" />
<ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" />
<ClInclude Include="CDeConeFrustumTria.h" />
@@ -425,7 +429,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="OffsetCurveOnX.cpp" />
<ClCompile Include="Polygon3d.cpp" />
<ClCompile Include="AdjustLoops.cpp" />
<ClCompile Include="ProjectCurveSurfTm.cpp" />
<ClCompile Include="ProjectCurveSurf.cpp" />
<ClCompile Include="RemoveCurveDefects.cpp" />
<ClCompile Include="SelfIntersCurve.cpp" />
<ClCompile Include="SfrCreate.cpp" />
+13 -1
View File
@@ -486,7 +486,7 @@
<ClCompile Include="IntersLineCaps.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="ProjectCurveSurfTm.cpp">
<ClCompile Include="ProjectCurveSurf.cpp">
<Filter>File di origine\GeoProject</Filter>
</ClCompile>
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp">
@@ -537,6 +537,15 @@
<ClCompile Include="Quaternion.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="SbzFromCurves.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="DistPointSurfFr.cpp">
<Filter>File di origine\GeoDist</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -1214,6 +1223,9 @@
<ClInclude Include="..\Include\EGkDistPointLine.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="CAvSilhouetteSurfTm.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+13
View File
@@ -147,6 +147,10 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
return nullptr ;
// verifico il minimo raggio
if ( dRadius < 10 * EPS_SMALL)
return nullptr ;
// eseguo calcoli
Point3d ptCen, ptTg1, ptTg2 ;
int nSide1, nSide2 ;
@@ -165,6 +169,11 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
return nullptr ;
}
// verifico dimensione minima
double dLen = Dist( ptTg1, ptTg2) ;
if ( dLen < 2 * EPS_SMALL)
return nullptr ;
// orientamento tra le curve
bool bCCW = ( dSinA > 0) ;
@@ -207,6 +216,10 @@ CreateChamfer( const ICurve& cCrv1, const Point3d& ptNear1,
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
return nullptr ;
// verifico lo smusso minimo
if ( dDist < 10 * EPS_SMALL)
return nullptr ;
// calcolo un riferimento sul piano perpendicolare alla normale
Frame3d frIntr ;
if ( ! frIntr.Set( ORIG, vtNorm))
+2 -2
View File
@@ -493,7 +493,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
int nLbLen ;
if ( IsLineBreak( vCode, i, nLbLen)) {
// salvo la linea, se contiene qualcosa
if ( vTmpCode.size() > 0) {
if ( ! vTmpCode.empty()) {
string sLine ;
SetCodePoints( vTmpCode, sLine) ;
vLine.push_back( sLine) ;
@@ -523,7 +523,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
dMaxW = vtMove.x ;
}
// salvo eventuale ultima linea
if ( vTmpCode.size() > 0) {
if ( ! vTmpCode.empty()) {
string sLine ;
SetCodePoints( vTmpCode, sLine) ;
vLine.push_back( sLine) ;
+2 -2
View File
@@ -619,7 +619,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
int nLbLen ;
if ( IsLineBreak( vCode, i, nLbLen)) {
// salvo la linea, se contiene qualcosa
if ( vTmpCode.size() > 0) {
if ( ! vTmpCode.empty()) {
string sLine ;
SetCodePoints( vTmpCode, sLine) ;
vLine.push_back( sLine) ;
@@ -646,7 +646,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
dMaxW = vtMove.x ;
}
// salvo eventuale ultima linea
if ( vTmpCode.size() > 0) {
if ( ! vTmpCode.empty()) {
string sLine ;
SetCodePoints( vTmpCode, sLine) ;
vLine.push_back( sLine) ;
+5 -5
View File
@@ -2267,7 +2267,7 @@ bool
GdbExecutor::SurfTriMeshEnd( const STRVECTOR& vsParams)
{
// nessun parametro
if ( vsParams.size() != 0)
if ( ! vsParams.empty())
return false ;
// recupero la superficie
ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ;
@@ -6632,7 +6632,7 @@ GdbExecutor::ExecuteDeselect( const string& sCmd2, const STRVECTOR& vsParams)
// deselezione di tutto
else if ( sCmd2 == "ALL") {
// nessun parametro
if ( vsParams.size() != 0)
if ( ! vsParams.empty())
return false ;
// cancello selezione oggetti
if ( ! m_pGDB->ClearSelection())
@@ -7773,7 +7773,7 @@ bool
GdbExecutor::ExecuteNew( const string& sCmd2, const STRVECTOR& vsParams)
{
// nessun parametro
if ( vsParams.size() != 0)
if ( ! vsParams.empty())
return false ;
// pulizia e reinizializzazione del DB geometrico
m_pGDB->Clear() ;
@@ -7946,7 +7946,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
// chiudo il file di uscita Tsc
else if ( sCmd2 == "CLOSE") {
// nessun parametro
if ( vsParams.size() != 0)
if ( ! vsParams.empty())
return false ;
// scrivo terminazioni e chiudo il file
return m_OutTsc.Close() ;
@@ -7969,7 +7969,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
else if ( sCmd2 == "SETGR") {
Frame3d frF ;
// nessun parametro
if ( vsParams.size() == 0)
if ( vsParams.empty())
frF.Reset() ;
// un parametro ( Id del gruppo)
else if ( vsParams.size() == 1) {
+2 -2
View File
@@ -1254,13 +1254,13 @@ GdbIterator::GetCalcStatus( int& nStat) const
//----------------------------------------------------------------------------
bool
GdbIterator::SetMark( void)
GdbIterator::SetMark( int nMark)
{
if ( m_pGDB == nullptr || m_pCurrObj == nullptr)
return false ;
// imposto la marcatura
return m_pCurrObj->SetMark() ;
return m_pCurrObj->SetMark( nMark) ;
}
//----------------------------------------------------------------------------
+1 -1
View File
@@ -103,7 +103,7 @@ class GdbIterator : public IGdbIterator
bool RevertStatus( void) override ;
bool GetStatus( int& nStat) const override ;
bool GetCalcStatus( int& nStat) const override ;
bool SetMark( void) override ;
bool SetMark( int nMark = GDB_MK_ON) override ;
bool ResetMark( void) override ;
bool GetMark( int& nMark) const override ;
bool GetCalcMark( int& nMark) const override ;
+4 -4
View File
@@ -612,14 +612,14 @@ GdbObj::GetCalcStatus( int& nStat, int nLev) const
//----------------------------------------------------------------------------
bool
GdbObj::SetMark( void)
GdbObj::SetMark( int nMark)
{
// verifico esistenza (con eventuale creazione) degli attributi
if ( GetSafeAttribs() == nullptr)
return false ;
// assegno la marcatura
m_pAttribs->SetMark() ;
m_pAttribs->SetMark( nMark) ;
return true ;
}
@@ -659,8 +659,8 @@ GdbObj::GetCalcMark( int& nMark) const
nObjMark = m_pAttribs->GetMark() ;
// se la marcatura è ON, non ho bisogno di sapere altro
if ( nObjMark == GDB_MK_ON) {
nMark = GDB_MK_ON ;
if ( nObjMark == GDB_MK_ON || nObjMark == GDB_MK_ON_2) {
nMark = nObjMark ;
return true ;
}
+1 -1
View File
@@ -81,7 +81,7 @@ class GdbObj
bool IsSelected( void) const ;
bool GetStatus( int& nStat) const ;
bool GetCalcStatus( int& nStat, int nLev = 0) const ;
bool SetMark( void) ;
bool SetMark( int nMark) ;
bool ResetMark( void) ;
bool GetMark( int& nMark) const ;
bool GetCalcMark( int& nMark) const ;
+2 -2
View File
@@ -2310,7 +2310,7 @@ GeomDB::GetCalcStatus( int nId, int& nStat) const
//----------------------------------------------------------------------------
bool
GeomDB::SetMark( int nId)
GeomDB::SetMark( int nId, int nMark)
{
// recupero l'oggetto
GdbObj* pGdbObj = GetGdbObj( nId) ;
@@ -2318,7 +2318,7 @@ GeomDB::SetMark( int nId)
return false ;
// imposto la marcatura
return pGdbObj->SetMark() ;
return pGdbObj->SetMark( nMark) ;
}
//----------------------------------------------------------------------------
+1 -1
View File
@@ -136,7 +136,7 @@ class GeomDB : public IGeomDB
bool RevertStatus( int nId) override ;
bool GetStatus( int nId, int& nStat) const override ;
bool GetCalcStatus( int nId, int& nStat) const override ;
bool SetMark( int nId) override ;
bool SetMark( int nId, int nMark = GDB_MK_ON) override ;
bool ResetMark( int nId) override ;
bool GetMark( int nId, int& nMark) const override ;
bool GetCalcMark( int nId, int& nMark) const override ;
+13 -13
View File
@@ -116,7 +116,7 @@ HashGrid1d::~HashGrid1d( void)
{
Clear() ;
for ( Cell* pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_CellCount ; ++ pCell) {
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
delete[] pCell->m_neighborOffset ;
}
@@ -396,8 +396,10 @@ HashGrid1d::Enlarge( void)
for ( auto pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
delete[] pCell->m_neighborOffset ;
pCell->m_neighborOffset = nullptr ;
}
delete[] m_cell ;
m_cell = nullptr ;
// ... the number of cells is doubled in each coordinate direction, ...
m_CellCount *= 2 ;
@@ -569,7 +571,7 @@ HashGrids1d::Update( void)
// Salvo stato di precedente attivazione delle griglie
bool bGridActivePrev = m_bGridActive ;
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
if ( m_objsToAdd.size() > 0 ) {
if ( ! m_objsToAdd.empty()) {
for ( auto pObj : m_objsToAdd) {
if ( m_bGridActive)
addGrid( *pObj) ;
@@ -634,24 +636,22 @@ HashGrids1d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
sort( vnIds.begin(), vnIds.end()) ;
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
return ( vnIds.size() > 0) ;
return ( ! vnIds.empty()) ;
}
//----------------------------------------------------------------------------
void
HashGrids1d::Clear( void)
{
for ( auto pGrid : m_GridList) {
delete pGrid ;
}
m_GridList.clear() ;
m_bGridActive = false ;
m_nonGridObjs.clear() ;
m_ObjsList.clear() ;
m_ObjsMap.clear() ;
m_objsToAdd.clear() ;
m_nonGridObjs.clear() ;
for ( auto pGrid : m_GridList)
delete pGrid ;
m_GridList.clear() ;
m_bActivate = true ;
m_bGridActive = false ;
m_b3Objs.Reset() ;
}
+13 -13
View File
@@ -125,7 +125,7 @@ HashGrid2d::~HashGrid2d( void)
{
Clear() ;
for ( Cell* pCell = m_cell ; pCell < m_cell + m_xyCellCount ; ++ pCell) {
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_xyCellCount ; ++ pCell) {
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
delete[] pCell->m_neighborOffset ;
}
@@ -445,8 +445,10 @@ HashGrid2d::Enlarge( void)
for ( auto pCell = m_cell ; pCell < m_cell + m_xyCellCount ; ++ pCell) {
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
delete[] pCell->m_neighborOffset ;
pCell->m_neighborOffset = nullptr ;
}
delete[] m_cell ;
m_cell = nullptr ;
// ... the number of cells is doubled in each coordinate direction, ...
m_xCellCount *= 2 ;
@@ -623,7 +625,7 @@ HashGrids2d::Update( void)
// Salvo stato di precedente attivazione delle griglie
bool bGridActivePrev = m_bGridActive ;
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
if ( m_objsToAdd.size() > 0 ) {
if ( ! m_objsToAdd.empty()) {
for ( auto pObj : m_objsToAdd) {
if ( m_bGridActive)
addGrid( *pObj) ;
@@ -688,24 +690,22 @@ HashGrids2d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
sort( vnIds.begin(), vnIds.end()) ;
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
return ( vnIds.size() > 0) ;
return ( ! vnIds.empty()) ;
}
//----------------------------------------------------------------------------
void
HashGrids2d::Clear( void)
{
for ( auto pGrid : m_GridList) {
delete pGrid ;
}
m_GridList.clear() ;
m_bGridActive = false ;
m_nonGridObjs.clear() ;
m_ObjsList.clear() ;
m_ObjsMap.clear() ;
m_objsToAdd.clear() ;
m_nonGridObjs.clear() ;
for ( auto pGrid : m_GridList)
delete pGrid ;
m_GridList.clear() ;
m_bActivate = true ;
m_bGridActive = false ;
m_b3Objs.Reset() ;
}
+13 -13
View File
@@ -132,7 +132,7 @@ HashGrid3d::~HashGrid3d( void)
{
Clear() ;
for ( Cell* pCell = m_cell ; pCell < m_cell + m_xyzCellCount ; ++ pCell) {
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_xyzCellCount ; ++ pCell) {
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
delete[] pCell->m_neighborOffset ;
}
@@ -486,8 +486,10 @@ HashGrid3d::Enlarge( void)
for ( auto pCell = m_cell ; pCell < m_cell + m_xyzCellCount ; ++ pCell) {
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
delete[] pCell->m_neighborOffset ;
pCell->m_neighborOffset = nullptr ;
}
delete[] m_cell ;
m_cell = nullptr ;
// ... the number of cells is doubled in each coordinate direction, ...
m_xCellCount *= 2 ;
@@ -667,7 +669,7 @@ HashGrids3d::Update( void)
// Salvo stato di precedente attivazione delle griglie
bool bGridActivePrev = m_bGridActive ;
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
if ( m_objsToAdd.size() > 0 ) {
if ( ! m_objsToAdd.empty()) {
for ( auto pObj : m_objsToAdd) {
if ( m_bGridActive)
addGrid( *pObj) ;
@@ -731,7 +733,7 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
sort( vnIds.begin(), vnIds.end()) ;
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
return ( vnIds.size() > 0) ;
return ( ! vnIds.empty()) ;
}
@@ -739,17 +741,15 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
void
HashGrids3d::Clear( void)
{
for ( auto pGrid : m_GridList) {
delete pGrid ;
}
m_GridList.clear() ;
m_bGridActive = false ;
m_nonGridObjs.clear() ;
m_ObjsList.clear() ;
m_ObjsMap.clear() ;
m_objsToAdd.clear() ;
m_nonGridObjs.clear() ;
for ( auto pGrid : m_GridList)
delete pGrid ;
m_GridList.clear() ;
m_bActivate = true ;
m_bGridActive = false ;
m_b3Objs.Reset() ;
}
+8 -5
View File
@@ -17,6 +17,9 @@
using namespace std ;
//----------------------------------------------------------------------------
static const double EPS_INTER_ARC = 0.1 * EPS_SMALL ;
//----------------------------------------------------------------------------
IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
{
@@ -60,15 +63,15 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
vtDir /= dDist ;
// cerchi esterni -> nessuna intersezione
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_SMALL)
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_INTER_ARC)
return ;
// cerchi interni -> nessuna intersezione
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_SMALL)
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_INTER_ARC)
return ;
// cerchi coincidenti -> sovrapposizioni e/o intersezioni agli estremi
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_SMALL) {
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_INTER_ARC) {
// coefficiente da parametro dell'arco 1 a lunghezza
double dU2L = abs( m_Arc1.GetAngCenter()) * DEGTORAD * m_Arc1.GetRadius() ;
// determino se sono equiversi o controversi
@@ -236,7 +239,7 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
double dSqH = m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA ;
// cerchi tangenti esterni -> una intersezione
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_SMALL) {
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_INTER_ARC) {
// tolleranza tangenziale sull'intersezione
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
// calcolo il punto di intersezione
@@ -358,7 +361,7 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
}
// cerchi tangenti interni -> una intersezione
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_SMALL) {
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_INTER_ARC) {
// tolleranza tangenziale sull'intersezione
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
// determino quale dei due contiene l'altro
+9 -1
View File
@@ -78,6 +78,8 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
case CRV_COMPO :
LineCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
break ;
default :
break ;
}
break ;
case CRV_ARC :
@@ -91,6 +93,8 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
case CRV_COMPO :
ArcCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
break ;
default :
break ;
}
break ;
case CRV_COMPO :
@@ -104,8 +108,12 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
case CRV_COMPO :
CrvCompoCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
break ;
default :
break ;
}
break ;
default :
break ;
}
// per curve approssimate, sistemo...
AdjustIntersParams( ( pCalcCrv[0] != m_pCurve[0]), ( pCalcCrv[1] != m_pCurve[1])) ;
@@ -245,7 +253,7 @@ bool
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
{
// se non ci sono intersezioni, non va fatto alcunché
if ( m_Info.size() == 0)
if ( m_Info.empty())
return true ;
// se le curve originali non sono state approssimate, non va fatto alcunché
if ( ! bAdjCrvA && ! bAdjCrvB)
+1 -1
View File
@@ -44,7 +44,7 @@ static void
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
{
// se non trovati, esco
if ( vInfo.size() == 0)
if ( vInfo.empty())
return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
+29 -24
View File
@@ -19,20 +19,18 @@
using namespace std ;
//----------------------------------------------------------------------------
// Il punto è esterno al FatSegment se dista da questo più di Tol e la sua proiezione sta sul segmento
bool
IsPointOutFatSegment( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
// Posizione del punto rispetto alla linea (+1=a destra, 0=nella banda di tolleranza, -1=a sinistra)
static int
GetPointToLineSide( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
{
// distanza del punto dalla linea del segmento (con compensazione piccolissimi errori)
if ( abs( CrossXY( ( ptP - ptS), vtDir)) < ( dTol + EPS_ZERO) * dLenXY)
return false ;
// distanza con segno della proiezione del punto sul segmento dall'inizio per lunghezza segmento
double dDistXY = ScalarXY( ( ptP - ptS), vtDir) ;
// se il punto non si proietta sul segmento entro la tolleranza
if ( dDistXY < - dTol * dLenXY || dDistXY > ( dLenXY + dTol) * dLenXY)
return false ;
// altrimenti
return true ;
double dCross = CrossXY( ( ptP - ptS), vtDir) ;
double dFat = ( dTol + EPS_ZERO) * dLenXY ;
if ( dCross > dFat)
return +1 ;
else if ( dCross < - dFat)
return -1 ;
else
return 0 ;
}
//----------------------------------------------------------------------------
@@ -44,7 +42,7 @@ IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2,
m_bOverlaps = false ;
m_nNumInters = 0 ;
// verifico validità linee
// verifico validità linee
if ( ! Line1.IsValid() || ! Line2.IsValid())
return ;
@@ -130,30 +128,36 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
if ( ! boxL1.OverlapsXY( boxL2))
return ;
// linea 1 : Start, End, Direzione e Lunghezza
// segmento 1 : Start, End, Direzione e Lunghezza
Point3d ptS1 = Line1.GetStart() ;
Point3d ptE1 = Line1.GetEnd() ;
Vector3d vtDir1 = ptE1 - ptS1 ;
double dLen1XY = vtDir1.LenXY() ;
if ( dLen1XY < EPS_SMALL)
return ;
// linea 2 : Start, Direzione e Lunghezza
// segmento 2 : Start, Direzione e Lunghezza
Point3d ptS2 = Line2.GetStart() ;
Point3d ptE2 = Line2.GetEnd() ;
Vector3d vtDir2 = ptE2 - ptS2 ;
double dLen2XY = vtDir2.LenXY() ;
if ( dLen2XY < EPS_SMALL)
return ;
// posizioni estremi segmento 1 rispetto a linea 2
int nS1Side = GetPointToLineSide( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ;
int nE1Side = GetPointToLineSide( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ;
if ( ( nS1Side == 1 && nE1Side == 1) || ( nS1Side == -1 && nE1Side == -1))
return ;
// posizioni estremi segmento 2 rispetto a linea 1
int nS2Side = GetPointToLineSide( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ;
int nE2Side = GetPointToLineSide( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ;
if ( ( nS2Side == 1 && nE2Side == 1) || ( nS2Side == -1 && nE2Side == -1))
return ;
// prodotto vettoriale nel piano XY tra le direzioni delle linee
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
// flag per linee parallele
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
// flag per segmenti che si allontanano significativamente
bool bFarEnds = ( /*( abs( dCrossXY) > SIN_EPS_ANG_SMALL * ( dLen1XY * dLen2XY)) ||*/
IsPointOutFatSegment( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ||
IsPointOutFatSegment( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ||
IsPointOutFatSegment( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ||
IsPointOutFatSegment( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL)) ;
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
// se non sono paralleli e si allontanano tra loro abbastanza
if ( ! bParallel && bFarEnds) {
@@ -168,6 +172,8 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
nPos1 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
nPos1 = ICurve::PP_MID ; // nell'interno
else
return ;
// verifica posizione intersezione su seconda linea
int nPos2 = ICurve::PP_NULL ; // fuori
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL)
@@ -176,8 +182,7 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
nPos2 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
nPos2 = ICurve::PP_MID ; // nell'interno
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
else
return ;
// limito i parametri a stare sui segmenti (0...1)
m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ;
@@ -190,7 +195,7 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
m_Info.IciA[0].nNextTy = ICCT_NULL ;
m_Info.IciB[0].nPrevTy = ICCT_NULL ;
m_Info.IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
+1 -1
View File
@@ -83,7 +83,7 @@ static void
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
{
// se non trovati, esco
if ( vInfo.size() == 0)
if ( vInfo.empty())
return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
+1 -1
View File
@@ -1670,7 +1670,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
// Studio le soluzioni
int nIntType = T_ERROR ;
if ( vdPar.size() == 0)
if ( vdPar.empty())
nIntType = T_NO_INT ;
else if ( vdPar.size() == 1) {
nIntType = T_ONE_TAN ;
+1 -1
View File
@@ -45,7 +45,7 @@ static void
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
{
// se non trovati, esco
if ( vInfo.size() == 0)
if ( vInfo.empty())
return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
+1 -1
View File
@@ -42,5 +42,5 @@ Inters3Planes( const Plane3d& plPlane1, const Plane3d& plPlane2, const Plane3d&
if ( IntersPlanePlane( plPlane1, plPlane2, ptL, vtL) != IPPT_YES)
return IPPT_NO ;
// intersezione della linea con il terzo piano
return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt) == ILPT_YES ? IPPT_YES : IPPT_NO) ;
return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt, false) == ILPT_YES ? IPPT_YES : IPPT_NO) ;
}
+6 -8
View File
@@ -2,7 +2,7 @@
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : OffsetAux.cpp Data : 23.11.23 Versione : 2.5k5
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
//
//
//
@@ -25,11 +25,7 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
{
// identifico le sottocurve di tipo fillet e assegno loro temp param 1.0 per riconoscerle nella funzione AdjustCurveFillets
for ( int i = 0 ; i < pCrvCo->GetCurveCount() ; i ++) {
// recupero la curva
PtrOwner<ICurve> pCrv( pCrvCo->GetCurve(i)->Clone()) ;
if ( IsNull( pCrv))
return false ;
if ( IsFillet( pCrv, dDist))
if ( IsFillet( pCrvCo->GetCurve( i), dDist))
pCrvCo->SetCurveTempParam( i, 1.0) ;
else
pCrvCo->SetCurveTempParam( i, 0.0) ;
@@ -39,12 +35,14 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
//----------------------------------------------------------------------------
bool
IsFillet( ICurve* pCrv, double dDist)
IsFillet( const ICurve* pCrv, double dDist)
{
if ( pCrv == nullptr)
return false ;
// deve essere un arco
if ( pCrv->GetType() != CRV_ARC)
return false ;
CurveArc* pArc = GetBasicCurveArc( pCrv) ;
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
// deve avere raggio uguale alla distanza di offset
if ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL)
return false ;
+2 -2
View File
@@ -2,7 +2,7 @@
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : OffsetAux.h Data : 23.11.23 Versione : 2.5k5
// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve.
// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve.
//
//
//
@@ -16,6 +16,6 @@
//----------------------------------------------------------------------------
bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ;
bool IsFillet( ICurve* pCrv, double dDist) ;
bool IsFillet( const ICurve* pCrv, double dDist) ;
bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ;
bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
+71 -23
View File
@@ -60,6 +60,8 @@ OffsetCurve::Reset( void)
}
}
m_CrvLst.clear() ;
m_ptOffs = P_INVALID ;
m_vtOut = V_INVALID ;
return true ;
}
@@ -74,7 +76,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// verifico che la curva esista
if ( pCrv == nullptr)
return false ;
// verifico se la curva è un segmento di retta
// verifico se la curva è un segmento di retta
bool bIsLine = false ;
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
if ( pLine != nullptr)
@@ -85,7 +87,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
if ( pCompo != nullptr && pCompo->IsALine( m_dLinTol, ptStart, ptEnd))
bIsLine = true ;
}
// verifico che la curva sia piana (per le linee è comunque sempre vero)
// verifico che la curva sia piana (per le linee è comunque sempre vero)
Plane3d plPlane ;
if ( ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL) && ! bIsLine)
return false ;
@@ -167,7 +169,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// -------------------- OFFSET STANDARD ---------------------------------
if ( ! USE_VORONOI) {
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( m_dLinTol, ANG_TOL_STD_DEG))
return false ;
@@ -187,11 +189,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
if ( ! ccCopy.MergeCurves( m_dLinTol, ANG_TOL_STD_DEG, bClosed, true))
return false ;
// verifico se il punto iniziale è stato modificato
// verifico se il punto iniziale è stato modificato
Point3d ptNewStart ; ccCopy.GetStartPoint( ptNewStart) ;
bChangeStart = ( ! AreSamePointApprox( ptNewStart, ptStart)) ;
// calcolo le lunghezze delle diverse entità
// calcolo le lunghezze delle diverse entità
DBLVECTOR vLens ;
{
const ICurve* pCrv1 = ccCopy.GetFirstCurve() ;
@@ -203,7 +205,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
pCrv1 = ccCopy.GetNextCurve() ;
}
}
// calcolo gli angoli tra le diverse entità
// calcolo gli angoli tra le diverse entità
DBLVECTOR vAngs ;
{
vAngs.push_back( 0) ;
@@ -230,7 +232,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
vAngs.push_back( 0) ;
}
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
CurveComposite ccCopy2 ;
if ( ! ccCopy2.CopyFrom( &ccCopy))
return false ;
@@ -285,9 +287,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// se originale chiuso, devo confrontare anche ultima e prima curva
if ( bClosed && m_CrvLst.size() >= 2) {
// la curva precedente è l'ultima dell'offset
// la curva precedente è l'ultima dell'offset
ICurve* pCrv1 = m_CrvLst.back() ;
// la curva successiva ora è la prima dell'offset
// la curva successiva ora è la prima dell'offset
ICurve* pCrv2 = m_CrvLst.front() ;
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
CurveComposite ccTemp ;
@@ -334,7 +336,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
bool bNextInt = NextIsLine( iIter, m_CrvLst, bClosed) &&
NextIsLonger( nInd1, vLens, bClosed) &&
( ( dDist < 0 && vAngs[nInd1] > 0) || ( dDist > 0 && vAngs[nInd1] < 0)) ;
// calcolo la massima estensione di offset (Voronoi con entità adiacenti)
// calcolo la massima estensione di offset (Voronoi con entità adiacenti)
double dMaxDist = INFINITO ;
if ( bPrevInt && bNextInt) {
double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ;
@@ -502,7 +504,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
if ( ! bClosed) {
// ciconferenza sull'estremità iniziale
// ciconferenza sull'estremità iniziale
Point3d ptStart ; ccCopy.GetStartPoint( ptStart) ;
PtrOwner<CurveArc> pCircS( CreateBasicCurveArc()) ;
if ( IsNull( pCircS) || ! pCircS->Set( ptStart, Z_AX, abs( dDist)))
@@ -551,7 +553,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// passo alla successiva
++ iIter ;
}
// circonferenza sull'estremità finale
// circonferenza sull'estremità finale
Point3d ptEnd ; ccCopy.GetEndPoint( ptEnd) ;
PtrOwner<CurveArc> pCircE( CreateBasicCurveArc()) ;
if ( IsNull( pCircE) || ! pCircE->Set( ptEnd, Z_AX, abs( dDist)))
@@ -697,6 +699,27 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// calcolo offset con Voronoi
ICURVEPOVECTOR vOffs ;
voronoiObj->CalcOffset( vOffs, dDist, nType) ;
if ( vOffs.empty()) {
// se non ho ottenuto offset e sono circa al valore limite ritento con valore leggermente diverso per le tolleranze di vroni
double dMaxOffs ;
if ( ! pCrv->IsClosed() || ( voronoiObj->CalcLimitOffset( 0, dDist < 0, dMaxOffs) && abs( dMaxOffs - abs( dDist)) < EPS_SMALL)) {
double dCorr = ( dDist > 0 ? - VRONI_OFFS_TOL : VRONI_OFFS_TOL) ;
voronoiObj->CalcOffset( vOffs, dDist + dCorr, nType) ;
}
// se ancora vuoto calcolo i punti speciali di offset ( punti e direzioni sui bisettore alla distanza richiesta)
if ( vOffs.empty()) {
PNTVECTVECTOR vPntOffs ;
voronoiObj->CalcSpecialPointOffset( vPntOffs, dDist) ;
// NB al momento vengono gestiti solo i casi in cui vi è un unico punto di offset. Se si ottengono più punti di offset
// ( e.g. alcune curve aperte) non se ne restiusce nessuno. Da estendere, se necessario, individuando i punti dal lato
// di offset richiesto
if ( vPntOffs.size() == 1) {
m_ptOffs = vPntOffs[0].first ;
m_vtOut = vPntOffs[0].second ;
}
}
}
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++)
m_CrvLst.emplace_back( Release( vOffs[i])) ;
@@ -724,10 +747,21 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
pCrv->ToGlob( frCopy) ;
}
if ( m_ptOffs.IsValid()) {
m_ptOffs.Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
m_ptOffs.ToGlob( frCopy) ;
m_vtOut.Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
m_vtOut.ToGlob( frCopy) ;
}
}
else if ( bNeedRef) {
for ( auto pCrv : m_CrvLst)
pCrv->ToGlob( frCopy) ;
if ( m_ptOffs.IsValid()) {
m_ptOffs.ToGlob( frCopy) ;
m_vtOut.ToGlob( frCopy) ;
}
}
// assegno estrusione e spessore come curva originale e unisco parti allineate
@@ -805,6 +839,20 @@ OffsetCurve::GetShorterCurve( void)
return pCrv ;
}
//----------------------------------------------------------------------------
bool
OffsetCurve::GetPointOffset( Point3d& ptOffs, Vector3d& vtOut)
{
// verifico se valori validi da restituire
if ( ! m_ptOffs.IsValid() || ! m_vtOut.IsValid())
return false ;
ptOffs = m_ptOffs ;
vtOut = m_vtOut ;
return true ;
}
//----------------------------------------------------------------------------
bool
PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool bClosed)
@@ -817,7 +865,7 @@ PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bo
// se non esiste e curva chiusa prendo l'ultimo
if ( iPrev == CrvLst.end() && bClosed)
-- iPrev ;
// se non esiste o non è una linea, test fallito
// se non esiste o non è una linea, test fallito
if ( iPrev == CrvLst.end() || (*iPrev)->GetType() != CRV_LINE )
return false ;
// test superato
@@ -830,7 +878,7 @@ PreviousIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed)
{
// massimo indice nel vettore
int nMax = int( vLens.size()) - 1 ;
// verifico validità indice (questo indice è incrementato di 1)
// verifico validità indice (questo indice è incrementato di 1)
if ( nInd1 < 1 || nInd1 > nMax + 1)
return false ;
// indice del precedente nel vettore di lunghezze
@@ -854,7 +902,7 @@ NextIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool b
// se non esiste e curva chiusa prendo il primo
if ( iNext == CrvLst.end() && bClosed)
iNext = CrvLst.begin() ;
// se non esiste o non è una linea, test fallito
// se non esiste o non è una linea, test fallito
if ( iNext == CrvLst.end() || (*iNext)->GetType() != CRV_LINE )
return false ;
// test superato
@@ -867,7 +915,7 @@ NextIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed)
{
// massimo indice nel vettore
int nMax = int( vLens.size()) - 1 ;
// verifico validità indice (questo indice è incrementato di 1)
// verifico validità indice (questo indice è incrementato di 1)
if ( nInd1 < 1 || nInd1 > nMax + 1)
return false ;
// indice del successivo nel vettore di lunghezze
@@ -946,7 +994,7 @@ VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
nRes = 4 ;
return true ;
}
// se coincidono esattamente, va bene così
// se coincidono esattamente, va bene così
if ( AreSamePointExact( ptP1, ptP2)) {
nRes = 0 ;
return true ;
@@ -976,7 +1024,7 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
IntersCurveCurve intCC( *pCrv1, *pCrv2) ;
if ( intCC.GetIntersCount() == 0)
return false ;
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
Point3d ptP1, ptP2 ;
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
return false ;
@@ -1024,7 +1072,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
vtDir2.Invert() ;
}
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposte)
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposte)
if ( abs( dAngDeg) < ( ANG_STRAIGHT - 10 * EPS_ANG_ZERO) &&
( ( dDist < 0 && dAngDeg > 0) ||
( dDist > 0 && dAngDeg < 0)))
@@ -1066,7 +1114,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
return false ;
ptP1a = ptP1 + vtDir1 * dLen ;
ptP2a = ptP2 - vtDir2 * dLen ;
// se prima c'è linea posso allungarla
// se prima c'è linea posso allungarla
if ( pCrv1->GetType() == CRV_LINE)
pCrv1->ModifyEnd( ptP1a) ;
// altrimenti, devo aggiungere una nuova linea
@@ -1085,7 +1133,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
if ( ! ccAux.AddCurve( Release( pCrv)))
return false ;
}
// se dopo c'è linea posso allungarla
// se dopo c'è linea posso allungarla
if ( pCrv2->GetType() == CRV_LINE)
pCrv2->ModifyStart( ptP2a) ;
// altrimenti, devo aggiungere una nuova linea
@@ -1108,7 +1156,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
return false ;
ptPc = ptP1 + vtDir1 * dLen ;
// se prima c'è linea o angolo molto piccolo posso allungarla
// se prima c'è linea o angolo molto piccolo posso allungarla
if ( ( pCrv1->GetType() == CRV_LINE) || bAngSmall)
pCrv1->ModifyEnd( ptPc) ;
// altrimenti, devo aggiungere una nuova linea
@@ -1119,7 +1167,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
if ( ! ccAux.AddCurve( Release( pCrv)))
return false ;
}
// se dopo c'è linea o angolo molto piccolo posso allungarla
// se dopo c'è linea o angolo molto piccolo posso allungarla
if ( ( pCrv2->GetType() == CRV_LINE) || bAngSmall)
pCrv2->ModifyStart( ptPc) ;
// altrimenti, devo aggiungere una nuova linea
+2 -2
View File
@@ -195,7 +195,7 @@ PointGrid3d::Find( const Point3d& ptTest, double dTol, INTVECTOR& vnIds) const
}
}
return ( vnIds.size() > 0) ;
return ( ! vnIds.empty()) ;
}
//----------------------------------------------------------------------------
@@ -221,7 +221,7 @@ PointGrid3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
}
}
return ( vnIds.size() > 0) ;
return ( ! vnIds.empty()) ;
}
//----------------------------------------------------------------------------
+41 -31
View File
@@ -14,36 +14,28 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "PointsPCA.h"
#include "/EgtDev/Extern/Eigen/Dense"
//----------------------------------------------------------------------------
PointsPCA::PointsPCA( void)
{
// azzero numero punti
m_dTotW = 0 ;
// azzero il baricentro
m_ptCen.Set( 0, 0, 0) ;
// azzero matrice di covarianza
m_CovMat.setZero() ;
// inizializzo il rank ad un valore assurdo
m_nRank = - 1 ;
// inizializzo baricentro
m_ptCen.Set( 0, 0, 0) ;
// inizializzo il peso totale
m_dTotW = 0 ;
// riservo memoria per la matrice di punti e pesi
m_vPntW.reserve( 128) ;
}
//----------------------------------------------------------------------------
void
PointsPCA::AddPoint( const Point3d& ptP, double dW)
{
// incremento numero punti
m_dTotW += dW ;
// aggiorno il baricentro
m_ptCen += dW * ptP ;
// aggiorno la matrice di covarianza (solo triangolo superiore perchč simmetrica)
m_CovMat(0,0) += dW * ( ptP.x * ptP.x) ;
m_CovMat(1,1) += dW * ( ptP.y * ptP.y) ;
m_CovMat(2,2) += dW * ( ptP.z * ptP.z) ;
m_CovMat(0,1) += dW * ( ptP.x * ptP.y) ;
m_CovMat(0,2) += dW * ( ptP.x * ptP.z) ;
m_CovMat(1,2) += dW * ( ptP.y * ptP.z) ;
// salvo i dati
m_vPntW.emplace_back( ptP, dW) ;
}
//----------------------------------------------------------------------------
@@ -58,29 +50,47 @@ PointsPCA::Finalize( void)
m_nRank = 0 ;
// se non sono stati assegnati punti, esco
if ( m_dTotW < EPS_ZERO)
if ( m_vPntW.empty())
return false ;
// fattore di scala per numero di punti
// calcolo del peso totale
for ( const auto& PntW : m_vPntW)
m_dTotW += PntW.second ;
if ( m_dTotW < EPS_ZERO)
return false ;
// fattore di scala
double dScale = 1 / m_dTotW ;
// calcolo del baricentro
for ( const auto& PntW : m_vPntW)
m_ptCen += PntW.second * PntW.first ;
m_ptCen *= dScale ;
// completo la matrice di covarianza
m_CovMat(0,0) = m_CovMat(0,0) * dScale - m_ptCen.x * m_ptCen.x ;
m_CovMat(1,1) = m_CovMat(1,1) * dScale - m_ptCen.y * m_ptCen.y ;
m_CovMat(2,2) = m_CovMat(2,2) * dScale - m_ptCen.z * m_ptCen.z ;
m_CovMat(0,1) = m_CovMat(0,1) * dScale - m_ptCen.x * m_ptCen.y ;
m_CovMat(0,2) = m_CovMat(0,2) * dScale - m_ptCen.x * m_ptCen.z ;
m_CovMat(1,2) = m_CovMat(1,2) * dScale - m_ptCen.y * m_ptCen.z ;
m_CovMat(1,0) = m_CovMat(0,1) ;
m_CovMat(2,0) = m_CovMat(0,2) ;
m_CovMat(2,1) = m_CovMat(1,2) ;
// matrice di covarianza
Eigen::Matrix3d CovMat ;
CovMat.setZero() ;
for ( const auto& PntW : m_vPntW) {
Point3d ptP( PntW.first.x - m_ptCen.x, PntW.first.y - m_ptCen.y, PntW.first.z - m_ptCen.z) ;
CovMat(0,0) += PntW.second * ( ptP.x * ptP.x) ;
CovMat(1,1) += PntW.second * ( ptP.y * ptP.y) ;
CovMat(2,2) += PntW.second * ( ptP.z * ptP.z) ;
CovMat(0,1) += PntW.second * ( ptP.x * ptP.y) ;
CovMat(0,2) += PntW.second * ( ptP.x * ptP.z) ;
CovMat(1,2) += PntW.second * ( ptP.y * ptP.z) ;
}
CovMat(0,0) = CovMat(0,0) * dScale ;
CovMat(1,1) = CovMat(1,1) * dScale ;
CovMat(2,2) = CovMat(2,2) * dScale ;
CovMat(0,1) = CovMat(0,1) * dScale ;
CovMat(0,2) = CovMat(0,2) * dScale ;
CovMat(1,2) = CovMat(1,2) * dScale ;
CovMat(1,0) = CovMat(0,1) ;
CovMat(2,0) = CovMat(0,2) ;
CovMat(2,1) = CovMat(1,2) ;
// calcolo gli autovalori e autovettori (essendo matrice 3x3 uso metodo diretto)
// calcolo gli autovalori e autovettori
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es ;
es.compute( m_CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
es.compute( CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
if ( es.info() == Eigen::NoConvergence)
return false ;
+3 -4
View File
@@ -13,8 +13,7 @@
#pragma once
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Extern/Eigen/Dense"
#include "/EgtDev/Include/EGkGeoCollection.h"
//----------------------------------------------------------------------------
class PointsPCA
@@ -33,9 +32,9 @@ class PointsPCA
static const int MAX_RANK = 3 ;
private :
double m_dTotW ; // peso totale (se pesi tutti unitari, allora è numero punti)
PNTUVECTOR m_vPntW ; // vettore dei punti con i loro pesi
Point3d m_ptCen ; // baricentro
Eigen::Matrix3d m_CovMat ; // matrice di covarianza
double m_dTotW ; // peso totale
int m_nRank ; // numero delle componenti principali (MAX_RANK = 3)
Vector3d m_vtPC[MAX_RANK] ; // direzioni delle componenti principali
} ;
+3 -3
View File
@@ -62,7 +62,7 @@ bool
PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
{
// se il punto è uguale al precedente (ignoro parametro e bulge), non lo inserisco ma ok
if ( m_lUPointBs.size() > 0 && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
if ( ! m_lUPointBs.empty() && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
// assegno parametro e bulge
m_lUPointBs.back().dU = dPar ;
m_lUPointBs.back().dB = dBulge ;
@@ -285,10 +285,10 @@ bool
PolyArc::Join( PolyArc& PA, double dOffsetPar)
{
// se l'altro poliarco non contiene alcunchè, esco con ok
if ( PA.m_lUPointBs.size() == 0)
if ( PA.m_lUPointBs.empty())
return true ;
// verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro
if ( m_lUPointBs.size() > 0 && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
if ( ! m_lUPointBs.empty() && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
return false ;
// cancello l'ultimo di questo
EraseLastUPoint() ;
+67 -20
View File
@@ -54,7 +54,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
// se da aggiungere in coda
if ( bEndOrStart) {
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
++ m_nRejected ;
return true ;
}
@@ -69,7 +69,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
// altrimenti si aggiunge in testa
else {
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
++ m_nRejected ;
return true ;
}
@@ -234,10 +234,10 @@ bool
PolyLine::Join( PolyLine& PL, double dOffsetPar)
{
// se l'altra polilinea non contiene alcunchè, esco con ok
if ( PL.m_lUPoints.size() == 0)
if ( PL.m_lUPoints.empty())
return true ;
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
if ( m_lUPoints.size() > 0 && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
if ( ! m_lUPoints.empty() && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
return false ;
// cancello l'ultimo di questa
EraseLastUPoint() ;
@@ -587,18 +587,29 @@ PolyLine::IsClosedAndFlat( Plane3d& plPlane, double& dArea, double dToler) const
// Test if closed
if ( ! IsClosed())
return false ;
// Compute a representative plane for the polygon
Point3d ptP ;
// Calcolo il centro (per minimizzare gli errori nelle successive operazioni)
Point3d ptCen = ORIG ;
int nCount = 0 ;
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
ptCen += ptP ;
++ nCount ;
}
ptCen /= nCount ;
Vector3d vtMove = ptCen - ORIG ;
// Compute a representative plane for the polygon (faccio il calcolo nel centro e poi traslo al contrario il piano)
PolygonPlane PolyPlane ;
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP))
PolyPlane.AddPoint( ptP) ;
PolyPlane.AddPoint( ptP - vtMove) ;
if ( ! PolyPlane.GetPlane( plPlane) || ! PolyPlane.GetArea( dArea)) {
dArea = 0 ;
return IsFlat( plPlane, dToler) ;
}
plPlane.Translate( vtMove) ;
// Sistemo il piano per l'offset utilizzato
// Test each vertex to see if it is farther from plane than allowed max distance
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
double dDist = ( ( ptP - ORIG) * plPlane.GetVersN()) - plPlane.GetDist() ;
double dDist = DistPointPlane( ptP, plPlane) ;
if ( abs( dDist) > dToler)
return false ;
}
@@ -1074,15 +1085,8 @@ PolyLine::Invert( bool bInvertU)
//----------------------------------------------------------------------------
bool
PolyLine::Flatten( double dZ)
PolyLine::MyRemoveSamePoints( double dToler)
{
// verifico non sia vuota
if ( m_lUPoints.empty())
return true ;
// ciclo su tutti gli elementi per portarli alla Z indicata
for ( auto& UPoint : m_lUPoints) {
UPoint.first.z = dZ ;
}
// elimino i punti consecutivi diventati coincidenti (almeno 2)
if ( m_lUPoints.size() < 2)
return true ;
@@ -1093,7 +1097,7 @@ PolyLine::Flatten( double dZ)
// mentre esiste un corrente
while ( currP != m_lUPoints.end()) {
// se coincidono
if ( AreSamePointApprox( precP->first, currP->first)) {
if ( AreSamePointEpsilon( precP->first, currP->first, dToler)) {
// elimino il punto corrente
currP = m_lUPoints.erase( currP) ;
// il precedente rimane inalterato
@@ -1108,6 +1112,50 @@ PolyLine::Flatten( double dZ)
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::Flatten( double dZ)
{
// verifico non sia vuota
if ( m_lUPoints.empty())
return true ;
// ciclo su tutti gli elementi per portarli alla Z indicata
for ( auto& UPoint : m_lUPoints)
UPoint.first.z = dZ ;
// elimino i punti consecutivi diventati coincidenti
MyRemoveSamePoints() ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::FlattenInAutoPlane( double dToler)
{
// verifico non sia vuota
if ( m_lUPoints.empty())
return true ;
// recupero dati sulla planarità della polilinea
int nRank ;
Point3d ptCen ;
Vector3d vtDir ;
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
// se non planare entro la tolleranza, esco
if ( ! bFlat)
return false ;
// se punto o linea, non devo fare alcunché
if ( nRank == 0 || nRank == 1)
return true ;
// assegno il piano medio
Plane3d plPlane ;
plPlane.Set( ptCen, vtDir) ;
// proietto i punti su questo piano
for ( auto& UPoint : m_lUPoints)
UPoint.first = ProjectPointOnPlane( UPoint.first, plPlane) ;
// elimino i punti consecutivi diventati coincidenti
MyRemoveSamePoints() ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::GetConvexHullXY( PNTVECTOR& vConvHull) const
@@ -1278,7 +1326,7 @@ bool
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
{
// se vuota non faccio alcunché
if ( m_lUPoints.size() == 0)
if ( m_lUPoints.empty())
return false ;
// determino le intersezioni dei lati con il piano
@@ -1597,7 +1645,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
// distanza del punto dal segmento della polilinea
DistPointLine PointLineDistCalc( vPnt1[i].first, vPnt2[j-1].first, vPnt2[j].first) ;
double dPlDist ;
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist) {
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) {
dDist = dPlDist ;
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
dMinDistPar += j - 1 ;
@@ -1628,8 +1676,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
// distanza del punto dal segmento della polilinea
DistPointLine PointLineDistCalc( vPnt2[j].first, vPnt1[i-1].first, vPnt1[i].first) ;
double dPlDist ;
PointLineDistCalc.GetDist( dPlDist) ;
if ( dPlDist < dDist) {
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) {
dDist = dPlDist ;
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
dMinDistPar += i - 1 ;
+784
View File
@@ -0,0 +1,784 @@
//----------------------------------------------------------------------------
// EgalTech 2023-2023
//----------------------------------------------------------------------------
// File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
//
//
//
// Modifiche : 31.08.23 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkProjectCurveSurf.h"
using namespace std ;
//----------------------------------------------------------------------------
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
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
const double COS_ANG_MAX_CORNER = 0.8660 ;
// Tipologia di punto
const int P5AX_TO_DELETE = -1 ; // da cancellare
const int P5AX_OUT = 0 ; // aggiunto prima di inizio o dopo fine
const int P5AX_STD = 1 ; // standard
const int P5AX_CVEX = 2 ; // su angolo convesso
const int P5AX_CONC = 3 ; // in angolo concavo
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
//----------------------------------------------------------------------------
static bool
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
{
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
double dSqDist ;
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir)
{
// Parametri di riferimento
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
double dSqTol = dLinTol * dLinTol ;
const double LENREF = 200 ;
double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ;
// Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo
int nInd = 0 ;
while ( nInd < int( vPt5ax.size())) {
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
// analizzo i punti appena precedenti
int nIpv = nInd - 1 ;
while ( nIpv >= 0) {
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nIpv].ptP) ;
if ( dSqLen < dSqMaxLen)
vPt5ax[nIpv].nFlag = P5AX_TO_DELETE ;
else {
vPt5ax[nIpv].nFlag = P5AX_BEFORE_CONC ;
break ;
}
-- nIpv ;
}
// analizzo i punti appena successivi
int nInx = nInd + 1 ;
while ( nInx < int( vPt5ax.size())) {
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
if ( dSqLen < dSqMaxLen)
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
else {
vPt5ax[nInx].nFlag = P5AX_AFTER_CONC ;
break ;
}
++ nInx ;
}
}
++ nInd ;
}
// Rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
int nCnt = 0 ;
int nPrec = 0 ;
int nCurr = 1 ;
int nNext = 2 ;
while ( nNext < int( vPt5ax.size())) {
bool bRemove = false ;
// lunghezza del segmento che unisce gli adiacenti
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
// se rimovibile (Flag standard) e lunghezza inferiore al massimo, passo agli altri controlli
if ( vPt5ax[nCurr].nFlag == P5AX_STD && dSqLen <= dSqMaxLen) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( vPt5ax[nCurr].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
double dSqDist ;
// se distanza inferiore a tolleranza lineare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vPt5ax, nPrec, nCurr, nNext, dSqTol)) {
// verifico se errore angolare inferiore a limite
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
if ( bTestDir) {
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir1, vPt5ax[nNext].vtDir1, dPar) ;
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir1 > dCosAngLim)
bRemove = true ;
}
else {
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir2, vPt5ax[nNext].vtDir2, dPar) ;
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir2 > dCosAngLim)
bRemove = true ;
}
}
}
// se da eliminare
if ( bRemove) {
// dichiaro da eliminare il punto
vPt5ax[nCurr].nFlag = P5AX_TO_DELETE ;
// avanzo con corrente e successivo
nCurr = nNext ;
++ nNext ;
}
// altrimenti da tenere
else {
// avanzo il terzetto di uno step
nPrec = nCurr ;
nCurr = nNext ;
++ nNext ;
// incremento contatore dei punti conservati
++ nCnt ;
}
}
// Copio i punti da conservare in un vettore temporaneo
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( nCnt) ;
for ( const auto& Pt5ax : vPt5ax) {
if ( Pt5ax.nFlag != P5AX_TO_DELETE)
vMyPt5ax.emplace_back( Pt5ax) ;
}
// scambio i due vettori
vPt5ax.swap( vMyPt5ax) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3d& frRefLine, const IntersParLinesSurfTm& intPLSTM,
double dPar, Point5ax& Pt5ax)
{
// intersezione retta di proiezione con superficie
Point3d ptL = GetToLoc( ptP, frRefLine) ;
ILSIVECTOR vIntRes ;
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! stmSurf.GetTriangle( vIntRes[nI].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 = frRefLine.VersZ() ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vtDir,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ;
switch ( sfSurf.GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
break ;
case SRF_BEZIER :
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea alla massima risoluzione
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
Frame3d frRefLine ;
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
IntersParLinesSurfTm intPLSTM( frRefLine, *pSurfTm) ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, frRefLine, intPLSTM, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
// precedente
int j = i - 1 ;
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
// intersezione tra le due facce
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
Point3d ptEdge ; Vector3d vtEdge ;
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, ( vPt5ax[i].ptP - vPt5ax[j].ptP) ^ vtDir) ;
Point3d ptInt ;
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
// verifico se spigolo convesso o concavo
bool bConvex ;
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
else
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
// se convesso, metto due punti con direzione appena prima e appena dopo
if ( bConvex) {
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
if ( dLen1 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = vtDir ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
if ( dLen2 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vtDir ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
}
// altrimenti concavo, aggiungo un solo punto con la direzione media
else {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ;
Pt5ax.vtDir2 = vtDir ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
}
}
}
}
}
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
{
// punto di riferimento
Point3d ptMin = gpRef.GetPoint() ;
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) {
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! stmSurf.GetTriangle( vIntRes[nI].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 ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ;
switch ( sfSurf.GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
break ;
case SRF_BEZIER :
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, gpRef, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli
if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
// precedente
int j = i - 1 ;
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
// punto medio
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptMid, *pSurfTm, gpRef, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ;
}
}
}
}
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
{
// punto a minima distanza
DistPointCurve dPC( ptP, crRef) ;
Point3d ptMin ;
int nFlag ;
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) {
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! stmSurf.GetTriangle( vIntRes[nI].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 ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{
// Sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ;
switch ( sfSurf.GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
break ;
case SRF_BEZIER :
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
// Controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// Approssimo la curva con una polilinea alla massima risoluzione
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, crRef, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
// precedente
int j = i - 1 ;
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
// intersezione tra le due facce
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
Point3d ptEdge ; Vector3d vtEdge ;
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir2 ^ vPt5ax[j].vtDir2) ;
Point3d ptInt ;
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
// verifico se spigolo convesso o concavo
bool bConvex ;
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
else
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
// se convesso, metto due punti con direzione appena prima e appena dopo
if ( bConvex) {
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
if ( dLen1 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
if ( dLen2 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
}
// altrimenti concavo, aggiungo un solo punto con la direzione media
else {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
}
}
}
}
}
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
{
// punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, stmRef) ;
Point3d ptMin ;
int nTriaMin ;
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
// recupero direzione della retta di minima distanza, altrimenti normale alla superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL)
vtLine /= dLineLen ;
else {
// calcolo la normale della superficie guida
Triangle3dEx trGuide ;
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
return false ;
if ( ! CalcNormal( ptMin, trGuide, vtLine))
vtLine = trGuide.GetN() ;
dLineLen = 100 ;
}
// intersezione della retta con la superficie
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) {
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! stmSurf.GetTriangle( vIntRes[nI].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 ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
const SurfTriMesh* pSurfTm = nullptr ;
switch ( sfSurf.GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
break ;
case SRF_BEZIER :
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
// sistemazioni per tipo di superficie di riferimento
const SurfTriMesh* pRefTm = nullptr ;
switch ( sfRef.GetType()) {
case SRF_TRIMESH :
pRefTm = GetBasicSurfTriMesh( &sfRef) ;
break ;
case SRF_BEZIER :
pRefTm = GetBasicSurfBezier( &sfRef)->GetAuxSurf() ;
break ;
case SRF_FLATRGN :
pRefTm = GetBasicSurfFlatRegion( &sfRef)->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pRefTm == nullptr)
return false ;
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, *pSurfTm, *pRefTm, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli
if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
// precedente
int j = i - 1 ;
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
// punto medio
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptMid, *pSurfTm, *pRefTm, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ;
}
}
}
}
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
-414
View File
@@ -1,414 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2023-2023
//----------------------------------------------------------------------------
// File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
//
//
//
// Modifiche : 31.08.23 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
using namespace std ;
//----------------------------------------------------------------------------
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
const double COS_ANG_LIM = 0.0175 ;
//----------------------------------------------------------------------------
static bool
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
{
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
double dSqDist ;
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, double dLinTol, double dMaxSegmLen)
{
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
double dSqTol = dLinTol * dLinTol ;
int nPrec = 0 ;
int nCurr = 1 ;
int nNext = 2 ;
while ( nNext < int( vMyPt5ax.size())) {
bool bRemove = false ;
// lunghezza del segmento che unisce gli adiacenti
double dSqLen = SqDist( vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
// se lunghezza inferiore al massimo, passo agli altri controlli
if ( dSqLen <= dSqMaxLen) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( vMyPt5ax[nCurr].ptP, vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
double dSqDist ;
// se distanza inferiore a tolleranza lineare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vMyPt5ax, nPrec, nCurr, nNext, dSqTol)) {
// verifico se errore angolare inferiore a limite
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ;
if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > cos( 2 * DEGTORAD))
bRemove = true ;
}
}
// se da eliminare
if ( bRemove) {
// dichiaro da eliminare il punto
vMyPt5ax[nCurr].nFlag = -1 ;
// avanzo con corrente e successivo
nCurr = nNext ;
++ nNext ;
}
// altrimenti da tenere
else {
// avanzo il terzetto di uno step
nPrec = nCurr ;
nCurr = nNext ;
++ nNext ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
PNT5AXVECTOR& vPt5ax)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea alla massima risoluzione
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
Frame3d frRefLine ;
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// intersezione retta di proiezione con superficie
Point3d ptL = GetToLoc( ptP, frRefLine) ;
ILSIVECTOR vIntRes ;
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, dPar, 1) ;
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// punto di riferimento
Point3d ptMin = gpRef.GetPoint() ;
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
}
}
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea alla massima risoluzione
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// punto sulla curva a minima distanza
DistPointCurve dPC( ptP, crRef) ;
Point3d ptMin ;
int nFlag ;
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
}
}
}
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ISurfTriMesh& tmRef,
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, tmRef) ;
Point3d ptMin ;
int nTriaMin ;
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
// 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) {
// calcolo il punto
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// calcolo la normale della superficie guida
Triangle3dEx trGuide ;
if ( ! tmRef.GetTriangle( nTriaMin, trGuide))
return false ;
Vector3d vtN2 ;
double dU2, dV2, dW2 ;
if ( BarycentricCoord( ptMin, trGuide, dU2, dV2, dW2))
vtN2 = dU2 * trGuide.GetVertexNorm( 0) + dV2 * trGuide.GetVertexNorm( 1) + dW2 * trGuide.GetVertexNorm( 2) ;
if ( ! vtN2.Normalize())
vtN2 = trGuide.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, vtN2, dPar, 1) ;
}
}
}
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
+1407
View File
File diff suppressed because it is too large Load Diff
+34 -1
View File
@@ -17,12 +17,13 @@
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "/EgtDev/Include/EGkSbzStandard.h"
#include "/EgtDev/Include/EGkSbzFromCurves.h"
using namespace std ;
//-------------------------------------------------------------------------------
ISurfBezier*
CreateBezierSphere( const Point3d& ptCenter, double dR)
GetSurfBezierSphere( const Point3d& ptCenter, double dR)
{
// creo una superficie di Bezier di grado 2 con 45 punti di controllo
PtrOwner<ISurfBezier> pSrfBez( CreateSurfBezier()) ;
@@ -78,3 +79,35 @@ CreateBezierSphere( const Point3d& ptCenter, double dR)
return Release( pSrfBez) ;
}
////-------------------------------------------------------------------------------
//ISurfBezier*
//GetSurfBezierCone( const Point3d& ptCenter, double dRadius, const Vector3d& dHeight)
//{
// // le dimensioni devono essere significative
// if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL)
// return nullptr ;
// // creo la circonferenza di base
// CurveArc cArc ;
// cArc.Set( ORIG, Z_AX, dRadius) ;
// if ( dHeight < 0)
// cArc.Invert() ;
// // punto di vertice
// Point3d ptTip( 0, 0, dHeight) ;
// // creo la superficie laterale del cono
// PtrOwner<ISurfBezier> pSbz( GetSurfBezierRuled( ptTip, &cArc)) ;
// if ( IsNull( pSbz))
// return nullptr ;
//
// //// creo la superficie di base e la inverto
// //PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc, dLinTol)) ;
// //if ( IsNull( pSTM1))
// // return nullptr ;
// //pSTM1->Invert() ;
// //// la unisco alla superficie del fianco
// //if ( ! pSTM->DoSewing( *pSTM1))
// // return nullptr ;
//
// // restituisco la superficie
// return Release( pSbz) ;
//}
+3 -1
View File
@@ -88,6 +88,8 @@ SelfIntersCurve::SelfIntersCurve( const ICurve& Curve)
}
}
break ;
default :
break ;
}
// per curva approssimata, sistemo...
AdjustIntersParams( ( pCalcCrv != m_pCurve), pCalcCrv, vTmpPar) ;
@@ -133,7 +135,7 @@ bool
SelfIntersCurve::AdjustIntersParams( bool bAdjCrv, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar)
{
// se la curva originale non è stata approssimata o non ci sono auto-intersezioni, non va fatto alcunché
if ( ! bAdjCrv || m_Info.size() == 0)
if ( ! bAdjCrv || m_Info.empty())
return true ;
// procedo ad aggiustare
for ( auto& aInfo : m_Info) {
+141 -30
View File
@@ -367,25 +367,14 @@ GetSurfFlatRegionFromTriangle( const Triangle3d& Tria)
ISurfFlatRegion*
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
{
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( ContourPolyLine))
return nullptr ;
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pLoop)))
return nullptr ;
Point3d ptSt, ptEn ;
bool bContinue = ContourPolyLine.GetFirstPoint( ptSt) &&
ContourPolyLine.GetNextPoint( ptEn) ;
while ( bContinue) {
CurveLine cvLine ;
cvLine.Set( ptSt, ptEn) ;
pLoop->AddCurve( cvLine) ;
ptSt = ptEn ;
bContinue = ContourPolyLine.GetNextPoint( ptEn) ;
}
pSfr->AddExtLoop( Release( pLoop)) ;
return Release( pSfr) ;
}
@@ -401,25 +390,17 @@ GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
for ( int nL = 0 ; nL < int( vContoursPolyLineVec.size()) ; ++ nL) {
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( vContoursPolyLineVec[nL]))
return nullptr ;
Point3d ptSt, ptEn ;
bool bContinue = vContoursPolyLineVec[nL].GetFirstPoint( ptSt) &&
vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
while ( bContinue) {
CurveLine cvLine ;
cvLine.Set( ptSt, ptEn) ;
pLoop->AddCurve( cvLine) ;
ptSt = ptEn ;
bContinue = vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
}
// Loop esterno
if ( nL == 0) {
pSfr->AddExtLoop( Release( pLoop)) ;
if ( ! pSfr->AddExtLoop( Release( pLoop)))
return nullptr ;
}
// Loop interno
else {
pSfr->AddIntLoop( Release( pLoop)) ;
if ( ! pSfr->AddIntLoop( Release( pLoop)))
return nullptr ;
}
}
return Release( pSfr) ;
@@ -590,4 +571,134 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
vId.push_back( pCrv->GetTempProp()) ;
}
return ( ! vId.empty()) ;
}
}
//-------------------------------------------------------------------------------
bool
CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert)
{
// vnPLIndMat : ogni riga corrisponde ad un chunk, in posizione 0 c'è il loop esterno e nelle successive i loop interni
// vbInvert : riferito al vettore delle polyline, riporta true se la polyline è stata invertita
// ricavo versore normale
Plane3d plPlane ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
vtN = plPlane.GetVersN() ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
VCT3DVECTOR vvtN ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
return false ;
// salvo la normale
vvtN.push_back( plPlane.GetVersN()) ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// restituisco la normale del loop più grande
bool bInvertAll = vvtN[m_vArea[0].first] * vtN < 0 ;
vtN = vvtN[m_vArea[0].first] ;
//// vettore di indici per ordinare le PolyLine
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
vPL_IndOrder[i] = m_vArea[i].first ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
vbInvert.resize( vPL.size()) ;
fill( vbInvert.begin(), vbInvert.end(), false) ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
vbInvert[j] = true ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vCrvCompo[j]->Invert() ;
vbInvert[j] = true ;
}
}
}
}
} while ( ! bFirstCrv) ;
if ( bInvertAll) {
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
vbInvert[i] = ! vbInvert[i] ;
}
return true ;
}
+35 -147
View File
@@ -31,10 +31,6 @@
using namespace std ;
//-------------------------------------------------------------------------------
static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN) ;
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol)
@@ -65,12 +61,25 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
return nullptr ;
// calcolo le polilinee che approssimano le curve della regione
POLYLINEVECTOR vPL ;
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return nullptr ;
}
Vector3d vtN ;
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
INTMATRIX vnPLIndMat ;
BOOLVECTOR vbInvert ;
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
return nullptr ;
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
if( vbInvert[vnPLIndMat[i][j]])
vPL[vnPLIndMat[i][j]].Invert() ;
}
}
// creo e setto la superficie trimesh
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL, vnPLIndMat))
return nullptr ;
// salvo tolleranza lineare usata
pSTM->SetLinearTolerance( dLinTol) ;
@@ -145,9 +154,20 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
return GetSurfTriMeshByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
// calcolo le polilinee che approssimano le curve della regione
POLYLINEVECTOR vPL ;
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return nullptr ;
}
Vector3d vtN ;
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
INTMATRIX vnPLIndMat ;
BOOLVECTOR vbInvert ;
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
return nullptr ;
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
if( vbInvert[i])
vPL[i].Invert() ;
}
// verifico la direzione di estrusione
double dOrthoExtr = vtN * vtExtr ;
if ( ( abs( dOrthoExtr) < EPS_SMALL))
@@ -159,7 +179,8 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
}
// creo la prima superficie di estremità
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
// alla funzione CreateByRegion passo anche la matrice che contiene la struttura dei chunk. Le polyline hanno già il verso giusto
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL, vnPLIndMat))
return nullptr ;
// creo la seconda superficie e la unisco alla prima
{ // copio la prima superficie
@@ -1279,8 +1300,9 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
}
}
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
if ( ! pSci->CreateByRegion( vPLi))
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
INTMATRIX vnPLIndMat ;
if ( ! pSci->CreateByRegion( vPLi, vnPLIndMat))
return nullptr ;
pStmSwept->DoSewing( *pSci) ;
// recupero i loops alla fine
@@ -1288,8 +1310,9 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
if ( ! pStmSwept->GetLoops( vPLe))
return nullptr ;
// creo la superficie alla fine e la attacco
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
if ( ! pSce->CreateByRegion( vPLe))
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
vnPLIndMat.clear() ;
if ( ! pSce->CreateByRegion( vPLe, vnPLIndMat))
return nullptr ;
// attacco la superficie finale alla swept
pSce->Invert() ;
@@ -1433,138 +1456,3 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
bool
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN)
{
// se non ho curve, non faccio nulla
if ( int( vpCurve.size()) == 0)
return true ;
// calcolo le polilinee che approssimano le curve
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return false ;
}
// ricavo versore normale
Plane3d plPlane ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
vtN = plPlane.GetVersN() ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// vettore di indici per ordinare le PolyLine
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
vPL_IndOrder[i] = m_vArea[i].first ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// ordino le PolyLine per area
POLYLINEVECTOR vPL_tmp ;
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
swap( vPL, vPL_tmp) ;
return true ;
}
+123 -6
View File
@@ -22,6 +22,18 @@
using namespace std ;
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshEmpty( void)
{
// creo oggetto con superficie vuota
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->AdjustTopology())
return nullptr ;
// restituisco la superficie
return Release( pStm) ;
}
//-------------------------------------------------------------------------------
static SurfTriMesh*
GetStandardSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
@@ -160,15 +172,15 @@ GetSurfTriMeshPyramid( double dDimX, double dDimY, double dHeight)
return nullptr ;
// creo la polilinea del contorno della base
PolyLine PL ;
PL.AddUPoint( 0, ORIG) ;
PL.AddUPoint( 1, Point3d( dDimX, 0, 0)) ;
PL.AddUPoint( 2, Point3d( dDimX, dDimY, 0)) ;
PL.AddUPoint( 3, Point3d( 0, dDimY, 0)) ;
PL.AddUPoint( 4, ORIG) ;
PL.AddUPoint( 0, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
PL.AddUPoint( 1, Point3d( dDimX / 2, -dDimY / 2, 0)) ;
PL.AddUPoint( 2, Point3d( dDimX / 2, dDimY / 2, 0)) ;
PL.AddUPoint( 3, Point3d( -dDimX / 2, dDimY / 2, 0)) ;
PL.AddUPoint( 4, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
if ( dHeight < 0)
PL.Invert() ;
// punto di vertice
Point3d ptTip( 0.5 * dDimX, 0.5 * dDimY, dHeight) ;
Point3d ptTip( 0, 0, dHeight) ;
// creo e setto la superficie trimesh laterale
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL))
@@ -245,6 +257,111 @@ GetSurfTriMeshSphere( double dRadius, double dLinTol)
return GetSurfTriMeshByRevolve( &cArc, ORIG, Z_AX, true, dLinTol) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshPyramidFrustum( double dBaseDimX, double dBaseDimY, double dTopDimX, double dTopDimY, double dHeight)
{
// le dimensioni devono essere significative
if ( ( min( dBaseDimX, dBaseDimY) < EPS_SMALL && min( dTopDimX, dTopDimY) < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
return nullptr ;
// se piramide
if ( min( dTopDimX, dTopDimY) < EPS_SMALL)
return GetSurfTriMeshPyramid( dBaseDimX, dBaseDimY, dHeight) ;
// se piramide inversa
if ( min( dBaseDimX, dBaseDimY) < EPS_SMALL)
return GetSurfTriMeshPyramid( dTopDimX, dTopDimY, -dHeight) ;
// se parallelepipedo
// continuo qui per avere l'origine in centro e non sullo spigolo in basso a sinistra
// creo la polilinea del contorno della base
PolyLine PL1 ;
PL1.AddUPoint( 0, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
PL1.AddUPoint( 1, Point3d( dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
PL1.AddUPoint( 2, Point3d( dBaseDimX / 2 , dBaseDimY / 2, 0)) ;
PL1.AddUPoint( 3, Point3d( -dBaseDimX / 2, dBaseDimY / 2, 0)) ;
PL1.AddUPoint( 4, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
if ( dHeight < 0)
PL1.Invert() ;
// creo la polilinea del contorno di sopra
PolyLine PL2 ;
PL2.AddUPoint( 0, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
PL2.AddUPoint( 1, Point3d( dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
PL2.AddUPoint( 2, Point3d( dTopDimX / 2, dTopDimY / 2, dHeight)) ;
PL2.AddUPoint( 3, Point3d( -dTopDimX / 2, dTopDimY / 2, dHeight)) ;
PL2.AddUPoint( 4, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
if ( dHeight < 0)
PL2.Invert() ;
// creo e setto la superficie trimesh laterale
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR_SMOOTH))
return nullptr ;
// creo la superficie di base e ne inverto la normale
SurfTriMesh STM1 ;
if ( ! STM1.CreateByFlatContour( PL1))
return nullptr ;
STM1.Invert() ;
// la unisco alla superficie del fianco
if ( ! pSTM->DoSewing( STM1))
return nullptr ;
// creo la superficie sopra
SurfTriMesh STM2 ;
if ( ! STM2.CreateByFlatContour( PL2))
return nullptr ;
// la unisco alla superficie del fianco
if ( ! pSTM->DoSewing( STM2))
return nullptr ;
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshConeFrustum( double dBaseRad, double dTopRad, double dHeight, double dLinTol)
{
// le dimensioni devono essere significative
if ( ( dBaseRad < EPS_SMALL && dTopRad < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
return nullptr ;
// se cono
if ( dTopRad < EPS_SMALL)
return GetSurfTriMeshCone( dBaseRad, dHeight, dLinTol) ;
// se cono rovescio
if ( dBaseRad < EPS_SMALL)
return GetSurfTriMeshCone( dTopRad, -dHeight, dLinTol) ;
// se cilindro
if ( abs( dTopRad - dBaseRad) < EPS_SMALL)
return GetSurfTriMeshCylinder( dBaseRad, dHeight, dLinTol) ;
// creo la circonferenza sotto
CurveArc cArc1 ;
cArc1.Set( ORIG, Z_AX, dBaseRad) ;
if ( dHeight < 0)
cArc1.Invert() ;
// creo la circonferenza sopra
CurveArc cArc2 ;
cArc2.Set( Point3d( 0, 0, dHeight), Z_AX, dTopRad) ;
if ( dHeight < 0)
cArc2.Invert() ;
// creo la superficie laterale del cono
PtrOwner<ISurfTriMesh> pSTM( GetSurfTriMeshRuled( &cArc1, &cArc2, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
if ( IsNull( pSTM))
return nullptr ;
// creo la superficie sotto e la inverto
PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc1, dLinTol)) ;
if ( IsNull( pSTM1))
return nullptr ;
pSTM1->Invert() ;
// la unisco alla superficie del fianco
if ( ! pSTM->DoSewing( *pSTM1))
return nullptr ;
// creo la superficie sopra
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMeshByFlatContour( &cArc2, dLinTol)) ;
if ( IsNull( pSTM2))
return nullptr ;
// la unisco alla superficie del fianco
if ( ! pSTM->DoSewing( *pSTM2))
return nullptr ;
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt)
+27 -2
View File
@@ -45,6 +45,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
for( int j = 0 ; j < snData.nCPV ; ++j) {
CNurbsData nuCurve ;
nuCurve.bPeriodic = true ;
nuCurve.bRat = snData.bRat ;
nuCurve.nDeg = snData.nDegU ;
nuCurve.vU = vU ;
// vettore dei punti di controllo
@@ -63,13 +64,23 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
nuCurve.vW = vWeCtrl ;
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
if ( snData.mCP.size() != nuCurve.vCP.size() ) {
snData.mCP.resize( nuCurve.vCP.size()) ;
if( snData.bRat)
snData.mW.resize( nuCurve.vW.size()) ;
}
for ( int i = 0 ; i < snData.nCPU ; ++i) {
snData.mCP[i][j] = nuCurve.vCP[i] ;
if( snData.bRat) {
snData.mW[i][j] = nuCurve.vW[i] ;
snData.mCP[i][j] *= nuCurve.vW[i] ;
}
}
snData.vU = nuCurve.vU ;
}
}
snData.bPeriodicU = false ;
snData.nCPU = int( snData.mCP.size()) ;
}
if ( snData.bPeriodicV || ! snData.bClampedV) {
bool bIsRational = snData.bRat ;
@@ -83,6 +94,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
for( int i = 0 ; i < snData.nCPU ; ++i) {
CNurbsData nuCurve ;
nuCurve.bPeriodic = true ;
nuCurve.bRat = snData.bRat ;
nuCurve.nDeg = snData.nDegV ;
nuCurve.vU = vV ;
// vettore dei punti di controllo
@@ -101,15 +113,28 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
nuCurve.vW = vWeCtrl ;
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
for ( int j = 0 ; j < snData.nCPV ; ++j ) {
if ( snData.mCP[i].size() != nuCurve.vCP.size()){
snData.mCP[i].clear() ;
snData.mCP[i].resize( nuCurve.vCP.size()) ;
if ( snData.bRat ) {
snData.mW[i].clear() ;
snData.mW[i].resize( nuCurve.vW.size()) ;
}
}
for ( int j = 0 ; j < int( nuCurve.vCP.size()) ; ++j ) {
snData.mCP[i][j] = nuCurve.vCP[j] ;
if ( snData.bRat ) {
snData.mW[i][j] = nuCurve.vW[j] ;
snData.mCP[i][j] *= nuCurve.vW[j] ;
}
}
snData.vV = nuCurve.vU ;
}
}
snData.bPeriodicV = false ;
snData.nCPV = int( snData.mCP[0].size()) ;
}
return true;
return true ;
}
//----------------------------------------------------------------------------
+2497 -471
View File
File diff suppressed because it is too large Load Diff
+47 -13
View File
@@ -25,6 +25,14 @@
using namespace std ;
class Tree ;
struct PairHashIntInt {
std::size_t operator()(const std::pair<int, int>& key) const {
std::size_t h1 = std::hash<int>{}(key.first);
std::size_t h2 = std::hash<int>{}(key.second);
return h1 ^ (h2 << 1); // Combine hashes
}
};
//----------------------------------------------------------------------------
class SurfBezier : public ISurfBezier, public IGeoObjRW
{
@@ -75,7 +83,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetVolume( double& dVolume) const override
{ if ( &dVolume == nullptr)
return false ;
if( m_pSTM == nullptr)
GetAuxSurf() ;
dVolume = 0 ;
if( m_pSTM != nullptr)
m_pSTM->GetVolume( dVolume) ;
return true ; }
bool GetCentroid( Point3d& ptCen) const override ;
bool Invert( void) override ;
@@ -99,6 +111,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
{ return GetControlWeight( GetInd( nIndU, nIndV), pbOk) ; }
double GetControlWeight( int nInd, bool* pbOk) const override ;
bool IsAPoint( void) const override ;
bool GetPoint( double dU, double dV, Side nUs, Side nVs, Point3d& ptPos) const override ;
bool GetPointD1D2( double dU, double dV, Side nUs, Side nVs,
Point3d& ptPos,
Vector3d* pvtDerU = nullptr, Vector3d* pvtDerV = nullptr,
@@ -109,23 +122,24 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
Vector3d* pvtDerUU = nullptr, Vector3d* pvtDerVV = nullptr, Vector3d* pvtDerUV = nullptr) const override ;
CurveComposite* GetCurveOnU( double dV) const override ;
CurveComposite* GetCurveOnV( double dU) const override ;
CurveComposite* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni)
CurveComposite* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni)
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
const SurfTriMesh* GetAuxSurfRefined( void) const override ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL) const override ;
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
// a nIL si può passare 5 come valore di default
// a nIL si può passare 5 come valore di default
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ;
// restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
// pPlCut è il piano di taglio su cui giace la curva
// pPlCut è il piano di taglio su cui giace la curva
bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ;
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
@@ -134,9 +148,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; // se la superficie non è trimmata restituisce un vettore di 4 elementi. Se la superficie è chiusa lungo un parametro i lati algi estremi di quel parametro saranno null.
bool IsPlanar( void) const override ;
bool CreateByFlatContour( const PolyLine& PL) override ;
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ;
bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ;
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -189,15 +210,20 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
double GetCurveOnVApproxLen( double dU) const ;
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
// restituisce il singolo edge della superficie non trimmata
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
bool UpdateEdgesFromTree( Tree& tr) const ;
// funzione che calcola se gli edge sono collassati in poli
bool CalcPoles( void) ;
bool CalcPoles( void) const ;
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ;
bool ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ;
bool ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ;
bool GetBernstein( double dU, int nDegU, DBLVECTOR& vBernU) const ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria per la visualizzazione
mutable SurfTriMesh* m_pSTMRefined ; // superficie trimesh ausiliaria raffinata per i calcoli
Status m_nStatus ; // stato
int m_nDegU ; // grado in U
int m_nDegV ; // grado in V
@@ -205,16 +231,24 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
int m_nSpanV ; // numero di pezze in V
bool m_bRat ; // flag di razionale/polinomiale
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_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
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 BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
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
mutable 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 int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
mutable DBLVECTOR m_vBernU ;
mutable PNTVECTOR m_ptTemp ;
mutable DBLVECTOR m_vBernV ;
mutable PNTVECTOR m_ptTempW ;
mutable DBLVECTOR m_dTempW ;
mutable PNTVECTOR m_vPtWCtrlLoc ;
mutable DBLVECTOR m_vWeCtrlLoc ;
} ;
//-----------------------------------------------------------------------------
+298 -28
View File
@@ -109,18 +109,25 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
return false ;
// aggiungo le singole curve
int nExtAdded = 0 ;
bool bOk = true ;
for ( auto& pSingCrv : CrvLst) {
if ( ! AddSimpleExtLoop( pSingCrv))
bool bAdded = false ;
if ( AddSimpleExtLoop( pSingCrv, bAdded))
++ nExtAdded ;
else
bOk = false ;
}
return bOk ;
return ( bOk && nExtAdded > 0) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
{
// default
bAdded = false ;
// acquisisco la curva
PtrOwner<ICurve> pMyCrv( pCrv) ;
if ( IsNull( pMyCrv))
@@ -133,8 +140,10 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
Plane3d plPlane ;
if ( ! pMyCrv->GetArea( plPlane, dArea))
return false ;
if ( dArea < SQ_EPS_SMALL)
return true ;
// se sto costruendo il primo chunk
if ( m_vExtInd.size() == 0) {
if ( m_vExtInd.empty()) {
// assegno il riferimento intrinseco
if ( ! m_frF.Set( ORIG + plPlane.GetVersN() * plPlane.GetDist(), plPlane.GetVersN()))
return false ;
@@ -198,6 +207,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
m_OGrMgr.Reset() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
bAdded = true ;
return true ;
}
@@ -547,7 +557,7 @@ SurfFlatRegion::Load( NgeReader& ngeIn)
string sName ;
int j ;
bool bOk = ngeIn.ReadString( sName, ";") &&
FromString( sName.substr(2), j) && i == j ;
FromString( sName.substr( 2), j) && i == j ;
int nChunk = 0, nLoop = 0 ;
bOk = ngeIn.ReadInt( nChunk, ",") &&
ngeIn.ReadInt( nLoop, ";", true) ;
@@ -912,9 +922,6 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
bool
SurfFlatRegion::GetArea( double& dArea) const
{
// controllo parametro di ritorno
if ( &dArea == nullptr)
return false ;
// inizio con area nulla
dArea = 0 ;
// la regione deve essere validata
@@ -937,9 +944,6 @@ SurfFlatRegion::GetArea( double& dArea) const
bool
SurfFlatRegion::GetGrossArea( double& dArea) const
{
// controllo parametro di ritorno
if ( &dArea == nullptr)
return false ;
// inizio con area nulla
dArea = 0 ;
// la regione deve essere validata
@@ -963,9 +967,6 @@ SurfFlatRegion::GetGrossArea( double& dArea) const
bool
SurfFlatRegion::GetCentroid( Point3d& ptCen) const
{
// controllo parametro di ritorno
if ( &ptCen == nullptr)
return false ;
// la regione deve essere validata
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
@@ -991,13 +992,20 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const
return true ;
}
//----------------------------------------------------------------------------
int
SurfFlatRegion::GetChunkCount( void) const
{
// la regione deve essere validata
if ( m_nStatus != OK)
return 0 ;
return int( m_vExtInd.size()) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
{
// controllo parametro di ritorno
if ( &ptCen == nullptr)
return false ;
// la regione deve essere validata
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
@@ -1011,13 +1019,53 @@ SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
}
//----------------------------------------------------------------------------
int
SurfFlatRegion::GetChunkCount( void) const
bool
SurfFlatRegion::GetChunkArea( int nChunk, double& dArea) const
{
// default, area nulla
dArea = 0 ;
// la regione deve essere validata
if ( m_nStatus != OK)
return 0 ;
return int( m_vExtInd.size()) ;
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
// il chunk deve esistere
if ( nChunk < 0 || nChunk >= GetChunkCount())
return false ;
// calcolo l'area
bool bOk = true ;
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
double dLoopArea ;
if ( pLoop != nullptr && pLoop->GetAreaXY( dLoopArea))
dArea += dLoopArea ;
else
bOk = false ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetChunkPerimeter( int nChunk, double& dLen) const
{
// default, perimetro nullo
dLen = 0 ;
// la regione deve essere validata
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
// il chunk deve esistere
if ( nChunk < 0 || nChunk >= GetChunkCount())
return false ;
// calcolo il perimetro
bool bOk = true ;
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
double dLoopLen ;
if ( pLoop != nullptr && pLoop->GetLength( dLoopLen))
dLen += dLoopLen ;
else
bOk = false ;
}
return bOk ;
}
//----------------------------------------------------------------------------
@@ -1118,6 +1166,19 @@ SurfFlatRegion::GetLoop( int nChunk, int nLoop) const
return pCrv ;
}
//----------------------------------------------------------------------------
int
SurfFlatRegion::GetLoopCurveCount( int nChunk, int nLoop) const
{
// recupero il loop nel riferimento intrinseco
const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ;
if ( pMyCrv == nullptr)
return 0 ;
// restituisco il numero di curve di cui è composto
const ICurveComposite* pMyCompo = GetCurveComposite( pMyCrv) ;
return ( pMyCompo == nullptr ? 1 : pMyCompo->GetCurveCount()) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const
@@ -1149,21 +1210,26 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
// calcolo le polilinee che approssimano i loop
POLYLINEVECTOR vPL ;
vPL.resize( GetLoopCount( i)) ;
vPL.reserve( GetLoopCount( i)) ;
int j = 0 ;
ICurve* pLoop = GetMyLoop( i, j) ;
ICurve* pLoop = GetMyLoop( i, j) ;
while ( pLoop != nullptr) {
// approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL[j]))
vPL.emplace_back( PolyLine()) ;
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL.back()))
return nullptr ;
double dLoopArea ;
if ( ! vPL.back().GetAreaXY( dLoopArea) || abs( dLoopArea) <= 25 * SQ_EPS_SMALL)
vPL.pop_back() ;
pLoop = GetMyLoop( i, ++j) ;
}
// se chunk abbastanza grande, creo la superficie trimesh relativa
double dArea ;
if ( vPL[0].GetAreaXY( dArea) && dArea > 100 * SQ_EPS_SMALL) {
if ( ! vPL.empty() && vPL[0].GetAreaXY( dArea) && dArea > 25 * SQ_EPS_SMALL) {
// creo, setto la superficie trimesh ed elimino punti ripetuti
PtrOwner<SurfTriMesh> pChSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL) || ! pChSTM->DoCompacting())
INTMATRIX vnPLIndMat ;
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL, vnPLIndMat) || ! pChSTM->DoCompacting())
return nullptr ;
// porto la trimesh in globale al riferimento intrinseco
pChSTM->ToGlob( m_frF) ;
@@ -1171,7 +1237,10 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
pSTM->DoSewing( *pChSTM) ;
}
}
// la restituisco
// se vuota
if ( pSTM->IsEmpty())
pSTM->AdjustTopology() ;
// la restituisco
return Release( pSTM) ;
}
@@ -1226,6 +1295,56 @@ SurfFlatRegion::CloneChunk( int nChunk) const
return Release( pSfr) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::EraseChunk(int nChunk)
{
// la regione deve essere validata
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
// il chunk deve esistere
if ( nChunk < 0 || nChunk >= GetChunkCount())
return false ;
// se un solo chunk, resetto la regione
if ( GetChunkCount() == 1) {
Clear() ;
return true ;
}
// se ultimo chunk
if ( nChunk == m_vExtInd.size() - 1) {
// elimino i loop
for ( int i = m_vExtInd[nChunk] ; i < int( m_vpLoop.size()) ; ++ i) {
delete m_vpLoop[i] ;
m_vpLoop[i] = nullptr ;
}
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.end()) ;
// elimino indice di loop esterno
m_vExtInd.pop_back() ;
}
// altrimenti
else {
// numero di loop da eliminare
int nLoopCnt = m_vExtInd[nChunk+1] - m_vExtInd[nChunk] ;
// elimino i loop
for ( int i = m_vExtInd[nChunk] ; i < m_vExtInd[nChunk+1] ; ++ i) {
delete m_vpLoop[i] ;
m_vpLoop[i] = nullptr ;
}
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.begin() + m_vExtInd[nChunk+1]) ;
// elimino indice di loop esterno
m_vExtInd.erase( m_vExtInd.begin() + nChunk) ;
// aggiorno indice inizio chunk successivi
for ( int i = nChunk ; i < int( m_vExtInd.size()) ; ++i)
m_vExtInd[i] -= nLoopCnt ;
}
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
ResetAuxSurf() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
@@ -1480,3 +1599,154 @@ SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const
return m_pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetChunkMaxOffset( int nChunk, double& dOffs) const
{
// verifico se è stato calcolato Voronoi
if ( m_pVoronoiObj == nullptr)
if ( ! CalcVoronoiObject())
return false ;
// il massimo offset per il chunk è il massimo offset del suo loop esterno
// ( il diagramma di Voronoi tiene già conto della limitazione con i loop interni)
int nInd = GetIndFromChunkLoop( nChunk, 0) ;
return m_pVoronoiObj->CalcLimitOffset( nInd, true, dOffs) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetMaxOffset( double& dOffs) const
{
int nChunks = GetChunkCount() ;
if ( nChunks == 0)
return false ;
// calcolo il massimo fra gli offset limite di tutti i suoi chunks
if ( ! GetChunkMaxOffset( 0, dOffs))
return false ;
for ( int i = 1 ; i < nChunks ; i++) {
double dCurrOffs ;
if ( ! GetChunkMaxOffset( i, dCurrOffs))
return false ;
if ( dCurrOffs > dOffs)
dOffs = dCurrOffs ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd)
{
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
if ( pLoop == nullptr)
return false ;
if ( pLoop->GetType() != CRV_COMPO) {
if ( nCrv != 0)
return false ;
pLoop->SetTempProp( nProp, nPropInd) ;
return true ;
}
return GetBasicCurveComposite( pLoop)->SetCurveTempProp( nCrv, nProp, nPropInd) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd) const
{
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
if ( pLoop == nullptr)
return false ;
if ( pLoop->GetType() != CRV_COMPO) {
if ( nCrv != 0)
return false ;
nProp = pLoop->GetTempProp( nPropInd) ;
return true ;
}
return GetBasicCurveComposite( pLoop)->GetCurveTempProp( nCrv, nProp, nPropInd) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::ResetAllCurveTempProps( void)
{
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
ICurve* pLoop = GetMyLoop( nC, nL) ;
if ( pLoop != nullptr) {
if ( pLoop->GetType() != CRV_COMPO) {
pLoop->SetTempProp( 0, 0) ;
pLoop->SetTempProp( 0, 1) ;
}
else {
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
pCompoLoop->SetCurveTempProp( nI, 0, 0) ;
pCompoLoop->SetCurveTempProp( nI, 0, 1) ;
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd)
{
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
if ( pLoop == nullptr)
return false ;
if ( pLoop->GetType() != CRV_COMPO) {
if ( nCrv != 0)
return false ;
pLoop->SetTempParam( dParam, nParamInd) ;
return true ;
}
return GetBasicCurveComposite( pLoop)->SetCurveTempParam( nCrv, dParam, nParamInd) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd) const
{
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
if ( pLoop == nullptr)
return false ;
if ( pLoop->GetType() != CRV_COMPO) {
if ( nCrv != 0)
return false ;
dParam = pLoop->GetTempParam( nParamInd) ;
return true ;
}
return GetBasicCurveComposite( pLoop)->GetCurveTempParam( nCrv, dParam, nParamInd) ;
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::ResetAllCurveTempParams( void)
{
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
ICurve* pLoop = GetMyLoop( nC, nL) ;
if ( pLoop != nullptr) {
if ( pLoop->GetType() != CRV_COMPO) {
pLoop->SetTempParam( 0, 0) ;
pLoop->SetTempParam( 0, 1) ;
}
else {
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
pCompoLoop->SetCurveTempParam( nI, 0, 0) ;
pCompoLoop->SetCurveTempParam( nI, 0, 1) ;
}
}
}
}
}
return true ;
}
+21 -9
View File
@@ -94,18 +94,30 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
{ return m_frF.Orig() ; }
const Vector3d& GetNormVersor( void) const override
{ return m_frF.VersZ() ; }
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
void ResetVoronoiObject( void) const override ;
bool GetMaxOffset( double& dOffs) const override ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
int GetChunkCount( void) const override ;
SurfFlatRegion* CloneChunk( int nChunk) const override ;
bool EraseChunk(int nChunk) override ;
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
bool GetChunkArea( int nChunk, double& dArea) const override ;
bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
int GetLoopCount( int nChunk) const override ;
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
SurfFlatRegion* CloneChunk( int nChunk) const override ;
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
void ResetVoronoiObject( void) const override ;
bool SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd = 0) override ;
bool GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd = 0) const override ;
bool ResetAllCurveTempProps( void) override ;
bool SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd = 0) const override ;
bool ResetAllCurveTempParams( void) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -136,7 +148,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
private :
bool CopyFrom( const SurfFlatRegion& clSrc) ;
bool AddSimpleExtLoop( ICurve* pCrv) ;
bool AddSimpleExtLoop( ICurve* pCrv, bool& bAdded) ;
bool MyAddExtLoop( ICurve* pCrv) ;
bool AddSimpleIntLoop( ICurve* pCrv) ;
bool MyAddIntLoop( ICurve* pCrv, int nChunk) ;
+2 -2
View File
@@ -168,7 +168,7 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
// creo una nuova regione a partire da questi loop
PtrOwner<SurfFlatRegion> pSfr ;
if ( vpLoop.size() == 0)
if ( vpLoop.empty())
pSfr.Set( new( nothrow) SurfFlatRegion) ;
else
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
@@ -258,7 +258,7 @@ SurfFlatRegion::Intersect( const ISurfFlatRegion& Other)
// creo una nuova regione a partire da questi loop
PtrOwner<SurfFlatRegion> pSfr ;
if ( vpLoop.size() == 0)
if ( vpLoop.empty())
pSfr.Set( new( nothrow) SurfFlatRegion) ;
else
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
+2 -2
View File
@@ -148,7 +148,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
return nullptr ;
// costruisco la superficie
if ( vOffs.size() > 0) {
if ( ! vOffs.empty()) {
PCRV_DEQUE vLoops ;
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
vOffs[i]->ToLoc( m_frF) ;
@@ -162,7 +162,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
}
// verifico di avere ancora dei loops
if ( vLoops.size() > 0) {
if ( ! vLoops.empty()) {
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
if ( IsNull( pSfr)) {
MyTestAndDelete( vLoops) ;
+518 -231
View File
@@ -33,8 +33,8 @@
#include "/EgtDev/Include/EGkUiUnits.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <new>
#include <set>
#include <tuple>
using namespace std ;
@@ -46,7 +46,7 @@ SurfTriMesh::SurfTriMesh( void)
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bShowEdges( false), m_bOriented( false), m_bClosed( false),
m_bFaceted( false), m_bFacEdged( false), m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0,0},
m_nMaxTFlag( 0), m_nParts( -1), m_nShells( -1), m_pHGrd3d( nullptr)
m_nMaxTFlag( 0), m_nShells( -1), m_pHGrd3d( nullptr)
{
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
@@ -85,8 +85,8 @@ SurfTriMesh::Init( int nNumVert, int nNumTria, int nNumFacet)
m_nStatus = OK ;
m_bClosed = false ;
m_nMaxTFlag = 0 ;
m_nParts = -1 ;
m_nShells = -1 ;
m_vPart.clear() ;
return true ;
}
@@ -117,8 +117,8 @@ SurfTriMesh::Clear( void)
m_dTempParam[0] = 0 ;
m_dTempParam[1] = 0 ;
m_nMaxTFlag = 0 ;
m_nParts = -1 ;
m_nShells = -1 ;
m_vPart.clear() ;
return true ;
}
@@ -128,8 +128,8 @@ SurfTriMesh::AddVertex( const Point3d& ptVert, double dU, double dV)
{
// imposto ricalcolo
m_nStatus = TO_VERIFY ;
m_nParts = - 1 ;
m_nShells = -1 ;
m_vPart.clear() ;
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
// inserisco il vertice
@@ -160,8 +160,8 @@ SurfTriMesh::MoveVertex( int nInd, const Point3d& ptNewVert)
m_vVert[nInd].ptP = ptNewVert ;
// imposto ricalcolo
m_nStatus = TO_VERIFY ;
m_nParts = - 1 ;
m_nShells = - 1 ;
m_vPart.clear() ;
m_bFaceted = false ;
m_bFacEdged = false ;
m_OGrMgr.Reset() ;
@@ -230,8 +230,8 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
return SVT_DEL ;
// imposto ricalcolo
m_nStatus = TO_VERIFY ;
m_nParts = - 1 ;
m_nShells = -1 ;
m_vPart.clear() ;
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
// inserisco il triangolo
@@ -322,8 +322,8 @@ SurfTriMesh::RemoveTriangle( int nId)
m_bFaceted = false ;
m_bFacEdged = false ;
// invalido calcolo connettività
m_nParts = - 1 ;
m_nShells = -1 ;
m_vPart.clear() ;
return true ;
}
@@ -912,8 +912,6 @@ SurfTriMesh::CloneTriangle( int nT) const
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
pSurfTM->m_nParts = 1 ;
pSurfTM->m_nShells = 1 ;
// Copio il triangolo
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[nT].nIdVert[0]].ptP),
@@ -1241,7 +1239,7 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
// Se non esiste la regione
if ( IsNull( pSfr))
return false ;
return true ;
// Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
@@ -1311,8 +1309,8 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
m_nTempProp[0] = stmSrc.m_nTempProp[0] ;
m_nTempProp[1] = stmSrc.m_nTempProp[1] ;
m_nMaxTFlag = stmSrc.m_nMaxTFlag ;
m_nParts = stmSrc.m_nParts ;
m_nShells = stmSrc.m_nShells ;
m_vPart = stmSrc.m_vPart ;
m_dTempParam[0] = stmSrc.m_dTempParam[0] ;
m_dTempParam[1] = stmSrc.m_dTempParam[1] ;
return true ;
@@ -1350,12 +1348,10 @@ SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const
// segnalo eventuale incongruenza di orientamento
if ( ! m_bOriented)
sOut += string( "Inconsistent Orientation") + szNewLine ;
// segnalo numero di parti
// segnalo numero di parti e di gusci
int nParts = GetPartCount() ;
sOut += string( "Parts=") + ToString( nParts) + szNewLine ;
// segnalo numero di gusci
int nShells = GetShellCount() ;
sOut += string( "Shells=") + ToString( nShells) + szNewLine ;
sOut += string( "Parts=") + ToString( nParts) + string( " Shells=") + ToString( nShells) + szNewLine ;
// numero di vertici
sOut += "Vert : Nbr=" + ToString( GetVertexCount()) +
" Size=" + ToString( GetVertexSize()) + szNewLine ;
@@ -1465,8 +1461,8 @@ SurfTriMesh::Load( NgeReader& ngeIn)
// imposto ricalcolo della grafica, della connessione e di hashgrids3d
m_OGrMgr.Clear() ;
m_nMaxTFlag = 0 ;
m_nParts = -1 ;
m_nShells = -1 ;
m_vPart.clear() ;
ResetHashGrids3d() ;
// leggo la prossima linea ( 2 parametri : dLinTol e dSmoothAng)
// tolleranza lineare di costruzione
@@ -1626,8 +1622,8 @@ SurfTriMesh::Validate( bool bCorrect)
}
// invalido calcolo connessione
m_nParts = - 1 ;
m_nShells = -1 ;
m_vPart.clear() ;
return ( m_nStatus == OK) ;
}
@@ -1902,8 +1898,8 @@ SurfTriMesh::AdjustTopology( void)
m_bFaceted = false ;
m_bFacEdged = false ;
// invalido calcolo connessione
m_nParts = - 1 ;
m_nShells = - 1 ;
m_vPart.clear() ;
// verifica indici
if ( ! Validate( true))
return false ;
@@ -2097,13 +2093,24 @@ SurfTriMesh::CreateByFlatContour( const PolyLine& PL)
//----------------------------------------------------------------------------
bool
SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL)
SurfTriMesh::CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL)
{
INTMATRIX vnPLIndMat ;
vnPLIndMat.push_back( { 0}) ;
for ( int i = 1 ; i < int( vPL.size()) ; ++ i)
vnPLIndMat[0].push_back( i) ;
return CreateByRegion( vPL, vnPLIndMat) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat)
{
// eseguo la triangolazione, dopo aver verificato che l'insieme di contorni costituisca una regione
PNTVECTOR vPnt ;
INTVECTOR vTria ;
Triangulate Tri ;
if ( ! Tri.MakeAdvanced( vPL, vPnt, vTria))
if ( ! Tri.MakeAdvanced( vPL, vPnt, vTria, vnPLIndMat))
return false ;
// inizializzo la superficie
@@ -2719,6 +2726,8 @@ VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vect
ptPc.z = 0 ;
++ nSeg ;
// verifico distanza
// se la curva è chiusa oppure è vicina all'asse ( entro EPS_SMALL), ma non ho che sono start o end ad essere sull'asse
// allora dovrò rimaneggiare la polyline
if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) {
if ( bClosed ||
( ! ( nSeg == 1 && AreSamePointApprox( ORIG, ptPp)) &&
@@ -3572,7 +3581,10 @@ SurfTriMesh::Invert( void)
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo della grafica e di hashgrids3d
// imposto ricalcolo numero delle parti (le shell non cambiano)
m_vPart.clear() ;
// imposto ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
@@ -3645,14 +3657,187 @@ SurfTriMesh::GetAllTriaBox( void) const
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetPartCount( void) const
bool
SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
{
if ( ! IsValid())
return 0 ;
if ( m_nParts == - 1 && ! VerifyConnection())
return 0 ;
return m_nParts ;
return false ;
// se non sono già note le shell
if ( m_nShells == -1) {
// reset connessione
for ( auto& Tria : m_vTria)
Tria.nShell = SVT_NULL ;
// ciclo sui triangoli per determinare le shells
m_nShells = 0 ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
m_vTria[i].nShell != SVT_NULL)
continue ;
// assegno indice di shell connessa al triangolo
m_vTria[i].nShell = m_nShells ;
++ m_nShells ;
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( i) ;
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nShell == SVT_NULL) {
m_vTria[nAdjT].nShell = m_vTria[nT].nShell ;
stTria.insert( nAdjT) ;
}
}
}
}
}
// reset delle parti
m_vPart.clear() ;
// se richiesta solo la determinazione delle shell, esco
if ( ! bShellsAndParts)
return true ;
// Se superficie vuota, allora non ho parti
if ( m_nShells == 0)
return true ;
// Se ho solo una shell, allora ho una sola parte
if ( m_nShells == 1) {
m_vPart.emplace_back( m_bClosed, INTVECTOR{ 0}) ;
return true ;
}
// Ho più shell devo controllare la loro posizione relativa
struct SHELLINFO {
SHELLINFO( int nI, double dVol, const BBox3d& b3B, ISurfTriMesh* pStm)
: nInd( nI), dVolume( dVol), b3Box( b3B), pStmShell( pStm) {}
int nInd ;
double dVolume ;
BBox3d b3Box ;
PtrOwner<ISurfTriMesh> pStmShell ;
} ;
vector<SHELLINFO> vOuterShells ;
vector<SHELLINFO> vInnerShells ;
INTVECTOR vOpenShells ;
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
// se la shell è chiusa
if ( IsShellClosed( nSh)) {
// creo una superficie clonata dalla shell
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
return false ;
// ne calcolo il volume (con segno)
double dVol = 0. ;
pStmShell->GetVolume( dVol) ;
// ne calcolo il bounding box
BBox3d b3Box ;
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
// la inserisco nel vettore opportuno
if ( dVol > 0)
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
else
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
}
// altrimenti aperta
else {
// la inserisco nel vettore delle shell aperte
vOpenShells.push_back( nSh) ;
}
}
// ordino il vettore delle shell esterne in senso crescente di volume (crescenti anche in valore assoluto)
sort( vOuterShells.begin(), vOuterShells.end(),
[]( const SHELLINFO& a, const SHELLINFO& b) {
return ( a.dVolume < b.dVolume) ;
}) ;
// ordino il vettore delle shell interne in senso crescente di volume (decrescenti in valore assoluto)
sort( vInnerShells.begin(), vInnerShells.end(),
[]( const SHELLINFO& a, const SHELLINFO& b) {
return ( a.dVolume < b.dVolume) ;
}) ;
// classifico le shell esterne
for ( int i = 0 ; i < int( vOuterShells.size()) ; ++ i) {
// inserisco nel vettore delle parti
m_vPart.emplace_back( true, INTVECTOR{ vOuterShells[i].nInd}) ;
// cerco eventuali interne che vi appartengono
CISURFTMPVECTOR vStmTest{ vOuterShells[i].pStmShell} ;
for ( int j = 0 ; j < int( vInnerShells.size()) ; ++ j) {
// se libera e il box è incluso, verifico se realmente interna
if ( vInnerShells[j].nInd >= 0 && vOuterShells[i].b3Box.Encloses( vInnerShells[j].b3Box)) {
Point3d ptCheck ;
vInnerShells[j].pStmShell->GetFirstVertex( ptCheck) ;
bool bIsInside = true ;
for ( const auto& pStmTest : vStmTest) {
BBox3d b3Test = pStmTest->GetAllTriaBox() ;
if ( b3Test.Overlaps( vInnerShells[j].b3Box)) {
DistPointSurfTm distCalculator( ptCheck, *pStmTest) ;
if ( ! distCalculator.IsPointInside()) {
bIsInside = false ;
break ;
}
}
}
if ( bIsInside) {
m_vPart.back().vShell.push_back( vInnerShells[j].nInd) ;
vInnerShells[j].nInd = -1 ;
vStmTest.push_back( vInnerShells[j].pStmShell) ;
}
}
}
}
// classifico le shell interne rimaste libere
bool bNewInner = true ;
CISURFTMPVECTOR vStmTest ;
for ( int i = 0 ; i < int( vInnerShells.size()) ; ++ i) {
if ( vInnerShells[i].nInd >= 0) {
// se non è nuova interna verifico sia interna alle altre correnti
if ( ! bNewInner) {
bool bIsInside = true ;
Point3d ptCheck ;
vInnerShells[i].pStmShell->GetFirstVertex( ptCheck) ;
// se il box interferisce con altri, verifico se realmente interna
for ( const auto& pStmTest : vStmTest) {
BBox3d b3Test = pStmTest->GetAllTriaBox() ;
if ( b3Test.Overlaps( vInnerShells[i].b3Box)) {
DistPointSurfTm distCalculator( ptCheck, *pStmTest) ;
if ( ! distCalculator.IsPointInside()) {
bIsInside = false ;
break ;
}
}
}
if ( bIsInside)
m_vPart.back().vShell.push_back( vInnerShells[i].nInd) ;
else
bNewInner = true ;
}
// se nuova interna
if ( bNewInner) {
bNewInner = false ;
m_vPart.emplace_back( true, INTVECTOR{ -1, vInnerShells[i].nInd}) ;
vStmTest.clear() ;
}
vInnerShells[i].nInd = -1 ;
vStmTest.push_back( vInnerShells[i].pStmShell) ;
}
}
// aggiungo all'elenco delle parti le shell aperte
for ( int i = 0 ; i < int( vOpenShells.size()) ; ++ i) {
m_vPart.emplace_back( false, INTVECTOR{ vOpenShells[i]}) ;
}
return true ;
}
//----------------------------------------------------------------------------
@@ -3661,209 +3846,67 @@ SurfTriMesh::GetShellCount( void) const
{
if ( ! IsValid())
return 0 ;
if ( m_nShells == - 1 && ! VerifyConnection())
if ( m_nShells == -1 && ! VerifyConnection())
return 0 ;
return m_nShells ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::VerifyConnection( void) const
SurfTriMesh::GetShellArea( int nShell, double& dArea) const
{
// Controllo parametro di ritorno
if ( &dArea == nullptr)
return false ;
// Imposto area nulla
dArea = 0 ;
// Verifiche sull'oggetto
if ( ! IsValid())
return false ;
// reset connessione
for ( auto& Tria : m_vTria) {
Tria.nPart = SVT_NULL ;
Tria.nShell = SVT_NULL ;
if ( m_nShells == -1 && ! VerifyConnection())
return false ;
// Se la componente non esiste, errore
if ( nShell < 0 || nShell >= m_nShells)
return false ;
// sommo l'area di tutti i triangoli della shell
Triangle3d Tria ;
int nId = GetFirstTriangle( Tria) ;
while ( nId != SVT_NULL) {
if ( m_vTria[nId].nShell == nShell)
dArea += Tria.GetArea() ;
nId = GetNextTriangle( nId, Tria) ;
}
// ciclo sui triangoli per determinare le shells
m_nShells = 0 ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
m_vTria[i].nShell != SVT_NULL)
continue ;
// assegno indice di parte connessa al triangolo
m_vTria[i].nShell = m_nShells ;
++ m_nShells ;
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( i) ;
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nShell == SVT_NULL) {
m_vTria[nAdjT].nShell = m_vTria[nT].nShell ;
stTria.insert( nAdjT) ;
}
}
}
}
// identifico le parti
m_nParts = 0 ;
if ( m_nShells == 1) { // se ho solo una shell allora ho una sola parte
m_nParts = 1 ;
for ( auto& Tria : m_vTria)
Tria.nPart = Tria.nShell ;
}
else { // se ho più shells devo controllare la loro posizione
// salvo solo le Shells chiuse e per ognuna di esse il loro volume e l'indice della shell
// < stmShell, ( nShellInd, dVol) >
// NB. I Volumi sono sempre finiti, il segno del volume mi dice solo se sto considerando
// la parte interna o esterna della superficie
typedef pair<PtrOwner<ISurfTriMesh>, pair<int, double>> SHELLINFO ;
vector<SHELLINFO> vClosedShells ;
vClosedShells.reserve( m_nShells) ;
INTVECTOR vOpenShells ; // vettore di indici di Shell aperte
for ( int s = 0 ; s < GetShellCount() ; ++ s) {
// recupero la Shell
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( s)) ;
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
return false ;
double dVol = 0. ;
// se chiusa calcolo il suo volume con segno
if ( pStmShell->IsClosed()) {
pStmShell->GetVolume( dVol) ;
vClosedShells.emplace_back( make_pair( Release( pStmShell), make_pair( s, dVol))) ;
}
// se aperta, non rientra nella classficazione ( sarà coincidente ad una Part)
else
vOpenShells.push_back( s) ;
}
// ordino il vettore in senso decrescente per volume, in valore assoluto
// NB. tutte le shell con volume negativo sono state invertite !
sort( vClosedShells.begin(), vClosedShells.end(),
[]( const SHELLINFO& a, const SHELLINFO& b) {
return abs( a.second.second) > abs( b.second.second) ;
}) ;
// se la superficie in prima posizione è negativa, allora le inverto tutte; il numero di
// Parts non cambia nel conto
if ( ! vClosedShells.empty() && vClosedShells.front().second.second < - EPS_SMALL)
for ( auto& Shell : vClosedShells)
Shell.first->Invert() ;
// creo una matrice di interi ; ogni riga corrisponde ad una Parte, dove in posizione 0 c'è
// la shell esterna e nelle successive le rispettiva shells interne
INTMATRIX vnShellIndMat ;
bool bFirstShell ; // flag per indicare se la shell corrente è esterna
int nIndExtShell = -1 ; // indice del vettore di shell chiuse della shell esterna
INTVECTOR vIndIntShells ; // vettore di indici di shell chiuse interne alla shell esterna corrente
do {
bFirstShell = true ;
for ( int i = 0 ; i < int( vClosedShells.size()) ; ++ i) {
// recupero l'indice della shell e verifico che sia valido
int j = vClosedShells[i].second.first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstShell) {
vnShellIndMat.push_back({ j}) ;
vClosedShells[i].second.first = -1 ;
bFirstShell = false ;
nIndExtShell = i ;
vIndIntShells.clear() ;
}
// altrimento verifico se la shell è interna o no
else {
// la shell è interna se è sia interna alla shell esterna corrente ( della riga di
// vnShellIndMat ) e allo stesso tempo esterna a tutte le shell già inserite nella riga
// attuale.
Point3d ptCheck ;
vClosedShells[i].first->GetFirstVertex( ptCheck) ;
// 1) verifica rispetto alla shell esterna
DistPointSurfTm distCalculator( ptCheck, *vClosedShells[nIndExtShell].first) ;
if ( ! distCalculator.IsPointInside())
continue ;
// 2) verifica rispetto a tutte la shell già trovate interne
bool bOk = true ;
for ( int k = 1 ; k < int( vIndIntShells.size()) ; ++ k) {
DistPointSurfTm distCalculator( ptCheck, *vClosedShells[vIndIntShells[k]].first) ;
// NB. tutte le shell hanno volume negativo !
if ( ! distCalculator.IsPointInside()) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnShellIndMat.back().push_back( j) ;
vClosedShells[i].second.first = - 1 ;
vIndIntShells.push_back( i) ;
}
}
}
} while ( ! bFirstShell) ;
// scorro le righe della matrice e assegno la Part ( ovvero la riga )
int nPart = 0 ;
for ( nPart = 0 ; nPart < int( vnShellIndMat.size()) ; ++ nPart) {
++ m_nParts ;
for ( int j = 0 ; j < int( vnShellIndMat[nPart].size()) ; ++ j) {
for ( auto& Tria : m_vTria) {
if ( Tria.nShell == j)
Tria.nPart = nPart ;
}
}
}
// per tutte le superfici aperte, assegno loro una Parte
for ( int i = 0 ; i < int( vOpenShells.size()) ; ++ i) {
++ m_nParts ;
for ( auto& Tria : m_vTria) {
if ( Tria.nShell == i)
Tria.nPart = i + ( nPart ++ ) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemovePart( int nPart)
bool
SurfTriMesh::IsShellClosed( int nShell) const
{
// Verifiche sull'oggetto
if ( ! IsValid())
return false ;
// Il numero delle componenti deve essere maggiore di zero o calcolabile
if ( m_nParts == -1 && ! VerifyConnection())
if ( m_nShells == -1 && ! VerifyConnection( false))
return false ;
// Se la componente non esiste, errore
if ( m_nParts <= 0 || nPart < 0 || nPart >= m_nParts)
if ( nShell < 0 || nShell >= m_nShells)
return false ;
int nPartsOld = m_nParts ;
// Rimuovo i triangoli della componente nPart
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
if ( m_vTria[i].nPart == nPart)
RemoveTriangle( i) ;
// ciclo sui triangoli della shell
bool bClosed = true ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// se triangolo non cancellato e della shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
// verifico le adiacenze
if ( m_vTria[i].nIdAdjac[0] == SVT_NULL ||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
bClosed = false ;
break ;
}
}
}
// Aggiorno il numero di componenti
m_nParts = nPartsOld - 1 ;
// imposto ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
return true ;
// restituisco il risultato
return bClosed ;
}
//----------------------------------------------------------------------------
@@ -3878,18 +3921,16 @@ SurfTriMesh::RemoveShell( int nShell)
return false ;
// Se la componente non esiste, errore
if ( m_nShells <= 0 || nShell < 0 || nShell >= m_nShells)
if ( nShell < 0 || nShell >= m_nShells)
return false ;
int nShellsOld = m_nShells ;
// Rimuovo i triangoli della componente nPart
// Rimuovo i triangoli della componente nShell
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
if ( m_vTria[i].nShell == nShell)
RemoveTriangle( i) ;
}
// Aggiorno il numero di componenti
m_nShells = nShellsOld - 1 ;
// I dati di Shells e Parts sono stati resettati da RemoveTriangle
// imposto ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
@@ -3899,18 +3940,18 @@ SurfTriMesh::RemoveShell( int nShell)
}
//----------------------------------------------------------------------------
SurfTriMesh*
SurfTriMesh::ClonePart( int nPart) const
SurfTriMesh*
SurfTriMesh::CloneShell( int nShell) const
{
if ( ! IsValid())
return nullptr ;
// Il numero delle componenti deve essere maggiore di zero o calcolabile
if ( m_nParts == -1 && ! VerifyConnection())
if ( m_nShells == -1 && ! VerifyConnection())
return nullptr ;
// Se la componente non esiste, errore
if ( m_nParts <= 0 || nPart < 0 || nPart >= m_nParts)
if ( nShell < 0 || nShell >= m_nShells)
return nullptr ;
// Creo nuovo oggetto SurfTriMesh
@@ -3924,12 +3965,10 @@ SurfTriMesh::ClonePart( int nPart) const
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
pSurfTM->m_nParts = 1 ;
pSurfTM->m_nShells = 1 ;
// Copio i triangoli
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nPart == nPart) {
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[0]].ptP),
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[1]].ptP),
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[2]].ptP)} ;
@@ -3946,18 +3985,266 @@ SurfTriMesh::ClonePart( int nPart) const
}
//----------------------------------------------------------------------------
SurfTriMesh*
SurfTriMesh::CloneShell( int nShell) const
int
SurfTriMesh::GetPartCount( void) const
{
if ( ! IsValid())
return 0 ;
if ( m_vPart.empty() && ! VerifyConnection())
return 0 ;
return int( m_vPart.size()) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartArea( int nPart, double& dArea) const
{
// Controllo parametro di ritorno
if ( &dArea == nullptr)
return false ;
// Imposto area nulla
dArea = 0 ;
// Verifiche sull'oggetto
if ( ! IsValid())
return false ;
if ( m_vPart.empty() && ! VerifyConnection())
return false ;
// Se la componente non esiste, errore
if ( nPart < 0 || nPart >= int( m_vPart.size()))
return false ;
// sommo l'area di tutti i triangoli della parte
Triangle3d Tria ;
int nId = GetFirstTriangle( Tria) ;
while ( nId != SVT_NULL) {
const auto& vShell = m_vPart[nPart].vShell ;
if ( find( vShell.begin(), vShell.end(), m_vTria[nId].nShell) != vShell.end())
dArea += Tria.GetArea() ;
nId = GetNextTriangle( nId, Tria) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::IsPartClosed( int nPart) const
{
// Verifiche sull'oggetto
if ( ! IsValid())
return false ;
if ( m_vPart.empty() && ! VerifyConnection())
return false ;
// Se la componente non esiste, errore
if ( nPart < 0 || nPart >= int( m_vPart.size()))
return false ;
return m_vPart[nPart].bClosed ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartVolume( int nPart, double& dVolume) const
{
// Controllo parametro di ritorno
if ( &dVolume == nullptr)
return false ;
// Imposto volume nullo
dVolume = 0 ;
// Verifiche sull'oggetto
if ( ! IsValid())
return false ;
if ( m_vPart.empty() && ! VerifyConnection())
return false ;
// Se la componente non esiste, errore
if ( nPart < 0 || nPart >= int( m_vPart.size()))
return false ;
// la parte deve essere chiusa
if ( ! m_vPart[nPart].bClosed)
return true ;
// sommo il volume con segno di tutte le piramidi della parte dall'origine ad ogni faccia
Triangle3d Tria ;
int nId = GetFirstTriangle( Tria) ;
while ( nId != SVT_NULL) {
const auto& vShell = m_vPart[nPart].vShell ;
if ( find( vShell.begin(), vShell.end(), m_vTria[nId].nShell) != vShell.end()) {
Vector3d vtA = ( Tria.GetP( 1) - Tria.GetP( 0)) ^ ( Tria.GetP( 2) - Tria.GetP( 0)) ;
dVolume += ( Tria.GetP( 0) - ORIG) * vtA ;
}
nId = GetNextTriangle( nId, Tria) ;
}
dVolume /= 6 ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
vPL.clear() ;
// aggiorno timestamp dei triangoli
++ m_nTimeStamp ;
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
// incremento time stamp
++ m_nTimeStamp ;
// recupero il vettore delle Shell che compongono la part
const auto& vShell = m_vPart[nPart].vShell ;
// ciclo sui triangoli
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
// se triangolo valido e non ancora visitato
if ( m_vTria[nT].nIdVert[0] != SVT_DEL && m_vTria[nT].nTemp != m_nTimeStamp &&
find( vShell.begin(), vShell.end(), m_vTria[nT].nShell) != vShell.end()) {
// determino i triangoli adiacenti
int nAdjT[3] ;
for ( int j = 0 ; j < 3 ; ++ j)
nAdjT[j] = m_vTria[nT].nIdAdjac[j] ;
// se tutti e tre i lati sono di contorno
if ( nAdjT[0] == SVT_NULL &&
nAdjT[1] == SVT_NULL &&
nAdjT[2] == SVT_NULL) {
// ho trovato un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
}
// se i due lati 0 e 1 sono di contorno
else if ( nAdjT[0] == SVT_NULL &&
nAdjT[1] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back()))
return false ;
}
// se i due lati 1 e 2 sono di contorno
else if ( nAdjT[1] == SVT_NULL &&
nAdjT[2] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back()))
return false ;
}
// se i due lati 2 e 0 sono di contorno
else if ( nAdjT[2] == SVT_NULL &&
nAdjT[0] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 0 è di contorno
else if ( nAdjT[0] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 1 è di contorno
else if ( nAdjT[1] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 2 è di contorno
else if ( nAdjT[2] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
// cammino lungo il loop fino a chiuderlo
if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back()))
return false ;
}
// altrimenti non c'è contorno
else {
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemovePart( int nPart)
{
if ( ! IsValid())
return false ;
// Il numero delle componenti deve essere maggiore di zero o calcolabile
if ( m_vPart.empty() && ! VerifyConnection())
return false ;
// Se la componente non esiste, errore
if ( nPart < 0 || nPart >= int( m_vPart.size()))
return false ;
// Rimuovo i triangoli della componente nPart (ovvero delle sue shell)
const auto vShell = m_vPart[nPart].vShell ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
if ( find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end())
RemoveTriangle( i) ;
}
// I dati di Shells e Parts sono stati resettati da RemoveTriangle
// imposto ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
return true ;
}
//----------------------------------------------------------------------------
SurfTriMesh*
SurfTriMesh::ClonePart( int nPart) const
{
if ( ! IsValid())
return nullptr ;
// Il numero delle componenti deve essere maggiore di zero o calcolabile
if ( m_nShells == -1 && ! VerifyConnection())
// Il numero delle parti deve essere maggiore di zero o calcolabile
if ( m_vPart.empty() && ! VerifyConnection())
return nullptr ;
// Se la componente non esiste, errore
if ( m_nShells <= 0 || nShell < 0 || nShell >= m_nShells)
// Se la parte non esiste, errore
if ( nPart < 0 || nPart >= int( m_vPart.size()))
return nullptr ;
// Creo nuovo oggetto SurfTriMesh
@@ -3971,12 +4258,12 @@ SurfTriMesh::CloneShell( int nShell) const
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
pSurfTM->m_nParts = 1 ;
pSurfTM->m_nShells = 1 ;
// Copio i triangoli
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
const auto& vShell = m_vPart[nPart].vShell ;
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[0]].ptP),
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[1]].ptP),
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[2]].ptP)} ;
+36 -16
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2023
// EgalTech 2014-2025
//----------------------------------------------------------------------------
// File : SurfTriMesh.h Data : 09.12.23 Versione : 2.5l2
// File : SurfTriMesh.h Data : 28.03.25 Versione : 2.7c4
// Contenuto : Dichiarazione della classe Superficie TriMesh.
//
//
@@ -52,16 +52,16 @@ class StmTria
public :
StmTria( void)
: nIdVert{ SVT_NULL, SVT_NULL, SVT_NULL}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
StmTria( const int nIdV[3])
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
StmTria( const int nIdV[3], int nTF)
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
vtN(), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( 0), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
vtN(), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( 0), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
StmTria( const int nIdV[3], const int nIdA[3], const Vector3d& vtV, int nTF, int nEF)
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ nIdA[0], nIdA[1], nIdA[2]}, nETempFlag{ 0, 0, 0},
vtN( vtV), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( nEF), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
vtN( vtV), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( nEF), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
public :
int nIdVert[3] ;
int nIdAdjac[3] ;
@@ -71,11 +71,24 @@ class StmTria
int nTFlag ;
int nEFlag ;
mutable int nShell ;
mutable int nPart ;
mutable int nTemp ;
mutable int nTempShell ;
mutable int nTempPart ;
} ;
//----------------------------------------------------------------------------
// Classe Part
class StmPart
{
public :
StmPart( void)
: bClosed( false) {}
StmPart( bool bClo, const INTVECTOR& vSh)
: bClosed( bClo), vShell( vSh) {}
int GetShellCount( void)
{ return ( vShell.empty() ? 0 : int( vShell.size()) - ( vShell[0] == -1 ? 1 : 0)) ; }
public :
bool bClosed ;
INTVECTOR vShell ;
} ;
//----------------------------------------------------------------------------
@@ -238,7 +251,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool RemoveTriangle( int nId) override ;
bool AdjustTopology( void) override ;
bool CreateByFlatContour( const PolyLine& PL) override ;
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
bool CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL) override ;
bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) override ;
bool CreateByPointCurve( const Point3d& ptP, const PolyLine& PL) override ;
bool CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nRuledType) override ;
@@ -319,12 +332,16 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ;
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
const BBox3d& GetAllTriaBox( void) const override ;
int GetPartCount( void) const override ;
int GetShellCount( void) const override ;
bool RemovePart( int nPart) override ;
int GetShellCount( void) const override ;
bool GetShellArea( int nShell, double& dArea) const override ;
bool RemoveShell( int nShell) override ;
SurfTriMesh* ClonePart( int nPart) const override ;
SurfTriMesh* CloneShell( int nShell) const override ;
int GetPartCount( void) const override ;
bool RemovePart( int nPart) override ;
bool GetPartArea( int nPart, double& dArea) const override ;
bool GetPartVolume( int nPart, double& dVolume) const override ;
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
SurfTriMesh* ClonePart( int nPart) const override ;
bool SetTFlag( int nId, int nTFlag) override ;
bool GetTFlag( int nId, int& nFlag) const override ;
int GetMaxTFlag( void) const override
@@ -349,6 +366,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error")
return *this ; }
bool Clear( void) ;
bool CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat) ;
bool ExistsTriangle( int nT) const
{ return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; }
bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ;
@@ -359,6 +377,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
private :
typedef std::vector<StmVert> VERTVECTOR ;
typedef std::vector<StmTria> TRIAVECTOR ;
typedef std::vector<StmPart> PARTVECTOR ;
typedef std::vector<StmFacEdge> FACEDGEVECTOR ;
typedef std::deque<Stm3Int> TRINTDEQUE ;
@@ -403,14 +422,15 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool UpdateFacetEdging( void) ;
void ResetHashGrids3d( void) const ;
bool VerifyHashGrids3d( void) const ;
bool VerifyConnection( void) const ;
bool VerifyConnection( bool bShellsAndParts = true) const ;
bool IsShellClosed( int nShell) const ;
bool IsPartClosed( int nPart) const ;
bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ;
bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ;
bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ;
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
bool IdentifyParts( void) const ;
bool IdentifyShells( void) const ;
bool RemoveDoubleTriangles( bool& bModified) ;
bool RemoveTJunctions( bool& bModified) ;
@@ -442,8 +462,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
int m_nMaxTFlag ; // massimo valore dei TFlag dei triangoli
mutable int m_nParts ; // numero di parti intese come volumi (-1 se da calcolare)
mutable int m_nShells ; // numero di gusci connessi (-1 se da calcolare)
mutable PARTVECTOR m_vPart ; // vettore delle parti (flag chiusura e elenco shell, prima sempre esterna o infinita)
mutable HashGrids3d* m_pHGrd3d ; // Hash Grid 3d nel suo riferimento
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
} ;
+7 -41
View File
@@ -56,7 +56,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// Divido il loop di partenza in sotto-loop
int nIterationCount = 0 ;
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
while ( ! cvOpenChain.empty()) { // per ogni catena aperta...
bool bLoopSplitted = false ;
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
if ( vnDegVec[nLastOpenLoopN] == 1) {
@@ -73,8 +73,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
// splitto
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted) ||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
if ( ! ( bChangedStart && bSplitted))
continue ; // la catena aperta non è interna al loop chiuso attuale
// il loop 2 segue sempre la direzione della catena, il loop 1 ha dentro la catena invertita
@@ -288,7 +287,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
// Recupero i concatenamenti
INTVECTOR vIds ;
Point3d ptNearStart = ( it->second.size() > 0 ? it->second[0].ptSt : ORIG) ;
Point3d ptNearStart = ( ! it->second.empty() ? it->second[0].ptSt : ORIG) ;
CHAINVECTOR vChain ;
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
Chain chTemp ;
@@ -433,9 +432,9 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
int nSameSeg = 0 ;
for ( int nSeg1 = 0 ; nSeg1 < nChainSize1 ; ++ nSeg1) {
for ( int nSeg2 = 0 ; nSeg2 < nChainSize2 ; ++ nSeg2) {
if ( AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt) &&
AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn) &&
AreSameVectorExact( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter)) {
if ( AreSamePointEpsilon( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt, 100 * EPS_ZERO) &&
AreSamePointEpsilon( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn, 100 * EPS_ZERO) &&
AreSameVectorEpsilon( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter, 100 * EPS_ZERO)) {
++ nSameSeg ;
}
}
@@ -714,7 +713,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
if ( vInnerLoop.size() == 0 || bDouble) {
if ( vInnerLoop.empty() || bDouble) {
// Eseguo triangolazione
PNTVECTOR vPt ;
INTVECTOR vTr ;
@@ -1404,39 +1403,6 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::IdentifyParts( void) const
{
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
abs( m_vTria[i].nTempPart) != 1)
continue ;
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( i) ;
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
if ( m_vTria[nT].nETempFlag[j] != 0)
continue ;
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nTempPart == 0) {
m_vTria[nAdjT].nTempPart = m_vTria[nT].nTempPart ;
stTria.insert( nAdjT) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::IdentifyShells( void) const
+3 -3
View File
@@ -613,7 +613,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
++ it ;
}
// Se più di una catena chiusa oppure catene chiuse e aperte, errore
if ( cvClosedChain.size() > 1 || ( cvClosedChain.size() > 0 && int( cvOpenChain.size()) > 0)) {
if ( cvClosedChain.size() > 1 || ( ! cvClosedChain.empty() && ! cvOpenChain.empty())) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
@@ -676,7 +676,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
}
// Loop aperti, devo chiuderli
else if ( cvOpenChain.size() > 0) {
else if ( ! cvOpenChain.empty()) {
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
@@ -691,7 +691,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop di partenza in sotto-loop
while ( cvOpenChain.size() > 0) {
while ( ! cvOpenChain.empty()) {
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
// Estremi del loop aperto
+2 -2
View File
@@ -644,7 +644,7 @@ SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
{
// recupero i loop della faccia
POLYLINEVECTOR vPL ;
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
return false ;
// calcolo il centro del loop esterno (è il primo)
PolygonPlane PolyPlane ;
@@ -682,7 +682,7 @@ SurfTriMesh::GetFacetArea( int nF, double& dArea) const
{
// recupero i loop della faccia
POLYLINEVECTOR vPL ;
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
return false ;
// sommo le aree dei diversi loop (quelli interni hanno area negativa)
dArea = 0 ;
+2 -2
View File
@@ -539,10 +539,10 @@ bool
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
{
// Se la catena da aggiungere è vuota, non devo fare alcunchè
if ( ChainToAdd.size() == 0)
if ( ChainToAdd.empty())
return true ;
// Se la catena originale è vuota, non è possibile aggiungere nulla
if ( OrigChain.size() == 0)
if ( OrigChain.empty())
return false ;
// Se la catena originale è chiusa non posso aggiungere nulla
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
+1620 -1492
View File
File diff suppressed because it is too large Load Diff
+51 -37
View File
@@ -20,6 +20,15 @@
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include <map>
#include <utility>
struct PairHashInt64 {
size_t operator()(const pair<int64_t, int64_t>& key) const {
size_t h1 = std::hash<int64_t>{}(key.first) ;
size_t h2 = std::hash<int64_t>{}(key.second) ;
return h1 ^ (h2 << 1); // Combine hashes
}
};
//----------------------------------------------------------------------------
struct Inters {
@@ -155,7 +164,7 @@ class Cell
~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_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false),
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_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) ;
@@ -163,7 +172,7 @@ class Cell
}
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_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false),
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_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
bool IsSame( const Cell& cOtherCell) const
{ return ( m_nId == cOtherCell.m_nId) ; }
@@ -185,19 +194,21 @@ class Cell
{ return Point3d( m_ptPtr.x, m_ptPbl.y); }
double GetSplitValue( void) const
{ 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, sennò orizzontalmente
{ 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) ; }
bool IsProcessed( void) const // flag che indica se tutti i figli della cella, se ce ne sono, sono stati processati
{ return m_bProcessed ; }
void SetProcessed( bool bProcessed = true)
{ m_bProcessed = bProcessed ; }
static bool minorX( const Cell& c1, const Cell& c2)
{ return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
{ return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
static bool minorY( const Cell& c1, const Cell& c2)
{ return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
{ return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
void AddPoly( int nPolyId)
{ m_vnPolyId.push_back( nPolyId) ;}
public :
int m_nId ; // Id della cella
int m_nTop ; // cella adiacente al lato top
@@ -209,14 +220,17 @@ class Cell
double m_dSplit ; // parametro a cui è stata splittata la cella
int m_nChild1 ; // prima cella figlio
int m_nChild2 ; // seconda cella figlio
int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim
int m_nFlag ; // flag che indica la caratterizzazione della cella rispetto ai loop di trim
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
bool m_bLabelled ; // flag che indica se la cella è stata attraversata durante l'ultima fase del labelling
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse sul parametro U)
bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V)
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
// ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella
int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo
// contati in senso CCW a partire dal bottom left
INTVECTOR m_vnPolyId ; // indici dei poligoni associati a questa cella nel vettore m_vPolygons del Tree
private :
Point3d m_ptPbl ; // punto bottom left
@@ -235,16 +249,17 @@ class Tree
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, 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 BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax il massimo per la dimensione maggiore di un triangolo della trimesh
// dSideMin lunghezza minima del lato di una cella nello spazio reale
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
// dSideMin è lunghezza minima del lato di una cella nello spazio reale
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
bool GetPolygons( POLYLINEMATRIX& vPolygons) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // 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
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
// 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
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
{ for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; };
bool GetEdges3D ( 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
{ 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
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
@@ -254,10 +269,9 @@ class Tree
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
private :
bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico
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
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondit di +- 1
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 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
@@ -268,37 +282,38 @@ class Tree
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, 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 FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
bool FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
// resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario
bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR.
bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3)
bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // sul lato nEdge controllo se ptP1 viene prima di ptP2.
bool AreSameEdge( int nEdge1, int nEdge2) const ; // indica se i due edge sono lo stesso. Un vertice adiacente ad un edge viene considerato uguale a questo edge
bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto
bool CheckIfBefore( int nEdgeA, int nEdgeB) const ; // per due edge uguali per la funzione AreSameEdge chiedo se EdgeA viene prima di EdgeB
bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c,
const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool ForTriangulation, Point3d& ptLast) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto
bool SetRightEdgeIn( int nId) ; // categorizza la cella in base all'edge destro per poter poi definire m_nFlag
bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata)
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW)
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL
bool AdjustCuts( void) ;
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
bool CloseOpenCuts( void) ;
bool CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& pl) const ;
bool UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt) ;
bool VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const ; // verifico l'orientazione ( CCW o CW) delle polyline in base a come sono contenute le une nelle altre
bool AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ;
bool GetPoint(double dU, double dV, Point3d& pt) const ;
bool SavePoint( double dU, double dV, Point3d& pt) ;
private :
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
//INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
std::map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
//ICURVEPOVECTOR m_vLoop ; // curve di loop
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
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
bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch
bool m_bClosedU ; // superficie chiusa lungo il parametro U
@@ -309,12 +324,11 @@ class Tree
int m_nDegV ; // grado della superficie nel parametro V
int m_nSpanU ; // numero di span lungo il parametro U
int m_nSpanV ; // numero di span lungo il parametro V
POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree
std::map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 puntatore Null e -1 root
std::map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id lo stesso che la cella ha in m_mTree
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)
INTVECTOR m_vnLeaves ; // vettore delle foglie
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
bool m_bTestMode ; // bool che indica se la test mode è attiva
POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
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.
} ;
+432 -122
View File
@@ -17,24 +17,32 @@
#include "Triangulate.h"
#include "ProjPlane.h"
#include "earcut.hpp"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "CurveComposite.h"
#include "IntersCrvCompoCrvCompo.h"
#include "/EgtDev/Extern/fist/Include/api_fist.h"
#include <algorithm>
using namespace std ;
//----------------------------------------------------------------------------
enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
enum TrgType { TRG_STD = 0, TRG_CAP = 1, TRG_NEEDLE = 2} ;
//----------------------------------------------------------------------------
static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
static bool MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
static bool RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr) ;
static int CalcTriangleType( const PNTVECTOR& vPt, const INTVECTOR& vTr, int nTrg) ;
static bool FindAdjacentOnLongerEdge( PNTVECTOR& vPt, INTVECTOR& vTr, int nTrgA, int&nEdgeA, int& nTrgB, int& nEdgeB) ;
static bool FlipTrg( INTVECTOR& vTr, int nTrgA, int nTrgB, int nEdgeA, int nEdgeB) ;
static bool TestAdjacentOnEdge( INTVECTOR& vTr, int nTrgA, int nEdgeA, int nTrgTest1, int nTrgTest2, int& nTrgB, int& nEdgeB) ;
//----------------------------------------------------------------------------
static bool FORCE_EARCUT_HPP = false ;
static bool FORCE_FIST = false ;
//----------------------------------------------------------------------------
// In : PolyLine
@@ -48,8 +56,13 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
vPt.clear() ;
vTr.clear() ;
// verifico che la polilinea contenga almeno 4 punti (primo e ultimo coincidenti)
if ( PL.GetPointNbr() < 4)
if ( PL.GetPointNbr() < 4 || ! PL.IsClosed())
return false ;
// se fist ( e geometria più complessa di un quadrilatero)
if ( FORCE_FIST && PL.GetPointNbr() > 5)
return MakeByFist( {PL}, vPt, vTr) ;
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
Plane3d plPlane ;
@@ -116,6 +129,11 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
// se una sola polilinea mi riconduco al caso precedente
if ( vPL.size() == 1)
return Make( vPL[0], vPt, vTr) ;
// se fist
if ( FORCE_FIST)
return MakeByFist( vPL, vPt, vTr) ;
// verifico che la polilinea esterna sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
Plane3d plExtPlane ;
@@ -133,7 +151,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea2, 50 * EPS_SMALL) ||
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
return false ;
}
}
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
@@ -223,121 +241,42 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
//---------------------------------------------------------------------------
bool
Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVECTOR& vTr)
{
INTMATRIX vnPLIndMat ;
return MakeAdvanced( vPLORIG, vPt, vTr, vnPLIndMat) ;
}
//---------------------------------------------------------------------------
bool
Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVECTOR& vTr, const INTMATRIX& vnPLIndMatPre)
{
vPt.clear() ;
vTr.clear() ;
// se non ho PolyLine, allora non faccio nulla
if ( int( vPLORIG.size()) == 0)
if ( vPLORIG.empty())
return true ;
// copio il vettore di PolyLine
POLYLINEVECTOR vPL ;
for ( int i = 0 ; i < int( vPLORIG.size()) ; ++ i)
vPL.push_back( vPLORIG[i]) ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
Vector3d vtN0 ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// imposto la normale del primo contorno come riferimento
if ( i == 0)
vtN0 = plPlane.GetVersN() ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN0) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN0) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
Vector3d vtN ;
// se non sono stati passate le info per ordinare le polyline allora le ordino
INTMATRIX vnPLIndMat ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
BOOLVECTOR vbInvert ;
if ( vnPLIndMatPre.empty()) {
if ( ! CalcRegionPolyLines( vPLORIG, vtN, vnPLIndMat, vbInvert))
return false ;
vPL = vPLORIG ;
for ( int i = 0 ; i < int( vbInvert.size()) ; i++) {
if ( vbInvert[i])
vPL[i].Invert() ;
}
} while ( ! bFirstCrv) ;
}
else {
// ho già calcolato e riordinato tutto, devo solo fare una copia delle polyline
// non serve fare le eventuali inversioni delle polyline, perché se è già stata calcolata la matrice dei chunck allora sono già state invertire
vPL = vPLORIG ;
vnPLIndMat = vnPLIndMatPre ;
}
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ;
@@ -352,7 +291,7 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
vTr.push_back( nSize + vTr_tmp[t]) ;
}
return true ;
}
@@ -525,7 +464,7 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
vTr.push_back( vPol[i]) ;
vTr.push_back( vPol[vNext[i]]) ;
}
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -654,7 +593,7 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
// Reset earity of diagonal endpoints
vEar[vPrev[i]] = EAS_NULL ;
vEar[vNext[i]] = EAS_NULL ;
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -792,7 +731,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
// Reset earity of diagonal endpoints
vEar[vPrev[i]] = EAS_NULL ;
vEar[vNext[i]] = EAS_NULL ;
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -886,7 +825,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
}
}
else {
// The ear triangle is clockwise so v[i] is not an ear
// The ear triangle is clockwise so v[i] is not an ear
bIsEar = false ;
}
@@ -1231,14 +1170,14 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
break ;
}
}
// non ho trovato alcunché, errore
// non ho trovato alcunchè, errore
if ( nI == - 1)
return false ;
// se ho trovato un punto esatto del contorno, non devo fare altri controlli
if ( AreSamePointApprox( ptInt, vPt[nI]))
return true ;
// devo ora verificare che il segmento che unisce i punti non intersechi altri lati del contorno esterno
// altrimenti tengo il punto con raggio più vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
// altrimenti tengo il punto con raggio più vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
int nJ = nI ;
Point3d ptPa = ptP ;
Point3d ptPb = vPt[nI] ;
@@ -1254,7 +1193,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
double dMinTan = INFINITO ;
double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < nNumPt ; ++ i) {
// salto il punto già trovato
// salto il punto già trovato
if ( i == nJ)
continue ;
// verifico se sta nel triangolo
@@ -1290,7 +1229,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
bool
Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const Point3d& ptCorn, const Point3d& ptNext)
{
// la parte valida del settore è a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
// la parte valida del settore è a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
// se corner convesso
if ( TriangleIsCCW( ptPrev, ptCorn, ptNext, 0))
return ( TriangleIsCCW( ptPrev, ptCorn, ptTest) &&
@@ -1305,13 +1244,384 @@ Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const
bool
ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi)
{
// se il nuovo inizio coincide col vecchio, non devo fare alcunché
// se il nuovo inizio coincide col vecchio, non devo fare alcunchè
if ( nNewStart == 0)
return true ;
// se il nuovo indice è oltre la dimensione del vettore, errore
// se il nuovo indice è oltre la dimensione del vettore, errore
if ( nNewStart >= int( vPi.size()))
return false ;
// ciclo di aggiustamento
rotate( vPi.begin(), vPi.begin() + nNewStart, vPi.end()) ;
return true ;
}
//----------------------------------------------------------------------------
// Funzioni per triangolare usando la libreria FIST
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int
CalcTriangleType( const PNTVECTOR& vPt, const INTVECTOR& vTr, int nTrg)
{
Vector3d vtV1 = vPt[vTr[3*nTrg + 1]] - vPt[vTr[3*nTrg]] ;
Vector3d vtV2 = vPt[vTr[3*nTrg + 2]] - vPt[vTr[3*nTrg + 1]] ;
Vector3d vtN = vtV1 ^ vtV2 ;
double dSqN = vtN.SqLen() ;
double dSqLen1 = vtV1.SqLen() ;
double dSqLen2 = vtV2.SqLen() ;
double dSqLen3 = ( vtV1 + vtV2).SqLen() ;
// un triangolo è invalido ( needle o cap) se viene scartato dai controlli di AddTriangle
if ( dSqN < SQ_EPS_ZERO || dSqN < SQ_EPS_TRIA_H * max( {dSqLen1, dSqLen2, dSqLen3})) {
if ( dSqLen1 < SQ_EPS_ZERO || dSqLen2 < SQ_EPS_ZERO || dSqLen3 < SQ_EPS_ZERO)
return TRG_NEEDLE ;
else
return TRG_CAP ;
}
else
return TRG_STD ;
}
//----------------------------------------------------------------------------
bool
FlipTrg( INTVECTOR& vTr, int nTA, int nTB, int nEA, int nEB)
{
vTr[3*nTA + nEA] = vTr[3*nTB + ( nEB + 2) % 3] ;
vTr[3*nTB + nEB] = vTr[3*nTA + ( nEA + 2) % 3] ;
return true ;
}
//----------------------------------------------------------------------------
bool
TestAdjacentOnEdge( INTVECTOR& vTr, int nTA, int nEA, int nTTest1, int nTTest2, int& nTB, int& nEB)
{
// individuo quale triangolo tra nTTest1 e nTTest2 è quello adiacente a nTA lungo il lato nEA
nTB = -1 ;
nEB = -1 ;
// recupero i vertici di nEA
int nV1 = vTr[3*nTA + nEA] ;
int nV2 = vTr[3*nTA + ( nEA + 1) % 3] ;
// verifico se è TTest1 quello adiacente
if ( vTr[3*nTTest1] == nV2 && vTr[3*nTTest1+1] == nV1) {
nEB = 0 ;
nTB = nTTest1 ;
}
else if ( vTr[3*nTTest1+1] == nV2 && vTr[3*nTTest1+2] == nV1) {
nEB = 1 ;
nTB = nTTest1 ;
}
else if ( vTr[3*nTTest1] == nV1 && vTr[3*nTTest1+2] == nV2) {
nEB = 2 ;
nTB = nTTest1 ;
}
// verifico se è TTest2 quello adiacente
else if ( vTr[3*nTTest2] == nV2 && vTr[3*nTTest2+1] == nV1) {
nEB = 0 ;
nTB = nTTest2 ;
}
else if ( vTr[3*nTTest2+1] == nV2 && vTr[3*nTTest2+2] == nV1) {
nEB = 1 ;
nTB = nTTest2 ;
}
else if ( vTr[3*nTTest2] == nV1 && vTr[3*nTTest2+2] == nV2) {
nEB = 2 ;
nTB = nTTest2 ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
FindAdjacentOnLongerEdge( PNTVECTOR& vPt, INTVECTOR& vTr, int nTA, int& nEA, int& nTB, int& nEB)
{
// recupero il lato più lungo del triangolo nTA
nEA = -1 ;
double dMaxLen = -1 ;
for ( int j = 0 ; j < 3 ; j++) {
double dCurrLen = SqDist( vPt[vTr[3*nTA + j]], vPt[vTr[3*nTA + ( j+1)%3]]) ;
if ( dCurrLen > dMaxLen) {
dMaxLen = dCurrLen ;
nEA = j ;
}
}
// cerco il triangolo nTB adiacente a nTA lungo nEA
nTB = -1 ;
nEB = -1 ;
int nV1 = vTr[3*nTA + nEA] ;
int nV2 = vTr[3*nTA + ( nEA + 1) % 3] ;
int nTria = vTr.size() / 3 ;
for ( int j = 0 ; j < nTria ; j++) {
if ( j == nTA)
continue ;
if ( vTr[3*j] == nV2 && vTr[3*j+1] == nV1) {
nEB = 0 ;
nTB = j ;
break ;
}
else if ( vTr[3*j+1] == nV2 && vTr[3*j+2] == nV1) {
nEB = 1 ;
nTB = j ;
break ;
}
else if ( vTr[3*j] == nV1 && vTr[3*j+2] == nV2) {
nEB = 2 ;
nTB = j ;
break ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
{
// scorro tutti i triangoli alla ricerca di triangoli validi per FIST ma invalidi per le nostre tolleranze.
// I triangoli invalidi possono essere di due tipologie: cap o needle.
// 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
// calcolo delle adiacenze dei triangoli cap.
int nTria = int( vTr.size()) / 3 ;
INTVECTOR vCapTria ;
INTVECTOR vNeedleTria ;
BOOLVECTOR vbIsValidTria( nTria, true) ;
bool bRemovedTrg = false ;
for ( int i = 0 ; i < nTria ; i ++) {
int nTrgType = CalcTriangleType( vPt, vTr, i) ;
if ( nTrgType == TRG_CAP) {
vbIsValidTria[i] = false ;
vCapTria.emplace_back( i) ;
}
else if ( nTrgType == TRG_NEEDLE) {
vNeedleTria.emplace_back( i) ;
}
}
// se non ci sono triangoli cap non c'è bisogno di modifiche
if ( vCapTria.empty())
return true ;
// 1) elimino i triangoli di tipo needle gestendo i vertici coincidenti
if ( ! vNeedleTria.empty()) {
bRemovedTrg = true ;
for ( int i = 0 ; i < int( vNeedleTria.size()) ; i++) {
int nT = vNeedleTria[i] ;
if ( vTr[3*nT] != vTr[3*nT+1] && vTr[3*nT] != vTr[3*nT+2] && vTr[3*nT+1] != vTr[3*nT+2]) {
// individuo i vertici coincidenti
int nOldId = -1 ;
int nNewId = -1 ;
Vector3d vtV1 = vPt[vTr[3*nT+1]] - vPt[vTr[3*nT]] ;
if ( vtV1.SqLen() < SQ_EPS_ZERO) {
// vertici coincidenti 0 e 1
nOldId = vTr[3*nT] ;
nNewId = vTr[3*nT+1] ;
}
else {
Vector3d vtV2 = vPt[vTr[3*nT+2]] - vPt[vTr[3*nT+1]] ;
if ( vtV2.SqLen() < SQ_EPS_ZERO) {
// vertici coincidenti 1 e 2
nOldId = vTr[3*nT+1] ;
nNewId = vTr[3*nT+2] ;
}
else {
// vertici coincidenti 0 e 2
nOldId = vTr[3*nT] ;
nNewId = vTr[3*nT+2] ;
}
}
// aggiorno il vettore dei triangoli unificando i vertici coincidenti
for ( int k = 0 ; k < int( vTr.size()) ; k ++) {
if ( vTr[k] == nOldId)
vTr[k] = nNewId ;
}
}
// annullo il triangolo
vTr[3*nT] = -1 ;
vTr[3*nT+1] = -1 ;
vTr[3*nT+2] = -1 ;
}
}
// 2) sistemo i triangoli di tipo cap
for ( int i = 0 ; i < int( vCapTria.size()) ; i++) {
int nTA = vCapTria[i] ;
// verifico se il triangolo è già stato resto valido ( da una catena)
if ( vbIsValidTria[nTA])
continue ;
// trovo l'adiacenza sul suo lato più lungo
int nEA = -1 ;
int nEB = -1 ;
int nTB = -1 ;
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
if ( nTB == -1) {
// se non ha un triangolo adiacente posso annullarlo
vTr[3*nTA] = -1 ;
vTr[3*nTA+1] = -1 ;
vTr[3*nTA+2] = -1 ;
vbIsValidTria[nTA] = true ;
bRemovedTrg = true ;
continue ;
}
else if ( vbIsValidTria[nTB]) {
// se è adiacente è valido, eseguo il flip
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
vbIsValidTria[nTA] = true ;
}
else {
// se adiacente è invalido, individuo una catena di triangoli invalidi da risolvere non appena si indentifica
// adiacenza con triangolo valido
INTVECTOR vChain, vChainEdges ;
vChain.emplace_back( nTA) ;
vChainEdges.emplace_back( nEA) ;
while ( nTB != -1 && ! vbIsValidTria[nTB]) {
// aggiungo alla catena
vChain.emplace_back( nTB) ;
// calcolo il successivo
nTA = nTB ;
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
vChainEdges.emplace_back( nEA) ;
// verifico di non aver trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
// e quindi di non essere entrato in un loop
if ( nTB == vChain[vChain.size()-2]) {
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
// aggiorno per iterazione successiva
if ( vChain.size() == 2) {
vChain.pop_back() ;
vChainEdges.pop_back() ;
FindAdjacentOnLongerEdge( vPt, vTr, vChain.back(), nEA, nTB, nEB) ;
vChainEdges[0] = nEA ;
}
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) ;
}
}
}
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
if ( nTB == -1) {
bRemovedTrg = true ;
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
vTr[3*vChain[k]] = -1 ;
vTr[3*vChain[k] + 1] = -1 ;
vTr[3*vChain[k] + 2] = -1 ;
vbIsValidTria[vChain[k]] = true ;
}
}
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido
else {
FlipTrg( vTr, vChain.back(), nTB, vChainEdges.back(), nEB) ;
vbIsValidTria[vChain.back()] = true ;
int nTrgTest1 = vChain.back() ;
int nTrgTest2 = nTB ;
for ( int i = int( vChain.size()-2) ; i >= 0 ; i--) {
// triangolo corrente
int nTA = vChain[i] ;
int nEA = vChainEdges[i] ;
// devo trovare il nuovo adiacente dopo il flip dei successivi nella catena
TestAdjacentOnEdge( vTr, nTA, nEA, nTrgTest1, nTrgTest2, nTB, nEB) ;
// flip per rendere valido il triangolo corrente
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
vbIsValidTria[nTA] = true ;
// aggiorno i trg di test per lo step successivo
nTrgTest1 = nTA ;
nTrgTest2 = nTB ;
}
}
}
}
// se sono stati annullati dei triangoli, li rimuovo dal vettore
if ( bRemovedTrg) {
INTVECTOR vTrTmp ;
vTrTmp.reserve( vTr.size()) ;
for ( int i = 0 ; i < int( vTr.size()) ; i++)
if ( vTr[i] != -1)
vTrTmp.emplace_back( vTr[i]) ;
swap( vTr, vTrTmp) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// opzioni di triangolazione
rt_options rt_opt ;
InitDefaults( &rt_opt) ;
rt_opt.ears_top = false ;
rt_opt.ears_random = false ;
rt_opt.ears_sorted = true ;
rt_opt.ears_fancy = true ;
// creo oggetto di fist per triangolazione
global_struct fist ;
InitGlobalStruct( &fist, &rt_opt, true) ;
// allocazione ottimizzata degli array di fist
int nLoops = int( vPL.size()) ;
int nVertices = 0 ;
for ( int i = 0 ; i < nLoops ; i ++)
nVertices += ( vPL[i].GetPointNbr() - 1) ;
OptimizeMemoryAllocation( &fist, nLoops, nVertices) ;
// assegno i dati a fist
for ( int i = 0 ; i < nLoops ; i ++) {
// salvo i vertici saltando il primo punto ( coincide con l'ultimo)
Point3d pt ;
if ( ! vPL[i].GetFirstPoint( pt))
return false ;
while ( vPL[i].GetNextPoint( pt))
StoreVertex( &fist.c_vertex, pt.x, pt.y, pt.z) ;
// salvo il loop
int nPoints = vPL[i].GetPointNbr() ;
AddLoopInFace( &fist, nLoops - 1, i == 0, nPoints - 1) ;
}
StoreGroupNumber( &fist.c_list, &fist.c_vertex) ;
// eseguo triangolazione
Triangulate( &fist) ;
// recupero i vertici da fist
vPt.reserve( fist.c_vertex.num_vertices) ;
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) ;
// recupero i triangoli da fist
vTr.reserve( 3 * fist.c_vertex.num_triangles) ;
for ( int i = 0 ; i < fist.c_vertex.num_triangles ; i ++) {
vTr.emplace_back( fist.c_vertex.triangles[i].v1) ;
vTr.emplace_back( fist.c_vertex.triangles[i].v2) ;
vTr.emplace_back( fist.c_vertex.triangles[i].v3) ;
}
// rimuovo eventuali triangoli validi per fist ma invalidi per le nostre tolleranze
RemoveFistInvalidTrg( vPt, vTr) ;
// chiudo fist e dealloco la sua memoria
FIST_TerminateProgram( &fist) ;
return true ;
}
+1
View File
@@ -23,6 +23,7 @@ class Triangulate
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeAdvanced( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeAdvanced( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, const INTMATRIX& vnPLIndMat) ;
private :
bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
+2 -2
View File
@@ -497,7 +497,7 @@ VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
int nPos = ic + jc * m_nNx[0] ;
if ( m_Values[0][nPos].size() > 0) {
if ( ! m_Values[0][nPos].empty()) {
Point3d ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersX() + dY * m_MapFrame.VersY() ;
b3Loc.Add( ptP + m_Values[0][nPos][0].dMin * m_MapFrame.VersZ()) ;
b3Loc.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * m_MapFrame.VersZ()) ;
@@ -541,7 +541,7 @@ VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
int nPos = ic + jc * m_nNx[0] ;
if ( nPos >= 0 && m_Values[0][nPos].size() > 0) {
if ( nPos >= 0 && ! m_Values[0][nPos].empty()) {
Point3d ptP = frUse.Orig() + dX * frUse.VersX() + dY * frUse.VersY() ;
b3Ref.Add( ptP + m_Values[0][nPos][0].dMin * frUse.VersZ()) ;
b3Ref.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * frUse.VersZ()) ;
+4 -4
View File
@@ -4013,7 +4013,7 @@ VolZmap::GetFirstVoxIJK( int& i, int& j, int& k) const
bool bNotEmpty = false ;
for ( nj = 0 ; nj < 2 ; ++ nj) {
int nDex = nj * int( m_nNx[0]) + ni ;
if ( ! m_Values[0].empty() && m_Values[0][nDex].size() > 0) {
if ( ! m_Values[0].empty() && ! m_Values[0][nDex].empty()) {
bNotEmpty = true ;
break ;
}
@@ -4026,7 +4026,7 @@ VolZmap::GetFirstVoxIJK( int& i, int& j, int& k) const
bool bNotEmpty = false ;
for ( mj = 0 ; mj < 2 ; ++ mj) {
int nDex = mj * int( m_nNx[1]) + mi ;
if ( ! m_Values[1].empty() && m_Values[1][nDex].size() > 0) {
if ( ! m_Values[1].empty() && ! m_Values[1][nDex].empty()) {
bNotEmpty = true ;
break ;
}
@@ -4056,7 +4056,7 @@ VolZmap::GetLastVoxIJK( int& i, int& j, int& k) const
bool bNotEmpty = false ;
for ( nj = int( m_nNy[0]) - 1 ; nj > int( m_nNy[0]) - 3 ; -- nj) {
int nDex = nj * int( m_nNx[0]) + ni ;
if ( ! m_Values[0].empty() && m_Values[0][nDex].size() > 0) {
if ( ! m_Values[0].empty() && ! m_Values[0][nDex].empty()) {
bNotEmpty = true ;
break ;
}
@@ -4069,7 +4069,7 @@ VolZmap::GetLastVoxIJK( int& i, int& j, int& k) const
bool bNotEmpty = false ;
for ( mj = int( m_nNy[1]) - 1 ; mj > int( m_nNy[1]) - 3 ; -- mj) {
int nDex = mj * int( m_nNx[1]) + mi ;
if ( ! m_Values[1].empty() && m_Values[1][nDex].size() > 0) {
if ( ! m_Values[1].empty() && ! m_Values[1][nDex].empty()) {
bNotEmpty = true ;
break ;
}
+41 -4
View File
@@ -55,13 +55,13 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ,
}
// Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a sistema intrinseco)
if ( !bSkipSwap && nGrid == 1) {
if ( ! bSkipSwap && nGrid == 1) {
swap( vtNmi.x, vtNmi.z) ;
swap( vtNmi.y, vtNmi.z) ;
swap( vtNma.x, vtNma.z) ;
swap( vtNma.y, vtNma.z) ;
}
else if ( !bSkipSwap && nGrid == 2) {
else if ( ! bSkipSwap && nGrid == 2) {
swap( vtNmi.y, vtNmi.z) ;
swap( vtNmi.x, vtNmi.z) ;
swap( vtNma.y, vtNma.z) ;
@@ -4544,11 +4544,44 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
double dLongLen = vtMoveLong.Len() ;
double dOrtLen = vtMoveOrt.Len() ;
// Parametri di contenimento
Vector3d vtPerp = vtToolDir ^ Z_AX ;
bool bPerpOk = vtPerp.Normalize() ;
if ( vtPerp * vtMove < 0)
vtPerp.Invert() ;
int nSkip = 0 ;
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) ;
// salto il controllo degli spilloni sotto il piano limite in basso o sopra il piano limite in alto
if ( ( ptC + Z_AX * m_dMinZ[nGrid] - ptITip) * vtToolDir < -EPS_SMALL &&
( ptC + Z_AX * m_dMaxZ[nGrid] - ptITip) * vtToolDir < -EPS_SMALL) {
++ nSkip ;
continue ;
}
if ( ( ptC + Z_AX * m_dMinZ[nGrid] - ptI - vtMoveLong) * vtToolDir > EPS_SMALL &&
( ptC + Z_AX * m_dMaxZ[nGrid] - ptI - vtMoveLong) * vtToolDir > EPS_SMALL) {
++ nSkip ;
continue ;
}
// salto il controllo degli spilloni prima del piano di fianco verticale di inizio o dopo il piano di fianco verticale di fine
if ( bPerpOk &&
( ptC + Z_AX * m_dMinZ[nGrid] - ptI + vtPerp * dRad) * vtPerp < -EPS_SMALL &&
( ptC + Z_AX * m_dMaxZ[nGrid] - ptI + vtPerp * dRad) * vtPerp < -EPS_SMALL) {
++ nSkip ;
continue ;
}
if ( bPerpOk &&
( ptC + Z_AX * m_dMinZ[nGrid] - ptF - vtPerp * dRad) * vtPerp > EPS_SMALL &&
( ptC + Z_AX * m_dMaxZ[nGrid] - ptF - vtPerp * dRad) * vtPerp > EPS_SMALL) {
++ nSkip ;
continue ;
}
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
@@ -4592,6 +4625,10 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
}
}
}
//string sLog = "Skipped dexel = " + ToString( nSkip) + " / " + ToString( ( nEndI - nStartI + 1) * ( nEndJ - nStartJ + 1)) ;
//LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())
return true ;
}
@@ -5090,7 +5127,7 @@ VolZmap::CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ,
// ---------- SFERA ----------------------------------------------------------
//---------------------------------------------------------------------------- pizza
//----------------------------------------------------------------------------
bool
VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe, double dRad, int nToolNum)
{
+420 -234
View File
@@ -20,6 +20,7 @@
#include "RemoveCurveDefects.h"
#include "Voronoi.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkChainCurves.h"
using namespace std ;
@@ -105,7 +106,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
return false ;
}
if ( m_vpCrvs.size() == 0) {
if ( m_vpCrvs.empty()) {
// se prima curva considerata assegno il frame al Voronoi
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
}
@@ -160,7 +161,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
// recupero il piano
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
Vector3d vtN = pSfr->GetNormVersor() ;
if ( m_vpCrvs.size() == 0) {
if ( m_vpCrvs.empty()) {
// assegno il frame al Voronoi
m_Frame.Set( ptCen, vtN) ;
}
@@ -371,6 +372,16 @@ Voronoi::GetCurve( int nId) const
return pCrv ;
}
//----------------------------------------------------------------------------
bool
Voronoi::GetVroniPlane( Plane3d& plPlane) const
{
if ( ! IsValid())
return false ;
plPlane.Set( m_Frame.Orig(), m_Frame.VersZ()) ;
return plPlane.IsValid() ;
}
//----------------------------------------------------------------------------
bool
Voronoi::CalcVoronoi( int nBound)
@@ -432,6 +443,9 @@ Voronoi::GetBisectorCurve( int i)
Point3d ptS, ptE, ptC ;
double dParS, dParE ;
m_vroni->GetDegenerateHyperEllipticBisectorData( i, ptS.v, ptE.v, ptC.v, dParS, dParE) ;
// se estremi coincidenti ignoro ( da vroni non possono arrivare circonferenze)
if ( AreSamePointApprox( ptS, ptE))
return nullptr ;
// creo arco
CurveArc* pArc = CreateBasicCurveArc() ;
if ( pArc == nullptr)
@@ -512,12 +526,12 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
// verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed || nBound != m_nBound)
CalcVoronoi( nBound) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// recupero la curva del bisettore
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
vCrvs.emplace_back( Release( pCrv)) ;
}
// libero la memoria di vroni utilizzata per calcolare bisettore
@@ -560,7 +574,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
if ( m_vroni->IsWMATEdge( i)) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
vCrvs.emplace_back( Release( pCrv)) ;
}
}
@@ -580,12 +594,8 @@ bool
Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
{
vOffs.clear() ;
if ( ! IsValid())
return false ;
// verifico se curve sono coerenti per calcolo dell'offset
if ( ! VerifyCurvesValidityForOffset())
if ( ! IsValid())
return false ;
// se offset nullo restituisco direttamente le curve
@@ -594,55 +604,235 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
vOffs.emplace_back( pCrv->Clone()) ;
}
bool bClosed = m_vpCrvs[0]->IsClosed() ;
// stabilisco lato offset
bool bRightOffs = true ;
bool bLeftOffs = true ;
if ( bClosed) {
bRightOffs = ( dOffs > EPS_SMALL ? true : false) ;
bLeftOffs = ( dOffs < - EPS_SMALL ? true : false) ;
}
// calcolo offset
ICRVCOMPOPLIST OffsList ;
if ( ! CalcVroniOffset( OffsList, abs( dOffs), bRightOffs, bLeftOffs))
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
return false ;
// sistemo le curve di offset calcolate con vroni
for ( auto pCrv : OffsList) {
// aggiustamento per curva aperta
if ( ! bClosed)
AdjustOpenOffsetCurve( *pCrv, dOffs) ;
if ( pCrv->IsValid()) {
// seleziono le porzioni dell'offset che si trovano dal lato richiesto
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
// eventuale inversione
if ( dOffs > EPS_SMALL)
pCrv->Invert() ;
vResult[i]->Invert() ;
// sistemo il punto di inizio
if ( vResult[i]->IsClosed())
AdjustOffsetStart( vResult[i]) ;
// sistemo i raccordi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
IdentifyFillets( pCrv, dOffs) ;
AdjustCurveFillets( pCrv, dOffs, nType) ;
IdentifyFillets( vResult[i], dOffs) ;
AdjustCurveFillets( vResult[i], dOffs, nType) ;
}
if ( bClosed) {
// forzo chiusura della curva per evitare piccole imprecisioni
pCrv->Close() ;
// sistemo il punto di inizio
AdjustOffsetStart( *pCrv) ;
}
// porto nel frame globale
pCrv->ToGlob( m_Frame) ;
vResult[i]->ToGlob( m_Frame) ;
// unisco le parti allineate
pCrv->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
vOffs.emplace_back( pCrv) ;
vOffs.emplace_back( Release( vResult[i])) ;
}
else
delete pCrv ;
// dealloco curva
delete( pCrv) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
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
// medial axis corrispondenti. L'offset invece restituirebbe curve chiuse formate da tratti praticamente sovrapposti.
vOffs.clear() ;
if ( abs( dOffs) < EPS_SMALL)
return true ;
if ( ! IsValid())
return false ;
try {
if ( ! m_bVDComputed)
CalcVoronoi() ;
// individuo il lato richiesto
bool bLeft = ( dOffs < 0) ;
bool bRight = ! bLeft ;
for ( int i = 0 ; i < int( m_vpCrvs.size()) ; i++) {
if ( ! m_vpCrvs[i]->IsClosed()) {
// se è presente una curva aperta il medial axis deve essere fatto sia a destra sia a sinistra
bLeft = true ;
bRight = true ;
break ;
}
}
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
// seleziono le curve del medial axis aventi parametro costante pari all'offset richiesto
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
ICURVEPOVECTOR vCrvs ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se bisettore di medial axis
if ( m_vroni->IsWMATEdge( i)) {
// verifico i parametri
double dParS, dParE ;
m_vroni->GetBisectorParams( i, dParS, dParE) ;
if ( abs( dParS - abs( dOffs)) < EPS_SMALL && abs( dParE - abs( dOffs)) < EPS_SMALL) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid()) {
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
if ( bLeft && bRight) {
// recupero i siti di riferimento
int nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2 ;
m_vroni->GetBisectorSites( i, nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2) ;
if ( nOrigCrv1 != -1) {
// verifico il lato rispetto al primo sito
pCrv->SetTempProp( nOrigSubCrv1 + 1, 0) ;
pCrv->SetTempProp( nOrigCrv1, 1) ;
int nSide = GetOffsetCurveSide( pCrv) ;
if ( nSide != nSideRef)
continue ;
}
if ( nOrigCrv2 != -1) {
// verifico il lato rispetto al secondo sito
pCrv->SetTempProp( nOrigSubCrv2 + 1, 0) ;
pCrv->SetTempProp( nOrigCrv2, 1) ;
int nSide = GetOffsetCurveSide( pCrv) ;
if ( nSide != nSideRef)
continue ;
}
}
vCrvs.emplace_back( Release( pCrv)) ;
}
}
}
}
// concateno le curve ottenute
if ( vCrvs.size() == 1)
vOffs.emplace_back( Release( vCrvs[0])) ;
else if ( ! vCrvs.empty()) {
ChainCurves chainC ;
chainC.Init( true, 10 * EPS_SMALL, int( vCrvs.size())) ;
for ( int i = 0 ; i < int( vCrvs.size()) ; ++ i) {
Point3d ptS, ptE ;
Vector3d vtS, vtE ;
if ( ! vCrvs[i]->GetStartPoint( ptS) || ! vCrvs[i]->GetStartDir( vtS) ||
! vCrvs[i]->GetEndPoint( ptE) || ! vCrvs[i]->GetEndDir( vtE))
return false ;
if ( ! chainC.AddCurve( i + 1, ptS, vtS, ptE, vtE))
return false ;
}
INTVECTOR vIds ;
while ( chainC.GetChainFromNear( ORIG, false, vIds)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return false ;
for ( int i = 0 ; i < int( vIds.size()) ; ++ i) {
// recupero l'indice della curva
int nInd = abs( vIds[i]) - 1 ;
// verifico se necessaria inversione
if ( vIds[i] < 0)
vCrvs[nInd]->Invert() ;
// aggiungo alla composita
if ( ! pCrvCompo->AddCurve( Release( vCrvs[nInd])))
return false ;
}
if ( pCrvCompo->IsValid()) {
pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
vOffs.emplace_back( Release( pCrvCompo)) ;
}
}
}
// libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
{
// calcola i punti e le tangenti sui bisettori del medial axis in corrispondenza del valore di offset richiesto
vResult.clear() ;
if ( abs( dOffs) < EPS_SMALL)
return true ;
if ( ! IsValid())
return false ;
try {
// verifico se necessario ricalcolo Voronoi
UpdateVoronoi( dOffs) ;
// 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)
bool bLeft = true, bRight = true ;
if ( m_vpCrvs[0]->IsClosed()) {
bLeft = dOffs < 0 ;
bRight = ! bLeft ;
}
// calcolo medial axis
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se il lato appartiene al medial axis
if ( m_vroni->IsWMATEdge( i)) {
// verifico se coinvolto dall'offset
double dParS, dParE ;
m_vroni->GetBisectorParams( i, dParS, dParE) ;
if ( dParS > dParE)
swap( dParS, dParE) ;
if ( abs( dOffs) < dParS || abs( dOffs) > dParE)
continue ;
// calcolo il punto sul bisettore in corrispondenza dell'offset
Point3d pt ;
m_vroni->GetBisectorPointAtParam( i, abs( dOffs), pt.v) ;
pt.ToGlob( m_Frame) ;
// calcolo il vettore tangente
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( IsNull( pCrv))
return false ;
double dPar ;
Point3d ptTemp ;
Vector3d vtDir ;
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
return false ;
vtDir.Normalize() ;
vResult.emplace_back( pt, vtDir) ;
}
}
// libero la memoria di vroni utilizzata per calcolare bisettori
m_vroni->apiFreeBisectorBuffer() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
@@ -662,7 +852,7 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
return false ;
ICRVCOMPOPLIST OffsList ;
if ( ! CalcVroniOffset( OffsList, abs( dOffs), true, true))
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
return false ;
// sistemo le curve di offset calcolate con vroni
@@ -706,21 +896,13 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
//----------------------------------------------------------------------------
bool
Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOffs, bool bLeftOffs)
Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
{
OffsList.clear() ;
if ( ! IsValid())
return false ;
int nOrigCrvCnt = 1 ;
if ( m_vpCrvs[0]->GetType() == CRV_COMPO) {
const CurveComposite * pOrigCompo = GetBasicCurveComposite( m_vpCrvs[0]) ;
if ( pOrigCompo == nullptr)
return false ;
nOrigCrvCnt = pOrigCompo->GetCurveCount() ;
}
try {
// reset di eventuali offset precedenti
m_vroni->apiResetOffsetData() ;
@@ -729,17 +911,14 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
UpdateVoronoi( dOffs) ;
string sTmp = "" ;
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, bLeftOffs, bRightOffs) ;
int nOffsCnt = m_vroni->GetOffsetCount() ;
if ( nOffsCnt == 0) {
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
m_vroni->apiResetOffsetData() ;
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs - VRONI_OFFS_TOL, 0.0, false, bLeftOffs, bRightOffs) ;
nOffsCnt = m_vroni->GetOffsetCount() ;
}
// viene sempre calcolato sia right_offset sia left_offset anche nel caso di curve chiuse per evitare problemi di identificazione
// di vroni nel caso di piccole autointersezioni
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ;
// recupero le curve di offset da vroni
int nOffsCnt = m_vroni->GetOffsetCount() ;
for ( int i = 0 ; i < nOffsCnt ; i++) {
Point3d ptSChain = P_INVALID ;
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
@@ -751,34 +930,75 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
if ( j == 0)
pCrvOffs->AddPoint( ptS) ;
pCrvOffs->AddPoint( ptS) ;
bool bOk = false ;
if ( nType == t_site::SEG)
bOk = pCrvOffs->AddLine( ptE) ;
else {
// se estremi coincidenti la curva va ignorata ( da vroni non possono arrivare circonferenze)
// ma controllo se appartiene ad una catena di tratti infinitesimi
if ( AreSamePointApprox( ptS, ptE)) {
if ( ptSChain.IsValid()) {
if ( ! AreSamePointApprox( ptSChain, ptE)) {
if ( ! pCrvOffs->AddLine( ptE))
return false ;
ptSChain = P_INVALID ;
}
}
else {
// assegno come inizio di possibile catena
ptSChain = ptS ;
}
continue ;
}
else
ptSChain = P_INVALID ;
if ( nType == t_site::SEG) {
if ( ! pCrvOffs->AddLine( ptE))
return false ;
}
else {
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ;
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
if ( ! pArc->SetC2P( ptC, ptS, ptE)) {
// se raggio minore di EPS_SMALL approssimo con linea
if ( AreSamePointApprox( ptC, ptS)) {
if ( ! pCrvOffs->AddLine( ptE))
return false ;
}
else
return false ;
}
else {
// verifico orientamento
double dAng = pArc->GetAngCenter() ;
if ( ( nType == CCW && dAng < - EPS_ANG_SMALL) || ( nType == CW && dAng > EPS_ANG_SMALL))
pArc->ToExplementary() ;
// aggiungo alla composita
if ( ! pCrvOffs->AddCurve( Release( pArc)))
return false ;
}
}
// se la curva è stata aggiunta
if ( bOk) {
// setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è raccordo relativo agli estremi della curva
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
}
// setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
// aperta e chiusa)
if ( nOrigCrv == -1) {
int nOrigCrvCnt = 1 ;
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
}
}
}
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
// aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
OffsList.push_back( Release( pCrvOffs)) ;
}
@@ -810,160 +1030,84 @@ Voronoi::UpdateVoronoi( double dOffs)
}
//----------------------------------------------------------------------------
bool
Voronoi::VerifyCurvesValidityForOffset()
{
if ( m_vpCrvs.size() == 1)
return true ;
// se ho più curve, devono essere tutte chiuse
for ( auto pCrv : m_vpCrvs) {
if ( ! pCrv->IsClosed())
return false ;
}
// verifico se gli orientamenti delle curve sono coerenti
DBLVECTOR vArea( m_vpCrvs.size()) ;
double dRefArea = 0.0 ;
for ( int i = 0 ; i < ( int)m_vpCrvs.size() ; i ++) {
m_vpCrvs[i]->GetAreaXY( vArea[i]) ;
if ( abs( vArea[i]) > abs( dRefArea))
dRefArea = vArea[i] ;
}
bool bRefCCW = ( dRefArea > EPS_SMALL) ;
for ( int i = 0 ; i < ( int)vArea.size() ; i++) {
// se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale
if ( vArea[i] * dRefArea > EPS_SMALL) {
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS)
return false ;
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) {
// se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento
// diverso dal principale
bool bFound = false ;
for ( int k = 0 ; k < ( int)vArea.size() ; k++) {
if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) {
bFound = true ;
break ;
}
}
}
if ( ! bFound)
return false ;
}
}
}
}
// se curva con orientamento diverso dal principale verifico sia contenuta in una curva con orientamento principale
else if ( vArea[i] * dRefArea < - EPS_SMALL) {
bool bInside = false ;
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
if ( j != i && vArea[j] * dRefArea > EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_OUT)) {
bInside = true ;
break ;
}
}
}
if ( ! bInside)
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
ICRVCOMPOPOVECTOR
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
{
ICRVCOMPOPOVECTOR vResult ;
int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ;
// recupero i raccordi relativi agli estremi della curva aperta
INTVECTOR vJunctions ;
for ( int i = 0 ; i < pCompo.GetCurveCount() ; i++) {
double dParTmp ;
pCompo.GetCurveTempParam( i, dParTmp) ;
if ( dParTmp > EPS_SMALL)
vJunctions.push_back( i) ;
// verifico se presenti giunzioni
bool bJunctions = false ;
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
double dParam ; pCompo->GetCurveTempParam( i, dParam) ;
if ( abs( dParam - VRONI_JUNCTION_OPEN) < EPS_SMALL) {
bJunctions = true ;
break ;
}
}
if ( vJunctions.size() == 0) {
// verifico se si trova dal lato corretto
int nSide = GetOffsetCurveSide( pCompo, 0) ;
if ( nSide != nSideRef)
// se lato errato, tutta la curva va cancellata
pCompo.Clear() ;
}
else if ( vJunctions.size() == 2) {
// recupero i due tratti di curva
PtrOwner<CurveComposite> pCompo1( ConvertCurveToBasicComposite( pCompo.CopyParamRange( vJunctions[0] + 1, vJunctions[1]))) ;
PtrOwner<CurveComposite> pCompo2( ConvertCurveToBasicComposite( pCompo.CopyParamRange( vJunctions[1] + 1, vJunctions[0]))) ;
pCompo.Clear() ;
if ( ! IsNull( pCompo1) && pCompo1->IsValid()) {
int nSide = GetOffsetCurveSide( *pCompo1, 0) ;
if ( nSide == nSideRef)
pCompo.CopyFrom( pCompo1) ;
else if ( ! IsNull( pCompo2) && pCompo2->IsValid())
pCompo.CopyFrom( pCompo2) ;
}
else if ( ! IsNull( pCompo2) && pCompo2->IsValid()) {
int nSide = GetOffsetCurveSide( *pCompo2, 0) ;
if ( nSide == nSideRef)
pCompo.CopyFrom( pCompo2) ;
}
}
else {
// mi posiziono dopo la junction
pCompo.ChangeStartPoint( vJunctions[0] + 1) ;
delete( pCompo.RemoveFirstOrLastCurve()) ;
// verifico validità della curva
int nSide = GetOffsetCurveSide( pCompo, 0) ;
if ( nSide == nSideRef) {
// scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine
for ( int i = 1 ; i < pCompo.GetCurveCount() ; i++) {
int nSide = GetOffsetCurveSide( pCompo, i) ;
if ( nSide != nSideRef)
pCompo.TrimEndAtParam( i) ;
}
}
else {
// elimino finchè non trovo una curva valida
while( nSide != nSideRef && pCompo.IsValid()) {
delete( pCompo.RemoveFirstOrLastCurve( false)) ;
if ( pCompo.IsValid())
nSide = GetOffsetCurveSide( pCompo, 0) ;
}
}
if ( ! bJunctions) {
// controllo la curva complessiva
int nSide = GetOffsetCurveSide( pCompo->GetCurve( 0)) ;
if ( nSide == nSideRef)
vResult.emplace_back( pCompo->Clone()) ;
}
else {
// scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato
PtrOwner<CurveComposite> pCompoCurr( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
bool bKeep = true ;
double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ;
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
bKeep = false ;
else {
int nSide = GetOffsetCurveSide( pCompo->GetCurve( i)) ;
bKeep = ( nSide == nSideRef) ;
}
return true ;
if ( bKeep)
pCompoCurr->AddCurve( pCompo->GetCurve( i)->Clone()) ;
else {
// salvo la curva ottenuta fino ad ora e resetto per i prossimi tratti validi
if ( pCompoCurr->IsValid()) {
vResult.emplace_back( Release( pCompoCurr)) ;
pCompoCurr.Set( CreateBasicCurveComposite()) ;
}
}
}
// salvo eventuale ultima curva
if ( pCompoCurr->IsValid())
vResult.emplace_back( Release( pCompoCurr)) ;
// verifico se posso concatenare prima e ultima curva
if ( vResult.size() > 1) {
Point3d ptStart ; vResult.front()->GetStartPoint( ptStart) ;
Point3d ptEnd ; vResult.back()->GetEndPoint( ptEnd) ;
if ( AreSamePointApprox( ptStart, ptEnd) && vResult.front()->AddCurve( vResult.back()->Clone(), false))
vResult.pop_back() ;
}
}
return vResult ;
}
//---------------------------------------------------------------------------
int
Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv)
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
{
Point3d ptM ; pOffs.GetCurve( nCrv)->GetMidPoint(ptM) ;
int nOrigCrv ; pOffs.GetCurveTempProp( nCrv, nOrigCrv) ;
if ( pCrv == nullptr)
return -1 ;
Point3d ptM ; pCrv->GetMidPoint( ptM) ;
const ICurve* pCrvRef = m_vpCrvs[0] ;
// se ha una sottocurva di riferimento
if ( nOrigCrv != 0 && m_vpCrvs[0]->GetType() == CRV_COMPO) {
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[0]) ;
// recupero curva e sottocurva di riferimento dalle temp prop
int nOrigSubCrv = pCrv->GetTempProp( 0) ;
int nOrigCrv = pCrv->GetTempProp( 1) ;
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
if ( pCompoOrig != nullptr)
pCrvRef = pCompoOrig->GetCurve( nOrigCrv - 1) ;
pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ;
}
DistPointCurve distPC( ptM, *pCrvRef) ;
@@ -974,19 +1118,19 @@ Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv)
//---------------------------------------------------------------------------
bool
Voronoi::AdjustOffsetStart( ICurveComposite& pCrv)
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
{
for ( int i = 0 ; i < pCrv.GetCurveCount() ; i++) {
// cerco il tratto associato alla prima curva originale
int nProp ; pCrv.GetCurveTempProp( i, nProp) ;
if ( nProp == 1) {
pCrv.ChangeStartPoint( i) ;
for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) {
// cerco il tratto associato alla prima sottocurva originale
int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ;
if ( nOrigCrv == 1) {
pCrv->ChangeStartPoint( i) ;
break ;
}
// oppure un raccordo di junction
double dParam ; pCrv.GetCurveTempParam( i, dParam) ;
if ( abs( dParam - 1) < EPS_SMALL) {
pCrv.ChangeStartPoint( i + 1) ;
// oppure associato ad una giunzione
double dParam ; pCrv->GetCurveTempParam( i, dParam) ;
if ( abs( dParam - VRONI_JUNCTION_CLOSED) < EPS_SMALL) {
pCrv->ChangeStartPoint( i + 1) ;
break ;
}
}
@@ -1003,7 +1147,8 @@ Voronoi::Translate( const Vector3d & vtMove)
}
//---------------------------------------------------------------------------
bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
bool
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
{
if ( ! IsValid())
return false ;
@@ -1011,7 +1156,8 @@ bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
}
//---------------------------------------------------------------------------
bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
bool
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
if ( ! IsValid())
return false ;
@@ -1019,7 +1165,8 @@ bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng,
}
//---------------------------------------------------------------------------
bool Voronoi::ToGlob( const Frame3d& frRef)
bool
Voronoi::ToGlob( const Frame3d& frRef)
{
if ( ! IsValid())
return false ;
@@ -1027,7 +1174,8 @@ bool Voronoi::ToGlob( const Frame3d& frRef)
}
//---------------------------------------------------------------------------
bool Voronoi::ToLoc( const Frame3d& frRef)
bool
Voronoi::ToLoc( const Frame3d& frRef)
{
if ( ! IsValid())
return false ;
@@ -1035,9 +1183,47 @@ bool Voronoi::ToLoc( const Frame3d& frRef)
}
//---------------------------------------------------------------------------
bool Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
bool
Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
if ( ! IsValid())
return false ;
return m_Frame.LocToLoc( frOri, frDest) ;
}
//---------------------------------------------------------------------------
bool
Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
{
if ( nCrv < 0 || nCrv > int( m_vpCrvs.size()) - 1)
return false ;
// se curva aperta errore
if ( ! m_vpCrvs[nCrv]->IsClosed())
return false ;
dOffs = - INFINITO ;
try {
// verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed)
CalcVoronoi() ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se è un bisettore relativo alla curva richiesta e dal lato opportuno
if ( m_vroni->IsRelatedEdge( i, nCrv, bLeft)) {
// calcolo i parametri del bisettore
double dParS, dParE ;
m_vroni->GetBisectorParams( i, dParS, dParE) ;
dOffs = max( { dParS, dParE, dOffs}) ;
}
}
// libero la memoria di vroni dedicata agli offset
m_vroni->apiFreeOffsetData() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
}
+10 -5
View File
@@ -25,6 +25,8 @@
static const bool USE_VORONOI = true ;
static const int VORONOI_STD_BOUND = 3 ;
static const double VRONI_OFFS_TOL = 1e-9 ;
static const double VRONI_JUNCTION_OPEN = 1.0 ;
static const double VRONI_JUNCTION_CLOSED = 2.0 ;
//-------------------------- Forward Definitions -------------------------------
class ISurfFlatRegion ;
@@ -50,10 +52,14 @@ class Voronoi
ICurve* GetCurve( int nId) const ;
int GetCurveCount( void) const
{ return m_vpCrvs.size() ; } ;
bool GetVroniPlane( Plane3d& plPlane) const ;
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) ;
bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ;
bool CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs) ;
bool CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) ;
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;
bool Translate( const Vector3d& vtMove) ;
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ;
@@ -73,12 +79,11 @@ class Voronoi
bool AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoopId) ;
bool CalcVoronoi( int nBound = VORONOI_STD_BOUND) ;
bool CalcVroniOffset( ICRVCOMPOPLIST& vOffs, double dOffs, bool bRightOffs, bool bLeftOffs) ;
bool CalcVroniOffset( ICRVCOMPOPLIST& vOffs, double dOffs) ;
bool UpdateVoronoi( double dOffs) ;
bool VerifyCurvesValidityForOffset( void) ;
bool AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs) ;
bool AdjustOffsetStart( ICurveComposite& pCompo) ;
int GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv) ;
ICRVCOMPOPOVECTOR AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const ;
bool AdjustOffsetStart( ICurveComposite* pCompo) const ;
int GetOffsetCurveSide( const ICurve* pCrv) const ;
ICurve* GetBisectorCurve( int i) ;
private :
+1
View File
@@ -30,6 +30,7 @@
#pragma comment(lib, EGTEXTDIR "zlib/Lib/zlib" EGTLIBVER ".lib")
#pragma comment(lib, EGTEXTDIR "vroni/Lib/vroni" EGTLIBVER ".lib")
#pragma comment(lib, EGTEXTDIR "fist/Lib/fist" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "EgtGeneral" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")