Compare commits

..

342 Commits

Author SHA1 Message Date
Daniele Bariletti 1f79def16c EgtGeomKernel :
- modifica alla sincronizzazione tra curve per trimming.
2026-05-08 18:15:01 +02:00
Daniele Bariletti a4f0a43273 Merge branch 'master' into Trimming 2026-05-08 17:25:43 +02:00
Daniele Bariletti 6646aee01c EgtGeomKernel :
- estratta funzione per trovare il punto corrispondente sulla seconda curva di una coppia di curve da sincronizzare.
- pulizia codice.
2026-05-08 17:25:32 +02:00
Riccardo Elitropi 7f8382f1b8 EgtGeomKernel :
- In CalcPocketing correzione entrate per utensili grandi su contorni aperti piccoli.
2026-05-08 17:23:01 +02:00
Daniele Bariletti 4bcdb03598 EgtGeomKernel 3.1e2 :
- piccola modifica
- cambio versione.
2026-05-07 14:28:07 +02:00
Dario Sassi 68e9be7901 EgtGeomKernel 3.1e1 :
- ricompilazione con cambio versione.
2026-05-07 12:23:08 +02:00
Daniele Bariletti 9e3bac4a68 Merge branch 'Trimming' 2026-05-07 11:18:56 +02:00
Daniele Bariletti 1fee7b8e49 Merge branch 'master' into Trimming 2026-05-07 11:18:09 +02:00
Daniele Bariletti f668d7ac11 EgtGeomKernel :
- cambiata distanza di campionamento in trimming.
2026-05-07 11:17:52 +02:00
Daniele Bariletti 4a1c13154f EgtGeomKernel :
- migliorie a regolarize.
2026-05-07 11:16:37 +02:00
Daniele Bariletti 68a9848748 EgtGeomKernel :
- miglioramenti alla regolarize.
2026-05-06 12:51:20 +02:00
Daniele Bariletti f5059166ed Merge branch 'master' into Trimming 2026-05-05 14:32:25 +02:00
Daniele Bariletti ad7f209fc9 EgtGeomKernel :
- correzione all'autointersezione di curve.
2026-05-05 13:32:25 +02:00
Daniele Bariletti 8b5bfb6e19 EgtGeomKernel :
- separazione delle due versioni di regolarize.
2026-05-05 09:11:27 +02:00
Daniele Bariletti 1efd17f6ee EgtGeomKernel :
- pulizia.
2026-04-29 11:23:15 +02:00
Daniele Bariletti b8caeb49e0 EgtGeomKernel :
- miglioria alla regolarize.
2026-04-29 11:17:57 +02:00
Daniele Bariletti a9fc259745 Merge branch 'master' into Trimming 2026-04-28 12:08:24 +02:00
Daniele Bariletti bbc98fe282 EgtGeomKernel :
- cambiata la chiamata a ModifyJoint
- cambiato nome alla ModifySingleCurve
- estesa la ModifyJoint con tolleranza
- modifiche stilistiche e pulizia codice.
2026-04-28 11:09:34 +02:00
Riccardo Elitropi a445ddd89b EgtGeomKernel :
- in CalcPocketing aggiunto prototipo per riconoscimento di svuotatura di un foro.
2026-04-28 11:04:42 +02:00
Daniele Bariletti e874b2eb36 Merge branch 'master' into Trimming 2026-04-27 16:01:59 +02:00
Daniele Bariletti a45faa4793 EgtGeomKernel :
- correzioni e migliorie a Regolarize.
2026-04-27 16:01:00 +02:00
Daniele Bariletti 344f0da7ff EgtGeomKernel :
- tolto flag di debug.
2026-04-27 15:06:27 +02:00
Daniele Bariletti cea869c6ee EgtGeomKernel :
- correzione al commit precedente.
2026-04-27 15:05:45 +02:00
Daniele Bariletti 8ad2887c38 Merge branch 'master' into Trimming 2026-04-27 15:04:02 +02:00
Daniele Bariletti 2b1d2a512d EgtGeomKernel :
- rimosso flag di debug.
2026-04-27 15:03:49 +02:00
Daniele Bariletti a55770d702 EgtGeomKernel :
- migliorata la Regolarize delle rigate per trimming.
- aggiunte funzioni di utilità per le CurveComposite.
2026-04-27 14:58:23 +02:00
Dario Sassi 2e4b1cdd40 EgtGeomKernel :
- spostamento di sorgente in cartella filtro.
2026-04-22 18:31:20 +02:00
Daniele Bariletti 3ffc0b40d8 EgtGeomKernel :
- tolto flag di debug.
2026-04-22 16:12:30 +02:00
Daniele Bariletti cd2cde40da EgtGeomKernel:
- correzioni alla regolarize.
2026-04-22 16:11:46 +02:00
Daniele Bariletti efc656a72c Merge branch 'Trimming' 2026-04-21 15:05:12 +02:00
Daniele Bariletti e1eb139aee Merge branch 'master' into Trimming 2026-04-21 15:04:54 +02:00
Daniele Bariletti e7d25b2d0e EgtGeomKernel :
- correzioni e migliorie a regolarize dei bordi per trimming.
2026-04-21 15:04:24 +02:00
Riccardo Elitropi ce05ce577c EgtGeomKernel 3.1d4 :
- In Voronoi migliorati i controlli sulla chiusura delle curve (copyright Sara)
- in CalcPocketing corrette le funzioni del calcolo delle Feed e migliorati i controlli sugli ingressi.
2026-04-20 15:05:03 +02:00
Daniele Bariletti ae2cac48d1 Merge branch 'master' into Trimming 2026-04-17 13:34:47 +02:00
Daniele Bariletti 37e9a05347 EgtGeomKernel :
- nuova versione regolarize.
2026-04-17 13:34:17 +02:00
Daniele Bariletti 02cb8a0d3c EgtGeomKernel :
- aggiornamento versione di RuledSmooth.
- aggiunta controlli.
- prima versione della regolarizzazione di curve bezier composte.
2026-04-16 09:41:22 +02:00
Dario Sassi 6942f5fc23 EgtGeomKernel :
- nella proiezione di curve su superfici aggiunto paramtetro bFromVsTo.
2026-04-15 08:54:32 +02:00
Riccardo Elitropi 6c4bf3f05a EgtGeomKernel :
- in CalcPocketing migliorati i controlli per i casi a Trapezio.
- in CAvToolTriangle migliorata la creazione del frame Locale in CAvDiskTriangle per direzioni generiche di vDiskAx e vtMove.
2026-04-14 19:07:16 +02:00
Daniele Bariletti 4bc8590ce9 Merge branch 'master' into Trimming 2026-04-14 12:08:17 +02:00
Daniele Bariletti 5b68e33d1f EgtGeomKernel :
- correzione al VM 5 assi.
2026-04-14 11:59:17 +02:00
Daniele Bariletti a70f7ee9c9 Merge branch 'Trimming' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel into Trimming 2026-04-14 10:56:00 +02:00
Daniele Bariletti 95a070413a EgtGeomKernel :
- miglioria nel posizionamento delle curve di sync.
2026-04-14 10:53:24 +02:00
Riccardo Elitropi 223489e80d EgtGeomKernel 3.1d3 :
- in CalcPocketing piccola modifica alle tolleranze per casi a Trapezio.
2026-04-13 15:26:34 +02:00
Daniele Bariletti f6a535d94c EgtGeomKernel :
- tolto flag di debug.
2026-04-13 14:29:59 +02:00
Daniele Bariletti dbc3e7d2bf Merge branch 'NewRuled' 2026-04-10 18:20:59 +02:00
Daniele Bariletti a3d44261bb Merge branch 'master' into NewRuled 2026-04-10 18:20:44 +02:00
Daniele Bariletti 9220fd568f EgtGeomKernel :
- aggiunte funzioni per la creazione delle smooth ruled bezier.
2026-04-10 18:20:22 +02:00
Daniele Bariletti 17346e1b42 EgtGeomKernel :
- correzione alla triangolazione bezier.
2026-04-10 15:23:28 +02:00
Daniele Bariletti c95ef6764d EgtGeomKernel :
- correzione alla triangolazione bezier.
2026-04-10 15:22:44 +02:00
Daniele Bariletti d0f2d56bdb EgtGeomKernel :
- correzione per split vicini a joint in RuledByIsoParamSet.
2026-04-10 12:35:22 +02:00
Daniele Bariletti fb037f2f2a EgtGeomKernel :
- correzione per split vicini a joint in RuledByIsoParamSet.
2026-04-10 12:35:07 +02:00
Daniele Bariletti 2d94dddccb EgtGeomKernel :
- correzioni alla RuledByIsoParamSet.
2026-04-10 10:25:04 +02:00
Daniele Bariletti d2d025a594 EgtGeomKernel :
- correzioni alla RuledByIsoParamSet.
2026-04-10 10:23:32 +02:00
Daniele Bariletti 64abf640f6 Merge remote-tracking branch 'origin/HEAD' into NewRuled 2026-04-10 09:34:02 +02:00
Daniele Bariletti cb2b63320a EgtGeomKernel :
- nuovo paradigma per la bezier ruled.
2026-04-10 09:20:02 +02:00
Riccardo Elitropi 951d3781d6 EgtGeomKernel :
- in IntersCurvePlane aggiunta implementazione funzione GetIntCrvPlnInfo.
2026-04-09 19:20:59 +02:00
Daniele Bariletti 27bd0e579e EgtGeomKernel :
- correzione al VM a 5 assi.
2026-04-08 17:08:37 +02:00
Daniele Bariletti ff7d564de8 Merge branch 'NewRuled' 2026-04-08 13:42:01 +02:00
Daniele Bariletti a27b9e871a EgtGeomKernel :
- piccola correzione alle rigate.
2026-04-08 13:41:43 +02:00
Daniele Bariletti eb497cbd39 Merge branch 'master' into NewRuled 2026-04-03 17:27:31 +02:00
Daniele Bariletti dd3091fc13 EgtGeomKernel :
- miglioramento delle rigate con bezier.
2026-04-03 17:27:13 +02:00
Daniele Bariletti 69d463713c EgtGeomKernel 3.1d2 :
- cambio versione.
2026-04-03 16:21:20 +02:00
Daniele Bariletti 5e918ff3aa Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-04-03 16:19:47 +02:00
Daniele Bariletti b4522c712d EgtGeomKernel :
- correzione alla IntersCrvCompoCrvCompo.
2026-04-03 16:19:39 +02:00
Riccardo Elitropi fa9a9e89cb EgtGeomKernel :
- in CalcPocketing aggiunte considerazioni per Lucidature su SmallRad.
2026-04-03 12:52:39 +02:00
Riccardo Elitropi d51a0d2258 EgtGeomKernel :
- in CalcPocketing correzione parametro Invert per Epicicli.
2026-04-03 08:23:13 +02:00
Daniele Bariletti 580230b38b Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-04-02 18:03:34 +02:00
Daniele Bariletti 4b24906d2e Merge branch 'NewRuled' 2026-04-02 18:03:26 +02:00
Daniele Bariletti 2094a1cc0d EgtGeomKernel :
- tolto flag di debug.
2026-04-02 18:03:05 +02:00
Daniele Bariletti b8b639699a EgtGeomKernel :
- correzione alla nuova versione rigate (riconoscimento automtico mismatch).
2026-04-02 18:02:20 +02:00
Riccardo Elitropi 0b86c4f72b EgtGeomKernel :
- in Trimming piccola correzione
2026-04-02 17:29:41 +02:00
Daniele Bariletti 5c93384690 Merge branch 'master' into NewRuled 2026-04-02 16:09:45 +02:00
Daniele Bariletti b77db4a5bc Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-04-02 15:14:38 +02:00
Daniele Bariletti c704d94829 EgtGeomKernel :
- piccola aggiunta per la gestione di spike nelle categorizzazioni tra curve.
2026-04-02 15:14:29 +02:00
Riccardo Elitropi 0373021b7a EgtGeomKernel :
- In CalcPocketing piccole correzioni alle curve singole e modifiche stilistiche.
2026-04-02 10:43:37 +02:00
Riccardo Elitropi 6de856b3e1 EgtGeomKernel 3.1d1 :
- In CalcPocketing piccola correzione per casi Conformal.
2026-04-01 18:06:00 +02:00
Dario Sassi a231d8f26c EgtGeomKernel :
- eliminato file inutile.
2026-04-01 10:19:56 +02:00
Riccardo Elitropi 745a7eb38c EgtGeomKernel :
- In PocketingNT ggiunta gestione per Lucidatura.
2026-03-31 18:53:52 +02:00
Daniele Bariletti 78c40ebca7 EgtGeomKernel :
- tolto bypass di debug.
2026-03-31 17:26:43 +02:00
Daniele Bariletti a39af1c3a3 EgtGeomKernel :
- gestite superfici con trim molto piccoli rispetto al totale.
2026-03-31 16:19:42 +02:00
Riccardo Elitropi c2a0f9dff1 Merge commit '6be67258d2ac30e94ee2ed5af4e648ffb62d842d' 2026-03-31 14:27:26 +02:00
Riccardo Elitropi 6be67258d2 EgtGeomKernel (Nst_SurfFr) :
- Modifiche stilistiche e cambio di versione.
2026-03-31 14:27:01 +02:00
Riccardo Elitropi 6c76943bf4 Merge commit '9306f5be9d43c0978d7b8d4707ca31d6cd475674' into Nst_SurfFr 2026-03-31 12:39:24 +02:00
Daniele Bariletti 9306f5be9d EgtGeomKernel :
- correzioni alla gestione dei loop.
2026-03-31 09:13:21 +02:00
Riccardo Elitropi 944ce79776 Merge commit '007ed1701c76ba7e1e648e3afcc4cdc61046b2c5' into Nst_SurfFr 2026-03-30 18:19:25 +02:00
Riccardo Elitropi 313c735956 EgtGeomKernel (Nst_SurfFr) :
- migliorata e raffinata la classe CAvSurfFrMove.
2026-03-30 18:19:13 +02:00
Dario Sassi 007ed1701c EgtGeomKernel 3.1c6 :
- ricompilazione con cambio versione.
2026-03-30 17:56:23 +02:00
Riccardo Elitropi 7385709bb4 EgtGeomKernel :
- in CalcPocketing piccola modifica a casi forzati dei trapezi.
2026-03-30 16:52:46 +02:00
Riccardo Elitropi da4cd4c482 EgtGeomKernel (Nst_SurfFr) :
- primo commit per CAv tra Regioni Piane con loop interni e Interferenza tra Regioni Piane.
2026-03-27 18:39:41 +01:00
Daniele Bariletti dee744725c EgtGeomKernel :
- rimossi try/catch dalla classe SurfFlatRegion.
- rimosso ricalcolo delle autointersezioni in AddSimpleExtLoop e AddSimpleIntLoop.
2026-03-27 15:11:28 +01:00
Daniele Bariletti 2aca943de4 EgtGeomKernel :
- estrapolata funzione per l'intersezione tra superficie di bezier 3x1 con una linea.
2026-03-26 12:42:05 +01:00
Daniele Bariletti 25f6bae120 EgtGeomKernel :
- pulizia codice.
2026-03-25 15:53:21 +01:00
Daniele Bariletti c92d841011 EgtGeomKernel :
- piccola correzione.
2026-03-25 15:07:40 +01:00
Daniele Bariletti 398c8c430a Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-03-25 12:38:17 +01:00
Daniele Bariletti 79dc8f8fc2 EgtGeomKernel :
- correzione alla chainCurves.
2026-03-25 12:38:12 +01:00
Riccardo Elitropi 1545bc07cd EgtGeomKernel 3.1c5 :
- Aggiunto controllo dimensioni Zmap per versioni a 32Bit.
2026-03-24 15:58:51 +01:00
Riccardo Elitropi 44edef378a EgtGeomKernel :
- in VolZmap migliorata la funzione RemoveFins.
2026-03-23 19:15:35 +01:00
Daniele Bariletti 679efc22e8 EgtGeomKernel :
- correzione alla MakeUniform nella ricostruzione della parte di trim nella striscia corrente.
2026-03-23 17:22:45 +01:00
Daniele Bariletti 1076dc54dc Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-03-20 13:41:33 +01:00
Daniele Bariletti e091f253d0 EgtGeomKernel :
- nella IntersCurveCurve non vengono mai cancellate info delle intersezioni durante il merge.
2026-03-20 13:41:13 +01:00
Dario Sassi 3206961b88 EgtGeomKernel :
- ricompilazione per cambio nome a metodo di VolZmap da EraseFins a RemoveFins.
2026-03-19 19:30:04 +01:00
Riccardo Elitropi 48b2029d19 EgtGeomKernel :
- aggiunta funzione EraseFins per gli Zmap ( prima versione semplice).
2026-03-19 18:45:38 +01:00
Daniele Bariletti a2ca0ac6f7 EgtGeomKernel 3.1c4 :
- cambio versione.
2026-03-19 15:36:09 +01:00
Daniele Bariletti 4155dd3e5a Merge branch 'NewIntersCurveCurve' 2026-03-19 15:34:59 +01:00
Daniele Bariletti 5a3b7e311c Merge remote-tracking branch 'origin/master' into NewIntersCurveCurve 2026-03-19 14:48:18 +01:00
Daniele Bariletti 991586a880 EgtGeomKernel :
- piccola aggiunta.
2026-03-19 14:45:14 +01:00
Daniele Bariletti de4165889a EgtGeomKernel :
- IntersCurveCurve: eliminata le intersezioni puntuali rimanenti vicine a overlap; corretto scorrimento delle intersezioni durante il merge.
2026-03-19 12:57:11 +01:00
Daniele Bariletti 42c5ffb014 EgtGeomKernel :
- correzioni e migliorie a IntersCurveCurve.
2026-03-19 10:33:18 +01:00
Dario Sassi e394615f84 EgtGeomKernel :
- in Polygon3d::FromPlaneTrimmedWithBox piccola correzione su parametro di tolleranza ignorato.
2026-03-17 18:12:01 +01:00
Riccardo Elitropi 1008ba4229 EgtGeomKernel 3.1c3 :
- Migliorata e corretta funzione MakeUniform per VolZMap.
2026-03-17 13:10:18 +01:00
Daniele Bariletti f4328430b9 EgtGeomKernel :
- revert manuale di una modifica in IntersCurveCurve.
2026-03-17 09:22:06 +01:00
Daniele Bariletti 1d6bc847da EgtGeomKernel 3.1c2 :
- cambio versione.
2026-03-17 08:56:41 +01:00
Daniele Bariletti d76beb09ee EgtGeomKernel :
- correzione alla GetChainedCurves
- aggiunto parametro alla GetSide della DistPointCurve
- migliorie alla IntersCurveCurve.
2026-03-16 17:01:48 +01:00
Dario Sassi 026436b914 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2026-03-15 18:31:34 +01:00
Dario Sassi ebc5fd7ee7 EgtGeomKernel :
- aggiunto INVISIBLE tra i colori predefiniti.
2026-03-15 18:28:23 +01:00
Daniele Bariletti 82a211753e EgtGeomKernel :
- correzione al VM 5 assi con movimenti che fanno perno.
2026-03-12 16:41:19 +01:00
Daniele Bariletti a258e9cb31 EgtGeomKernel :
- piccola correzione alla richiesta del box di una bezier.
2026-03-10 13:24:40 +01:00
Daniele Bariletti 157885f71a EgtGeomKernel 3.1c1 :
- cambio versione.
2026-03-10 09:05:59 +01:00
Daniele Bariletti f227a9cba7 Merge branch 'NewMakeUniform' 2026-03-10 09:04:16 +01:00
Daniele Bariletti 39360eefd7 EgtGeomKernel :
- raffinamento finale della intersCompoCompo.
2026-03-06 17:25:50 +01:00
Daniele Bariletti 6b5fb15c9b EgtGeomKernel :
- piccola correzione alla IntersCurveCurve.
2026-03-06 12:37:26 +01:00
Daniele Bariletti 4e698d4049 EgtGeomKernel :
- spostato rilevamento spike nelle intersezioni tra curve.
- pulizia codice.
2026-03-05 17:33:55 +01:00
Daniele Bariletti e20bd7fd0c Merge branch 'master' into NewMakeUniform 2026-03-04 15:55:39 +01:00
Daniele Bariletti 7e62acf351 EgtGeomKernel :
- aggiunta funzione per richiedere Part e Shell cui appartiene una faccia.
2026-03-04 15:55:25 +01:00
Daniele Bariletti 421bc2eb3b EgtGeomKernel :
- correzione alla make uniform.
2026-03-04 15:24:33 +01:00
Daniele Bariletti db98fa5d5a Merge branch 'master' into NewMakeUniform 2026-03-03 17:10:06 +01:00
Daniele Bariletti 5f28258d16 EgtGeomKernel :
- migliorie e correzioni all'importazione delle bezier.
- tolto limite alle bezier per rivoluzione.
2026-03-03 17:09:30 +01:00
Daniele Bariletti 8f06488b33 EgtGeomKernel :
- miglioramento all'intersezione tra curve.
2026-02-27 16:52:55 +01:00
Riccardo Elitropi ac7ba1b12c EgtGeomKernel :
- in CalcPocketing piccola miglioria su tolleranza trapezi.
2026-02-25 16:56:30 +01:00
Dario Sassi 67131a1482 EgtGeomKernel :
- salvato file come UTF-8.
2026-02-25 15:17:56 +01:00
Daniele Bariletti a92cba8697 Merge branch 'master' into NewMakeUniform 2026-02-24 12:36:18 +01:00
Daniele Bariletti 52cca7233e EgtGeomKernel 3.1b3 :
- correzione alle intersezioni tra curve.
- cambio versione.
2026-02-24 12:36:05 +01:00
Dario Sassi b2beed0fe0 EgtGeomKernel :
- ora From string per Color accette sia RGBA che RGB.
2026-02-24 08:39:23 +01:00
Daniele Bariletti 1f301b6100 Merge branch 'master' into NewMakeUniform 2026-02-23 16:26:55 +01:00
Daniele Bariletti c74ca4932f Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-23 16:26:29 +01:00
Daniele Bariletti fafcd67a2c EgtGeomKernel :
- correzione alle ruled guided.
2026-02-23 16:26:23 +01:00
Riccardo Elitropi 390cc3bd8b EgtGeomKernel :
- in trimming migliorata la gestione delle curve di sincronizzazione mediante interpolazione.
2026-02-23 15:47:14 +01:00
Daniele Bariletti b2ccda1b34 Merge branch 'master' into NewMakeUniform 2026-02-23 10:59:22 +01:00
Daniele Bariletti 69916e7756 EgtGeomKernel :
- correzione alla ruled guided.
2026-02-23 10:57:15 +01:00
Daniele Bariletti 3a7b6f1343 EgtGeomKernel :
- aggiunto flag Refined alla funzione GetLeaves.
2026-02-23 09:44:39 +01:00
Daniele Bariletti 71a054749c EgtGeomKernel :
- miglioria alla bezier ruled guided.
2026-02-23 09:35:04 +01:00
Daniele Bariletti 06d87d5c52 Merge branch 'master' into NewMakeUniform 2026-02-23 09:27:55 +01:00
Daniele Bariletti 98c576afe0 Merge branch 'master' into NewRuled 2026-02-23 09:12:05 +01:00
Daniele Bariletti 6d544f93f4 EgtGeomKernel :
- miglioramento dell'approssimazione con curve di bezier.
2026-02-23 09:11:28 +01:00
Riccardo Elitropi 3c1a7ff1bb EgtGeomKernel 3.1b2 :
- in Trimming aggiunta prima versione di interpolazione per le curve di sincronizzazione.
2026-02-20 16:47:42 +01:00
Daniele Bariletti ae8f80d6e9 EgtGeomKernel :
- miglioria alla bezier ruled guided.
2026-02-20 14:54:50 +01:00
Daniele Bariletti 9b933bd26d EgtGeomKernel :
- miglioramento dell'approssimazione con curve di bezier.
2026-02-19 18:15:58 +01:00
Daniele Bariletti baa8736276 Merge branch 'master' into NewRuled 2026-02-19 15:41:12 +01:00
Daniele Bariletti 73bedf4f55 EgkGeomKernel :
- correzione all'intersezione tra curva e piano.
2026-02-19 15:39:43 +01:00
Daniele Bariletti bae8d4651d EgtGeomKernel :
- piccola correzione alla Surf Bez Ruled Guided.
2026-02-19 11:50:44 +01:00
Daniele Bariletti c75a7e9514 EgtGeomKernel :
- migliorie alla rigata bezier.
- correzioni alle tolleranze di triangolazione
- aggiunta di un parametro alla funzione GetLeaves delle surf bezier.
2026-02-19 11:49:28 +01:00
Daniele Bariletti 233f64e68f EgtGeomKernel :
- correzioni alle rigate bezier.
2026-02-17 14:41:37 +01:00
Riccardo Elitropi f9127ce64d EgtGeomKernel 3.1b1 :
- cambio di versione.
2026-02-17 10:00:13 +01:00
Riccardo Elitropi 86338db67d EgtGeomKernel :
- in CalcPocketing piccola correzione.
2026-02-17 09:24:18 +01:00
Daniele Bariletti da7ebd6f61 EgtGeomKernel :
- miglioramenti e correzioni alle rigate con le bezier.
2026-02-16 12:45:50 +01:00
Daniele Bariletti 8db1765505 Merge remote-tracking branch 'origin/master' into NewRuled 2026-02-12 17:00:02 +01:00
Daniele Bariletti 2438d1d23a Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-12 16:25:34 +01:00
Daniele Bariletti f790736fd7 EgtGeomKernel :
- modificata conversione da linea a bezier.
2026-02-12 16:25:28 +01:00
Daniele Bariletti 985b69ae33 EgtGeomKernel :
- correzione alla triangolazione delle bezier.
- riduzione della dimensione minima dei triangoli nelle surf bezier.
2026-02-12 16:17:11 +01:00
Riccardo Elitropi 6faf5ccde2 EgtGeomKernel 3.1a8 :
- in CalcPocketing migliorati i casi a trapezio.
2026-02-12 15:46:42 +01:00
Daniele Bariletti 2e129d7b06 EgtGeomKernel :
- tolto un argomento alla funzione ApproxCurveWithBezier.
2026-02-11 16:50:50 +01:00
Daniele Bariletti 5d2e1ff608 EgtGeomKernel :
- tolto un argomento alla funzione ApproxCurveWithBezier.
2026-02-11 16:47:01 +01:00
Daniele Bariletti a9f8ef2ff3 Merge branch 'master' into NewRuled 2026-02-11 15:58:21 +01:00
Daniele Bariletti 2b7070e408 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-11 15:27:04 +01:00
Daniele Bariletti 571a24b419 EgtGeomKernel :
- migliorata approssimazione con curve di bezier.
2026-02-11 15:26:57 +01:00
Dario Sassi 5f132ae3d3 EgtGeomKernel 3.1a7 :
- ricompilazione con cambio versione.
2026-02-11 12:20:15 +01:00
Riccardo Elitropi fe5a09281e EgtGeomKernel :
- rimozione memory leaks in CalcPocketing.
2026-02-11 11:31:08 +01:00
Riccardo Elitropi b66522de33 EgtGeomKernel 3.1a6 :
- in CalcPocketing migliorati i casi ottimizzati a Trapezio.
2026-02-10 17:03:46 +01:00
Daniele Bariletti e87ef178c2 EgtGeomKernel :
- correzione alla distanza punto- curva di bezier.
2026-02-10 15:42:03 +01:00
Dario Sassi 0987496caf EgtGeomKernel :
- piccoli aggiustamenti.
2026-02-09 12:48:38 +01:00
Riccardo Elitropi 5ad9c48285 EgtGeomKernel :
- in Trimming rimozione memory Leaks.
2026-02-09 11:21:06 +01:00
Dario Sassi ec6eb3e645 EgtGeomKernel :
- modifica a Trimming
- sistemazioni estetiche varie.
2026-02-09 08:24:16 +01:00
Daniele Bariletti 64c3363426 Merge branch 'NewApproxWithBezier' 2026-02-06 17:28:46 +01:00
Daniele Bariletti 2023ba3f7d EgtGeomKernel :
- modifica all'approssimazione delle curve tramite bezier.
2026-02-06 17:28:28 +01:00
Daniele Bariletti 27c1823a54 Merge branch 'master' into NewApproxWithBezier 2026-02-05 16:56:35 +01:00
Daniele Bariletti f111827545 EgtGeomKernel :
- modificata la CreateByExtrusion per le bezier.
2026-02-05 16:56:09 +01:00
Daniele Bariletti 7cdc1ba5a3 EgtGeomKernel :
- implementazione dell'approsimazione tramite curve di bezier.
2026-02-05 16:54:09 +01:00
Riccardo Elitropi 1d68a1ee8e EgtGeomKernel 3.1a5 :
- in Trimming aggiunte le funzioni per ricerca di fori e asole
- in Trimming migliorate e corrette le funzioni per la ricerca delle Patch dalle superfici
- in Trimming corrette le tolleranze lineari per le approssimazioni dei bordi
- in Trimming rimozione Memory Leaks e pulizia del codice.
2026-02-03 17:18:46 +01:00
Daniele Bariletti b426ccc04d EgtGeomKernel :
- modifica alla funzione MakeUniform: utilizzo solo di curve anziché di flat region.
2026-02-03 16:22:57 +01:00
Daniele Bariletti a1c448d8dd EgtGeomKernel :
- tentativo di miglioria alle ruled. Da debuggare.
2026-02-03 16:13:07 +01:00
Daniele Bariletti 25d53338c2 Merge branch 'master' into NewRuled 2026-01-28 15:24:09 +01:00
Dario Sassi 6f7b614c3a EgtGeomKernel :
- corretta assegnazione valore.
2026-01-27 16:35:55 +01:00
Daniele Bariletti f02f29c543 EgtGeomKernel 3.1a4 :
- correzione all'intersezione LineLine
- correzione all'intersezione CompoCompo
- cambio versione.
2026-01-27 13:36:42 +01:00
Daniele Bariletti 06cfe1bb96 EgtGeomKernel :
- correzione alle bezier ruled per il match degli edge.
2026-01-27 10:21:51 +01:00
Riccardo Elitropi 736353bbac EgtGeomKernel :
- in Trimming piccole correzioni e migliorie.
2026-01-26 18:02:59 +01:00
Daniele Bariletti f4b3312672 EgtGeomKernel :
- disattivati salvataggi debug.
2026-01-26 13:08:47 +01:00
Daniele Bariletti 3178bb5f27 EgtGeomKernel :
- miglioramento della Bezier ruled
- miglioramento della Nezier ruled guided.
2026-01-26 12:34:32 +01:00
Riccardo Elitropi 552ce70231 EgtGeomKernel :
- in Trimming introdotta una prima approssimazione delle curve di bordo.
2026-01-23 17:57:18 +01:00
Riccardo Elitropi c2a79b2665 EgtGeomKernel :
- InTestSurfTmSurfTm affinato il controllo collisione quando una delle due superfici è chiusa e contiene l'altra.
In CalcPocketing aggiunta piccola miglioria.
2026-01-23 12:38:16 +01:00
Dario Sassi f72c949563 EgtGeomKernel :
- In TestSurfTmSurfTm aggiunto flag per segnalare collisione anche quando una delle due è chiusa e contiene l'altra.
2026-01-23 10:18:30 +01:00
Riccardo Elitropi bdcb00d1bd Merge commit '42fcb1847bca4340cf9cd283d095a6d5276cd86e' 2026-01-23 08:49:36 +01:00
Daniele Bariletti 42fcb1847b EgtGeomKernel :
- GetSurfBezierRuledGuided.
2026-01-22 11:23:58 +01:00
Riccardo Elitropi a7b36280f3 EgtGeomKernel :
- in Trimming semplificazione delle funzioni per le curve di sincronizzazione.
2026-01-21 18:27:28 +01:00
Daniele Bariletti cdef3931be EgtGeomKernel :
- spostata la funzione GetChainedCurves.
2026-01-21 10:05:54 +01:00
Riccardo Elitropi d3f2587cc2 EgtGeomKernel 3.1a3 :
- In Trimming aggiunta una prima versione per l'analisi dei triangoli durante la ricerca di facce piane
- In Trimming aggiunto l'ultilizzo delle Normali Smussate per recupero Edge mediate Estrusione
- In Trimming migliorata la gestione e la creazione delle Rigate di Bezier mediante curve di sincronizzazione.
2026-01-20 17:26:28 +01:00
Riccardo Elitropi d343f474e4 EgtGeomKernel :
- Aggiunti controlli in PolygonElevation.
2026-01-20 15:21:26 +01:00
Daniele Bariletti b7fee9696e EgtGeomKernel :
- piccola correzione.
2026-01-19 15:46:50 +01:00
Daniele Bariletti 4f48337f62 EgtGeomKernel :
- piccola correzione.
2026-01-19 15:31:56 +01:00
Daniele Bariletti 96907d5952 EgtGeomKernel :
- aggiunta di una funzionalità per il chain diretto di un vettore di curve.
2026-01-19 15:27:19 +01:00
Daniele Bariletti 3c5d2571fe EgtGeomKernel :
- piccola correzione.
2026-01-19 15:15:11 +01:00
Daniele Bariletti 7005bf43a4 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-01-19 12:32:26 +01:00
Daniele Bariletti 4726cf4d35 EgtGeomKernel :
- cambiamento della chiamata alla GetSurfBezierRuledGuided.
2026-01-19 12:32:13 +01:00
Dario Sassi b971eda771 EgtGeomJKernel :
- in Zmap sostituiti mutex con atomic_flag.
2026-01-19 08:03:57 +01:00
Dario Sassi 3ded6fe87d EgtGeomKernel :
- piccole modifiche estetiche.
2026-01-16 18:44:36 +01:00
Riccardo Elitropi 5195c23dfb EgtGeomKernel :
- in CalcPocketing piccola modifica sulle Entrate per casi a Trapezio.
2026-01-16 17:27:33 +01:00
Daniele Bariletti 5f1255a625 EgtGeomKernel :
- piccola miglioria alla intersLineLine
- piccola correzione alla intersCurveCurve.
2026-01-16 15:12:01 +01:00
Daniele Bariletti 82accd45c1 EgtGeomKernel :
- piccola correzione.
2026-01-15 12:47:50 +01:00
Daniele Bariletti e46768b14b EgtGeomKernel :
- modificata la funzione per la creazione di una surf Bezier ruled guided.
2026-01-15 11:50:03 +01:00
Daniele Bariletti 32307efd78 Merge remote-tracking branch 'origin/master' 2026-01-14 08:49:12 +01:00
Daniele Bariletti e84df69f6f EgtGeomkernel :
- piccola correzione alla remove span
- aggiunto comando di debug.
2026-01-14 08:47:14 +01:00
Riccardo Elitropi 669f38a731 EgtGeomKernel 3.1a2 :
- In CalcPocketing aggiunti controlli per casi a Spirale e Trapezio in presenza di lati aperti.
2026-01-13 14:36:02 +01:00
Dario Sassi afef5597b2 EgtGeomKernel :
- tentaivo di correzione intersezione tra segmenti di retta quasi paralleli.
2026-01-12 08:15:06 +01:00
Riccardo Elitropi 4a0bd638fa EgtGeomKernel :
- in CalcPocketing migliorata la gestione dei punti iniziali dei percorsi nel caso dei Trapezi o di punti di riferimento generici.
2026-01-08 19:19:08 +01:00
Daniele Bariletti 4bfb38b9d5 EgtGeomKernel :
- piccola correzione alla triangolazione delle surf di bezier.
2026-01-07 12:28:11 +01:00
Daniele Bariletti 0d62cd9bbd EgtGeomKernel :
- aggiunta controlli e correzione al VM 5 assi in caso di movimento a perno sulla punta del tool.
2026-01-07 12:26:13 +01:00
Dario Sassi 913d5f60ca EgtGeomKernel :
- piccole sistemazioni per normali di vertici di Trimesh pesate su angoli.
2026-01-07 11:29:57 +01:00
Dario Sassi 3dddbdf5cd EgtGeomKernel :
- nelle TriMesh calcolo normali di vertici con peso da angoli
- in Zmap pezza per movimenti 5assi sul tip (da correggere veramente).
2026-01-07 09:23:02 +01:00
Dario Sassi 3245f7fe75 EgtGeomKernel :
- aggiunte funzioni di striping per trimming dei termoformati.
2026-01-04 20:39:33 +01:00
Dario Sassi f144cda136 EgtGeomKernel :
- modifiche per consentire di proiettare curve chiuse su superfici conservando i punti di inizio e fine.
2026-01-04 12:55:28 +01:00
Dario Sassi d374e133f0 EgtGeomKernel 3.1a1 :
- ricompilazione con cambio major versione.
2026-01-02 12:33:47 +01:00
Dario Sassi 0c435a646d EgtGeomKernel :
- migliorato controllo e sistemazione chiusura curva di intersezione piano con Zmap.
2025-12-30 19:24:56 +01:00
Dario Sassi d0ac226753 EgtGeomKernel :
- aggiunta lettura file Nge binari compressi.
2025-12-29 19:24:56 +01:00
Dario Sassi d92344f2bb EgtGeomKernel :
- - modifiche a NgeReader per semplificare e velocizzare lettura file binari.
2025-12-29 11:55:09 +01:00
Dario Sassi 51c584c6c4 EgtGeomKernel 2.7l6 :
- modifiche a NgeWriter per semplificare e velocizzare scrittura file binari (ora anche compressi).
2025-12-29 08:45:03 +01:00
Dario Sassi 176bbec8a7 EgtGeomKernel 2.7l3 :
- aggiunta funzione DuplicateGeomDB.
2025-12-23 15:35:32 +01:00
Riccardo Elitropi b3ebb35d01 EgtGeomKernel :
- aggiunte prime funzioni di Trimming.
2025-12-22 17:15:02 +01:00
Daniele Bariletti a508da8b18 EgtGemoKernel :
- piccola correzione.
2025-12-19 15:58:30 +01:00
Daniele Bariletti 91ca84f77a EgtGeomKernel :
- miglioramento delle superfici di bezier.
- aggiunta di una funzione per l'eliminazione delle span collassate e di una per l'inversione dei paramettri di una superficie.
2025-12-19 15:03:19 +01:00
Dario Sassi d27fdb9904 EgtGeomKernel :
- piccole migliorie.
2025-12-16 13:03:59 +01:00
Daniele Bariletti 3b816e2a45 EgtGeomKernel :
- correzione alla conversione da sup nurbs a bezier.
2025-12-16 11:27:19 +01:00
Daniele Bariletti 1ad96ce8ca EgtGeomKernel :
- tentativo di miglioramento delle ruled nei punti di mismatch.
2025-12-15 15:08:53 +01:00
Daniele Bariletti 36422c43b3 Merge branch 'master' into NewRuled 2025-12-15 15:07:21 +01:00
Riccardo Elitropi 11a46ca58c EgtGeomKernel 2.7l2 :
- Modificate le funzioni di Offset per superfici TriMesh aperte
- Aggiunta la funzione per la creazione di Shell per TriMesh.
2025-12-15 11:35:15 +01:00
Dario Sassi 6e0aec3bec EgtGeomkernel :
- migliorie alle varie ProjectPointOnSurf per gestione corner esterni e interni.
2025-12-15 08:17:11 +01:00
Dario Sassi 11dd35af44 EgtGeomKernel :
- aggiunta funzione di proiezione a minima distanza di curva su superfcie
- migliorato LockAddErase per atomic_flag.
2025-12-09 08:14:56 +01:00
Dario Sassi 17fe5f0c9c EgtGeomKernel 2.7l1 :
- piccola ottimizzazione in LockAddErase.
2025-12-04 19:10:07 +01:00
Riccardo Elitropi c8e2d88bb7 EgtGeomKernel :
- Migliorata la gestione intersezioni Linea con Box.
2025-12-01 08:32:02 +01:00
Dario Sassi c6ac9fbcf8 EgtGeomKernel :
- migliorie al calcolo BBox di Zmap.
2025-11-24 19:27:08 +01:00
Daniele Bariletti e636e75b76 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-11-24 13:07:48 +01:00
Daniele Bariletti a01346577f EgtGeomKernel :
- correzioni alle bezier.
2025-11-24 13:07:43 +01:00
Dario Sassi 61a5e53351 EgtGeomKernel :
- sistemazioni varie legate a scalature per aumentare la precisione.
2025-11-24 10:05:39 +01:00
Daniele Bariletti 739c17b4b6 EgtGeomKernel :
- piccola correzione.
2025-11-21 12:32:30 +01:00
Daniele Bariletti 144ef16b0b EgtGeomKernel :
- piccola modifica.
2025-11-21 09:21:37 +01:00
Daniele Bariletti 58c635cb9d EgtGeomKernel :
- piccola miglioria.
2025-11-20 16:12:56 +01:00
Daniele Bariletti a39b9a7651 EgtGeomKernel :
- correzioni alle bezier.
2025-11-20 12:26:08 +01:00
Daniele Bariletti 75889983de egtGeomKernel :
- correzione alle bezier.
2025-11-19 17:42:35 +01:00
Daniele Bariletti e4a14b629c EgtGeomKernel :
- aggiunta la possibilità di filtrare le intersezioni 3D di una IntersCurveCurve.
2025-11-19 13:09:46 +01:00
Daniele Bariletti 3640a17632 EgtGeomKernel :
- migliorata gestione della triangolazione per le bezier.
2025-11-19 11:24:21 +01:00
Daniele Bariletti 2a3f809e4e EgtGeomKernel :
- funzioni che restituiscono punti nel parametrico di una bezier ora li restituiscono riscalati.
2025-11-18 16:16:54 +01:00
Dario Sassi d7dd7b9f80 EgtGeomKernel 2.7k4 :
- cambio versione.
2025-11-15 11:05:43 +01:00
Dario Sassi cd48e2de3b EgtGeomKernel :
- varie correzioni ortografiche.
2025-11-15 11:00:21 +01:00
Daniele Bariletti 8f43efe282 EgtGeomKernel :
- correzione di commenti.
2025-11-14 15:49:28 +01:00
Daniele Bariletti 025bcbba1d EgtGeomKernel :
- correzione alla creazione guidata di bezier ruled.
2025-11-14 15:47:00 +01:00
Daniele Bariletti d0131deb40 EgtGeomKernel :
- tolto codice di debug.
2025-11-12 14:30:51 +01:00
Daniele Bariletti 1325f83291 Merge branch 'NewRuled' 2025-11-12 13:05:54 +01:00
Daniele Bariletti 961acdbc76 EgtGeomKernel :
- correzioni alla inters curve-piano
- migliorata la ruled con bezier.
2025-11-12 13:03:28 +01:00
Daniele Bariletti 6789d74abc Merge branch 'master' into NewRuled 2025-11-12 08:58:12 +01:00
Daniele Bariletti 062c92377e EgtGeomKernel :
- piccola correzione alla intersCurvePlane.
2025-11-12 08:57:31 +01:00
Daniele Bariletti 383f4c7abd GeomKernel :
- aggiunta funzione surf bez ruled guided.
2025-11-12 08:56:43 +01:00
Riccardo Elitropi 4cc6161918 EgtGeomKernel :
- in PolyLine corretta funzione per modifica al punto inziale.
2025-11-11 17:12:55 +01:00
Daniele Bariletti c0ebbee347 EgtGeomKernel :
- aggiunto default per parametro della unproject di una bezier.
2025-11-11 11:53:47 +01:00
Daniele Bariletti e3b4f5bd2d EgtGeomKernel :
- aggiunta la classe per l'intersezione curva-piano.
2025-11-11 11:53:13 +01:00
Daniele Bariletti 5df3ab6d98 EgtGeomKernel :
- migliorata la nuova versione di ruled.
2025-11-07 17:39:52 +01:00
Dario Sassi 63fb9a638b EgtGeomKernel 2.7k3 :
- a SimpleOffset di Curve aggiunto parametro opzionale dMaxAngExt (angolo esterno oltre il quale estendi diventa smussa) con default 90deg.
2025-11-06 18:49:55 +01:00
Riccardo Elitropi d62d6946c3 EgtGeomKernel :
- miglioramento della funzione per calcolo curvatura di una superficie TriMesh.
2025-11-06 13:04:40 +01:00
Dario Sassi 7f0237ced4 EgtGeomKernel :
- ricompilato con Eigen 3.4.1 perchè la versione 5.0.0 dà assert in debug 32bit.
2025-11-06 08:42:56 +01:00
Dario Sassi 23621630d5 EgtGeoMkernel :
- semplificazione interfaccia di GetCurvature di SurfTriMesh.
2025-11-05 11:29:02 +01:00
Riccardo Elitropi b3abcf73c3 EgtGeomKernel 2.7k2 :
- aggiunta funzione per il calcolo della curvatura in un vertice per una superficie TriMesh.
2025-11-04 16:02:04 +01:00
Daniele Bariletti 1219e9bd80 EtgGeomKernel :
- primo tentativo.
2025-11-04 14:37:34 +01:00
Dario Sassi dced59b9a1 EgtGeomKernel :
- piccolo miglioramento.
2025-11-03 18:04:52 +01:00
Dario Sassi 3bf2972089 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2025-11-01 17:25:33 +01:00
Dario Sassi 6dd3ea5cc2 EgtGeomKernel 2.7k1 :
- aggiustamenti e ricompilazione per passaggio a C++ 20
2025-11-01 17:24:43 +01:00
Daniele Bariletti 592a92ebdb EgtGeomKernel :
- correzione alla getLoops.
2025-10-31 15:05:44 +01:00
Daniele Bariletti 1321742afe EgtGeomKernel :
- piccola correzione.
2025-10-31 13:21:37 +01:00
Daniele Bariletti f1f93124a0 EgtGeomKernel :
- correzione alle sup di bezier.
2025-10-31 13:16:10 +01:00
Daniele Bariletti c8e9d1e012 EgtGeomKernel :
- rimozione parti di debug.
2025-10-31 11:09:11 +01:00
Daniele Bariletti 7b0cd0939b Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-10-31 11:08:28 +01:00
Daniele Bariletti 3b5ab5089b EgtGeomKernel .
- ulteriore piccola correzione alle rigate.
2025-10-31 11:08:22 +01:00
Dario Sassi b36d919d8f EgtGeomKernel 2.7j5 :
- ricompilazione con cambio versione.
2025-10-31 09:44:03 +01:00
Daniele Bariletti e22a207f03 EgtGeomKernel :
- ulteriore miglioramento alle rigate con le bezier.
2025-10-30 15:28:53 +01:00
Daniele Bariletti 24dbef52c9 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-10-30 12:06:46 +01:00
Daniele Bariletti 5498b1e25c EgtGeomKernel :
- miglioramento alle rigate con le bezier.
2025-10-30 12:06:39 +01:00
Dario Sassi 86851bb67e EgtGeomKernel 2.7j4 :
- ricompilazione con cambio versione.
2025-10-29 17:10:50 +01:00
Daniele Bariletti b99e12c56f EgtGeomKernel :
- aggiunta la classe per calcolare la distanza tra un punto e una surf bezier.
2025-10-29 14:50:02 +01:00
Daniele Bariletti 129b1b919e EgtGeomKernel :
- aggiunta funzione per restituire tutte le isoparametriche di bordo delle patch in un parametro
- migliorata la gestione del recupero delle isocurve.
2025-10-29 10:35:43 +01:00
Daniele Bariletti 711c250cfc EgtGeomKernel :
- migliorata la interpolate con curve di bezier.
2025-10-24 11:54:19 +02:00
Daniele Bariletti 0f05216474 Merge branch 'DevelopTemp' 2025-10-24 11:17:23 +02:00
Daniele Bariletti c57b7c95c1 EgtGeomKernel :
- piccola miglioria alle surf bez.
2025-10-24 11:17:12 +02:00
Daniele Bariletti 62e041ed8c EgtGeomKernel :
- correzione alle superfici di bezier.
2025-10-24 09:11:21 +02:00
Daniele Bariletti 2983454ce2 EgtGeomKernel :
- piccola correzione.
2025-10-22 15:09:34 +02:00
Daniele Bariletti 6d5046cb6d EgtGeomKernel :
- cambiata la gestione della razionalità delle curve di bezier durante le conversioni da curva generica a bezier.
2025-10-22 12:53:55 +02:00
Daniele Bariletti 91fcf43da9 EgtGeomKernel :
- piccola correzione.
2025-10-22 09:57:41 +02:00
Daniele Bariletti aef1a57e1c EgtGeomKernel :
- correzione alla chiamata della funzione CurveToBezierCurve.
2025-10-21 12:50:15 +02:00
Daniele Bariletti 71316bac6a EgtGeomKernel :
- surf di bezier restituisce solo edge raffinati.
- aggiornato il valore di default per la bezier raffinata.
2025-10-21 12:25:05 +02:00
Daniele Bariletti f1c4f06461 EgtGeomKernel :
- aggiunto paramentro MaxLen per l'interpolazione con le bezier.
2025-10-21 09:36:47 +02:00
Daniele Bariletti 412bbd2a8b Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-10-20 12:30:42 +02:00
Daniele Bariletti be64cedfc3 EgtGeomKernel :
- piccola correzione.
2025-10-20 12:30:35 +02:00
Dario Sassi 2a6b35d658 EgtGeomKernel 2.7j3 :
- ricompilazione con cambio versione.
2025-10-20 12:25:08 +02:00
Daniele Bariletti f51c5c36d0 EgtGeomKernel :
- correzione tolleranza per l'interpolazione di punti con curve di bezier.
2025-10-20 10:39:32 +02:00
Daniele Bariletti 5599901185 EgtGeomKernel :
- correzione nel restituire i bordi di una surf di bezier chiusa.
2025-10-17 17:06:04 +02:00
Daniele Bariletti fb235bf985 EgtGeomKernel :
- aggiunta la funzione per l'approssimazione di una curva generica con una serie di bezier.
- piccole modifiche.
2025-10-17 15:36:32 +02:00
Daniele Bariletti 717d7a3fe3 EgtGeomKernel :
- piccola correzione.
2025-10-17 14:38:34 +02:00
Daniele Bariletti c91f468dce EgtGeomKernel :
- migliorata gestione input per l'interpolazione con curve di bezier.
2025-10-17 14:32:12 +02:00
Daniele Bariletti 1f36657efd EgtGeomKernel :
- correzione all'interpolazione tramite curve di bezier.
2025-10-16 17:40:14 +02:00
Daniele Bariletti b70ad5c808 EgtGeomKernel :
- migliorata gestione della validità delle curve di bezier.
2025-10-15 09:08:04 +02:00
SaraP da56ef91fd EgtGeomKernel :
- piccola correzione.
2025-10-15 08:30:20 +02:00
Daniele Bariletti 9bd7a152d7 EgtGeomKernel :
- piccola correzione.
2025-10-14 16:44:24 +02:00
Daniele Bariletti 5c287d49bb EgtGeomKernel :
- aggiornamento funzioni per recuperare i loop di una surf di bezier.
2025-10-14 16:30:45 +02:00
Daniele Bariletti 942f15b49d Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2025-10-13 15:21:19 +02:00
Daniele Bariletti 20b61cda42 EgtGeomKernel :
- correzione alla bezier ruled.
2025-10-13 15:21:13 +02:00
Dario Sassi b1b1d6d434 EgtGeomKernel :
- adattamento per modifiche nei puntatori a funzione.
2025-10-13 08:46:09 +02:00
Dario Sassi c7ad32ef30 EgtGeomKernel :
- in Dump di TriMesh e Zmap aggiunta info ShowEdges.
2025-10-11 12:30:46 +02:00
Daniele Bariletti 6016db837e EgtGeomKernel :
- correzione del merge.
2025-10-10 16:50:59 +02:00
Daniele Bariletti 2051e0b5d9 Merge branch 'FasterVMill' 2025-10-10 16:49:26 +02:00
Daniele Bariletti fddb3f5707 EgtGeomKernel :
- pulizia.
2025-10-10 16:46:50 +02:00
Daniele Bariletti 096dd84511 EgtGeomKernel :
- correzione e pulizia.
2025-10-10 16:42:13 +02:00
Dario Sassi e16a2078fc EgtGeomKernel 2.7j2 :
- ricompilazione con Eigen 3.4.1.
2025-10-10 15:55:54 +02:00
Daniele Bariletti e388ae34e3 Merge branch 'master' into FasterVMill 2025-10-10 12:55:34 +02:00
Daniele Bariletti b64c747082 EgtGeomKernel :
- aggiunto un tipo di interpolazione con bezier.
2025-10-10 12:11:56 +02:00
Daniele Bariletti 8afa3ae47d EgtGeomKernel :
- corretta la copia di un VolZmap.
2025-10-10 10:22:20 +02:00
Daniele Bariletti 1eba68e95b EgtGeomKernel :
- aggiunta controllo box con tratti sugli spilloni( direz generica tool).
2025-10-09 16:45:03 +02:00
Daniele Bariletti 047b339006 EgtGeomKernel :
- piccola correzione.
2025-10-09 14:56:24 +02:00
Daniele Bariletti acd7415835 EgtGeomKernel :
- aggiunta controllo box con tratti sugli spilloni.
2025-10-09 14:46:31 +02:00
Daniele Bariletti a48460ef76 EgtGeomKernel :
- pulizia codice.
2025-10-09 11:32:36 +02:00
Daniele Bariletti 8ab3896e3a Merge branch 'FasterVMill5Axis_Bez3x1' 2025-10-09 10:54:46 +02:00
Daniele Bariletti 2d481c8a71 Merge branch 'master' into FasterVMill5Axis_Bez3x1 2025-10-09 10:34:53 +02:00
Daniele Bariletti 7968a4e5ed EgtGeomKernel :
- miglioria gestione box (Oriented BB).
- pulizia codice.
2025-10-09 10:25:58 +02:00
Riccardo Elitropi 39d295f412 EgtGeomKernel :
- Migliorata e Corretta la funzione MakeUniform per VolZMap.
2025-10-09 09:50:07 +02:00
Dario Sassi 0bf2cc2a77 EgtGeomKernel :
- aggiunte funzioni per copia da un db a un altro (CopyEx e CopyGlobEx).
2025-10-08 18:31:15 +02:00
Daniele Bariletti 433f486091 EgtGeomKernel :
- corretto un bug nel taglio spilloni.
2025-10-07 17:03:07 +02:00
Riccardo Elitropi fee6604d5e EgtGeomKernel 2.7j1 :
- in CalcPocketing migliorata la gestione delle svuotature Conformal.
2025-10-07 14:38:07 +02:00
Daniele Bariletti c339fced5c EgtGeomKernel :
- correzioni e debug.
2025-10-07 10:23:23 +02:00
Daniele Bariletti a87351778d EgtGeomKernel :
- tolte parti di debug.
2025-10-06 09:43:15 +02:00
Daniele Bariletti 42687457e0 Merge branch 'master' into FasterVMill5Axis_Bez3x1 2025-10-06 09:39:07 +02:00
Daniele Bariletti 4a541402da EgtGeomKernel :
- log per calcolo tempi.
2025-10-06 09:31:59 +02:00
Riccardo Elitropi ecef487746 EgtGeomKernel 2.7i7 :
- In SurfFlatRegion corretta funzione di Clear.
2025-10-03 10:30:31 +02:00
Riccardo Elitropi df483b5623 EgtGeomKernel :
- In CalcPocketing piccola correzione per i punti iniziali nei casi Spiral e per i Trapezi.
2025-10-02 17:57:41 +02:00
Daniele Bariletti e4d3f5f9a4 EgtGeomkernel :
- confronto tempi.
2025-09-30 17:22:23 +02:00
Daniele Bariletti 02e164dcdf EgtGeomKernel :
- evitati duplicati di archi di bezier.
2025-09-30 16:05:59 +02:00
Daniele Bariletti ead94e7915 EgtGeomKernel :
- VM 5 assi verisione con box object oriented.
2025-09-30 10:01:01 +02:00
Daniele Bariletti dfc3c29439 EgtGeomKernel :
- aggiunto codice per debug.
2025-09-29 16:00:34 +02:00
Daniele Bariletti ab538f4bf7 Merge branch 'master' into FasterVMill5Axis_Bez3x1 2025-09-29 09:20:34 +02:00
89 changed files with 18329 additions and 4040 deletions
+2 -2
View File
@@ -151,11 +151,11 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
else {
double dParA = vIccInfo[i].IciA[0].dU ;
double dParB = vIccInfo[i].IciB[0].dU ;
if ( abs( dParA - dEnd) < EPS_SMALL)
if ( dParA > dParB)
swap( dParA, dParB) ;
// verifico se uno dei due intervalli dà origine ad un tratto trascurabile
PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ;
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
double dArea1 = 0, dArea2 = 0 ;
if ( ! IsNull( pCrv1))
pCrv1->GetAreaXY( dArea1) ;
+4
View File
@@ -140,16 +140,20 @@ MyCAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) {
m_SCollInfo = scInfoCurr ;
m_SCollInfo.nChunkM = j ;
m_SCollInfo.nLoopM = 0 ;
m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = i ;
m_SCollInfo.nLoopF = 0 ;
m_SCollInfo.nCrvF = l ;
}
}
else if ( dNewLenXY < dPrevLenXY) {
m_SCollInfo = scInfoCurr ;
m_SCollInfo.nChunkM = j ;
m_SCollInfo.nLoopM = 0 ;
m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = i ;
m_SCollInfo.nLoopF = 0 ;
m_SCollInfo.nCrvF = l ;
}
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
+2 -2
View File
@@ -30,7 +30,7 @@ class MyCAvSimpleSurfFrMove
const SCollInfo& GetSCollInfo()
{ return m_SCollInfo ;}
private :
protected :
bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2,
const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ;
bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
@@ -40,7 +40,7 @@ class MyCAvSimpleSurfFrMove
bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
const Point3d& ptCen, double& dAng) ;
private :
protected :
const SurfFlatRegion* m_pRegM ;
const SurfFlatRegion* m_pRegF ;
SCollInfo m_SCollInfo ;
+257
View File
@@ -0,0 +1,257 @@
//----------------------------------------------------------------------------
// EgalTech 2026-2026
//----------------------------------------------------------------------------
// File : CASurfFrMove.cpp Data : 26.03.2026 Versione : 3.1c7
// Contenuto : Implementazione delle funzioni di movimento per SurfFlatRegion
// senza collisione con altri oggetti dello stesso tipo e nello
// stesso piano o in piani paralleli.
//
//
// Modifiche : 26.03.2026 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CAvSurfFrMove.h"
#include "SurfFlatRegion.h"
#include "CurveLine.h"
#include "CurveArc.h"
#include "CurveComposite.h"
#include "IntersLineArc.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkCAvSurfFrMove.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
// CASurfFrMove
//----------------------------------------------------------------------------
CAvSurfFrMove::CAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF)
{
// salvo puntatori alle regioni
m_pRegM = &SfrM ;
m_pRegF = &SfrF ;
}
//----------------------------------------------------------------------------
bool
CAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
{
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
m_CollInfo.nType = SCI_NONE ;
if ( ! ScdMove.Translate( vtDir, dLen))
return false ;
m_CollInfo = ScdMove.GetCollInfo() ;
return true ;
}
//----------------------------------------------------------------------------
bool
CAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
{
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
m_CollInfo.nType = SCI_NONE ;
return ScdMove.Rotate( ptCen, dAng) ;
}
//----------------------------------------------------------------------------
bool
MyCAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
{
// verifico validità regioni
if ( m_pRegM == nullptr || m_pRegF == nullptr)
return false ;
// verifico che le due regioni giacciano in piani paralleli
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
return false ;
// reset info di collisione
m_SCollInfo.nType = SCI_NONE ;
// porto il vettore di movimento nel riferimento intrinseco e ne annullo la componente Z
Vector3d vtDirL = vtDir ;
vtDirL.ToLoc( m_pRegM->m_frF) ;
vtDirL.z = 0 ;
double dLenXY = vtDirL.Len() ;
if ( dLenXY < EPS_SMALL)
return true ;
vtDirL /= dLenXY ;
dLenXY *= dLen ;
double dNewLenXY = dLenXY ;
// ciclo sui chunk della seconda superficie
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
// ciclo sui bordi dei chunk
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
const ICurve* pCrv2Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
else {
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
pCrv2Loc = pCopyCrv ;
}
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
// ciclo sui chunk della prima superficie
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
// ciclo sui bordi del chunk
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
// per CAv non ha senso confrontare due loop interni tra di loro.
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
if ( nLF > 0 && nLM > 0)
continue ;
// curva corrente del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
// verifico la collisione tra le entità dei loop esterni dei due chunk
int k = 0 ;
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
while ( pCrv1 != nullptr) {
int l = 0 ;
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
while ( pCrv2 != nullptr) {
SCollInfo cInfoCurr ;
double dPrevLenXY = dNewLenXY ;
if ( ! TranslateCurveNoCollisionCurve( pCrv1, pCrv2, vtDirL, dNewLenXY, cInfoCurr))
return false ;
if ( abs( dNewLenXY - dPrevLenXY) < EPS_SMALL) {
if ( cInfoCurr.nType == SCI_LINE_LINE || cInfoCurr.nType == SCI_PNT_LINE) {
m_SCollInfo = cInfoCurr ;
m_SCollInfo.nChunkM = nCM ;
m_SCollInfo.nLoopM = nLM ;
m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = nCF ;
m_SCollInfo.nLoopF = nLF ;
m_SCollInfo.nCrvF = l ;
}
}
else if ( dNewLenXY < dPrevLenXY) {
m_SCollInfo = cInfoCurr ;
m_SCollInfo.nChunkM = nCM ;
m_SCollInfo.nLoopM = nLM ;
m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = nCF ;
m_SCollInfo.nLoopF = nLF ;
m_SCollInfo.nCrvF = l ;
}
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
++ l ;
}
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
++ k ;
}
}
}
}
}
// se da limitare il movimento
if ( dNewLenXY < dLenXY - EPS_SMALL)
dLen *= dNewLenXY / dLenXY ;
// porto i punti e le direzioni di SCollInfo da intrinseco a locale della prima regione
if ( m_SCollInfo.nType != SCI_NONE) {
m_SCollInfo.ptP1.ToGlob( m_pRegM->m_frF) ;
m_SCollInfo.vtDirM.ToGlob( m_pRegM->m_frF) ;
m_SCollInfo.vtDirF.ToGlob( m_pRegM->m_frF) ;
}
if ( m_SCollInfo.nType == SCI_LINE_LINE)
m_SCollInfo.ptP2.ToGlob( m_pRegM->m_frF) ;
return true ;
}
//----------------------------------------------------------------------------
bool
MyCAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
{
// verifico validità regioni
if ( m_pRegM == nullptr || m_pRegF == nullptr)
return false ;
// verifico che le due regioni giacciano in piani paralleli
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
return false ;
// reset info di collisione
m_SCollInfo.nType = SCI_NONE ;
// porto il centro di rotazione nel riferimento intrinseco e ne annullo la componente Z
Point3d ptCenL = ptCen ;
ptCenL.ToLoc( m_pRegM->m_frF) ;
ptCenL.z = 0 ;
if ( abs( dAng) < EPS_ANG_SMALL)
return true ;
double dNewAng = dAng ;
// ciclo sui chunk della seconda superficie
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
// ciclo sui bordi del Chunk
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
const ICurve* pCrv2Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
else {
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
pCrv2Loc = pCopyCrv ;
}
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
// ciclo sui chunk della prima superficie
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
// ciclo sui bordi del chunk
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
// per CAv non ha senso confrontare due loop interni tra di loro.
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
if ( nLF > 0 && nLM > 0)
continue ;
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
// verifico la collisione tra le entità dei loop esterni dei due chunk
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
while ( pCrv1 != nullptr) {
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
while ( pCrv2 != nullptr) {
if ( ! RotateCurveNoCollisionCurve( pCrv1, pCrv2, ptCenL, dNewAng))
return false ;
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
}
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
}
}
}
}
}
// se da limitare il movimento
if ( ( dAng > 0 && dNewAng < dAng - EPS_ANG_SMALL) ||
( dAng < 0 && dNewAng > dAng + EPS_ANG_SMALL))
dAng = dNewAng ;
return true ;
}
+29
View File
@@ -0,0 +1,29 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2018
//----------------------------------------------------------------------------
// File : CAvSurfFrMove.h Data : 27.04.18 Versione : 3.1c7
// Contenuto : Dich.ne classe privata per movimento di superfici flat region
// nel loro piano evitando collisioni
//
// Modifiche : 26.03.2026 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "CAvSimpleSurfFrMove.h"
//----------------------------------------------------------------------------
class MyCAvSurfFrMove : public MyCAvSimpleSurfFrMove
{
public :
MyCAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) :
MyCAvSimpleSurfFrMove( SfrM, SfrF) {} ;
public :
bool Translate( const Vector3d& vtDir, double& dLen) ;
bool Rotate( const Point3d& ptCen, double& dAng) ;
const SCollInfo& GetCollInfo()
{ return m_SCollInfo ; }
} ;
+2 -4
View File
@@ -2440,12 +2440,10 @@ CAvDiskTriangle( const Point3d& ptDiskCen, const Vector3d& vtDiskAx, double dDis
// Allontanamento dall'interno
double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ;
// Allontanamento dalla frontiera
Vector3d vtMoveOrt = vtMove - vtMove * vtDiskAx * vtDiskAx ;
Vector3d vtMoveOrt = OrthoCompo( vtMove, vtDiskAx) ;
vtMoveOrt.Normalize() ;
Frame3d DiskFrame ;
Vector3d vtJ = vtDiskAx ^ vtMoveOrt ;
vtJ.Normalize() ;
DiskFrame.Set( ptDiskCen, vtMoveOrt, vtJ, vtDiskAx) ;
DiskFrame.Set( ptDiskCen, vtDiskAx, vtMoveOrt) ;
Triangle3d trTriaLoc = trTria ;
Vector3d vtMoveLoc = vtMove ;
trTriaLoc.ToLoc( DiskFrame) ;
+40 -20
View File
@@ -1,12 +1,13 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2024
// EgalTech 2020-2026
//----------------------------------------------------------------------------
// File : CDeClosedSurfTmClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
// File : CDeClosedSurfTmClosedSurfTm.h Data : 23.01.26 Versione : 3.1a3
// Contenuto : Implementazione funzione verifica collisione tra
// SurfTm e SurfTm.
//
// Modifiche : 13.11.20 LM Creazione modulo.
// 24.03.24 DS Aggiunta TestSurfTmSurfTm.
// 23.01.26 DS In TestSurfTmSurfTm aggiunto flag per collisione quando una delle due è chiusa e contiene l'altra.
//
//----------------------------------------------------------------------------
@@ -45,10 +46,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ;
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ;
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
if ( ! b3BoxA.Overlaps( b3BoxB))
return false ;
// Recupero i triangoli di A che interferiscono col box di B
@@ -61,13 +62,13 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
continue ;
BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( b3BoxTriaA) ;
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
// Settare tutti i triangoli come già processati.
// Settare tutti i triangoli come già processati.
// Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
@@ -84,14 +85,14 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
// Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge
// non è stato processato, processo il vertice e l'edge.
// non è stato processato, processo il vertice e l'edge.
int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ;
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ;
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ;
@@ -111,10 +112,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
}
}
// Non ho trovato collisioni fra triangoli delle superfici.
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA))
return false ;
// La collisione c'è se una superficie è dentro l'altra.
// La collisione c'è se una superficie è dentro l'altra.
Point3d ptPointA, ptPointB ;
pSrfA->GetFirstVertex( ptPointA) ;
pSrfB->GetFirstVertex( ptPointB) ;
@@ -127,7 +128,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
// Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
//----------------------------------------------------------------------------
bool
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist)
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist, bool bTestEnclosion)
{
// Recupero le superfici base
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
@@ -140,10 +141,10 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ;
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ;
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
if ( ! b3BoxA.Overlaps( b3BoxB))
return false ;
// Recupero i triangoli di A che interferiscono col box di B
@@ -156,13 +157,13 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
continue ;
BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( b3BoxTriaA) ;
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
// Settare tutti i triangoli come già processati.
// Settare tutti i triangoli come già processati.
// Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
@@ -179,14 +180,14 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
// Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge
// non è stato processato, processo il vertice e l'edge.
// non è stato processato, processo il vertice e l'edge.
int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ;
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ;
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ;
@@ -205,6 +206,25 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
pSrfB->SetTempInt( nTB, 1) ;
}
}
// Non c'è interferenza
// Se non richiesto test di inclusione, non c'è interferenza
if ( ! bTestEnclosion)
return false ;
// Se la prima superficie è chiusa, verifico se include totalmente la seconda
if ( pSrfA->IsClosed() && b3BoxA.Encloses( b3BoxB)) {
Point3d ptPointB ;
pSrfB->GetFirstVertex( ptPointB) ;
DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ;
if ( DistPoinBSrfA.IsPointInside() || DistPoinBSrfA.IsEpsilon( dSafeDist))
return true ;
}
// Se la seconda superficie è chiusa, verifico se include totalmente la prima
if ( pSrfB->IsClosed() && b3BoxB.Encloses( b3BoxA)) {
Point3d ptPointA ;
pSrfA->GetFirstVertex( ptPointA) ;
DistPointSurfTm DistPoinASrfB( ptPointA, *pSrfB) ;
if ( DistPoinASrfB.IsPointInside() || DistPoinASrfB.IsEpsilon( dSafeDist))
return true ;
}
// Non c'è interferenza
return false ;
}
+233
View File
@@ -0,0 +1,233 @@
//----------------------------------------------------------------------------
// EgalTech 2026
//----------------------------------------------------------------------------
// File : CalcDerivate.cpp Data : 03.02.26 Versione : 1.5h1
// Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima.
//
//
//
// Modifiche : 03.02.26 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "stdafx.h"
#include "CalcDerivate.h"
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EgtNumCollection.h"
#include "/EgtDev/Include/EGkGeoCollection.h"
//----------------------------------------------------------------------------
bool
ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
{
// pulisco i vettori dei parametri e delle tangenti
vPrevDer.clear() ;
vNextDer.clear() ;
// numero di punti
int nSize = int( vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
vPrevDer.reserve( nSize) ;
vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
vPrevDer.emplace_back( 0, 0, 0) ;
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
vPrevDer.push_back( vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
// se non ci sono almeno 5 punti
if ( nSize < 5) {
if ( ! CalcCircleMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[nSize-3] - vPar[nSize-1], vPnt[nSize-3], vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti, uso arco sui primi tre punti
else {
if ( ! CalcCircleStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = vPrevDer[0] ;
vtNextDer = vNextDer[0] ;
}
// altrimenti, uso arco sugli ultimi tre punti
else {
if ( ! CalcCircleEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
// se secondo punto
if ( i == 1) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// se penultimo punto
else if ( i == nSize - 2) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[1] + vPar[i+1], vPnt[1], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// salvo la derivata
vPrevDer.push_back( vtPrevDer) ;
vNextDer.push_back( vtNextDer) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
{
// pulisco i vettori dei parametri e delle tangenti
vPrevDer.clear() ;
vNextDer.clear() ;
// numero di punti
int nSize = int( vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
vPrevDer.reserve( nSize) ;
vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
vPrevDer.emplace_back( 0, 0, 0) ;
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
vPrevDer.push_back( vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
if ( ! CalcBesselMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti, uso i primi tre punti
else {
if ( ! CalcBesselStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = vPrevDer[0] ;
vtNextDer = vNextDer[0] ;
}
// altrimenti, uso gli ultimi tre punti
else {
if ( ! CalcBesselEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
if ( ! CalcBesselMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// salvo la derivata
vPrevDer.push_back( vtPrevDer) ;
vNextDer.push_back( vtNextDer) ;
}
return true ;
}
+5
View File
@@ -14,6 +14,8 @@
#pragma once
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EgtNumCollection.h"
#include "/EgtDev/Include/EGkGeoCollection.h"
//----------------------------------------------------------------------------
@@ -179,3 +181,6 @@ CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP
}
return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ;
}
bool ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
bool ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
+1363 -519
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -16,6 +16,7 @@
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EGkGeomDB.h"
#include "/EgtDev/Include/EGkCurve.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include <algorithm>
using namespace std ;
@@ -168,7 +169,7 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
// verifico se sono arrivato al punto di chiusura
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
if ( AreSamePointEpsilon( ptCurr, ptStop, 0.5 * EPS_SMALL)) {
bStopped = true ;
break ;
}
+3 -2
View File
@@ -45,7 +45,8 @@ static const NamedColor StdColor[] = {
{ "FUCHSIA", FUCHSIA},
{ "PURPLE", PURPLE},
{ "ORANGE", ORANGE},
{ "BROWN", BROWN}
{ "BROWN", BROWN},
{ "INVISIBLE", INVISIBLE}
} ;
static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ;
@@ -127,7 +128,7 @@ GetHSVFromColor( const Color& cCol)
hsv.dSat = dDelta / dMax ;
if ( cCol.GetRed() >= dMax) // tra giallo e magenta
hsv.dHue = ( cCol.GetGreen() - cCol.GetBlue()) / dDelta ;
else if( cCol.GetGreen() >= dMax) // tra ciano e giallo
else if ( cCol.GetGreen() >= dMax) // tra ciano e giallo
hsv.dHue = 2.0 + ( cCol.GetBlue() - cCol.GetRed()) / dDelta ;
else // tra magenta e ciano
hsv.dHue = 4.0 + ( cCol.GetRed() - cCol.GetGreen()) / dDelta ;
+2 -2
View File
@@ -1294,7 +1294,7 @@ CurveArc::Invert( void)
//----------------------------------------------------------------------------
bool
CurveArc::SimpleOffset( double dDist, int nType)
CurveArc::SimpleOffset( double dDist, int nType, double dMaxAngExt)
{
// la curva deve essere validata
if ( m_nStatus != OK)
@@ -1329,7 +1329,7 @@ CurveArc::SimpleOffset( double dDist, int nType)
//----------------------------------------------------------------------------
bool
CurveArc::MyExtendedOffset( double dDist, bool bAll, int nType)
CurveArc::MyExtendedOffset( double dDist, bool bAll)
{
// bAll == true fa accettare raggi nulli ==> da usare solo internamente
// quando si è sicuri di aumentare subito il raggio o di cancellare
+4 -4
View File
@@ -116,7 +116,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
bool Invert( void) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
bool ModifyStart( const Point3d& ptNewStart) override ;
bool ModifyEnd( const Point3d& ptNewEnd) override ;
bool SetExtrusion( const Vector3d& vtExtr) override
@@ -178,8 +178,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW
bool ChangeDeltaN( double dNewDeltaN) override ;
bool ChangeAngCenter( double dNewAngCenDeg) override ;
bool ChangeStartPoint( double dU) override ;
bool ExtendedOffset( double dDist, int nType = OFF_FILLET) override
{ return MyExtendedOffset( dDist, false, nType) ; }
bool ExtendedOffset( double dDist) override
{ return MyExtendedOffset( dDist, false) ; }
bool ToExplementary( void) override ;
bool Flip( void) override ;
@@ -200,7 +200,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
{ if ( ! CopyFrom( caSrc))
LOG_ERROR( GetEGkLogger(), "CurveArc : copy error")
return *this ; }
bool MyExtendedOffset( double dDist, bool bAll, int nType = OFF_FILLET) ;
bool MyExtendedOffset( double dDist, bool bAll) ;
bool MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, double dLinTol) const ;
Voronoi* GetVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
+737 -110
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -35,3 +35,4 @@ bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
+115 -35
View File
@@ -93,8 +93,11 @@ CurveBezier::Init( int nDeg, bool bIsRational)
bool
CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl)
{
// verifico validità indice
if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg)
// verifico validità indice e punto
if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg || ! ptCtrl.IsValid())
return false ;
if ( abs( ptCtrl.x) > INFINITO || abs( ptCtrl.y) > INFINITO || abs( ptCtrl.z) > INFINITO)
return false ;
// assegno il valore
@@ -123,8 +126,11 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
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)
// verifico che il punto sia valido e il peso non sia nullo o negativo
if ( ! ptCtrl.IsValid() || dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
return false ;
if ( abs( ptCtrl.x) > INFINITO || abs( ptCtrl.y) > INFINITO || abs( ptCtrl.z) > INFINITO)
return false ;
// assegno il valore e il peso
@@ -151,7 +157,7 @@ CurveBezier::SetControlWeight( int nInd, double dW)
return false ;
// verifico che il peso non sia nullo o negativo
if ( dW < EPS_SMALL)
if ( dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
return false ;
// assegno il valore e il peso
@@ -267,22 +273,21 @@ CurveBezier::FromArc( const ICurveArc& crArc)
bool
CurveBezier::FromLine( const ICurveLine& crLine)
{
if ( ! crLine.IsValid())
if ( m_nStatus != OK || ! crLine.IsValid())
return false ;
double dWeight = 1 ;
int nCount = 0 ;
Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
SetControlPoint( nCount, ptStart, dWeight) ;
SetControlPoint( nCount, ptStart) ;
++nCount ;
double dPart = 1. / m_nDeg ;
for ( int i = 1 ; i < m_nDeg ; ++i) {
double dU = i * dPart ;
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
SetControlPoint( nCount, ptMid, dWeight) ;
SetControlPoint( nCount, ptMid) ;
++nCount ;
}
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
SetControlPoint( nCount, ptEnd, dWeight) ;
SetControlPoint( nCount, ptEnd) ;
++nCount ;
return true ;
}
@@ -367,6 +372,8 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc)
{
if ( &cbSrc == this)
return true ;
if ( ! cbSrc.IsValid())
return false ;
if ( ! Init( cbSrc.m_nDeg, cbSrc.m_bRat))
return false ;
m_dParSing = cbSrc.m_dParSing ;
@@ -517,21 +524,21 @@ bool
CurveBezier::Validate( void)
{
if ( m_nStatus == TO_VERIFY) {
for ( const auto& ptP : m_vPtCtrl) {
if ( ! ptP.IsValid()) {
m_nStatus = ERR ;
break ;
for ( const auto& ptP : m_vPtCtrl) {
if ( ! ptP.IsValid()) {
m_nStatus = ERR ;
break ;
}
}
}
}
if ( m_nStatus == TO_VERIFY) {
for ( const auto& dWe : m_vWeCtrl) {
if ( ! isfinite( dWe)) {
m_nStatus = ERR ;
break ;
for ( const auto& dWe : m_vWeCtrl) {
if ( ! isfinite( dWe)) {
m_nStatus = ERR ;
break ;
}
}
}
}
if ( m_nStatus == TO_VERIFY)
m_nStatus = ( ( m_nDeg >= 1 && m_vPtCtrl.size() >= 2) ? OK : ERR) ;
@@ -1658,6 +1665,10 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo
ICurve*
CurveBezier::CopyParamRange( double dUStart, double dUEnd) const
{
// la curva deve essere valida
if ( m_nStatus != OK)
return nullptr ;
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
if ( dUStart < - EPS_PARAM || dUStart > 1 + EPS_PARAM ||
dUEnd < - EPS_PARAM || dUEnd > 1 + EPS_PARAM)
@@ -1800,6 +1811,10 @@ CurveBezier::TrimEndAtParam( double dUTrim)
bool
CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
if ( dUStartTrim < - EPS_PARAM || dUStartTrim > 1 + EPS_PARAM ||
dUEndTrim < - EPS_PARAM || dUEndTrim > 1 + EPS_PARAM)
@@ -1809,19 +1824,19 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
return false ;
// se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim
Point3d ptStart ;
if( m_bRat)
if ( m_bRat)
GetPointD1D2( dUStartTrim, ptStart) ;
// trim finale
if ( ! TrimEndAtParam( dUEndTrim))
return false ;
// trim iniziale con il parametro opportunamente ricalcolato
double dNewUStartTrim ;
if( m_bRat)
if ( m_bRat)
GetParamAtPoint( ptStart, dNewUStartTrim) ;
else
dNewUStartTrim = dUStartTrim / dUEndTrim ;
//trim iniziale
if( ! TrimStartAtParam( dNewUStartTrim))
if ( ! TrimStartAtParam( dNewUStartTrim))
return false ;
return true ;
@@ -1831,6 +1846,10 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
bool
CurveBezier::TrimStartAtLen( double dLenTrim)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
// lunghezze negative vengono considerate nulle
dLenTrim = max( dLenTrim, 0.) ;
@@ -1840,7 +1859,7 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
return false ;
// utilizzo il trim sui parametri
if( ! TrimStartAtParam( dUTrim))
if ( ! TrimStartAtParam( dUTrim))
return false ;
return true ;
@@ -1850,6 +1869,10 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
bool
CurveBezier::TrimEndAtLen( double dLenTrim)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
// lunghezze negative vengono considerate nulle
dLenTrim = max( dLenTrim, 0.) ;
@@ -1859,7 +1882,7 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
return false ;
// utilizzo il trim sui parametri
if( ! TrimEndAtParam( dUTrim))
if ( ! TrimEndAtParam( dUTrim))
return false ;
return true ;
@@ -1869,6 +1892,10 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
bool
CurveBezier::ExtendStartByLen( double dLenExt)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
// la lunghezza deve essere positiva
if ( dLenExt < - EPS_ZERO)
return false ;
@@ -1920,6 +1947,10 @@ CurveBezier::ExtendStartByLen( double dLenExt)
bool
CurveBezier::ExtendEndByLen( double dLenExt)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
// la lunghezza deve essere positiva
if ( dLenExt < - EPS_ZERO)
return false ;
@@ -2259,6 +2290,10 @@ CurveBezier::ResetVoronoiObject() const
bool
CurveBezier::MakeRational( void)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
if ( m_bRat)
return true ;
// creo il vettore dei pesi e li setto tutti a 1
@@ -2273,6 +2308,10 @@ CurveBezier::MakeRational( void)
bool
CurveBezier::MakeRationalStandardForm( void)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
if ( ! m_bRat)
return false ;
double dW0 = m_vWeCtrl.front() ;
@@ -2294,6 +2333,10 @@ CurveBezier::MakeRationalStandardForm( void)
bool
CurveBezier::MakeNonRational( double dTol)
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
if ( ! m_bRat)
return true ;
@@ -2308,15 +2351,44 @@ CurveBezier::MakeNonRational( double dTol)
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) ;
}
// semplicemente tolgo il booleano della razionalità e i punti restano gli stessi
m_bRat = false ;
}
else {
// provo ad approssimare la curva di bezier con una controparte non razionale
int nDeg = m_nDeg ;
// se ho una curva razionale di grado 2 verifico se è un arco, in quel caso la converto in una curva di grado 3 non razionale con la funzione dedicata
if ( nDeg == 2 && m_bRat) {
// prendo due punti sulla curva e calcolo l'intersezione dei due assi dei segmenti formati da pt2-pt0 e pt3-pt1
Point3d pt0 ; GetStartPoint( pt0) ;
Point3d pt1 ; GetPointD1D2( 0.3, pt1) ;
Point3d pt2 ; GetPointD1D2( 0.6, pt2) ;
Point3d pt3 ; GetEndPoint( pt3) ;
Vector3d vtDir1 = pt2 - pt0 ;
Vector3d vtDir2 = pt3 - pt1 ;
Vector3d vtN = vtDir2 ^ vtDir1 ;
CurveLine cl1 ; cl1.Set( pt1, pt1 + (vtDir1 ^ vtN) * 5) ;
CurveLine cl2 ; cl1.Set( pt2, pt2 + (vtDir2 ^ vtN) * 5) ;
IntersLineLine ill( cl1, cl2, false) ;
IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
Point3d ptCen = iccInfo.IciA[0].ptI ;
// se sia l'inizio che la fine della curva distano uguale dal punto di intersezione tra i due assi trovati allora la curva è un arco di circonferenza
if ( abs(Dist( pt0, ptCen) - Dist( pt3, ptCen)) < EPS_SMALL) {
PtrOwner<ICurveBezier> pNew ( ApproxArcCurveBezierWithSingleCubic( this, ptCen, vtN)) ;
if ( IsNull( pNew) || ! pNew->IsValid())
return false ;
Init( 3, false) ;
for ( int i = 0 ; i < 3 ; ++i)
SetControlPoint( i, pNew->GetControlPoint(i)) ;
return true ;
}
}
// punto di rientro in caso fallisca il primo tentativo
retry :
nDeg += 2 ;
@@ -2339,7 +2411,7 @@ CurveBezier::MakeNonRational( double dTol)
Point3d pt ; pNewBez->GetPointD1D2( double( p) / nDeg, pt) ;
Vector3d vDiff = vPntSampling[p] - pt ;
double dErrLoc = vDiff.Len() ;
if( dErrLoc > dErrMax)
if ( dErrLoc > dErrMax)
dErrMax = dErrLoc ;
// aggiorno il vettore dei punti di controllo della nuova curva
vPntCtrl[p] += vDiff ;
@@ -2352,7 +2424,7 @@ CurveBezier::MakeNonRational( double dTol)
}
// calcolo l'errore di approssimazione sulla curva
CalcBezierApproxError( this, pNewBez, dErr) ;
CalcApproxError( this, pNewBez, dErr) ;
bOk = dErr < dTol ;
if ( bOk) {
// aggiorno la curva di bezier originale con quella approssimata
@@ -2373,13 +2445,17 @@ CurveBezier::MakeNonRational( double dTol)
bool
CurveBezier::IsALine( void) const
{
// la curva deve essere valida
if ( m_nStatus != OK)
return false ;
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)
if ( dDist > EPS_SMALL)
return false ;
}
return true ;
@@ -2389,6 +2465,10 @@ CurveBezier::IsALine( void) const
PNTVECTOR
CurveBezier::GetAllControlPoints( void) const
{
PNTVECTOR vPntCtrl = m_vPtCtrl ;
return vPntCtrl ;
PNTVECTOR vPntCtrl ;
// la curva deve essere valida
if ( m_nStatus != OK)
return vPntCtrl ;
return m_vPtCtrl ;
}
+1 -1
View File
@@ -116,7 +116,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
bool Invert( void) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
bool ModifyStart( const Point3d& ptNewStart) override ;
bool ModifyEnd( const Point3d& ptNewEnd) override ;
+2 -201
View File
@@ -202,213 +202,14 @@ CurveByApprox::CalcParameterization( void)
bool
CurveByApprox::CalcAkimaTangents( bool bDetectCorner)
{
// pulisco i vettori delle tangenti
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
// se non ci sono almeno 5 punti
if ( nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti, uso arco sui primi tre punti
else {
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso arco sugli ultimi tre punti
else {
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
// se secondo punto
if ( i == 1) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// se penultimo punto
else if ( i == nSize - 2) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
}
//----------------------------------------------------------------------------
bool
CurveByApprox::CalcBesselTangents( void)
{
// pulisco i vettori delle tangenti
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti, uso i primi tre punti
else {
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso gli ultimi tre punti
else {
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
}
//----------------------------------------------------------------------------
+34 -225
View File
@@ -50,7 +50,37 @@ CurveByInterp::AddPoint( const Point3d& ptP)
ICurve*
CurveByInterp::GetCurve( int nMethod, int nType)
{
// calcolo le tangenti
// se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs)
if ( nType == CUBIC_BEZIERS_LONG) {
// creo la curva composita
PtrOwner<ICurve> pCrv ;
//pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ;
//debug
pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 0.1, 100)) ;
if ( IsNull(pCrv) || ! pCrv->IsValid())
return nullptr ;
return Release( pCrv) ;
}
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return nullptr ;
// calcolo le distanze tra i punti per derivarne i parametri
m_vPar.reserve( nSize) ;
double dPar = 0 ;
m_vPar.push_back( dPar) ;
for ( int i = 1 ; i < nSize ; ++ i) {
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
dPar += dDist ;
m_vPar.push_back( dPar) ;
}
// calcolo le tangenti
if ( nMethod == BESSEL) {
if ( ! CalcBesselTangents())
return nullptr ;
@@ -110,233 +140,12 @@ CurveByInterp::GetCurve( int nMethod, int nType)
bool
CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
{
// pulisco i vettori dei parametri e delle tangenti
m_vPar.clear() ;
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le distanze tra i punti per derivarne i parametri
m_vPar.reserve( nSize) ;
double dPar = 0 ;
m_vPar.push_back( dPar) ;
for ( int i = 1 ; i < nSize ; ++ i) {
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
dPar += dDist ;
m_vPar.push_back( dPar) ;
}
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
// se non ci sono almeno 5 punti
if ( nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti, uso arco sui primi tre punti
else {
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso arco sugli ultimi tre punti
else {
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
// se secondo punto
if ( i == 1) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// se penultimo punto
else if ( i == nSize - 2) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
}
//----------------------------------------------------------------------------
bool
CurveByInterp::CalcBesselTangents( void)
{
// pulisco i vettori dei parametri e delle tangenti
m_vPar.clear() ;
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le distanze tra i punti per derivarne i parametri
m_vPar.reserve( nSize) ;
double dPar = 0 ;
m_vPar.push_back( dPar) ;
for ( int i = 1 ; i < nSize ; ++ i) {
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
dPar += dDist ;
m_vPar.push_back( dPar) ;
}
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti, uso i primi tre punti
else {
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso gli ultimi tre punti
else {
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
}
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
}
+180 -8
View File
@@ -889,14 +889,21 @@ CurveComposite::Validate( void)
//----------------------------------------------------------------------------
bool
CurveComposite::TestClosure( void)
CurveComposite::TestClosure( double dLinTol)
{
// se non è chiusa, esco subito
if ( ! IsClosed())
// se non valida o vuota, esco subito
if ( m_nStatus != OK || m_CrvSmplS.empty())
return true ;
// se non è chiusa entro la tolleranza, esco subito
Point3d ptStart, ptEnd ;
if ( ! m_CrvSmplS.front()->GetStartPoint( ptStart) ||
! m_CrvSmplS.back()->GetEndPoint( ptEnd) ||
! AreSamePointEpsilon( ptStart, ptEnd, dLinTol))
return true ;
// se singola retta, esco subito
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_LINE)
return true ;
// verifico ed eventualmente aggiusto coincidenza punti estremi
Point3d ptStart ; m_CrvSmplS.front()->GetStartPoint( ptStart) ;
Point3d ptEnd ; m_CrvSmplS.back()->GetEndPoint( ptEnd) ;
// se distanza superiore al limite ridotto forzo i punti a coincidere
if ( ! AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT)) {
// se un solo arco
@@ -1707,7 +1714,7 @@ CurveComposite::Invert( void)
//----------------------------------------------------------------------------
bool
CurveComposite::SimpleOffset( double dDist, int nType)
CurveComposite::SimpleOffset( double dDist, int nType, double dMaxAngExt)
{
// se distanza di offset nulla, non devo fare alcunché
if ( abs( dDist) < EPS_SMALL)
@@ -1729,7 +1736,7 @@ CurveComposite::SimpleOffset( double dDist, int nType)
}
// eseguo l'offset nel piano XY
bool bOk = SimpleOffsetXY( dDist, nType) ;
bool bOk = SimpleOffsetXY( dDist, nType, dMaxAngExt) ;
// riporto la curva nel riferimento originale
if ( bNeedRef)
@@ -1960,7 +1967,120 @@ CurveComposite::AddJoint( double dU)
//----------------------------------------------------------------------------
bool
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol)
{
int nCrvCount = GetCurveCount() ;
// verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount)
return false ;
// salvo le vecchie curve e nel caso le ripristino
int nPrevCrv = -1 ;
// recupero l'indice e il puntatore alla curva precedente (se esiste)
if ( nU >= 0)
nPrevCrv = nU - 1 ;
else if ( IsClosed())
nPrevCrv = nCrvCount - 1 ;
PtrOwner<CurveComposite> pOrigCrv( CreateBasicCurveComposite()) ;
if ( nPrevCrv >= 0)
pOrigCrv->AddCurve( m_CrvSmplS[ nPrevCrv]->Clone()) ;
// recupero il puntatore alla curva successiva (se esiste)
int nNextCrv = -1 ;
if ( nU < nCrvCount)
nNextCrv = nU ;
else if ( IsClosed())
nNextCrv = 0 ;
else
nNextCrv = - 1 ;
if ( nNextCrv >= 0)
pOrigCrv->AddCurve( m_CrvSmplS[ nNextCrv]->Clone()) ;
int nCrvNmbr = GetCurveCount() ;
int nFlagDel = DeletedCurve::NONE ;
if ( ! ModifyJoint( nU, ptNewJoint, &nFlagDel))
return false ;
bool bErasedSomeCrv = nCrvCount > GetCurveCount() ;
bool bErasedPrev = ( nFlagDel == DeletedCurve::PREV) ;
bool bErasedNext = ( nFlagDel == DeletedCurve::NEXT) ;
if ( ( bErasedPrev && nNextCrv == -1) || ( bErasedNext && nPrevCrv == -1)) {
// se sono su un estremo di una curva aperta e ho cancellato la sottocurva di estremità devo verificare che fosse più piccola della tolleranza
if ( bErasedPrev && nNextCrv == -1) {
Point3d ptOrigEnd ; pOrigCrv->GetEndPoint( ptOrigEnd) ;
Point3d ptNewEnd ; GetEndPoint( ptNewEnd) ;
if ( Dist( ptOrigEnd, ptNewEnd) > dTol)
m_CrvSmplS.push_back( Release( pOrigCrv)) ;
return true ;
}
if ( bErasedNext && nPrevCrv == -1) {
Point3d ptOrigStart ; pOrigCrv->GetStartPoint( ptOrigStart) ;
Point3d ptNewStart ; GetStartPoint( ptNewStart) ;
if ( Dist( ptOrigStart, ptNewStart) > dTol)
m_CrvSmplS.insert( m_CrvSmplS.begin(), Release( pOrigCrv)) ;
return true ;
}
}
double dStart ;
double dEnd ;
if ( bErasedPrev) {
dStart = nU ;
dEnd = nNextCrv + 1 ;
}
else if ( bErasedNext) {
dStart = nPrevCrv ;
dEnd = nU ;
if ( nU == 0)
dStart -= 1 ;
}
else { // ! bErasedSomeCrv
dStart = ( nPrevCrv != -1 ? nPrevCrv : 0) ;
dEnd = ( nNextCrv != -1 ? nNextCrv + 1 : nCrvNmbr) ;
}
PtrOwner<ICurve> pNewCurve( CopyParamRange( dStart, dEnd)) ;
double dErr = 0 ;
if ( ! CalcApproxError( pOrigCrv, pNewCurve, dErr, 6) || dErr > dTol) {
// se ho fallito il check o la variazione è superiore alla tolleranza richiesta, ripristino le curve originali
if ( ! bErasedSomeCrv) {
if ( nNextCrv != -1) {
delete m_CrvSmplS[nNextCrv] ;
m_CrvSmplS[nNextCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
}
if ( nPrevCrv != -1) {
delete m_CrvSmplS[nPrevCrv] ;
m_CrvSmplS[nPrevCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
}
}
else {
if ( bErasedNext) {
int nPos = nU == 0 ? nPrevCrv - 1 : nU ;
delete m_CrvSmplS[nPos] ;
if ( nU == 0) {
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( false) ;
nPos = 0 ;
}
else
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
}
else {
int nPos = nU == 0 ? nU : nPrevCrv ;
delete m_CrvSmplS[nPos] ;
if ( nU == 0) {
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
nPos = nCrvNmbr - 1 ;
}
else
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
{
// verifico lo stato
if ( m_nStatus != OK)
@@ -1970,6 +2090,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
// verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount)
return false ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::NONE ;
// recupero l'indice e il puntatore alla curva precedente (se esiste)
int nPrevCrv = -1 ;
if ( nU > 0)
@@ -1998,6 +2120,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
delete pPrevCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::PREV ;
}
// altrimenti diventa un segmento di retta
else {
@@ -2017,6 +2141,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
delete pNextCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::NEXT ;
}
// altrimenti diventa un segmento di retta
else {
@@ -3851,3 +3977,49 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
ptStart = m_ptStart ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurveToAdd, double dTolStartEnd, double dTolAlong)
{
// prendo il possesso e verifico la curva
PtrOwner<ICurve> pNewCurve( pNewCurveToAdd) ;
if ( IsNull( pNewCurve) || ! pNewCurve->IsValid())
return false ;
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico l'indice sia sensato
if ( nSubCrv < 0 || nSubCrv > GetCurveCount())
return false ;
// verifico che start e end coincidano entro la tolleranza
Point3d ptStart ; m_CrvSmplS[nSubCrv]->GetStartPoint( ptStart) ;
Point3d ptEnd ; m_CrvSmplS[nSubCrv]->GetEndPoint( ptEnd) ;
Point3d ptNewStart ; pNewCurve->GetStartPoint( ptNewStart) ;
Point3d ptNewEnd ; pNewCurve->GetEndPoint( ptNewEnd) ;
if ( ! AreSamePointApprox( ptStart, ptNewStart) || ! AreSamePointApprox( ptEnd, ptNewEnd)) {
// se i punti di inizio e fine non sono entro EPS_SMALL ma sono entro la tolleranza passata allora modifico la curva da aggiungere
if ( AreSamePointEpsilon( ptStart, ptNewStart, dTolStartEnd) && AreSamePointEpsilon( ptEnd, ptNewEnd, dTolStartEnd)) {
if ( ! pNewCurve->ModifyStart( ptStart) || ! pNewCurve->ModifyEnd( ptEnd))
return false ;
}
else
return false ;
}
// se presente una tolleranza lungo la curva controllo che sia rispettata
if ( dTolAlong < INFINITO) {
double dErr = 0 ;
CalcApproxError( m_CrvSmplS[nSubCrv], pNewCurve, dErr, 20) ;
if ( dErr > dTolAlong)
return false ;
}
delete m_CrvSmplS[nSubCrv] ;
m_CrvSmplS[nSubCrv] = Release( pNewCurve) ;
return true ;
}
+11 -4
View File
@@ -26,6 +26,9 @@ class Voronoi ;
//----------------------------------------------------------------------------
class CurveComposite : public ICurveComposite, public IGeoObjRW
{
public :
enum DeletedCurve { NONE = 0, PREV = 1, NEXT = 2 } ;
public : // IGeoObj
~CurveComposite( void) override ;
CurveComposite* Clone( void) const override ;
@@ -113,7 +116,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override ;
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
bool Invert( void) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
bool ModifyStart( const Point3d& ptNewStart) override ;
bool ModifyEnd( const Point3d& ptNewEnd) override ;
bool SetExtrusion( const Vector3d& vtExtr) override
@@ -156,7 +159,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddJoint( double dU) override ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override
{ return ModifyJoint( nU, ptNewJoint, nullptr) ; }
bool ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) override ; // verifico se le curve interessate sono in tolleranza con la versione prima della modifica
bool RemoveJoint( int nU) override ;
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ;
@@ -178,6 +183,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
bool GetOnlyPoint( Point3d& ptStart) const override ;
bool ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -198,19 +204,20 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
return *this ; }
bool RelocateFrom( CurveComposite& ccSrc) ;
bool GetApproxLength( double& dLen) const ;
bool TestClosure( double dLinTol = EPS_SMALL) ;
Voronoi* GetVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
bool CopyFrom( const CurveComposite& ccSrc) ;
bool Validate( void) ;
bool TestClosure( void) ;
bool AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ;
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ;
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
bool CalcVoronoiObject( void) const ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel) ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
+14 -10
View File
@@ -19,6 +19,7 @@
#include "GeoConst.h"
#include "/EgtDev/Include/EGkCurve.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
@@ -30,14 +31,14 @@ static const int TP_IS_VERT_LINE = 1 ;
static bool IsVerticalLine( const ICurve* pCrv, double* pdLenZ) ;
static bool VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType,
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
CurveComposite& ccAux) ;
static bool AddFirstLastVerticalLines( CurveComposite& ccOffs, double dLenVertFirst, double dLenVertLast) ;
static bool MediaInternalAngleDeltaZ( CurveComposite& ccOffs) ;
//----------------------------------------------------------------------------
bool
CurveComposite::SimpleOffsetXY( double dDist, int nType)
CurveComposite::SimpleOffsetXY( double dDist, int nType, double dMaxAngExt)
{
// creo una copia formata solo da rette e archi che giacciono nel piano XY (VtExtr è Z+)
CurveComposite ccCopy ;
@@ -98,7 +99,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType)
CurveComposite ccTemp ;
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrv2, ccTemp) ||
VerifyAndAdjustInternalAngle( pCrvPrev, pCrv2, ccTemp) ||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, ccTemp)) {
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, dMaxAngExt, ccTemp)) {
if ( ccTemp.GetCurveCount() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
return false ;
}
@@ -122,7 +123,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType)
CurveComposite ccTemp ;
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrvNext, ccTemp) ||
VerifyAndAdjustInternalAngle( pCrvPrev, pCrvNext, ccTemp) ||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, ccTemp)) {
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, dMaxAngExt, ccTemp)) {
int nCrvCount = ccTemp.GetCurveCount() ;
if ( nCrvCount > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
return false ;
@@ -174,7 +175,7 @@ bool
VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
{
// verifica dei puntatori
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
if ( pCrv1 == nullptr || pCrv2 == nullptr)
return false ;
// pulisco la curva ausiliaria
@@ -218,7 +219,7 @@ bool
VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
{
// verifica dei puntatori
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
if ( pCrv1 == nullptr || pCrv2 == nullptr)
return false ;
// pulisco la curva ausiliaria
@@ -259,11 +260,11 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAu
//----------------------------------------------------------------------------
bool
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType,
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
CurveComposite& ccAux)
{
// verifica dei puntatori
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
if ( pCrv1 == nullptr || pCrv2 == nullptr)
return false ;
// pulisco la curva ausiliaria
@@ -272,6 +273,9 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nT
// elimino dal tipo le parti estranee all'angolo esterno
nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ;
// porto il massimo angolo per tipo Extend in limiti accettabili (90° - 150°)
dMaxAngExt = Clamp( dMaxAngExt, ANG_RIGHT, 1.667 * ANG_RIGHT) ;
// calcolo direzioni tangenti sull'estremo in comune
Vector3d vtDir1, vtDir2 ;
if ( ! pCrv1->GetEndDir( vtDir1) || ! pCrv2->GetStartDir( vtDir2))
@@ -319,8 +323,8 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nT
( dDist > 0 && dAngDeg < 0)))
return false ;
// se l'angolo esterno supera il retto, offset extend diventa offset chamfer
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL)
// se l'angolo esterno supera il limite, offset extend diventa offset chamfer
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > dMaxAngExt + EPS_ANG_SMALL)
nType = ICurve::OFF_CHAMFER ;
// se angolo esterno molto piccolo, semplifico tutto
+1 -1
View File
@@ -577,7 +577,7 @@ CurveLine::Invert( void)
//----------------------------------------------------------------------------
bool
CurveLine::SimpleOffset( double dDist, int nType)
CurveLine::SimpleOffset( double dDist, int nType, double dMaxAngExt)
{
// verifico lo stato
if ( m_nStatus != OK)
+1 -1
View File
@@ -117,7 +117,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
bool Invert( void) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
bool ModifyStart( const Point3d& ptNewStart) override ;
bool ModifyEnd( const Point3d& ptNewEnd) override ;
bool SetExtrusion( const Vector3d& vtExtr) override
+15 -2
View File
@@ -116,6 +116,7 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
vtDiff = ptQ - ptP ;
// angolo tra vettore e tangente
dTemp = vtDer1 * vtDiff ;
bool bEquiverse = dTemp > 0 ;
if ( abs( dTemp) > EPS_ZERO)
dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ;
else
@@ -123,8 +124,20 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
// stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U))
dPrevPar = dPar ;
dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ;
if ( abs( dTemp) > EPS_ZERO)
dPar = dPrevPar - ( vtDer1 * vtDiff) / dTemp ;
// se il coseno tra questi due vettori è troppo grande potrei aver avuto una cattiva stima iniziale
// provo quindi ad aggiustare a mano, anziché usare il segno suggerito da newton, che con queste premesse potrebbe divergere
double dCos75 = 0.2588 ;
if ( abs( dTemp) > EPS_ZERO) {
double dDelta = ( vtDer1 * vtDiff) / dTemp ;
if ( dSqCosA > dCos75) {
if ( ( bEquiverse && dDelta > 0) || ( ! bEquiverse && dDelta < 0))
dDelta *= -1 ;
dPar = dPrevPar + dDelta ;
}
else
dPar = dPrevPar - dDelta ;
}
// clipping parametro
if ( dPar < approxMin.dParMin) {
if ( approxMin.bParMinSing && ! bClampedFromSing) {
+12 -1
View File
@@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
// distanza non calcolata
m_dDist = - 1 ;
if ( &CrvBez == nullptr || ! CrvBez.IsValid())
if ( ! CrvBez.IsValid())
return ;
// determino tolleranza di approssimazione in base a ingombro curva
@@ -42,6 +42,17 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
return ;
int nDeg = CrvBez.GetDegree() ;
if ( PL.GetPointNbr() < nDeg + 1) {
// costruisco una polilinea con un numero di curve scelto in base al grado della curva
PL.Clear() ;
for ( int i = 0 ; i <= nDeg + 1 ; ++i) {
double dU = double(i) / (nDeg + 1) ;
Point3d ptBez ;
CrvBez.GetPointD1D2( dU, ICurve::Side::FROM_MINUS, ptBez) ;
PL.AddUPoint( dU, ptBez) ;
}
}
// cerco la minima distanza per la polilinea
MDCVECTOR vApproxMin ;
if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin))
+5 -5
View File
@@ -211,13 +211,13 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
//----------------------------------------------------------------------------
bool
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide) const
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide, double dTol) const
{
if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size())
return false ;
// se distanza nulla, il punto giace sulla curva
if ( m_dDist <= EPS_SMALL) {
if ( m_dDist <= dTol) {
nSide = MDS_ON ;
return true ;
}
@@ -259,7 +259,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
// determino il lato di giacitura del punto
double dSide = vtRef * ( m_ptP - ptQ) ;
if ( abs( dSide) < EPS_SMALL)
if ( abs( dSide) < dTol)
nSide = MDS_ON ;
else if ( dSide > 0)
nSide = MDS_LEFT ;
@@ -270,7 +270,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
//----------------------------------------------------------------------------
bool
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide) const
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide, double dTol) const
{
if ( m_dDist < 0 || m_Info.empty())
return false ;
@@ -286,7 +286,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
}
}
// mi sono ricondotto al caso precedente
return GetSideAtMinDistPoint( nInd, vtN, nSide) ;
return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ;
}
//----------------------------------------------------------------------------
+120
View File
@@ -0,0 +1,120 @@
//----------------------------------------------------------------------------
// EgalTech 2025
//----------------------------------------------------------------------------
// File : DistPointSurfBz.cpp Data : 29.10.25 Versione : 2.7j3
// Contenuto : Implementazione della classe distanza Punto da superficie Bezier.
//
//
//
// Modifiche : 29.10.25 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "/EgtDev/Include/EGkDistPointTria.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
using namespace std ;
//----------------------------------------------------------------------------
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
: m_dDist( -1), m_bIsInside( false), m_bIsSurfClosed( false)
{
// Bezier non valida
if ( ! pSrfBz.IsValid())
return ;
// Calcolo la distanza
Calculate( ptP, pSrfBz) ;
}
//----------------------------------------------------------------------------
void
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
{
// Inizializzo distanza non calcolata
m_dDist = -1 ;
// Controllo se la superficie è chiusa
m_bIsSurfClosed = srfBz.IsClosed() ;
// Lavoro con l'oggetto superficie trimesh di base
const ISurfTriMesh* pStmRef = srfBz.GetAuxSurfRefined() ;
if ( pStmRef == nullptr)
return ;
DistPointSurfTm dpst( ptP, *pStmRef) ;
// recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo
Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ;
int nT ; dpst.GetMinDistTriaIndex( nT) ;
// salvo il punto corrispondente nel parametrico
srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ;
// salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto
srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ;
// salvo la distanza minima
m_dDist = Dist( ptP, m_ptMinDistPoint) ;
// se il punto è sulla superficie
if ( m_dDist < EPS_SMALL) {
m_bIsInside = false ;
return ;
}
else {
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * m_vtN < - EPS_SMALL) ;
return ;
}
}
//----------------------------------------------------------------------------
bool
DistPointSurfBz::GetDist( double& dDist) const
{
// Distanza non valida
if ( m_dDist < -EPS_ZERO)
return false ;
// Distanza valida
dDist = m_dDist ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
{
// Distanza non valida
if ( m_dDist < -EPS_ZERO)
return false ;
// Distanza valida
ptMinDistPoint = m_ptMinDistPoint ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfBz::GetParamsAtMinDistPoint( double& dU, double& dV) const
{
// Distanza non valida
if ( m_dDist < -EPS_ZERO)
return false ;
// Distanza valida
dU = m_ptParam.x ;
dV = m_ptParam.y ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointSurfBz::GetNorm( Vector3d& vtN) const
{
// Distanza non valida
if ( m_dDist < -EPS_ZERO)
return false ;
// Distanza valida
vtN = m_vtN ;
return true ;
}
+2 -2
View File
@@ -194,11 +194,11 @@ GetDefaultFont( void)
}
//-----------------------------------------------------------------------------
static pfProcEvents s_pFunProcEvents = nullptr ;
static psfProcEvents s_pFunProcEvents = nullptr ;
//-----------------------------------------------------------------------------
bool
SetEGkProcessEvents( pfProcEvents pFun)
SetEGkProcessEvents( psfProcEvents pFun)
{
s_pFunProcEvents = pFun ;
return ( pFun != nullptr) ;
BIN
View File
Binary file not shown.
+12 -5
View File
@@ -116,8 +116,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>false</EnablePREfast>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>C:\EgtDev\Extern\abseil\Include</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -152,7 +151,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
</ClCompile>
<Link>
@@ -200,7 +199,7 @@ copy $(TargetPath) \EgtProg\DllD64</Command>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -246,7 +245,7 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
<IntelJCCErratum>true</IntelJCCErratum>
</ClCompile>
@@ -282,8 +281,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="BBox3d.cpp" />
<ClCompile Include="BiArcs.cpp" />
<ClCompile Include="CalcPocketing.cpp" />
<ClCompile Include="CalcDerivate.cpp" />
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
<ClCompile Include="CAvSurfFrMove.cpp" />
<ClCompile Include="CAvToolSurfTm.cpp" />
<ClCompile Include="CAvToolTriangle.cpp" />
<ClCompile Include="CDeBoxClosedSurfTm.cpp" />
@@ -311,7 +312,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="CurveByApprox.cpp" />
<ClCompile Include="CurveByInterp.cpp" />
<ClCompile Include="CurveCompositeOffset.cpp" />
<ClCompile Include="DistPointSurfBz.cpp" />
<ClCompile Include="DistPointSurfFr.cpp" />
<ClCompile Include="IntersCurvePlane.cpp" />
<ClCompile Include="IntersCurveSurfTm.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
@@ -321,6 +324,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="Trimming.cpp" />
<ClCompile Include="MultiGeomDB.cpp" />
<ClCompile Include="SurfTriMeshOffset.cpp" />
<ClCompile Include="VolZmapOffset.cpp" />
<ClCompile Include="PolygonElevation.cpp" />
@@ -341,6 +346,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
<ClInclude Include="..\Include\EGkMultiGeomDB.h" />
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
<ClInclude Include="..\Include\EGkQuaternion.h" />
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
@@ -348,6 +354,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
<ClInclude Include="CAvSilhouetteSurfTm.h" />
<ClInclude Include="CAvSurfFrMove.h" />
<ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" />
<ClInclude Include="CDeConeFrustumTria.h" />
+30
View File
@@ -55,6 +55,9 @@
<Filter Include="File di origine\GeoCollisionDetection">
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoStriping">
<UniqueIdentifier>{54901321-08f6-4428-80c7-a1f859136a32}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Vector3d.cpp">
@@ -552,6 +555,27 @@
<ClCompile Include="SurfTriMeshOffset.cpp">
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
<ClCompile Include="MultiGeomDB.cpp">
<Filter>File di origine\Gdb</Filter>
</ClCompile>
<ClCompile Include="DistPointSurfBz.cpp">
<Filter>File di origine\GeoDist</Filter>
</ClCompile>
<ClCompile Include="IntersCurvePlane.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter>
</ClCompile>
<ClCompile Include="CalcDerivate.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="CAvSurfFrMove.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -1235,6 +1259,12 @@
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkMultiGeomDB.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="CAvSurfFrMove.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+1 -1
View File
@@ -1087,7 +1087,7 @@ ExtDimension::Update( void) const
if ( m_nType == DT_RADIAL)
sVal = "R " + sVal ;
else if ( m_nType == DT_DIAMETRAL)
sVal = u8"\u00D8 " + sVal ;
sVal = reinterpret_cast<const char *>( u8"\u00D8") + sVal ;
ReplaceString( m_sCalcText, IS_MEASURE, sVal) ;
}
// punto di inserimento del testo
+14
View File
@@ -101,6 +101,20 @@ GdbObj::CopyFrom( const GdbObj* pSou)
return ( CopyAttribsFrom( pSou) && CopyTextureDataFrom( pSou) && CopyUserObjFrom( pSou)) ;
}
//----------------------------------------------------------------------------
bool
GdbObj::CopyStippleDataFrom( const GdbObj* pSou)
{
// se l'oggetto sorgente non esiste
if ( pSou == nullptr)
return false ;
// copio stipple
m_nStpFactor = pSou->m_nStpFactor ;
m_nStpPattern = pSou->m_nStpPattern ;
return true ;
}
//----------------------------------------------------------------------------
bool
GdbObj::CopyAttribsFrom( const GdbObj* pSou)
+1
View File
@@ -57,6 +57,7 @@ class GdbObj
GdbObj( void) ;
bool CopyFrom( const GdbObj* pSou) ;
bool CopyAttribsFrom( const GdbObj* pSou) ;
bool CopyStippleDataFrom( const GdbObj* pSou) ;
bool CopyTextureDataFrom( const GdbObj* pSou) ;
bool CopyUserObjFrom( const GdbObj* pSou) ;
+35 -35
View File
@@ -28,41 +28,6 @@
#define GEOOBJ_NGEIDTOTYPE( nNgeId) GeoObjFactory::NgeIdToType( nNgeId)
#define GEOOBJ_CREATE( nKey) GeoObjFactory::Create( nKey)
//----------------------------------------------------------------------------
template <class T>
class GeoObjRegister
{
public :
static bool DoRegister( int nKey, int nNgeId)
{ if ( ! GeoObjFactory::Register( nKey, NgeAscKeyW[nNgeId], nNgeId, Create))
return false ;
GetTypePrivate() = nKey ;
GetKeyPrivate() = NgeAscKeyW[nNgeId] ;
GetNgeIdPrivate() = nNgeId ;
return true ; }
static IGeoObj* Create( void)
{ return new( std::nothrow) T ; }
static int GetType( void)
{ return GetTypePrivate() ; }
static const std::string& GetKey( void)
{ return GetKeyPrivate() ; }
static int GetNgeId( void)
{ return GetNgeIdPrivate() ; }
private :
GeoObjRegister( void) {}
~GeoObjRegister( void) {}
static int& GetTypePrivate( void)
{ static int s_nType ;
return s_nType ; }
static std::string& GetKeyPrivate( void)
{ static std::string s_sKey ;
return s_sKey ; }
static int& GetNgeIdPrivate( void)
{ static int s_nNgeId ;
return s_nNgeId ; }
} ;
//----------------------------------------------------------------------------
class GeoObjFactory
{
@@ -117,3 +82,38 @@ class GeoObjFactory
{ static CreatorMap s_CreatorMap ;
return s_CreatorMap ; }
} ;
//----------------------------------------------------------------------------
template <class T>
class GeoObjRegister
{
public :
static bool DoRegister( int nKey, int nNgeId)
{ if ( ! GeoObjFactory::Register( nKey, NgeAscKeyW[nNgeId], nNgeId, Create))
return false ;
GetTypePrivate() = nKey ;
GetKeyPrivate() = NgeAscKeyW[nNgeId] ;
GetNgeIdPrivate() = nNgeId ;
return true ; }
static IGeoObj* Create( void)
{ return new( std::nothrow) T ; }
static int GetType( void)
{ return GetTypePrivate() ; }
static const std::string& GetKey( void)
{ return GetKeyPrivate() ; }
static int GetNgeId( void)
{ return GetNgeIdPrivate() ; }
private :
GeoObjRegister( void) {}
~GeoObjRegister( void) {}
static int& GetTypePrivate( void)
{ static int s_nType ;
return s_nType ; }
static std::string& GetKeyPrivate( void)
{ static std::string s_sKey ;
return s_sKey ; }
static int& GetNgeIdPrivate( void)
{ static int s_nNgeId ;
return s_nNgeId ; }
} ;
+9 -7
View File
@@ -38,20 +38,22 @@ using namespace std ;
class LockAddErase
{
public :
LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
LockAddErase( atomic_flag& bAddEraseOn, bool bUse = true)
: m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
{ if ( ! m_bUse) return ;
while ( m_bAddEraseOn.test_and_set()) {
this_thread::sleep_for( chrono::nanoseconds{ 1}) ;
while ( m_bAddEraseOn.test_and_set( memory_order_acquire)) {
m_bAddEraseOn.wait( true, memory_order_relaxed) ;
}
} ;
~LockAddErase( void)
{ if ( ! m_bUse) return ;
m_bAddEraseOn.clear() ;
m_bAddEraseOn.clear( memory_order_release) ;
m_bAddEraseOn.notify_one() ;
} ;
private :
std::atomic_flag& m_bAddEraseOn ;
atomic_flag& m_bAddEraseOn ;
bool m_bUse ;
} ;
@@ -611,7 +613,7 @@ GeomDB::GetGdbObj( int nId) const
// radice
else if ( nId == GDB_ID_ROOT)
return &m_GrpRadix ;
// un nodo qualubque
// un nodo qualunque
else
return m_IdManager.FindObj( nId) ;
}
@@ -658,7 +660,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLo
return false ;
}
// inserisco come figlio, in testa alla lista del padre
else if ( nSonBeforeAfter == GDB_FIRST_SON){
else if ( nSonBeforeAfter == GDB_FIRST_SON) {
GdbGroup* pGroup = ::GetGdbGroup( pGRef) ;
if ( pGroup == nullptr)
return false ;
+4
View File
@@ -29,6 +29,10 @@ class GeomDB : public IGeomDB
friend class GdbObj ;
friend class GdbGroup ;
friend class GdbGeo ;
friend int CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ;
friend int CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ;
friend int DuplicateGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId) ;
friend int DuplicateGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, bool bSkipTemp) ;
public :
~GeomDB( void) override ;
+510 -137
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -43,6 +43,9 @@ class IntersCrvCompoCrvCompo
bool bAutoInters, bool bClosed, int nCurvesNbr) ;
bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ;
bool EraseOtherInfo( int& nIndCurr, int& nIndOther) ;
bool EraseBothInfo( int& nIndCurr, int& nIndOther) ;
bool CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ;
bool MergeNewOverlap( int i, bool bCrvAOrB) ;
private :
bool m_bOverlaps ;
+104 -18
View File
@@ -47,7 +47,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
// ciclo sulle curve per verificare se da approssimare
for ( int i = 0 ; i < 2 ; ++ i) {
// se curva è arco da approssimare oppure è curva di Bezier
// se curva è arco da approssimare oppure è curva di Bezier
if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) ||
m_pCurve[i]->GetType() == CRV_BEZIER) {
// approssimo con rette
@@ -127,7 +127,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve)
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
if ( pArc == nullptr)
return false ;
// verifico se non è nel piano XY o ha più di un giro al centro
// verifico se non è nel piano XY o ha più di un giro al centro
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
}
@@ -252,10 +252,10 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
bool
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
{
// se non ci sono intersezioni, non va fatto alcunché
// se non ci sono intersezioni, non va fatto alcunché
if ( m_Info.empty())
return true ;
// se le curve originali non sono state approssimate, non va fatto alcunché
// se le curve originali non sono state approssimate, non va fatto alcunché
if ( ! bAdjCrvA && ! bAdjCrvB)
return true ;
// procedo ad aggiustare
@@ -291,6 +291,24 @@ IntersCurveCurve::GetIntersCount( void)
return m_nIntersCount ;
}
//----------------------------------------------------------------------------
int
IntersCurveCurve::GetInters3DCount( void)
{
int nCount = 0 ;
for ( int i = 0 ; i < m_nIntersCount ; ++i) {
if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ;
}
else {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
++nCount ;
}
}
return nCount ;
}
//----------------------------------------------------------------------------
int
IntersCurveCurve::GetCrossIntersCount( void)
@@ -340,6 +358,30 @@ IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
{
if ( nInd < 0 || nInd >= GetInters3DCount())
return false ;
int nCount = - 1 ;
for ( int i = 0 ; i < m_nIntersCount ; ++i) {
if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ;
}
else {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
++nCount ;
}
if ( nCount == nInd) {
aInfo = m_Info[nInd] ;
return true ;
}
}
return false ;
}
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d& ptI)
@@ -347,11 +389,11 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
return false ;
// ricerca del punto più vicino tra le intersezioni singole
// ricerca del punto più vicino tra le intersezioni singole
bool bFound = false ;
double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// se è un'intersezione singola
// se è un'intersezione singola
if ( ! m_Info[i].bOverlap) {
// faccio la verifica sul punto
Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ;
@@ -416,7 +458,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
}
@@ -433,7 +475,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
}
@@ -498,7 +540,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dU2 = Info[j].IciA[1].dU ;
if ( dU2 < dU1 && pCurve->IsClosed())
dU2 += dEndPar ;
// se cade nell'intervallo è da saltare
// se cade nell'intervallo è da saltare
if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) {
bToSkip = true ;
break ;
@@ -517,7 +559,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dCurrPar = dStartPar ;
double dCurrLen = 0 ;
double dEndLen ; pCurve->GetLength( dEndLen) ;
// se è chiusa, recupero come finisce
// se è chiusa, recupero come finisce
if ( pCurve->IsClosed()) {
if ( ! InfoCorr[nNumInters-1].bOverlap)
nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ;
@@ -534,9 +576,25 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
}
}
// costruisco il vettore delle classificazioni
for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente
for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
/*int j = i < nNumInters - 1 ? i + 1 : -1 ;
if ( pCurve->IsClosed() && j == - 1)
j = 0 ;*/
int j = i == 0 ? -1 : i - 1 ;
if ( pCurve->IsClosed() && j == - 1)
j = nNumInters - 1 ;
bool bSpike = false ;
if ( j != -1) {
bSpike = InfoCorr[i].bOverlap && InfoCorr[j].bOverlap && InfoCorr[i].bCBOverEq != InfoCorr[j].bCBOverEq ;
if ( bSpike) {
bSpike = abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ;
}
}
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
@@ -557,7 +615,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
// altrimenti, salvo il tipo
else
nLastTy = InfoCorr[i].IciA[0].nNextTy ;
// se è definito un tratto in sovrapposizione
// se è definito un tratto in sovrapposizione
if ( InfoCorr[i].bOverlap) {
// assegno i dati
CrvClass segClass ;
@@ -568,7 +626,11 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
// salvo dati correnti
dCurrPar = InfoCorr[i].IciA[1].dU ;
dCurrLen = dLenU ;
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
// se sono in un caso di spike devo trattare l'overlap in modo diverso
if ( ! bSpike)
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
else
nLastTy = InfoCorr[i].IciA[0].nPrevTy ;
}
}
// eventuale tratto finale rimasto
@@ -597,7 +659,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
double dStartParB, dEndParB ;
if ( ! pCurveB->GetDomain( dStartParB, dEndParB))
return false ;
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
BBox3d boxCrvA, boxCrvB ;
if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
! pCurveB->GetLocalBBox( boxCrvB))
@@ -640,13 +702,37 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
IntersCurveCurve iCC( clLine, *pCurveB) ;
// dichiaro la classe della curva per default
int nClass = CRVC_OUT ;
// se c'è almeno una intersezione
// se c'è almeno una intersezione
if ( iCC.GetIntersCount() > 0) {
// se quanto precede la prima intersezione è interno, allora la curva è interna
// se quanto precede la prima intersezione è interno, allora la curva è interna
IntCrvCrvInfo aInfo ;
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nClass = CRVC_IN ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
nClass = CRVC_OUT ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_NULL) {
// se il primo punto scelto non va bene allora ne cerco uno che mi dia informazioni sull'essere interno o esterno
CurveLine clLine ;
Point3d ptNewChoice ; pCurveA->GetPointD1D2( 0.25, ICurve::FROM_MINUS, ptNewChoice) ;
if ( ! clLine.SetPDL( ptNewChoice, 0, dLen))
return false ;
// calcolo l'intersezione
IntersCurveCurve iCC( clLine, *pCurveB) ;
if ( iCC.GetIntersCount() > 0) {
// se quanto precede la prima intersezione è interno, allora la curva è interna
IntCrvCrvInfo aInfo ;
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nClass = CRVC_IN ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
nClass = CRVC_OUT ;
else
return false ; // se arrivo qui potrei ritentare la ricerca
}
else
return false ;
}
}
// altrimenti sono esterni tra loro
else {
@@ -670,7 +756,7 @@ IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
double dArea ;
if ( ! pCurve->GetAreaXY( dArea))
return false ;
nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ;
nClass = (( dArea >= 0) ? CRVC_OUT : CRVC_IN) ;
return true ;
}
+459
View File
@@ -0,0 +1,459 @@
//----------------------------------------------------------------------------
// EgalTech 2025
//----------------------------------------------------------------------------
// File : IntersCurvePlane.cpp Data : 07.11.25 Versione : 2.7k1
// Contenuto : Implementazione della classe intersezione curva-piano.
//
//
//
// Modifiche : 07.11.25 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "CurveLine.h"
#include "CurveComposite.h"
#include "IntersLineLine.h"
#include "IntersLineArc.h"
#include "IntersArcArc.h"
#include "IntersCrvCompoCrvCompo.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
using namespace std ;
//----------------------------------------------------------------------------
IntersCurvePlane::IntersCurvePlane( const ICurve& Curve, const Point3d& ptOrig, const Vector3d& vtN)
{
// Le intersezioni sono calcolate nel piano XY locale.
// Il flag bAreSegments vale solo per intersezione tra due linee e riguarda entrambe.
// inizializzazioni
m_nIntersCount = 0 ;
m_pCurve = &Curve ;
m_plPlane.Set( ptOrig, vtN) ;
// puntatore alla curva usata nei calcoli (originali o temporanee)
const ICurve* pCalcCrv ;
// per eventuale esplosione temporanea delle curve
PtrOwner<ICurve> pTmpCrv ;
// se curva è arco da approssimare oppure è curva di Bezier
if ( m_pCurve->GetType() == CRV_ARC || m_pCurve->GetType() == CRV_BEZIER || m_pCurve->GetType() == CRV_COMPO) {
// approssimo con rette
PolyLine PL ;
if ( ! m_pCurve->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return ;
pTmpCrv.Set( CreateBasicCurveComposite()) ;
if ( IsNull( pTmpCrv))
return ;
if ( ! GetBasicCurveComposite( pTmpCrv)->FromPolyLine( PL))
return ;
pCalcCrv = pTmpCrv ;
}
else
pCalcCrv = m_pCurve ;
m_Info.clear() ;
if ( pCalcCrv->GetType() == CRV_LINE) {
CalcIntersLinePlane( m_plPlane, *pCalcCrv) ;
}
else if ( pCalcCrv->GetType() == CRV_COMPO){
for ( int i = 0 ; i < GetBasicCurveComposite( pCalcCrv)->GetCurveCount(); ++i) {
const ICurve& subCurve = *GetBasicCurveComposite( pCalcCrv)->GetCurve( i) ;
CalcIntersLinePlane( m_plPlane, subCurve, i) ;
}
OrderAndCompleteIntersections() ;
}
// per curve approssimate, sistemo...
AdjustIntersParams( pCalcCrv != m_pCurve) ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Curve, int nCrv)
{
if ( Curve.GetType() != CRV_LINE)
return false ;
Point3d ptStart ; Curve.GetStartPoint( ptStart) ;
Point3d ptEnd ; Curve.GetEndPoint( ptEnd) ;
Point3d ptInt ;
double dLen = 0 ; Curve.GetLength( dLen) ;
int nIntersType = IntersLinePlane( ptStart, ptEnd, m_plPlane, ptInt, true) ;
// intersezione con attraversamento
if ( nIntersType == ILPT_YES) {
IntCrvPlnInfo icpi ;
icpi.Ici[0].ptI = ptInt ;
icpi.Ici[0].dU = Dist( ptInt, ptStart) / dLen + nCrv ;
Vector3d vtPos = ptStart - m_plPlane.GetPoint() ;
icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
icpi.Ici[0].nNextTy = icpi.Ici[0].nPrevTy == ICPT_IN ? ICPT_OUT : ICPT_IN ;
m_Info.push_back( icpi) ;
}
// intersezione con tocco
else if ( nIntersType == ILPT_START || nIntersType == ILPT_END) {
IntCrvPlnInfo icpi ;
icpi.Ici[0].ptI = ptInt ;
icpi.Ici[0].dU = nIntersType == ILPT_START ? 0 : 1 + nCrv ;
if ( nIntersType == ILPT_START) {
Vector3d vtPos = ptEnd - m_plPlane.GetPoint() ;
icpi.Ici[0].nNextTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
icpi.Ici[0].nPrevTy = ICPT_NULL ;
}
else {
Vector3d vtPos = ptStart - m_plPlane.GetPoint() ;
icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
icpi.Ici[0].nNextTy = ICPT_NULL ;
}
m_Info.push_back( icpi) ;
}
// intersezione con sovrapposizione
else if ( nIntersType == ILPT_INPLANE) {
IntCrvPlnInfo icpi ;
icpi.bOverlap = true ;
icpi.Ici[0].ptI = ptStart ;
icpi.Ici[0].dU = 0 + nCrv;
icpi.Ici[1].ptI = ptEnd ;
icpi.Ici[1].dU = 1 + nCrv ;
icpi.Ici[0].nPrevTy = ICPT_NULL ;
icpi.Ici[0].nNextTy = ICPT_ON ;
icpi.Ici[1].nPrevTy = ICPT_ON ;
icpi.Ici[1].nNextTy = ICPT_NULL ;
m_Info.push_back( icpi) ;
}
return true ;
}
//----------------------------------------------------------------------------
void
IntersCurvePlane::OrderAndCompleteIntersections()
{
// cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione
// riempio le info PrevTy e NexyTy
sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ;
for ( int curr = m_Info.size() - 1 ; curr > - 1 ; --curr) {
int prev = curr == 0 ? m_Info.size() - 1 : curr - 1 ;
int next = curr == m_Info.size() - 1 ? 0 : curr + 1 ;
bool bErasedCurr = false ;
// solo le intersezioni di sovrapposizione o puntuali sullo start o end delle curve possono avere il PrevTy o NextTy non definito
if ( ! m_Info[curr].bOverlap) {
if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) {
if ( ! m_Info[prev].bOverlap) {
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ;
// se ho due puntuali che coincidono cancello il successivo tra i due ( corrente)
if ( AreSamePointApprox( m_Info[curr].Ici[0].ptI, m_Info[prev].Ici[0].ptI)) {
m_Info.erase(m_Info.begin() + curr) ;
bErasedCurr = true ;
}
}
// se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello
else {
m_Info[prev].Ici[1].nNextTy = m_Info[curr].Ici[0].nNextTy ;
m_Info.erase(m_Info.begin() + curr) ;
bErasedCurr = true ;
}
}
if ( ! bErasedCurr && m_Info[curr].Ici[0].nNextTy == ICPT_NULL){
if ( ! m_Info[prev].bOverlap)
m_Info[curr].Ici[0].nNextTy = m_Info[next].Ici[0].nPrevTy ;
// se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello
else {
m_Info[next].Ici[0].nPrevTy = m_Info[curr].Ici[0].nPrevTy ;
m_Info.erase(m_Info.begin() + curr) ;
}
}
}
else {
if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) {
if ( ! m_Info[prev].bOverlap)
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ;
else
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[1].nNextTy ;
}
if ( m_Info[curr].Ici[1].nNextTy == ICPT_NULL) {
if ( ! m_Info[next].bOverlap)
m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[0].nPrevTy ;
else
m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[1].nPrevTy ;
}
}
}
m_nIntersCount = m_Info.size() ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::IsArcToApprox( const ICurve& Curve)
{
// recupero l'arco
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
if ( pArc == nullptr)
return false ;
// verifico se non è nel piano XY o ha più di un giro al centro
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::AdjustIntersParams( bool bAdjCrv)
{
// se non ci sono intersezioni, non va fatto alcunché
if ( m_Info.empty())
return true ;
// se le curve originali non sono state approssimate, non va fatto alcunché
if ( ! bAdjCrv)
return true ;
// procedo ad aggiustare
for ( auto& aInfo : m_Info) {
// se curve originali approssimate, devo ricalcolare i parametri dei punti di intersezione
if ( bAdjCrv) {
if ( ! m_pCurve->GetParamAtPoint( aInfo.Ici[0].ptI, aInfo.Ici[0].dU, 10 * EPS_SMALL))
return false ;
if ( aInfo.bOverlap && ! m_pCurve->GetParamAtPoint( aInfo.Ici[1].ptI, aInfo.Ici[1].dU, 10 * EPS_SMALL))
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
int
IntersCurvePlane::GetIntersCount( void)
{
return m_nIntersCount ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::GetIntCrvPlnInfo( int nInd, IntCrvPlnInfo& aInfo)
{
if ( nInd < 0 || nInd >= m_nIntersCount)
return false ;
aInfo = m_Info[nInd] ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam)
{
if ( m_nIntersCount == 0)
return false ;
// ricerca del punto più vicino tra le intersezioni singole
bool bFound = false ;
double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// se è un'intersezione singola
if ( ! m_Info[i].bOverlap) {
// faccio la verifica sul punto
Point3d ptP = m_Info[i].Ici[0].ptI ;
double dSqDist = SqDist( ptNear, ptP) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
ptI = ptP ;
dParam = m_Info[i].Ici[0].dU ;
bFound = true ;
}
}
// altrimenti
else {
// recupero il tratto di sovrapposizione
double dUStartTrim, dUEndTrim ;
dUStartTrim = m_Info[i].Ici[0].dU ;
dUEndTrim = m_Info[i].Ici[1].dU ;
PtrOwner<ICurve> pCrv( m_pCurve->CopyParamRange( dUStartTrim, dUEndTrim)) ;
if ( IsNull( pCrv))
continue ;
// cerco il punto
int nFlag ;
Point3d ptP ;
if ( DistPointCurve( ptNear, *pCrv).GetMinDistPoint( 0.5, ptP, nFlag)) {
// faccio la verifica
double dSqDist = SqDist( ptNear, ptP) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
ptI = ptP ;
m_pCurve->GetParamAtPoint( ptP, dParam) ;
bFound = true ;
}
}
}
}
return bFound ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::GetCurveClassification( double dLenMin, CRVPLNCVECTOR& ccClass)
{
// pulisco vettore classificazioni
ccClass.clear() ;
// verifico definizione della curva
if ( m_pCurve == nullptr)
return false ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve, m_Info, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve, ccClass) ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::CalcCurveClassification( const ICurve* pCurve, const ICPIVECTOR& Info, double dLenMin, CRVPLNCVECTOR& ccClass)
{
// numero intersezioni
int nNumInters = int( Info.size()) ;
if ( nNumInters < 1)
return false ;
// recupero il dominio parametrico della curva in esame
double dStartPar, dEndPar ;
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
return false ;
// limito lunghezza minima
dLenMin = max( dLenMin, EPS_ZERO) ;
// elimino intersezioni senza attraversamento che giacciono in intervalli di sovrapposizione
ICPIVECTOR InfoCorr ;
InfoCorr.reserve( Info.size()) ;
for ( size_t i = 0 ; i < Info.size() ; ++ i) {
// se intersezione puntuale senza attraversamento
if ( ! Info[i].bOverlap && Info[i].Ici[0].nPrevTy == Info[i].Ici[0].nNextTy) {
// confronto con le intersezioni con sovrapposizione
bool bToSkip = false ;
for ( size_t j = 0 ; j < Info.size() ; ++ j) {
// se coincide o puntuale
if ( j == i || ! Info[j].bOverlap)
continue ;
// determino l'intervallo parametrico tenendo conto di eventuale avvolgimento attorno all'inizio
double dU1 = Info[j].Ici[0].dU ;
double dU2 = Info[j].Ici[1].dU ;
if ( dU2 < dU1 && pCurve->IsClosed())
dU2 += dEndPar ;
// se cade nell'intervallo è da saltare
if ( Info[i].Ici[0].dU >= dU1 && Info[i].Ici[0].dU <= dU2) {
bToSkip = true ;
break ;
}
}
if ( bToSkip)
continue ;
}
// salvo dati intersezione
InfoCorr.emplace_back( Info[i]) ;
}
// aggiorno numero di intersezioni da considerare
nNumInters = int( InfoCorr.size()) ;
// recupero la classificazione all'inizio della curva
int nLastTy = ICCT_NULL ;
double dCurrPar = dStartPar ;
double dCurrLen = 0 ;
double dEndLen ; pCurve->GetLength( dEndLen) ;
// se è chiusa, recupero come finisce
if ( pCurve->IsClosed()) {
if ( ! InfoCorr[nNumInters-1].bOverlap)
nLastTy = InfoCorr[nNumInters-1].Ici[0].nNextTy ;
else {
nLastTy = InfoCorr[nNumInters-1].Ici[1].nNextTy ;
// se attraversa il punto di giunzione (parametro di fine minore di quello di inizio)
if ( InfoCorr[nNumInters-1].Ici[1].dU < InfoCorr[nNumInters-1].Ici[0].dU) {
dCurrPar = InfoCorr[nNumInters-1].Ici[1].dU ;
double dTmpLen ; pCurve->GetLengthAtParam( dCurrPar, dTmpLen) ;
dCurrLen = dTmpLen - dEndLen ;
dEndPar = dCurrPar ;
dEndLen = dTmpLen ;
}
}
}
// costruisco il vettore delle classificazioni
for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].Ici[0].dU, dLenU) ;
if ( InfoCorr[i].Ici[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].Ici[0].nPrevTy ;
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
nPrevTy == ICCT_NULL || nPrevTy == ICCT_ON)
return false ;
// assegno i dati
CrvPlaneClass segClass ;
segClass.dParS = dCurrPar ;
segClass.dParE = InfoCorr[i].Ici[0].dU ;
segClass.nClass = (( nPrevTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
ccClass.push_back( segClass) ;
// salvo dati correnti
dCurrPar = InfoCorr[i].Ici[0].dU ;
dCurrLen = dLenU ;
nLastTy = InfoCorr[i].Ici[0].nNextTy ;
}
// altrimenti, salvo il tipo
else
nLastTy = InfoCorr[i].Ici[0].nNextTy ;
// se è definito un tratto in sovrapposizione
if ( InfoCorr[i].bOverlap) {
// assegno i dati
CrvPlaneClass segClass ;
segClass.dParS = dCurrPar ;
segClass.dParE = InfoCorr[i].Ici[1].dU ;
segClass.nClass = CRVPLN_ON ;
ccClass.push_back( segClass) ;
// salvo dati correnti
dCurrPar = InfoCorr[i].Ici[1].dU ;
dCurrLen = dLenU ;
nLastTy = InfoCorr[i].Ici[1].nNextTy ;
}
}
// eventuale tratto finale rimasto
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia valida
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
return false ;
// assegno i dati
CrvPlaneClass segClass ;
segClass.dParS = dCurrPar ;
segClass.dParE = dEndPar ;
segClass.nClass = (( nLastTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
ccClass.push_back( segClass) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCurvePlane::CalcCurveInOrOut( const ICurve* pCurve, CRVPLNCVECTOR& ccClass)
{
// controllo di non avere intersezioni
int nNumInters = int( m_Info.size()) ;
if ( nNumInters > 0)
return false ;
// se non ho intersezioni tra curva e piano devo solo capire da che parte del piano sta la curva
CrvPlaneClass cpClass ;
double dStartPar, dEndPar ;
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
return false ;
Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
Vector3d vtCrv = ptStart - m_plPlane.GetPoint() ;
CrvPlaneClass segClass ;
segClass.dParS = dStartPar ;
segClass.dParE = dEndPar ;
segClass.nClass = ( (vtCrv * m_plPlane.GetVersN() < 0) ? CRVC_IN : CRVC_OUT) ;
ccClass.push_back( segClass) ;
return true ;
}
+17 -5
View File
@@ -113,7 +113,7 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
double dU1, dU2 ;
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
// Se non c'è intersezione
// Se non c'è intersezione
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
return true ;
@@ -144,8 +144,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
else if ( dU2 < EPS_SMALL)
vInters.emplace_back( ILBT_OUT, 0) ;
else {
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
if ( dU1 < - EPS_SMALL)
vInters.emplace_back( ILBT_TG_INSIDE, 0.) ;
else
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
if ( dU2 > dLen + EPS_SMALL)
vInters.emplace_back( ILBT_TG_INSIDE, dLen) ;
else
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
}
}
return true ;
@@ -162,8 +168,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
else if ( dU2 < EPS_SMALL)
vInters.emplace_back( ILBT_OUT, 0) ;
else {
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
if ( dU1 < - EPS_SMALL)
vInters.emplace_back( ILBT_INSIDE, 0.) ;
else
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
if ( dU2 > dLen + EPS_SMALL)
vInters.emplace_back( ILBT_INSIDE, dLen) ;
else
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
}
}
return true ;
+30
View File
@@ -159,6 +159,36 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
// flag per segmenti che si allontanano significativamente
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
// analisi casi speciali di quasi parallelismo
// segmento sovrapposto all'altro
double dDist1, dDist2 ;
if ( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) {
dDist1 = CrossXY( ptS1 - ptS2, vtDir2) ;
dDist2 = CrossXY( ptE1 - ptS2, vtDir2) ;
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) {
bParallel = true ;
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
}
}
else if ( nS2Side == 0 || nE2Side == 0 || nS2Side == nE2Side) {
dDist1 = CrossXY( ptS2 - ptS1, vtDir1) ;
dDist2 = CrossXY( ptE2 - ptS1, vtDir1) ;
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY) {
bParallel = true ;
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
}
}
// estremità sovrapposte di poco
if ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) {
if (( nS1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
( nS1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
( nE1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
( nE1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
bParallel = true ;
bFarEnds = false ;
}
}
// se non sono paralleli e si allontanano tra loro abbastanza
if ( ! bParallel && bFarEnds) {
// posizioni parametriche dell'intersezione sulle linee
+392 -55
View File
@@ -34,7 +34,6 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz)
{
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
// usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta
DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ;
double dDistNew = 0, dDistPre = 0 ;
@@ -48,18 +47,18 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
while ( dDistNew > EPS_SMALL && nCount < 100) {
dDistPre = dDistNew ;
Point3d ptIBzNew1 ;
pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
pSurfBz->GetPointD1D2( ( ptSP.x + dh), ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ;
dplNewU.GetDist( dDistNew) ;
double dfdU = ( dDistNew - dDistPre) / dh ;
Point3d ptIBzNew2 ;
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
pSurfBz->GetPointD1D2( ptSP.x, ( ptSP.y + dh), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ;
dplNewV.GetDist( dDistNew) ;
double dfdV = ( dDistNew - dDistPre) / dh ;
// mi avvicino cercando di annullare la distanza in un colpo solo
double dr = - dDistPre / ( dfdU + dfdV) ;
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU), ( ptSP.y + dr * dfdV), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ;
dplNew.GetDist( dDistNew) ;
++ nCount ;
@@ -73,14 +72,28 @@ static void
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
{
int nType = LSBT_NONE ;
if ( dCos > EPS_ZERO)
nType = LSBT_IN ;
else if ( dCos < EPS_ZERO)
nType = LSBT_OUT ;
else
nType = LSBT_TOUCH ;
if ( nILT == ILTA_IN || nILT == ILTA_EDGE || nILT == ILTA_VERT || nILT == ILTA_NO_TRIA) {
double dU = ( ptIBz - ptL) * vtDir ;
vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
vInfo.emplace_back( nType, dU, nT, dCos, ptIBz, ptSP) ;
}
else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) {
double dU = ( ptIBz - ptL) * vtDir ;
double dU2 = ( ptIBz2 - ptL) * vtDir ;
vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
int nType2 = LSBT_NONE ;
if ( dCos2 > EPS_ZERO)
nType2 = LSBT_IN ;
else if ( dCos2 < EPS_ZERO)
nType2 = LSBT_OUT ;
vInfo.emplace_back( nType, dU, 0, nT, dCos, ptIBz, P_INVALID, ptSP, P_INVALID) ;
vInfo.emplace_back( nType2, dU2, 0, nT, dCos2, ptIBz2, P_INVALID, ptSP2, P_INVALID) ;
}
}
@@ -94,9 +107,7 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
{ double dUa = ( ( a.nILTA == ILTA_SEGM || a.nILTA == ILTA_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
double dUb = ( ( b.nILTA == ILTA_SEGM || b.nILTA == ILTA_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
return ( dUa < dUb) ; }) ;
{ return ( a.dU < b.dU) ; }) ;
}
//----------------------------------------------------------------------------
@@ -143,12 +154,12 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
double dU0, dV0 ;
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
ptSP = ptSP + Point3d( dU0, dV0, 0) ;
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
return false ;
}
Vector3d vtN ;
pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
pSurfBz->GetPointNrmD1D2(ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
double dCos = vtN * vtL ;
double dCos2 = 0 ;
// eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione)
@@ -163,7 +174,7 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
return false ;
}
pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
pSurfBz->GetPointNrmD1D2( ptSP2.x, ptSP2.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
dCos2 = vtN * vtL ;
}
UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ;
@@ -182,19 +193,9 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
// ciclo sulle intersezioni
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTA == ILTA_VERT || Info.nILTA == ILTA_EDGE || Info.nILTA == ILTA_IN) {
int nFlag = LSBT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = LSBT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LSBT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTA == ILTA_SEGM || Info.nILTA == ILTA_SEGM_ON_EDGE) {
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
}
vInters.emplace_back( Info.nILSB, Info.dU) ;
// se intersezione sovrapposta
// da sviluppare
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
@@ -240,7 +241,343 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
}
//----------------------------------------------------------------------------
// Intersezione di una linea con una superficie di Bezier
// Intersezione di una linea con una superficie di Bezier di grado 3x1 monopatch
//----------------------------------------------------------------------------
bool
IntersLineSurfBzCubicLinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
ILSBIVECTOR& vInfo, bool bFinite)
{
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
// funzione pensata per funzionare solo con una monopatch di grado 3x1
if ( nDegU != 3 || nDegV != 1 || nSpanU > 1 || nSpanV > 1 || bRat)
return false ;
int nInters = int( vInfo.size()) ;
Point3d r = ptL ;
Vector3d q = vtL ;
bool bNeedToRotX = AreSameVectorApprox( q, X_AX) ;
bool bNeedToRotY = AreSameVectorApprox( q, Y_AX) ;
bool bNeedToRot = bNeedToRotX || bNeedToRotY ;
Frame3d frRot ;
if ( bNeedToRotX)
frRot.Set( ORIG, X_AX) ;
if ( bNeedToRotY)
frRot.Set( ORIG, Y_AX) ;
if ( bNeedToRot) {
r.ToLoc( frRot) ;
q.ToLoc( frRot) ;
}
PNTVECTOR vPntCtrl = pSurfBz->GetAllControlPoints() ;
if ( bNeedToRot) {
for ( Point3d& pt: vPntCtrl)
pt.ToLoc( frRot) ;
}
Vector3d A = vPntCtrl[4] - vPntCtrl[0] ;
Vector3d B = vPntCtrl[5] - vPntCtrl[1] ;
Vector3d C = vPntCtrl[6] - vPntCtrl[2] ;
Vector3d D = vPntCtrl[7] - vPntCtrl[3] ;
Vector3d E = vPntCtrl[0] - ORIG ;
Vector3d F = vPntCtrl[1] - ORIG ;
Vector3d G = vPntCtrl[2] - ORIG ;
Vector3d H = vPntCtrl[3] - ORIG ;
Vector3d a3 = -A + 3 * B - 3 * C + D ;
Vector3d a2 = 3 * A - 6 * B + 3 * C ;
Vector3d a1 = -3 * A + 3 * B ;
Vector3d a0 = A ;
Vector3d b3 = -E + 3 * F - 3 * G + H ;
Vector3d b2 = 3 * E - 6 * F + 3 * G ;
Vector3d b1 = -3 * E + 3 * F ;
Vector3d b0 = E ;
DBLVECTOR vdCoeff, vdRoots ;
// coefficienti dal grado più basso al grado più alto
vdCoeff = { // c0
q.x*q.z*a0.y*b0.z - q.x*q.y*a0.z*b0.z // 3
- r.z*q.x*q.z*a0.y + r.z*q.x*q.y*a0.z + // 3
q.y*q.z*a0.z*b0.z - q.z*q.z*a0.y*b0.x // 4
- r.x*q.y*q.z*a0.z + r.x*q.z*q.z*a0.y + // 4
q.z*q.z*a0.x*b0.y - q.y*q.z*a0.x*b0.z - q.x*q.z*a0.z*b0.y + q.x*q.y*a0.z*b0.z // 5
- r.y*q.z*q.z*a0.x + r.z*q.y*q.z*a0.x + r.y*q.x*q.z*a0.z - r.z*q.x*q.y*a0.z, // 5
// c1
q.x*q.z*(a1.y*b0.z + a0.y*b1.z) - q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 3
- r.z*q.x*q.z*a1.y + r.z*q.x*q.y*a1.z + // 3
q.y*q.z*(a1.z*b0.x + a0.z*b1.x) - q.z*q.z*(a1.y*b0.x + a0.y*b1.x) // 4
- r.x*q.y*q.z*a1.z + r.x*q.z*q.z*a1.y + // 4
q.z*q.z*(a1.x*b0.y + a0.x*b1.y) - q.y*q.z*(a1.x*b0.z + a0.x*b1.z) // 5
- q.x*q.z*(a1.z*b0.y + a0.z*b1.y) + q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 5
- r.y*q.z*q.z*a1.x + r.z*q.y*q.z*a1.x + r.y*q.x*q.z*a1.z - r.z*q.x*q.y*a1.z, // 5
// c2
q.x*q.z*(a2.y*b0.z + a1.y*b1.z + a0.y*b2.z) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z) // 3
- r.z*q.x*q.z*a2.y + r.z*q.x*q.y*a2.z + // 3
q.y*q.z*(a2.z*b0.x + a1.z*b1.x + a0.z*b2.x) - q.z*q.z*(a2.y*b0.x + a1.y*b1.x + a0.y*b2.x) // 4
- r.x*q.y*q.z*a2.z + r.x*q.z*q.z*a2.y + // 4
q.z*q.z*(a2.x*b0.y + a1.x*b1.y + a0.x*b2.y) - q.y*q.z*(a2.x*b0.z + a1.x*b1.z + a0.x*b2.z) // 5
- q.x*q.z*(a2.z*b0.y + a1.z*b1.y + a0.z*b2.y) + q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z)// 5
- r.y*q.z*q.z*a2.x + r.z*q.y*q.z*a2.x + r.y*q.x*q.z*a2.z - r.z*q.x*q.y*a2.z, // 5
// c3
q.x*q.z*(a3.y*b0.z + a2.y*b1.z + a1.y*b2.z + a0.y*b3.z) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z) // 3
- r.z*q.x*q.z*a3.y + r.z*q.x*q.y*a3.z + // 3
q.y*q.z*(a3.z*b0.x + a2.z*b1.x + a1.z*b2.x + a0.z*b3.x) - q.z*q.z*(a3.y*b0.x + a2.y*b1.x + a1.y*b2.x + a0.y*b3.x) // 4
- r.x*q.y*q.z*a3.z + r.x*q.z*q.z*a3.y + // 4
q.z*q.z*(a3.x*b0.y + a2.x*b1.y + a1.x*b2.y + a0.x*b3.y) - q.y*q.z*(a3.x*b0.z + a2.x*b1.z + a1.x*b2.z + a0.x*b3.z) // 5
- q.x*q.z*(a3.z*b0.y + a2.z*b1.y + a1.z*b2.y + a0.z*b3.y) + q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z)// 5
- r.y*q.z*q.z*a3.x + r.z*q.y*q.z*a3.x + r.y*q.x*q.z*a3.z - r.z*q.x*q.y*a3.z, // 5
// c4
q.x*q.z*(a3.y*b1.z + a2.y*b2.z + a1.y*b3.z) - q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z) + // 3
q.y*q.z*(a3.z*b1.x + a2.z*b2.x + a1.z*b3.x) - q.z*q.z*(a3.y*b1.x + a2.y*b2.x + a1.y*b3.x) + // 4
q.z*q.z*(a3.x*b1.y + a2.x*b2.y + a1.x*b3.y) - q.y*q.z*(a3.x*b1.z + a2.x*b2.z + a1.x*b3.z) // 5
- q.x*q.z*(a3.z*b1.y + a2.z*b2.y + a1.z*b3.y) + q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z), // 5
// c5
q.x*q.z*(a3.y*b2.z + a2.y*b3.z) - q.x*q.y*(a3.z*b2.z + a2.z*b3.z) + // 3
q.y*q.z*(a3.z*b2.x + a2.z*b3.x) - q.z*q.z*(a3.y*b2.x + a2.y*b3.x) + // 4
q.z*q.z*(a3.x*b2.y + a2.x*b3.y) - q.y*q.z*(a3.x*b2.z + a2.x*b3.z) // 5
- q.x*q.z*(a3.z*b2.y + a2.z*b3.y) + q.x*q.y*(a3.z*b2.z + a2.z*b3.z), // 5
// c6
q.x*q.z*a3.y*b3.z - q.x*q.y*a3.z*b3.z + // 3
q.y*q.z*a3.z*b3.x - q.z*q.z*a3.y*b3.x + // 4
q.z*q.z*a3.x*b3.y - q.y*q.z*a3.x*b3.z - q.x*q.z*a3.z*b3.y + q.x*q.y*a3.z*b3.z} ; // 5
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
bool bFound = false ;
for ( int w = 0 ; w < nRoots ; ++w) {
double dU = 0, dV = 0 ;
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
dU = vdRoots[w] ;
// verifico che non sia una soluzione con molteplicità > 1
bool bAlreadyFound = false ;
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
bAlreadyFound = ( abs( dU - vdRoots[k]) < EPS_PARAM) ;
if ( ! bAlreadyFound) {
Vector3d vAlpha = a3 * pow(dU, 3) + a2 * pow( dU, 2) + a1 * dU + a0 ;
Vector3d vBeta = b3 * pow(dU, 3) + b2 * pow( dU, 2) + b1 * dU + b0 ;
double dDen = ( vAlpha.x * q.z - vAlpha.z * q.x) ;
if ( abs( dDen) > EPS_ZERO)
dV = ( ( vBeta.z - r.z) * q.x - ( vBeta.x - r.x ) * q.z) / dDen ;
else {
// se la prima equazione risulta un x/0 allora uso la seconda equazione per trovare il secondo parametro
double dDen2 = ( vAlpha.y * q.z - vAlpha.z * q.y) ;
dV = ( ( vBeta.z - r.z) * q.y - ( vBeta.y - r.y ) * q.z) / dDen2 ;
}
if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) {
Point3d ptIBez, ptIBez2 ;
Vector3d vtN ;
pSurfBz->GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez, vtN) ;
Point3d ptSP( dU, dV, 0), ptSP2 ;
double dCos = vtN * vtL, dCos2 = 0 ;
int nType = ILTA_NO_TRIA ;
UpdateInfoIntersLineSurfBz( ptL, vtL, nType, -1, ptSP, ptIBez, dCos, ptSP2, ptIBez2, dCos2, vInfo) ;
bFound = true ;
}
}
}
}
//// se tutti i coefficienti sono zero allora potrei avere una linea che giace sulla superficie
//// per trovare i punti di inizio e fine sovrapposizione trovo i punti a minima distanza tra la linea e gli edge della superficie
//if ( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) {
// ICRVCOMPOPOVECTOR vCrvEdge( 4) ;
// vCrvEdge[0].Set(pSurfBz->GetCurveOnU( 0)) ;
// vCrvEdge[1].Set(pSurfBz->GetCurveOnV( 1)) ;
// vCrvEdge[2].Set(pSurfBz->GetCurveOnU( 1)) ;
// vCrvEdge[3].Set(pSurfBz->GetCurveOnV( 0)) ;
// double dAngTolDeg = 5 ;
// for ( int i = 0 ; i < 4 ; ++i) {
// PolyLine plApprox ; vCrvEdge[0]->ApproxWithLines( EPS_SMALL, dAngTolDeg, ICurve::ApprLineType::APL_STD, plApprox) ;
// //CurveComposite cCC ;
// //cCC.FromPolyLine( plApprox) ;
// int nClosestLine = -1 ;
// double dMinDist = INFINITO ;
// Point3d pt ; plApprox.GetFirstPoint( pt) ;
// Point3d ptClosest ;
// int c = 0 ;
// int nTot = plApprox.GetPointNbr() ;
// for ( int j = 0 ; j < nTot ; ++j) {
// DistPointLine dpl( pt, ptL, vtL, dLen, bFinite) ;
// double dDist = INFINITO ;
// dpl.GetDist( dDist) ;
// if ( dDist < dMinDist) {
// nClosestLine = c ;
// dMinDist = dDist ;
// }
// plApprox.GetNextPoint( pt) ;
// ++ c ;
// }
// Point3d ptInt1, ptInt2 ;
// if ( nClosestLine < nTot - 1 && nClosestLine > 0) {
// // tra i due tratti dell'approssimazione che arrivano al punto selezionato come più vicino, devo trovare quale si avvicina di più
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
// Point3d ptEnd ;
// for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
// plApprox.GetNextPoint( ptStart) ;
// plApprox.GetNextPoint( ptEnd) ;
// // linea precedente al punto
// Vector3d vtLinePre = ptEnd - ptStart ;
// double dLenPre = vtLinePre.Len() ;
// DistLineLine dllPre( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
// double dDistPre = INFINITO ;
// dllPre.GetDist( dDistPre) ;
// // linea che inzia con quel punto
// ptStart = ptEnd ;
// plApprox.GetNextPoint( ptEnd) ;
// Vector3d vtLineCurr = ptEnd - ptStart ;
// double dLenCurr = vtLineCurr.Len() ;
// DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
// double dDistCurr = INFINITO ;
// dllCurr.GetDist( dDistCurr) ;
// if ( dDistPre < dDistCurr)
// dllPre.GetMinDistPoints( ptInt1, ptInt2) ;
// else
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
// }
// else if ( nClosestLine == 0) {
// // il punto più vicino è sulla prima linea
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
// Point3d ptEnd ; plApprox.GetNextPoint( ptEnd) ;
// Vector3d vtLineCurr = ptEnd - ptStart ;
// double dLenCurr = vtLineCurr.Len() ;
// DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
// }
// else if ( nClosestLine == nTot- 1) {
// // il punto più vicino è sull'ultima linea
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
// Point3d ptEnd ;
// for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
// plApprox.GetNextPoint( ptStart) ;
// plApprox.GetNextPoint( ptEnd) ;
// Vector3d vtLinePre = ptEnd - ptStart ;
// double dLenPre = vtLinePre.Len() ;
// DistLineLine dllCurr( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
// }
//
// double dU1 = 0, dV1 = 0, dU2 = 0, dV2 = 0 ;
// // se ho trovato due punti vuol dire che la linea coincide con un edge e ho trovato tutto quello che serve
// if ( ! AreSamePointExact( ptInt2, ORIG)) {
// if ( i == 0) {
// //dV1 = 0 ; dV2 = 0 ;
// vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
// vCrvEdge[0]->GetParamAtPoint( ptInt2, dU2) ;
// }
// else if ( i == 1) {
// //dU1 = 1 ; dU2 = 1 ;
// vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
// vCrvEdge[1]->GetParamAtPoint( ptInt2, dV2) ;
// }
// else if ( i == 2){
// //dV1 = 1 ; dV2 = 1 ;
// vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
// vCrvEdge[2]->GetParamAtPoint( ptInt2, dU2) ;
// }
// else if ( i == 3){
// //dU1 = 0 ; dU2 = 0 ;
// vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
// vCrvEdge[3]->GetParamAtPoint( ptInt2, dV2) ;
// }
// Point3d ptIBez1, ptIBez2 ;
// Vector3d vtN1, vtN2 ;
// pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
// pSurfBz->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez2, vtN2) ;
// Point3d ptSP1( dU1, dV1, 0) ;
// double dCos1 = vtN1 * vtL ;
// Point3d ptSP2( dU2, dV2, 0) ;
// double dCos2 = vtN2 * vtL ;
// // se avevo già trovato un punto singolo che coincide col primo punto di questa intersezione sovrapposta, allora cancello l'intersezione singola che
// // avevo salvato e aggiungo quella sovrapposto che ho trovato ora
// if ( bFound) {
// int nNewTot = int(vInfo.size()) ;
// int nNewInters = nNewTot - nInters ;
// bool bAlreadyFound = false ;
// for ( int i = 0 ; i < nNewInters ; ++i) {
// bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) || AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP2) ;
// if ( bAlreadyFound) {
// vInfo.erase( vInfo.begin() + nNewTot - i) ;
// break ;
// }
// }
// }
// UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
// bFound = true ;
// break ;
// }
// // se ho trovato un punto a distanza zero dalla linea allora ho trovato l'intersezione
// else if ( dMinDist < EPS_SMALL) {
// if ( i == 0) {
// //dV1 = 0 ;
// vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
// }
// else if ( i == 1) {
// //dU1 = 1 ;
// vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
// }
// else if ( i == 2) {
// //dV1 = 1 ;
// vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
// }
// else if ( i == 3) {
// //dU1 = 0 ;
// vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
// }
// Point3d ptSP1( dU1, dV1, 0), ptSP2 ;
// // se avevo trovato già altri punti controllo di non essere esattamente su una diagonale ( e quindi avere un'intersezione con ogni edge, ma due sono doppie)
// if ( bFound) {
// int nNewTot = int(vInfo.size()) ;
// int nNewInters = nNewTot - nInters ;
// bool bAlreadyFound = false ;
// for ( int i = 0 ; i < nNewInters ; ++i)
// bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) ;
// if ( bAlreadyFound)
// continue ;
// }
// Point3d ptIBez1, ptIBez2 ;
// Vector3d vtN1, vtN2 ;
// pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
// double dCos1 = vtN1 * vtL, dCos2 = 0 ;
// UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
// bFound = true ;
// }
// }
//}
// se la superficie è trimmed verifico che i punti trovati siano all'interno del parametrico trimmato
if ( bTrimmed && bFound) {
int nNewTot = int(vInfo.size()) ;
int nNewInters = nNewTot - nInters ;
const ISurfFlatRegion* pFRTrim = pSurfBz->GetTrimRegion() ;
for ( int i = 0 ; i < nNewInters ; ++i) {
Point3d ptTest = vInfo[nNewTot - i].ptUV * SBZ_TREG_COEFF ;
bool bInside = false ;
double dDist = INFINITO ;
IsPointInsideSurfFr( ptTest, pFRTrim, dDist, bInside) ;
if ( ! bInside)
vInfo.erase( vInfo.begin() + nNewTot - i) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Intersezione di una linea con una superficie di Bezier bilineare monopatch
//----------------------------------------------------------------------------
bool
IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
@@ -251,13 +588,13 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
// funzione pensata per funzionare solo con una monopatch bilineare
if( nDegU > 1 || nDegV > 1 || nSpanU > 1 || nSpanV > 1 || bRat)
if ( nDegU > 1 || nDegV > 1 || nSpanU > 1 || nSpanV > 1 || bRat)
return false ;
int nInters = int( vInfo.size()) ;
PNTVECTOR vPntCtrl ;
for( int p = 0 ; p < 4 ; ++p) {
for ( int p = 0 ; p < 4 ; ++p) {
bool bOk = false ;
vPntCtrl.push_back( pSurfBz->GetControlPoint( p, &bOk)) ;
}
@@ -281,14 +618,14 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
vdCoeff = { (B2 * D1 - B1 * D2), ( A2 * D1 - A1 * D2 + B2 * C1 - B1 * C2), ( A2 * C1 - A1 * C2)} ;
int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ;
bool bFound = false ;
for( int w = 0 ; w < nRoots ; ++w) {
for ( int w = 0 ; w < nRoots ; ++w) {
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO ) {
double dU = 0, dV = vdRoots[w] ;
// verifico che non sia una soluzione con molteplicità > 1
bool bAlreadyFound = false ;
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
bAlreadyFound = abs( dV - vdRoots[k]) < EPS_PARAM ;
if( ! bAlreadyFound) {
if ( ! bAlreadyFound) {
dU = (dV * (C1 - C2) + ( D1 - D2)) / ( dV * ( A2 - A1) + ( B2 - B1)) ;
if ( dU > - EPS_ZERO && dU < 1 + EPS_ZERO) {
Point3d ptIBez, ptIBez2 ;
@@ -305,14 +642,14 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
// se tutti i coefficienti sono zero allora potrei avere una linea che giace sulla superficie
// per trovare i punti di inizio e fine sovrapposizione trovo i punti a minima distanza tra la linea e gli edge della superficie
if( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) {
if ( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) {
ICRVCOMPOPOVECTOR vCrvEdge( 4) ;
vCrvEdge[0].Set(pSurfBz->GetCurveOnU( 0)) ;
vCrvEdge[1].Set(pSurfBz->GetCurveOnV( 1)) ;
vCrvEdge[2].Set(pSurfBz->GetCurveOnU( 1)) ;
vCrvEdge[3].Set(pSurfBz->GetCurveOnV( 0)) ;
double dAngTolDeg = 5 ;
for( int i = 0 ; i < 4 ; ++i) {
for ( int i = 0 ; i < 4 ; ++i) {
PolyLine plApprox ; vCrvEdge[0]->ApproxWithLines( EPS_SMALL, dAngTolDeg, ICurve::ApprLineType::APL_STD, plApprox) ;
//CurveComposite cCC ;
//cCC.FromPolyLine( plApprox) ;
@@ -322,7 +659,7 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
Point3d ptClosest ;
int c = 0 ;
int nTot = plApprox.GetPointNbr() ;
for( int j = 0 ; j < nTot ; ++j) {
for ( int j = 0 ; j < nTot ; ++j) {
DistPointLine dpl( pt, ptL, vtL, dLen, bFinite) ;
double dDist = INFINITO ;
dpl.GetDist( dDist) ;
@@ -339,7 +676,7 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
// tra i due tratti dell'approssimazione che arrivano al punto selezionato come più vicino, devo trovare quale si avvicina di più
Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
Point3d ptEnd ;
for( int z = 1 ; z < nClosestLine - 1 ; ++z)
for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
plApprox.GetNextPoint( ptStart) ;
plApprox.GetNextPoint( ptEnd) ;
// linea precedente al punto
@@ -357,12 +694,12 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
double dDistCurr = INFINITO ;
dllCurr.GetDist( dDistCurr) ;
if( dDistPre < dDistCurr)
if ( dDistPre < dDistCurr)
dllPre.GetMinDistPoints( ptInt1, ptInt2) ;
else
dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
}
else if ( nClosestLine == 0){
else if ( nClosestLine == 0) {
// il punto più vicino è sulla prima linea
Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
Point3d ptEnd ; plApprox.GetNextPoint( ptEnd) ;
@@ -375,7 +712,7 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
// il punto più vicino è sull'ultima linea
Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
Point3d ptEnd ;
for( int z = 1 ; z < nClosestLine - 1 ; ++z)
for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
plApprox.GetNextPoint( ptStart) ;
plApprox.GetNextPoint( ptEnd) ;
Vector3d vtLinePre = ptEnd - ptStart ;
@@ -386,23 +723,23 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
double dU1 = 0, dV1 = 0, dU2 = 0, dV2 = 0 ;
// se ho trovato due punti vuol dire che la linea coincide con un edge e ho trovato tutto quello che serve
if( ! AreSamePointExact( ptInt2, ORIG)) {
if( i == 0) {
if ( ! AreSamePointExact( ptInt2, ORIG)) {
if ( i == 0) {
//dV1 = 0 ; dV2 = 0 ;
vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
vCrvEdge[0]->GetParamAtPoint( ptInt2, dU2) ;
}
else if( i == 1) {
else if ( i == 1) {
//dU1 = 1 ; dU2 = 1 ;
vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
vCrvEdge[1]->GetParamAtPoint( ptInt2, dV2) ;
}
else if( i == 2){
else if ( i == 2){
//dV1 = 1 ; dV2 = 1 ;
vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
vCrvEdge[2]->GetParamAtPoint( ptInt2, dU2) ;
}
else if( i == 3){
else if ( i == 3){
//dU1 = 0 ; dU2 = 0 ;
vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
vCrvEdge[3]->GetParamAtPoint( ptInt2, dV2) ;
@@ -417,11 +754,11 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
double dCos2 = vtN2 * vtL ;
// se avevo già trovato un punto singolo che coincide col primo punto di questa intersezione sovrapposta, allora cancello l'intersezione singola che
// avevo salvato e aggiungo quella sovrapposto che ho trovato ora
if( bFound) {
if ( bFound) {
int nNewTot = int(vInfo.size()) ;
int nNewInters = nNewTot - nInters ;
bool bAlreadyFound = false ;
for( int i = 0 ; i < nNewInters ; ++i) {
for ( int i = 0 ; i < nNewInters ; ++i) {
bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) || AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP2) ;
if ( bAlreadyFound) {
vInfo.erase( vInfo.begin() + nNewTot - i) ;
@@ -434,32 +771,32 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
break ;
}
// se ho trovato un punto a distanza zero dalla linea allora ho trovato l'intersezione
else if( dMinDist < EPS_SMALL) {
if( i == 0) {
else if ( dMinDist < EPS_SMALL) {
if ( i == 0) {
//dV1 = 0 ;
vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
}
else if( i == 1) {
else if ( i == 1) {
//dU1 = 1 ;
vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
}
else if( i == 2){
else if ( i == 2) {
//dV1 = 1 ;
vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
}
else if( i == 3){
else if ( i == 3) {
//dU1 = 0 ;
vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
}
Point3d ptSP1( dU1, dV1, 0), ptSP2 ;
// se avevo trovato già altri punti controllo di non essere esattamente su una diagonale ( e quindi avere un'intersezione con ogni edge, ma due sono doppie)
if( bFound) {
if ( bFound) {
int nNewTot = int(vInfo.size()) ;
int nNewInters = nNewTot - nInters ;
bool bAlreadyFound = false ;
for( int i = 0 ; i < nNewInters ; ++i)
for ( int i = 0 ; i < nNewInters ; ++i)
bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) ;
if( bAlreadyFound)
if ( bAlreadyFound)
continue ;
}
@@ -474,16 +811,16 @@ IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen,
}
// se la superficie è trimmed verifico che i punti trovati siano all'interno del parametrico trimmato
if( bTrimmed && bFound) {
if ( bTrimmed && bFound) {
int nNewTot = int(vInfo.size()) ;
int nNewInters = nNewTot - nInters ;
const ISurfFlatRegion* pFRTrim = pSurfBz->GetTrimRegion() ;
for( int i = 0 ; i < nNewInters ; ++i) {
for ( int i = 0 ; i < nNewInters ; ++i) {
Point3d ptTest = vInfo[nNewTot - i].ptUV * SBZ_TREG_COEFF ;
bool bInside = false ;
double dDist = INFINITO ;
IsPointInsideSurfFr( ptTest, pFRTrim, dDist, bInside) ;
if( ! bInside)
if ( ! bInside)
vInfo.erase( vInfo.begin() + nNewTot - i) ;
}
}
+1 -1
View File
@@ -1662,7 +1662,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
// Riordino le soluzioni
for ( int ni = 0 ; ni < int( vdPar.size()) - 1 ; ++ ni) {
for ( int nj = ni ; nj < int( vdPar.size()) ; ++ nj) {
if( vdPar[ni] > vdPar[nj]) {
if ( vdPar[ni] > vdPar[nj]) {
swap( vdPar[ni], vdPar[nj]) ;
}
}
+1 -4
View File
@@ -19,7 +19,7 @@
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di unpiano con la superficie di un solido VolZmap
// Intersezione di un piano con la superficie di un solido VolZmap
//----------------------------------------------------------------------------
bool
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
@@ -28,9 +28,6 @@ IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR&
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
if ( pVzm == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vpLoop == nullptr)
return false ;
// eseguo intersezione
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
+258
View File
@@ -0,0 +1,258 @@
//----------------------------------------------------------------------------
// EgalTech 2025-2025
//----------------------------------------------------------------------------
// File : MultiGeomDB.cpp Data : 08.10.25 Versione : 2.7j1
// Contenuto : Implementazione delle funzioni tra due GeomDB.
//
//
//
// Modifiche : 08.10.25 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeomDB.h"
#include "/EgtDev/Include/EGkMultiGeomDB.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
static int
CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
{
// recupero l'oggetto da copiare dal GeomDB sorgente
PtrOwner<IGeoObj> pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ;
if ( IsNull( pGObj))
return GDB_ID_NULL ;
// se in globale
if ( bGlob) {
// recupero il riferimento del sorgente
Frame3d frSou ;
if ( ! pSouGDB->GetGlobFrame( nSouId, frSou))
return GDB_ID_NULL ;
// recupero il riferimento del gruppo destinazione
Frame3d frDest ;
int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ;
if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest))
return GDB_ID_NULL ;
// porto la copia da riferimento sorgente a quello destinazione
pGObj->LocToLoc( frSou, frDest) ;
}
// lo inserisco nel GeomDB destinazione
int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, nSonBeforeAfter, Release( pGObj)) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio le caratteristiche non geometriche
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
pDstGDB->Erase( nNewId) ;
return GDB_ID_NULL ;
}
return nNewId ;
}
//----------------------------------------------------------------------------
static int
CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
{
// recupero il riferimento del gruppo
Frame3d frFrame = *( pSouGDB->GetGroupFrame( nSouId)) ;
// se in globale
if ( bGlob) {
// recupero il riferimento del gruppo in globale
if ( ! pSouGDB->GetGroupGlobFrame( nSouId, frFrame))
return GDB_ID_NULL ;
// recupero il riferimento del gruppo destinazione
Frame3d frDest ;
int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ;
if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest))
return GDB_ID_NULL ;
// porto la copia da riferimento sorgente a quello destinazione
frFrame.ToLoc( frDest) ;
}
// inserisco un nuovo gruppo nel GeomDB destinazione
int nNewId = pDstGDB->InsertGroup( nDestId, nRefId, nSonBeforeAfter, frFrame) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// copio le caratteristiche non geometriche
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
pDstGDB->Erase( nNewId) ;
return GDB_ID_NULL ;
}
// copio gli eventuali figli
int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ;
while ( nSonSouId != GDB_ID_NULL) {
// nuovo identificativo oggetto destinazione
int nSonNewId = GDB_ID_NULL ;
// recupero il tipo di oggetto sorgente
int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ;
// se l'oggetto da copiare è geometrico
if ( nSonSouType == GDB_TY_GEO)
nSonNewId = CopyGeoObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ;
// se altrimenti è un gruppo
else if ( nSonSouType == GDB_TY_GROUP)
nSonNewId = CopyGroupObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ;
// se copia non riuscita, esco con errore
if ( nSonNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// passo al figlio successivo
nSonSouId = pSouGDB->GetNext( nSonSouId) ;
}
return nNewId ;
}
//----------------------------------------------------------------------------
static int
Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
{
// adatto e verifico i GeomDB
const GeomDB* pSouGDB = static_cast<GeomDB*>( pSouGeomDB) ;
GeomDB* pDstGDB = static_cast<GeomDB*>( pDestGeomDB) ;
if ( pSouGDB == nullptr || pDstGDB == nullptr)
return GDB_ID_NULL ;
// il sorgente non può essere il gruppo radice
if ( nSouId == GDB_ID_ROOT)
return GDB_ID_NULL ;
// nuovo identificativo oggetto destinazione
int nNewId = GDB_ID_NULL ;
// recupero il tipo di oggetto sorgente
int nSouType = pSouGDB->GetGdbType( nSouId) ;
// se l'oggetto da copiare è geometrico
if ( nSouType == GDB_TY_GEO) {
nNewId = CopyGeoObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ;
}
// se altrimenti è un gruppo
else if ( nSouType == GDB_TY_GROUP) {
nNewId = CopyGroupObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ;
}
return nNewId ;
}
//----------------------------------------------------------------------------
int
Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter)
{
return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, false) ;
}
//----------------------------------------------------------------------------
int
CopyGlob( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter)
{
return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, true) ;
}
//----------------------------------------------------------------------------
static int
DuplicateGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId)
{
// recupero l'oggetto da copiare dal GeomDB sorgente
PtrOwner<IGeoObj> pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ;
if ( IsNull( pGObj))
return GDB_ID_NULL ;
// lo inserisco nel GeomDB destinazione
int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, GDB_LAST_SON, Release( pGObj)) ;
if ( nNewId != nDestId) {
pDstGDB->Erase( nNewId) ;
return GDB_ID_NULL ;
}
// copio le caratteristiche non geometriche
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
pDstGDB->Erase( nNewId) ;
return GDB_ID_NULL ;
}
return nNewId ;
}
//----------------------------------------------------------------------------
static int
DuplicateGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, bool bSkipTemp)
{
int nNewId = GDB_ID_ROOT ;
if ( nSouId != GDB_ID_ROOT) {
// recupero il riferimento del gruppo
Frame3d frFrame = *( pSouGDB->GetGroupFrame( nSouId)) ;
// inserisco un nuovo gruppo nel GeomDB destinazione
nNewId = pDstGDB->InsertGroup( nDestId, nRefId, GDB_LAST_SON, frFrame) ;
if ( nNewId != nSouId) {
pDstGDB->Erase( nNewId) ;
return GDB_ID_NULL ;
}
// copio le caratteristiche non geometriche
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
pDstGDB->Erase( nNewId) ;
return GDB_ID_NULL ;
}
}
// copio gli eventuali figli
int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ;
while ( nSonSouId != GDB_ID_NULL) {
// verifico se non richiesto di saltare i temporanei oppure non lo è
int nLevel ;
if ( ! bSkipTemp || ! pSouGDB->GetLevel( nSonSouId, nLevel) || nLevel != GDB_LV_TEMP) {
// nuovo identificativo oggetto destinazione
int nSonNewId = GDB_ID_NULL ;
// recupero il tipo di oggetto sorgente
int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ;
// se l'oggetto da copiare è geometrico
if ( nSonSouType == GDB_TY_GEO)
nSonNewId = DuplicateGeoObj( pSouGDB, nSonSouId, pDstGDB, nSonSouId, nNewId) ;
// se altrimenti è un gruppo
else if ( nSonSouType == GDB_TY_GROUP)
nSonNewId = DuplicateGroupObj( pSouGDB, nSonSouId, pDstGDB, nSonSouId, nNewId, bSkipTemp) ;
// se copia non riuscita, esco con errore
if ( nSonNewId != nSonSouId)
return GDB_ID_NULL ;
}
// passo al figlio successivo
nSonSouId = pSouGDB->GetNext( nSonSouId) ;
}
return nNewId ;
}
//----------------------------------------------------------------------------
bool
DuplicateGeomDB( IGeomDB* pSouGeomDB, IGeomDB* pDestGeomDB, bool bSkipTemp)
{
// adatto e verifico i GeomDB
const GeomDB* pSouGDB = static_cast<GeomDB*>( pSouGeomDB) ;
GeomDB* pDstGDB = static_cast<GeomDB*>( pDestGeomDB) ;
if ( pSouGDB == nullptr || pDstGDB == nullptr)
return false ;
// verifico che la destinazione sia vuota
if ( pDstGDB->GetFirstInGroup( GDB_ID_ROOT) != GDB_ID_NULL)
return false ;
// eseguo la copia di tutto (se richiesto salto gli oggetti temporanei)
return ( DuplicateGroupObj( pSouGDB, GDB_ID_ROOT, pDstGDB, GDB_ID_ROOT, GDB_ID_ROOT, bSkipTemp) != GDB_ID_NULL) ;
}
+63 -74
View File
@@ -17,6 +17,7 @@
#include "NgeKeyW.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtStringConverter.h"
#include "/EgtDev/Extern/zlib/Include/zlib.h"
using namespace std ;
@@ -34,8 +35,12 @@ NgeReader::Init( const string& sFileIn)
break ;
case NGE_BINARY :
m_bBinary = true ;
m_InFile.open( stringtoW( sFileIn), ios::in | ios::binary, _SH_DENYWR) ;
return ( ! m_InFile.fail()) ;
m_InFile = gzopen_w( stringtoW( sFileIn), "rb") ;
if ( m_InFile == nullptr)
return false ;
const int DIM_BUFFER = 65536 ;
gzbuffer( m_InFile, DIM_BUFFER) ;
return true ;
break ;
}
return false ;
@@ -46,10 +51,12 @@ bool
NgeReader::Close( void)
{
if ( m_bBinary) {
bool bOk = ( m_InFile.good() && m_InFile.is_open()) ;
if ( m_InFile.is_open())
m_InFile.close() ;
return bOk ;
if ( m_InFile != nullptr) {
bool bOk = ( gzclose( m_InFile) == Z_OK) ;
m_InFile = nullptr ;
return bOk ;
}
return true ;
}
else
return m_Scan.Terminate() ;
@@ -59,31 +66,24 @@ NgeReader::Close( void)
int
NgeReader::NgeType( const string& sFile)
{
// apertura del file di ingresso
ifstream InFile ;
InFile.open( stringtoW( sFile), ios::in | ios::binary) ;
if ( InFile.fail())
// apertura file
gzFile_s* InFile = gzopen_w( stringtoW( sFile), "rb") ;
if ( InFile == nullptr)
return NGE_ERROR ;
// lettura dei primi 31 byte
char cBuff[32] ;
InFile.read( cBuff, 31) ;
cBuff[InFile.gcount()] = '\0' ;
// chiusura del file
InFile.close() ;
// verifico se file compresso (gz)
if ( cBuff[0] == '\x1F' && cBuff[1] == '\x8B')
return NGE_ASCII ;
// verifico se iniziano con "START"
string sBuff = cBuff ;
size_t nPos = sBuff.find( "START") ;
if ( nPos != string::npos && nPos < 10)
return NGE_ASCII ;
else
// lettura dei primi caratteri
char szBuff[9] = "\0\0\0\0\0\0\0\0" ;
int nLen = gzread( InFile, &szBuff, 8) ;
if ( gzclose( InFile) != Z_OK || nLen == Z_ERRNO)
return NGE_ERROR ;
// se binario
if ( szBuff[0] == '\x0F' && szBuff[1] == '\x0F')
return NGE_BINARY ;
// se testo
string sBuff{ szBuff} ;
if ( sBuff.find( "START") != string::npos)
return NGE_ASCII ;
// altrimenti errore
return NGE_ERROR ;
}
//----------------------------------------------------------------------------
@@ -91,7 +91,7 @@ int
NgeReader::GetCurrPos( void)
{
if ( m_bBinary)
return int( m_InFile.tellg()) ;
return int( gztell( m_InFile)) ;
else
return m_Scan.GetCurrLineNbr() ;
}
@@ -131,10 +131,9 @@ bool
NgeReader::ReadUchar( unsigned char& ucVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &ucVal, sizeof( ucVal)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &ucVal, sizeof( ucVal)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -154,10 +153,9 @@ bool
NgeReader::ReadBool( bool& bVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &bVal, sizeof( bVal)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &bVal, sizeof( bVal)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -173,10 +171,9 @@ bool
NgeReader::ReadInt( int& nVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &nVal, sizeof( nVal)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &nVal, sizeof( nVal)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -203,10 +200,9 @@ bool
NgeReader::ReadDouble( double& dVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &dVal, sizeof( dVal)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &dVal, sizeof( dVal)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -222,10 +218,9 @@ bool
NgeReader::ReadVector( Vector3d& vtV, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &vtV.v, sizeof( vtV.v)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &vtV.v, sizeof( vtV.v)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -241,10 +236,9 @@ bool
NgeReader::ReadPoint( Point3d& ptP, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &ptP.v, sizeof( ptP.v)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &ptP.v, sizeof( ptP.v)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -260,11 +254,10 @@ bool
NgeReader::ReadPointW( Point3d& ptP, double& dW, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
m_InFile.read( (char*) &ptP.v, sizeof( ptP.v)) ;
m_InFile.read( (char*) &dW, sizeof( dW)) ;
return m_InFile.good() ;
return ( gzread( m_InFile, &ptP.v, sizeof( ptP.v)) != Z_ERRNO &&
gzread( m_InFile, &dW, sizeof( dW)) != Z_ERRNO) ;
}
else {
// recupero il token
@@ -280,17 +273,13 @@ bool
NgeReader::ReadFrame( Frame3d& frF, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
Point3d ptOrig ;
m_InFile.read( (char*) &ptOrig.v, sizeof( ptOrig.v)) ;
Vector3d vtDirX ;
m_InFile.read( (char*) &vtDirX.v, sizeof( vtDirX.v)) ;
Vector3d vtDirY ;
m_InFile.read( (char*) &vtDirY.v, sizeof( vtDirY.v)) ;
Vector3d vtDirZ ;
m_InFile.read( (char*) &vtDirZ.v, sizeof( vtDirZ.v)) ;
if ( ! m_InFile.good())
Point3d ptOrig ; Vector3d vtDirX, vtDirY, vtDirZ ;
if ( gzread( m_InFile, &ptOrig.v, sizeof( ptOrig.v)) == Z_ERRNO ||
gzread( m_InFile, &vtDirX.v, sizeof( vtDirX.v)) == Z_ERRNO ||
gzread( m_InFile, &vtDirY.v, sizeof( vtDirY.v)) == Z_ERRNO ||
gzread( m_InFile, &vtDirZ.v, sizeof( vtDirZ.v)) == Z_ERRNO)
return false ;
return frF.Set( ptOrig, vtDirX, vtDirY, vtDirZ) ;
}
@@ -308,18 +297,20 @@ bool
NgeReader::ReadString( string& sVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( m_InFile == nullptr)
return false ;
const int MAX_STR_DIM = 65535 ;
if ( ! m_InFile.is_open())
return false ;
int nDim ;
m_InFile.read( (char*) &nDim, sizeof( nDim)) ;
if ( nDim > MAX_STR_DIM || ! m_InFile.good())
if ( gzread( m_InFile, &nDim, sizeof( nDim)) == Z_ERRNO || nDim > MAX_STR_DIM)
return false ;
if ( nDim == 0) {
sVal = "" ;
return true ;
}
char* szBuff = new( nothrow) char[ nDim + 1] ;
if ( szBuff == nullptr)
return false ;
m_InFile.read( szBuff, nDim) ;
if ( ! m_InFile.good()) {
if ( gzread( m_InFile, szBuff, nDim) == Z_ERRNO) {
delete[] szBuff ;
return false ;
}
@@ -348,12 +339,11 @@ NgeReader::ReadKey( int& nKey)
return true ;
}
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
// leggo il dato
int nVal ;
m_InFile.read( (char*) &nVal, sizeof( nVal)) ;
if ( ! m_InFile.good())
if ( gzread( m_InFile, &nVal, sizeof( nVal)) == Z_ERRNO)
return false ;
// ricavo l'indice
for ( int i = 0 ; i <= NGE_LAST_ID ; ++ i) {
@@ -386,11 +376,10 @@ bool
NgeReader::ReadCol( Color& cCol, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_InFile.is_open())
if ( m_InFile == nullptr)
return false ;
unsigned char ucCol[4] ;
m_InFile.read( (char*) &ucCol, sizeof( ucCol)) ;
if ( ! m_InFile.good())
if ( gzread( m_InFile, &ucCol, sizeof( ucCol)) == Z_ERRNO)
return false ;
cCol.Set( ucCol[0], ucCol[1], ucCol[2], ucCol[3]) ;
return true ;
+7 -5
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
// EgalTech 2014-2025
//----------------------------------------------------------------------------
// File : NgeReader.h Data : 14.04.14 Versione : 1.5d5
// File : NgeReader.h Data : 29.12.25 Versione : 2.7l6
// Contenuto : Dichiarazione della classe NgeReader.
//
//
@@ -18,14 +18,16 @@
#include "/EgtDev/Include/EGkColor.h"
#include "/EgtDev/Include/EGnScanner.h"
#include "/EgtDev/Include/EgtStringBase.h"
#include <fstream>
struct gzFile_s ;
//----------------------------------------------------------------------------
class NgeReader
{
public :
NgeReader( void)
: m_iPosStart( std::string::npos), m_bUngetKey( false), m_nFileVer() {}
: m_bBinary( false), m_InFile( nullptr), m_iPosStart( std::string::npos),
m_bUngetKey( false), m_nLastKey(), m_nFileVer() {}
~NgeReader( void)
{ Close() ; }
bool Init( const std::string& sFileIn) ;
@@ -60,7 +62,7 @@ class NgeReader
private :
bool m_bBinary ;
// per file binari
std::ifstream m_InFile ;
gzFile_s* m_InFile ;
// per file ASCII
Scanner m_Scan ;
std::string::size_type m_iPosStart ;
+64 -86
View File
@@ -23,23 +23,23 @@
using namespace std ;
//----------------------------------------------------------------------------
inline bool
WriteStringOutTxt( gzFile OutTxtFile, const char* szVal, const char* szSep, bool bEndL)
static bool
WriteStringOutTxt( gzFile OutFile, const char* szVal, const char* szSep, bool bEndL)
{
// verifico apertura file
if ( OutTxtFile == nullptr)
if ( OutFile == nullptr)
return false ;
// scrivo stringa
if ( gzputs( OutTxtFile, szVal) == Z_ERRNO)
if ( gzputs( OutFile, szVal) == Z_ERRNO)
return false ;
// se fornito, scrivo separatore
if ( szSep != nullptr && szSep[0] != '\0') {
if ( gzputs( OutTxtFile, szSep) == Z_ERRNO)
if ( gzputs( OutFile, szSep) == Z_ERRNO)
return false ;
}
// se richiesto, scrivo fine linea
if ( bEndL) {
if ( gzputs( OutTxtFile, "\r\n") == Z_ERRNO)
if ( gzputs( OutFile, "\r\n") == Z_ERRNO)
return false ;
}
return true ;
@@ -50,27 +50,22 @@ bool
NgeWriter::Init( const string& sFileOut, int nFlag)
{
// salvo tipo file
m_bBinary = ( nFlag == GDB_SV_BIN) ;
m_bBinary = ( nFlag == GDB_SV_BIN || nFlag == GDB_SV_CMPBIN) ;
// apertura del file di uscita
if ( m_bBinary) {
ios_base::openmode nMode = ios::out | ( m_bBinary ? ios::binary : 0) ;
int nProt = _SH_DENYWR ;
m_OutBinFile.open( stringtoW( sFileOut), nMode, nProt) ;
return m_OutBinFile.good() ;
if ( nFlag == GDB_SV_TXT || nFlag == GDB_SV_BIN) {
m_OutFile = gzopen_w( stringtoW( sFileOut), "wbT") ;
return ( m_OutFile != nullptr) ;
}
else {
if ( nFlag == GDB_SV_TXT)
m_OutTxtFile = gzopen_w( stringtoW( sFileOut), "wbT") ;
else // GDB_SV_CMPTXT
m_OutTxtFile = gzopen_w( stringtoW( sFileOut), "wb") ;
if ( m_OutTxtFile == nullptr)
else { // GDB_SV_CMPTXT o GDB_SV_CMPBIN
m_OutFile = gzopen_w( stringtoW( sFileOut), "wb") ;
if ( m_OutFile == nullptr)
return false ;
const int DIM_BUFFER = 65536 ;
if ( gzbuffer( m_OutTxtFile, DIM_BUFFER) != Z_OK)
if ( gzbuffer( m_OutFile, DIM_BUFFER) != Z_OK)
return false ;
const int COMPR_LEVEL = 3 ; // 0 = no compression ... 9 = max compression
if ( gzsetparams( m_OutTxtFile, COMPR_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
if ( gzsetparams( m_OutFile, COMPR_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
return false ;
return true ;
}
@@ -80,20 +75,12 @@ NgeWriter::Init( const string& sFileOut, int nFlag)
bool
NgeWriter::Close( void)
{
if ( m_bBinary) {
bool bOk = ( m_OutBinFile.good() && m_OutBinFile.is_open()) ;
if ( m_OutBinFile.is_open())
m_OutBinFile.close() ;
if ( m_OutFile != nullptr) {
bool bOk = ( gzclose( m_OutFile) == Z_OK) ;
m_OutFile = nullptr ;
return bOk ;
}
else {
if ( m_OutTxtFile != nullptr) {
bool bOk = ( gzclose( m_OutTxtFile) == Z_OK) ;
m_OutTxtFile = nullptr ;
return bOk ;
}
return true ;
}
return true ;
}
//----------------------------------------------------------------------------
@@ -101,13 +88,12 @@ bool
NgeWriter::WriteUchar( unsigned char ucVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &ucVal, sizeof( ucVal)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &ucVal, sizeof( ucVal)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( ucVal).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( ucVal).c_str(), szSep, bEndL) ;
}
}
@@ -116,13 +102,12 @@ bool
NgeWriter::WriteBool( bool bVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &bVal, sizeof( bVal)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &bVal, sizeof( bVal)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( bVal).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( bVal).c_str(), szSep, bEndL) ;
}
}
@@ -131,13 +116,12 @@ bool
NgeWriter::WriteInt( int nVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &nVal, sizeof( nVal)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &nVal, sizeof( nVal)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( nVal).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( nVal).c_str(), szSep, bEndL) ;
}
}
@@ -146,13 +130,12 @@ bool
NgeWriter::WriteDouble( double dVal, const char* szSep, bool bEndL, int nPrec)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &dVal, sizeof( dVal)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &dVal, sizeof( dVal)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( dVal, nPrec).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( dVal, nPrec).c_str(), szSep, bEndL) ;
}
}
@@ -161,15 +144,14 @@ bool
NgeWriter::WriteString( const string& sVal, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
int nDim = int( sVal.size()) ;
m_OutBinFile.write( (char*) &nDim, sizeof( nDim)) ;
m_OutBinFile.write( sVal.c_str(), sVal.size()) ;
return m_OutBinFile.good() ;
int nDim = ssize( sVal) ;
return ( gzwrite( m_OutFile, &nDim, sizeof( nDim)) > 0 &&
( nDim == 0 || gzwrite( m_OutFile, sVal.c_str(), sVal.size()) > 0)) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, sVal.c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, sVal.c_str(), szSep, bEndL) ;
}
}
@@ -178,13 +160,12 @@ bool
NgeWriter::WriteVector( const Vector3d& vtV, const char* szSep, bool bEndL, int nPrec)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &vtV.v, sizeof( vtV.v)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &vtV.v, sizeof( vtV.v)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( vtV, nPrec).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( vtV, nPrec).c_str(), szSep, bEndL) ;
}
}
@@ -193,13 +174,12 @@ bool
NgeWriter::WritePoint( const Point3d& ptP, const char* szSep, bool bEndL, int nPrec)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &ptP.v, sizeof( ptP.v)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &ptP.v, sizeof( ptP.v)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( ptP, nPrec).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( ptP, nPrec).c_str(), szSep, bEndL) ;
}
}
@@ -208,14 +188,13 @@ bool
NgeWriter::WritePointW( const Point3d& ptP, double dW, const char* szSep, bool bEndL, int nPrecP, int nPrecW)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &ptP.v, sizeof( ptP.v)) ;
m_OutBinFile.write( (char*) &dW, sizeof( dW)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &ptP.v, sizeof( ptP.v)) > 0 &&
gzwrite( m_OutFile, &dW, sizeof( dW)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( ptP, dW, nPrecP, nPrecW).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( ptP, dW, nPrecP, nPrecW).c_str(), szSep, bEndL) ;
}
}
@@ -224,16 +203,15 @@ bool
NgeWriter::WriteFrame( const Frame3d& frF, const char* szSep, bool bEndL, int nPrecP, int nPrecV)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &frF.Orig().v, sizeof( frF.Orig().v)) ;
m_OutBinFile.write( (char*) &frF.VersX().v, sizeof( frF.VersX().v)) ;
m_OutBinFile.write( (char*) &frF.VersY().v, sizeof( frF.VersY().v)) ;
m_OutBinFile.write( (char*) &frF.VersZ().v, sizeof( frF.VersZ().v)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &frF.Orig().v, sizeof( frF.Orig().v)) > 0 &&
gzwrite( m_OutFile, &frF.VersX().v, sizeof( frF.VersX().v)) > 0 &&
gzwrite( m_OutFile, &frF.VersY().v, sizeof( frF.VersY().v)) > 0 &&
gzwrite( m_OutFile, &frF.VersZ().v, sizeof( frF.VersZ().v)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( frF, nPrecP, nPrecV).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( frF, nPrecP, nPrecV).c_str(), szSep, bEndL) ;
}
}
@@ -245,13 +223,12 @@ NgeWriter::WriteKey( int nKey)
return false ;
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
m_OutBinFile.write( (char*) &NgeBinKeyW[nKey], sizeof( int)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, &NgeBinKeyW[nKey], sizeof( int)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, NgeAscKeyW[nKey].c_str(), nullptr, true) ;
return WriteStringOutTxt( m_OutFile, NgeAscKeyW[nKey].c_str(), nullptr, true) ;
}
}
@@ -260,18 +237,17 @@ bool
NgeWriter::WriteCol( const Color& cCol, const char* szSep, bool bEndL)
{
if ( m_bBinary) {
if ( ! m_OutBinFile.is_open())
if ( m_OutFile == nullptr)
return false ;
unsigned char ucCol[4] ;
ucCol[0] = cCol.GetIntRed() ;
ucCol[1] = cCol.GetIntGreen() ;
ucCol[2] = cCol.GetIntBlue() ;
ucCol[3] = cCol.GetIntAlpha() ;
m_OutBinFile.write( (char*) ucCol, sizeof( ucCol)) ;
return m_OutBinFile.good() ;
return ( gzwrite( m_OutFile, ucCol, sizeof( ucCol)) > 0) ;
}
else {
return WriteStringOutTxt( m_OutTxtFile, ToString( cCol).c_str(), szSep, bEndL) ;
return WriteStringOutTxt( m_OutFile, ToString( cCol).c_str(), szSep, bEndL) ;
}
}
@@ -279,9 +255,11 @@ NgeWriter::WriteCol( const Color& cCol, const char* szSep, bool bEndL)
bool
NgeWriter::WriteRemark( const string& sVal)
{
if ( m_bBinary)
if ( m_bBinary) {
return true ;
else
return ( WriteStringOutTxt( m_OutTxtFile, "//", nullptr, false) &&
WriteStringOutTxt( m_OutTxtFile, sVal.c_str(), nullptr, true)) ;
}
else {
return ( WriteStringOutTxt( m_OutFile, "//", nullptr, false) &&
WriteStringOutTxt( m_OutFile, sVal.c_str(), nullptr, true)) ;
}
}
+5 -9
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
// EgalTech 2014-2025
//----------------------------------------------------------------------------
// File : NgeWriter.h Data : 12.04.14 Versione : 1.5d5
// File : NgeWriter.h Data : 29.12.25 Versione : 2.7l6
// Contenuto : Dichiarazione della classe NgeWriter.
//
//
@@ -16,7 +16,6 @@
#include "NgeConst.h"
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EGkColor.h"
#include <fstream>
struct gzFile_s ;
@@ -24,7 +23,7 @@ struct gzFile_s ;
class NgeWriter
{
public :
NgeWriter( void) : m_bBinary( false), m_OutTxtFile( nullptr) {}
NgeWriter( void) : m_bBinary( false), m_OutFile( nullptr) {}
~NgeWriter( void)
{ Close() ; }
bool Init( const std::string& sFileOut, int nFlag) ;
@@ -44,9 +43,6 @@ class NgeWriter
bool WriteRemark( const std::string& sVal /* bEndL = true*/) ;
private :
bool m_bBinary ;
// per file binari
std::ofstream m_OutBinFile ;
// per file ASCII
gzFile_s* m_OutTxtFile ;
bool m_bBinary ;
gzFile_s* m_OutFile ;
} ;
+4 -4
View File
@@ -243,11 +243,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
if ( IsNull( pCrv1))
return false ;
pCrv1->SetTempProp( nInd1) ;
if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET)) {
if ( ! pCrv1->SimpleOffset( dDist)) {
CurveArc* pArc = GetBasicCurveArc( pCrv1) ;
if ( pArc == nullptr)
return false ;
if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
if ( pArc->MyExtendedOffset( dDist, true))
pCrv1->SetTempProp( - nInd1) ;
}
// curve successive
@@ -255,11 +255,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
while ( ! IsNull( pCrv2)) {
// eseguo semplice offset
pCrv2->SetTempProp( nInd1 + 1) ;
if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET)) {
if ( ! pCrv2->SimpleOffset( dDist)) {
CurveArc* pArc = GetBasicCurveArc( pCrv2) ;
if ( pArc == nullptr)
return false ;
if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
if ( pArc->MyExtendedOffset( dDist, true))
pCrv2->SetTempProp( - ( nInd1 + 1)) ;
}
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
+1
View File
@@ -14,6 +14,7 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "PointsPCA.h"
#define EIGEN_NO_IO
#include "/EgtDev/Extern/Eigen/Dense"
+10 -12
View File
@@ -775,7 +775,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
//----------------------------------------------------------------------------
bool
PolyLine::RemoveAlignedPoints( double dToler)
PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd)
{
// se non ci sono almeno 3 punti, esco subito
if ( m_lUPoints.size() < 3)
@@ -825,8 +825,8 @@ PolyLine::RemoveAlignedPoints( double dToler)
// ordino in senso crescente
sort( vInd.begin(), vInd.end()) ;
// se chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
if ( IsClosed() && vInd.size() >= 4) {
// se richiesto e chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
if ( bStartEnd && IsClosed() && vInd.size() >= 4) {
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[int(vInd.size())-2]].first).IsEpsilon( dToler)) {
vInd.erase( vInd.begin()) ;
vInd.back() = vInd.front() ;
@@ -1531,6 +1531,10 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
return false ;
// Riferimento alla lista dei punti
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Se il punto inziale è già quello, non faccio nulla
if ( AreSamePointEpsilon( LoopList.begin()->first, ptNewStart, dToler))
return true ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
@@ -1970,7 +1974,7 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType,
for ( int z = int( vbRep2.size()) - 1 ; z >= nCrv2 ; --z)
vbRep2[z] = true ;
}
if( nCrv1 < nPnt1) {
if ( nCrv1 < nPnt1) {
nRep1 += nPnt1 - nCrv1 ;
for ( int z = int( vbRep1.size()) - 1 ; z >= nCrv1 ; --z)
vbRep1[z] = true ;
@@ -1987,17 +1991,11 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType,
nAddedSpan = 0 ;
nCrv1 = 0 ;
nCrv2 = 0 ;
bool bLast1 = false ;
bool bLast2 = false ;
while ( nAddedSpan < nPnt) {
if ( nCrv1 >= nPnt1) {
if ( nCrv1 >= nPnt1)
nCrv1 = nPnt1 - 1 ;
bLast1 = true ;
}
if ( nCrv2 >= nPnt2) {
if ( nCrv2 >= nPnt2)
nCrv2 = nPnt2 - 1 ;
bLast2 = true ;
}
bool bRep1 = vbRep1[nCrv1] ;
bool bRep2 = vbRep2[nCrv2] ;
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
+1 -1
View File
@@ -173,7 +173,7 @@ Polygon3d::FromPlaneTrimmedWithBox( const Point3d& ptOn, const Vector3d& vtN,
{
Plane3d plPlane ;
plPlane.Set( ptOn, vtN) ;
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt) ;
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt, dToler) ;
}
//----------------------------------------------------------------------------
+22 -14
View File
@@ -172,9 +172,9 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
return true ;
}
}
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
dElev = max( dElev, Inters.dU) ;
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
dElev = max( dElev, Inters.dU2) ;
}
}
@@ -206,22 +206,30 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
continue ;
// calcolo il segmento di linea
CurveLine clLine ;
CurveLine clLine ;
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
return false ;
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
IntersCurveCurve intLL( clLine, ccLoop) ;
IntCrvCrvInfo aInfo ;
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
if ( aInfo.bOverlap)
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
dElev = max( dElev, vEdges[i].first.z) ;
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
dElev = max( dElev, vEdges[i].second.z) ;
if ( intLL.GetIntersCount() == 0) {
Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ;
ptM.z = 0 ;
if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL))
dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.z)) ;
}
else {
IntCrvCrvInfo aInfo ;
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
if ( aInfo.bOverlap)
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
dElev = max( dElev, vEdges[i].first.z) ;
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
dElev = max( dElev, vEdges[i].second.z) ;
}
}
}
+443 -255
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2023-2025
// EgalTech 2023-2026
//----------------------------------------------------------------------------
// File : ProjectCurveSurfTm.cpp Data : 29.08.25 Versione : 2.7h2
// File : ProjectCurveSurfTm.cpp Data : 03.01.26 Versione : 3.1a1
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
//
//
@@ -19,6 +19,7 @@
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
@@ -59,6 +60,83 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
return true ;
}
//----------------------------------------------------------------------------
static bool
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
{
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ 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) ^ ( vPt5ax[i].vtDir1 + vPt5ax[j].vtDir1)) ;
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 = vPt5ax[j].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
Pt5ax.vtDirV = vPt5ax[j].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
else
vPt5ax[j].nFlag = P5AX_CVEX ;
if ( dLen2 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
Pt5ax.vtDirV = vPt5ax[i].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
else
vPt5ax[i].nFlag = P5AX_CVEX ;
}
// 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.vtDir1.Normalize() ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ;
Pt5ax.vtDirU = Media( vPt5ax[i].vtDirU, vPt5ax[j].vtDirU) ; Pt5ax.vtDirU.Normalize() ;
Pt5ax.vtDirV = Media( vPt5ax[i].vtDirV, vPt5ax[j].vtDirV) ; Pt5ax.vtDirV.Normalize() ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
static bool
RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir)
@@ -70,7 +148,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
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())) {
while ( nInd < ssize( vPt5ax)) {
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
// analizzo i punti appena precedenti
int nIpv = nInd - 1 ;
@@ -86,7 +164,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
}
// analizzo i punti appena successivi
int nInx = nInd + 1 ;
while ( nInx < int( vPt5ax.size())) {
while ( nInx < ssize( vPt5ax)) {
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
if ( dSqLen < dSqMaxLen)
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
@@ -104,7 +182,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
int nPrec = 0 ;
int nCurr = 1 ;
int nNext = 2 ;
while ( nNext < int( vPt5ax.size())) {
while ( nNext < ssize( vPt5ax)) {
bool bRemove = false ;
// lunghezza del segmento che unisce gli adiacenti
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
@@ -161,38 +239,211 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
return true ;
}
//----------------------------------------------------------------------------
static const SurfTriMesh*
MyGetAuxSurf( const ISurf* pSrf)
{
if ( pSrf == nullptr)
return nullptr ;
switch ( pSrf->GetType()) {
case SRF_TRIMESH :
return GetBasicSurfTriMesh( pSrf) ;
case SRF_FLATRGN :
return GetBasicSurfFlatRegion( pSrf)->GetAuxSurf() ;
case SRF_BEZIER :
return GetBasicSurfBezier( pSrf)->GetAuxSurf() ;
default :
return nullptr ;
}
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar, Point5ax& Pt5ax)
{
// punto sulle superfici a minima distanza
int nSurfMin = -1 ;
int nTriaMin = -1 ;
double dUMin = -1, dVMin = -1 ;
Point3d ptMin ;
double dMinDist = NAN ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
// punto sulla superficie a minima distanza
int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetMinDistTriaIndex ( nTriaMin) ;
dMinDist = dDist ;
}
}
else if ( nSrfType == SRF_BEZIER) {
DistPointSurfBz dPS( ptP, *GetBasicSurfBezier( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetParamsAtMinDistPoint( dUMin, dVMin) ;
dMinDist = dDist ;
}
}
}
// se trovato
if ( nSurfMin >= 0) {
// assegno il punto
Point3d ptInt = ptMin ;
// calcolo gli altri dati
int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
// recupero superficie trimesh
const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! pSurfTm->GetTriangle( nTriaMin, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
else if ( nSrfType == SRF_BEZIER) {
Point3d ptSB ;
Vector3d vtN, vtDerU, vtDerV ;
if ( ! GetBasicSurfBezier( vpSurf[nSurfMin])->GetPointNrmD1D2( dUMin, dVMin, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS,
ptSB, vtN, &vtDerU, &vtDerV))
return false ;
vtDerU.Normalize() ;
vtDerV.Normalize() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = vtDerU ;
Pt5ax.vtDirV = vtDerV ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
// ritorno con successo
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, 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 tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
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 secondo la direzione di minima distanza
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurf, 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)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
// --- vettore di oggetti intersezione massiva rette parallele SurfTM --------
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
double dPar, Point5ax& Pt5ax)
double dPar, bool bFromVsTo, Point5ax& Pt5ax)
{
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
Point3d ptL = GetToLoc( ptP, frRefLine) ;
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( vpIntPLSTM[i]->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) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
// se dalla direzione
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso la direzione
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
@@ -216,6 +467,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = frRefLine.VersZ() ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -227,11 +480,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -257,9 +510,11 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea alla massima risoluzione
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
@@ -270,10 +525,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) {
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
if ( pIntPLSTM == nullptr) {
for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j)
for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j)
delete vpIntPLSTM[j] ;
return false ;
}
@@ -291,79 +546,19 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// Libero oggetti per calcolo massivo
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i)
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i)
delete vpIntPLSTM[i] ;
// 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 ;
}
}
}
}
}
}
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
@@ -373,7 +568,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, bool bFromVsTo,
Point5ax& Pt5ax)
{
// punto di riferimento
Point3d ptMin = gpRef.GetPoint() ;
@@ -385,26 +581,51 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
// conservo l'intersezione più alta
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], 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) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
// se dal punto
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso il punto
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
@@ -428,6 +649,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -440,11 +663,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -471,9 +694,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
@@ -490,32 +714,15 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, bFromVsTo, 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) {
// 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, vpSurfTm, gpRef, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ;
}
}
}
}
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
@@ -525,7 +732,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, bool bFromVsTo,
Point5ax& Pt5ax)
{
// punto a minima distanza
DistPointCurve dPC( ptP, crRef) ;
@@ -540,26 +748,51 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
// conservo l'intersezione più alta
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], 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) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
// se dalla curva
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso la curva
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
@@ -582,7 +815,9 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDir2 = ( bFromVsTo ? vtLine : -vtLine) ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -596,11 +831,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// Sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -627,9 +862,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// Approssimo la curva con una polilinea alla massima risoluzione
// Approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
@@ -646,75 +882,15 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, bFromVsTo, 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 ;
}
}
}
}
}
}
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
@@ -724,7 +900,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, bool bFromVsTo,
Point5ax& Pt5ax)
{
// punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, stmRef) ;
@@ -748,26 +925,51 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
// intersezione della retta con le superfici (conservo l'intersezione più alta)
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], 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) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
// se dalla superficie
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso la superficie
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
@@ -798,6 +1000,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -810,11 +1014,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -862,9 +1066,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
@@ -881,32 +1086,15 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, bFromVsTo, 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) {
// 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, vpSurfTm, *pRefTm, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ;
}
}
}
}
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
+94 -22
View File
@@ -78,7 +78,7 @@ GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ;
if( vbInvert[vnPLIndMat[i][j]])
if ( vbInvert[vnPLIndMat[i][j]])
vPLOrd.back().Invert() ;
}
}
@@ -221,7 +221,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
const ICurve* pCrv = pCC->GetCurve( i) ;
if( pCrv->GetType() != CRV_LINE) {
if ( pCrv->GetType() != CRV_LINE) {
if ( pCrv->GetType() == CRV_BEZIER) {
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
bGuideIsPolyLine = pCrvBez->IsALine() ;
@@ -249,7 +249,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
int nSpanV = 0 ;
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
if ( bGuideIsPolyLine ) {
if( pGuide->GetType() == CRV_LINE)
if ( pGuide->GetType() == CRV_LINE)
nSpanV = 1 ;
else if ( pGuide->GetType() == CRV_COMPO)
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
@@ -260,7 +260,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
else {
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
if( ! pGuideBez->IsRational())
if ( ! pGuideBez->IsRational())
pCrvV->AddCurve( pGuide->Clone()) ;
else
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
@@ -297,7 +297,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
ICRVCOMPOPOVECTOR vCC ;
INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ;
int nMaxSpanV = nSpanV ;
for( int i = 0 ; i < nSpanU ; ++i) {
for ( int i = 0 ; i < nSpanU ; ++i) {
const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
@@ -327,7 +327,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
for ( int w = 0 ; w < int( vCC.size()) ; ++w) {
const ICurveComposite* pCCOther = vCC[w] ;
int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ;
if( nPropCheck != 0)
if ( nPropCheck != 0)
mRep[w][z] = 1 ;
}
}
@@ -337,11 +337,11 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
// conto in quante colonne di mRep la somma degli elementi è != 0
// questo numero va aggiunto all'attuale nSpanV
int nSpanPlus = 0 ;
for( int z = 0 ; z < nMaxSpanV ; ++z) {
for ( int z = 0 ; z < nMaxSpanV ; ++z) {
int nPosTot = 0 ;
for ( int k = 0 ; k < int( mRep.size()) ; ++k )
nPosTot += mRep[k][z] ;
if( nPosTot != 0)
if ( nPosTot != 0)
nSpanPlus += 1 ;
}
nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ;
@@ -349,14 +349,14 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
//// aggiungo i punti di controllo alla superficie
//for( int i = 0 ; i < nSpanU ; ++i) {
//for ( int i = 0 ; i < nSpanU ; ++i) {
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
// const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ;
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
// if( pCL == nullptr)
// if ( pCL == nullptr)
// return nullptr ;
// if( z == 0) {
// if ( z == 0) {
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
// }
@@ -367,13 +367,13 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
//}
//// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO
//for( int i = 0 ; i < int( vCC.size()) ; ++i) {
//for ( int i = 0 ; i < int( vCC.size()) ; ++i) {
// const ICurveComposite* pOffsetCrv = vCC[i] ;
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
// if( pCL == nullptr)
// if ( pCL == nullptr)
// return nullptr ;
// if( z == 0) {
// if ( z == 0) {
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
// }
@@ -422,7 +422,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
//// porto la sezione nel sistema di riferimento del piano in cui giace
//pCrvU->ToLoc( frStart) ;
//for( int i = 0 ; i < nSpanU ; ++i) {
//for ( int i = 0 ; i < nSpanU ; ++i) {
// const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
// Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
@@ -458,7 +458,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
// // aggiungo i punti di controllo alla superficie
// for ( int z = 0 ; z < nSpanV ; ++z) {
// const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ;
// if( pCrvBez == nullptr)
// if ( pCrvBez == nullptr)
// return nullptr ;
// for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) {
// Point3d ptCtrl = pCrvBez->GetControlPoint( k) ;
@@ -572,7 +572,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
else {
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
if( ! pSectBez->IsRational())
if ( ! pSectBez->IsRational())
pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
else
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
@@ -709,7 +709,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, true, false)) ;
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
@@ -718,7 +718,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, true, false)) ;
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
@@ -733,18 +733,90 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
{
// verifico che le curve siano valide
for ( int i = 0 ; i < int( vCrv.size()) ; ++i) {
if( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
if ( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
return nullptr ;
}
// se ho solo due curve allora faccio la rigata
if( vCrv.size() == 2)
if ( vCrv.size() == 2)
return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ;
//trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado
@@ -752,7 +824,7 @@ GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
ICURVEPOVECTOR vCrvBez ;
for( int c = 0 ; c < int( vCrv.size()) ; ++c){
for ( int c = 0 ; c < int( vCrv.size()) ; ++c){
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
if ( vCrv[c]->GetType() != CRV_BEZIER )
pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ;
+2 -2
View File
@@ -73,7 +73,7 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
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]])
if ( vbInvert[vnPLIndMat[i][j]])
vPL[vnPLIndMat[i][j]].Invert() ;
}
}
@@ -165,7 +165,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
return nullptr ;
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
if( vbInvert[i])
if ( vbInvert[i])
vPL[i].Invert() ;
}
// verifico la direzione di estrusione
+14 -7
View File
@@ -76,11 +76,18 @@ FromString( const string& sVal, Frame3d& frFrame)
bool
FromString( const string& sVal, Color& cCol)
{
// devono essere 4 parametri : Red, Green, Blue, Alpha
int vnVal[4] ;
if ( ! FromString( sVal, vnVal))
return false ;
// assegno il colore
cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[3]) ;
return true ;
// dovrebbero essere 4 parametri : Red, Green, Blue, Alpha
int vnRGBA[4] ;
if ( FromString( sVal, vnRGBA)) {
cCol.Set( vnRGBA[0], vnRGBA[1], vnRGBA[2], vnRGBA[3]) ;
return true ;
}
// riprovo con 3 parametri : Red, Green, Blue
int vnRGB[3] ;
if ( FromString( sVal, vnRGB)) {
cCol.Set( vnRGB[0], vnRGB[1], vnRGB[2]) ;
return true ;
}
// altrimenti errore
return false ;
}
+1 -1
View File
@@ -302,7 +302,7 @@ SetTmpPropByOverlap( ICurveComposite* pCrvCheck, const int nInd, const ICurveCom
// ultimo tratto di curva della Composita iniziale
PtrOwner<CurveComposite> pCrvB( GetBasicCurveComposite( pCrvCheck->CopyParamRange( nInd + 1, pCrvCheck->GetCurveCount()))) ;
if ( ! IsNull( pCrvB) && pCrvB->GetCurveCount() > 0 && pCrvB->IsValid())
if( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
if ( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
nStat = 2 ;
return true ;
}
+324 -78
View File
@@ -24,6 +24,14 @@
#include "/EgtDev/Include/EGkSurfAux.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#define SAVEMKUNIF_CRVS 0
#if SAVEMKUNIF_CRVS
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ;
@@ -37,12 +45,12 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
bool bIsRational = snData.bRat ;
// vettore dei nodi
DBLVECTOR vU ;
int nKnot = (int) snData.vU.size() ;
int nKnot = ssize( snData.vU) ;
for ( int k = 0 ; k < nKnot ; ++k ) {
double dKnot = snData.vU[k] ;
vU.push_back( dKnot) ;
}
for( int j = 0 ; j < snData.nCPV ; ++j) {
for ( int j = 0 ; j < snData.nCPV ; ++j) {
CNurbsData nuCurve ;
nuCurve.bPeriodic = true ;
nuCurve.bRat = snData.bRat ;
@@ -66,12 +74,16 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
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)
if ( snData.bRat)
snData.mW.resize( nuCurve.vW.size()) ;
}
for ( int i = 0 ; i < snData.nCPU ; ++i) {
for ( int i = 0 ; i < ssize( nuCurve.vCP) ; ++i) {
if ( snData.mCP[i].empty())
snData.mCP[i].resize( snData.nCPV) ;
snData.mCP[i][j] = nuCurve.vCP[i] ;
if( snData.bRat) {
if ( snData.bRat) {
if ( snData.mW[i].empty())
snData.mW[i].resize( snData.nCPV) ;
snData.mW[i][j] = nuCurve.vW[i] ;
snData.mCP[i][j] *= nuCurve.vW[i] ;
}
@@ -80,18 +92,18 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
}
}
snData.bPeriodicU = false ;
snData.nCPU = int( snData.mCP.size()) ;
snData.nCPU = ssize( snData.mCP) ;
}
if ( snData.bPeriodicV || ! snData.bClampedV) {
bool bIsRational = snData.bRat ;
// vettore dei nodi
DBLVECTOR vV ;
int nKnot = (int) snData.vV.size() ;
int nKnot = ssize( snData.vV) ;
for ( int k = 0 ; k < nKnot ; ++k ) {
double dKnot = snData.vV[k] ;
vV.push_back( dKnot) ;
}
for( int i = 0 ; i < snData.nCPU ; ++i) {
for ( int i = 0 ; i < snData.nCPU ; ++i) {
CNurbsData nuCurve ;
nuCurve.bPeriodic = true ;
nuCurve.bRat = snData.bRat ;
@@ -132,7 +144,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
}
}
snData.bPeriodicV = false ;
snData.nCPV = int( snData.mCP[0].size()) ;
snData.nCPV = ssize( snData.mCP[0]) ;
}
return true ;
}
@@ -526,6 +538,25 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
return Release( pSrfBz) ;
}
//----------------------------------------------------------------------------
ICurveComposite*
GetRectangleCurve( const Point3d& ptStart, double dWidth, double dHeight)
{
PolyLine PL ;
PL.AddUPoint( 0, ptStart) ;
PL.AddUPoint( 1, Point3d( ptStart.x + dWidth, ptStart.y)) ;
PL.AddUPoint( 2, Point3d( ptStart.x + dWidth, ptStart.y + dHeight, 0)) ;
PL.AddUPoint( 3, Point3d( ptStart.x , ptStart.y + dHeight, 0)) ;
PL.AddUPoint( 4, ptStart) ;
// creo la curva e la inserisco nel GDB
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
bool bOk = true ;
bOk = bOk && ! IsNull( pCrvCompo) ;
// inserisco i segmenti che uniscono i punti
bOk = bOk && pCrvCompo->FromPolyLine( PL) ;
return Release( pCrvCompo) ;
}
//----------------------------------------------------------------------------
bool
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
@@ -535,36 +566,33 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
bool bRescaledU = false ;
bool bRescaledV = false ;
int nSpanU = 1, nSpanV = 1 ;
PtrOwner<ISurfFlatRegion> pRescaledSfr( CreateSurfFlatRegion()) ;
ICRVCOMPOPOVECTOR vUniformedCurves ;
BOOLVECTOR vbUniform(2) ;
fill( vbUniform.begin(), vbUniform.end(), true) ;
DBLMATRIX mKnots(2) ;
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
// vettore dei nodi
DBLVECTOR vU ;
DBLVECTOR& vU = mKnots[nDir] ;
int nExtraKnots = 0 ;
// controllo in U
if ( nDir == 0) {
if ( nDegU > 1) {
nExtraKnots = nDegU - 1 ;
}
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
for ( int i = nExtraKnots ; i < ssize( vU0) - nExtraKnots ; ++i ) {
double dKnot = vU0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
vU.push_back( dKnot) ;
}
nSpanU = (int)vU.size() - 1 ;
nSpanU = ssize( vU) - 1 ;
}
// controllo in V
else if ( nDir == 1 ) {
if ( nDegV > 1) {
nExtraKnots = nDegV - 1 ;
}
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
for ( int i = nExtraKnots ; i < ssize( vV0) - nExtraKnots ; ++i ) {
double dKnot = vV0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
vU.push_back( dKnot) ;
}
nSpanV = (int)vU.size() - 1 ;
nSpanV = ssize( vU) - 1 ;
}
// controllo se il vettore dei nodi è uniforme
@@ -577,76 +605,268 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
if ( b < (int)vU.size())
d1 = abs( vU[b] - vU[a]) ;
}
if ( b != (int)vU.size()) {
if ( b != (int)vU.size())
vbUniform[nDir] = false ;
}
// vettore delle curve di loop della regione di trim
ICRVCOMPOPOVECTOR vLoop ;
if ( ! vbUniform[0] || ! vbUniform[1]) {
for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++c) {
for ( int l = 0 ; l < pSfr->GetLoopCount( c); ++l)
vLoop.emplace_back( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ;
}
}
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vLoop); ++i){
vGeo.push_back(vLoop[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_loops.nge") ;
//debug
#endif
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
DBLVECTOR& vU = mKnots[nDir] ;
if ( ! vbUniform[nDir]) {
nDir == 0 ? bRescaledU = true : bRescaledV = true ;
pRescaledSfr.Set( CreateSurfFlatRegion()) ;
if ( IsNull( pRescaledSfr))
return false ;
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
if ( IsNull( pSfr_copy))
return false ;
// creo il vettore delle curve all'interno di una striscia
ICRVCOMPOPOVECTOR vCrvStrip ;
for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) {
double dLenStrip = abs( vU[p+1] - vU[p]) ;
if ( dLenStrip < EPS_SMALL)
continue ;
// creo la maschera per tagliare la superficie originale e ottenere una striscia
PtrOwner<ISurfFlatRegion> pSfrTrim( CreateSurfFlatRegion()) ;
PtrOwner<ICurveComposite> pTrimMask ;
// ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
Vector3d vtTrim ;
if ( nDir == 0) {
pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ;
vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ;
Point3d ptStart( abs(vU[p] - vU.front()), - 1, 0) ;
pTrimMask.Set( GetRectangleCurve( ptStart, dLenStrip, dScaleV + 2)) ;
}
else{
pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ;
vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ;
Point3d ptStart( - 1, abs(vU[p] - vU.front()), 0) ;
pTrimMask.Set( GetRectangleCurve( ptStart, dScaleU + 2, dLenStrip)) ;
}
pSfrTrim->Translate( vtTrim) ;
if ( ! pSfr_copy->Intersect( *pSfrTrim))
return false ;
// qui potrei decidere di eliminare tutti i tratti dei loop paralleli alla direzione del parametro che sto analizzando ( e di valore coincidente a quello di un nodo)
// aggiungo la nuova striscia solo se è valida
if ( pSfr_copy->IsValid() ) {
for ( int l = 0 ; l < ssize( vLoop); ++l) {
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
vGeo.push_back(pTrimMask->Clone()) ;
vGeo.push_back(vLoop[l]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ;
//debug
#endif
IntersCurveCurve icc( *vLoop[l], *pTrimMask) ;
int nInters = icc.GetIntersCount() ;
ICCIVECTOR vICCI ;
for ( int i = 0 ; i < nInters ; ++i) {
IntCrvCrvInfo icci ; icc.GetIntCrvCrvInfo( i, icci) ;
vICCI.push_back( std::move( icci)) ;
}
CRVCVECTOR vCrvClass, vMaskClass ;
icc.GetCurveClassification( 0, EPS_SMALL, vCrvClass) ;
icc.GetCurveClassification( 1, EPS_SMALL, vMaskClass) ;
// se dei pezzi di trim risultano esterni allo spazio parametrico tengo il bordo della maschera di trim
double dLastParam1 = 0 ;
double dStartA = 0, dEndA = 0 ; vLoop[l]->GetDomain( dStartA, dEndA) ;
double dEndB = 4 ;
for ( int i = 0 ; i < ssize( vCrvClass); ++i) {
if ( vCrvClass[i].nClass == CRVC_IN || vCrvClass[i].nClass == CRVC_ON_P) {
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE))) ;
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs( vICCI[j].IciA[k].dU - vCrvClass[i].dParE) < EPS_PARAM) {
dLastParam1 = vICCI[j].IciB[k].dU ;
break ;
}
}
}
else if ( vCrvClass[i].nClass == CRVC_OUT && ( p == 0 || p == ssize(vU) - 2)){
double dMin, dMax ;
if ( p == 0) {
dMin = nDir == 0 ? 3 : 0 ;
dMax = nDir == 0 ? 4 : 1 ;
}
else {
dMin = nDir == 0 ? 1 : 2 ;
dMax = nDir == 0 ? 2 : 3 ;
}
// aggiungo la parte di curva di edge al posto della parte di curva che esce dal parametrico
// se non ho ancora aggiunto un tratto parto dal primo punto di intersezione
if ( ssize( vCrvStrip) == 0) {
double dPar0 = vCrvClass[i].dParS ;
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs(vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM ||
( abs( dEndA - vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM)) {
if ( abs( dEndB - vICCI[j].IciB[k].dU) < EPS_PARAM)
dLastParam1 = 0 ;
else
dLastParam1 = vICCI[j].IciB[k].dU ;
break ;
}
}
}
int c = 0 ;
while ( c < ssize( vMaskClass) - 1 && abs( vMaskClass[c].dParS - dLastParam1) > EPS_PARAM)
++c ;
if ( vMaskClass[c].nClass == CRVC_IN && vMaskClass[c].dParS < dMax && vMaskClass[c].dParS >= dMin) {
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
dLastParam1 = vMaskClass[c].dParE ;
// se sono alla fine curva verifico se devo aggiungere anche un pezzo di inizio
if ( dLastParam1 == dEndB && vMaskClass[0].nClass == CRVC_IN) {
c = 0 ;
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
dLastParam1 = vMaskClass[c].dParE ;
}
}
}
}
}
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
//debug
#endif
// riscalo le curve nella striscia
if ( ! vCrvStrip.empty()) {
double dCoeffX = 1, dCoeffY = 1 ;
if ( nDir == 0)
pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
// prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo
Point3d pt ;
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
if ( nDir == 0)
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
Vector3d vtJoin ;
if ( nDir == 0)
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
else
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
pSfr_copy->Translate( vtJoin) ;
// se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET
if ( bRetry)
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // OFFSET
if ( pRescaledSfr->IsValid()) {
if ( ! pRescaledSfr->Add( *pSfr_copy))
dCoeffX = SBZ_TREG_COEFF / dLenStrip ;
else
dCoeffY = SBZ_TREG_COEFF / dLenStrip ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i) {
if( ! IsNull( vCrvStrip[i]))
vCrvStrip[i]->Scale( GLOB_FRM, dCoeffX, dCoeffY, 1) ;
else
return false ;
}
else
pRescaledSfr.Set( pSfr_copy) ;
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo (nDir == 0)
// oppure sul bordo superiore ( nDir == 1)
Point3d pt ;
Vector3d vtJoin ;
if ( nDir == 0) {
pt.Set( abs( vU[p] - vU.front()), 0, 0) ;
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
}
else {
pt.Set( 0, abs(vU[p] - vU.front()), 0) ;
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
}
for( int i = 0 ; i < ssize( vCrvStrip); ++i)
vCrvStrip[i]->Translate( vtJoin) ;
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
//debug
#endif
// faccio la chain con le curve delle striscie precedenti
if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) {
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
//debug
#endif
ChainCurves chainCrv ;
double dChainTol = 5 * EPS_SMALL ;
chainCrv.Init( false, dChainTol, max(ssize( vUniformedCurves), ssize(vCrvStrip))) ;
for ( int c = 0 ; c < ssize( vUniformedCurves) ; ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vUniformedCurves[c]->GetStartPoint( ptStart) ;
vUniformedCurves[c]->GetEndPoint( ptEnd) ;
vUniformedCurves[c]->GetStartDir( vtStart) ;
vUniformedCurves[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
for ( int c = 0 ; c < ssize( vCrvStrip); ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vCrvStrip[c]->GetStartPoint( ptStart) ;
vCrvStrip[c]->GetEndPoint( ptEnd) ;
vCrvStrip[c]->GetStartDir( vtStart) ;
vCrvStrip[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + ssize( vUniformedCurves) + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
INTVECTOR vIds ;
ICRVCOMPOPOVECTOR vNewCrv ;
int nCrvPrec = ssize( vUniformedCurves) ;
while ( chainCrv.GetChainFromNear( ORIG, false, vIds)) {
// se ho una solo curva piccola allora la salto
if ( ssize(vIds) == 1) {
double dLen = 0 ;
int nId = vIds[0] - 1 ;
bool bSkip = false ;
if ( nId < nCrvPrec)
bSkip = vUniformedCurves[nId]->GetLength( dLen) && dLen < dChainTol ;
else
bSkip = vCrvStrip[nId - ssize(vUniformedCurves)]->GetLength(dLen) && dLen < dChainTol ;
if ( bSkip)
continue ;
}
vNewCrv.emplace_back( CreateBasicCurveComposite()) ;
for ( int nId : vIds) {
nId -= 1 ;
if ( nId < nCrvPrec)
vNewCrv.back()->AddCurve( Release( vUniformedCurves[nId]), true, dChainTol) ;
else
vNewCrv.back()->AddCurve( Release( vCrvStrip[nId - ssize( vUniformedCurves)]), true, dChainTol) ;
}
}
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vNewCrv); ++i){
vGeo.push_back(vNewCrv[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\trim_crv_unif_AFTERchain.nge") ;
//debug
#endif
// aggiorno le curve
vUniformedCurves.clear() ;
vUniformedCurves.swap( vNewCrv) ;
}
}
vCrvStrip.clear() ;
}
if ( nDir == 0) {
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
if ( pRescaledSfr->IsValid()) {
if ( bRetry)
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
if( ! vbUniform[1]) {
vLoop.swap( vUniformedCurves) ;
vUniformedCurves.clear() ;
}
}
else
@@ -654,12 +874,38 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
}
}
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
if ( bRetry)
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
if ( ! vUniformedCurves.empty()) {
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
//debug
#endif
// controllo che tutte le curve siano chiuse, sennò vuol dire che ho perso qualche pezzo durante le intersezioni
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i) {
if ( ! vUniformedCurves[i]->IsClosed() && ! vUniformedCurves[i]->Close())
return false ;
}
// creo una regione dalle curve riscalate
SurfFlatRegionByContours sfrRescaled ;
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i)
sfrRescaled.AddCurve( Release( vUniformedCurves[i])) ;
PtrOwner<ISurfFlatRegion> pRescaledSfr( sfrRescaled.GetSurf()) ;
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
}
else
return false ;
}
else if( ! vbUniform[0] || ! vbUniform[1])
return false ;
if ( ! bRescaledU && ! bRescaledV)
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
+2735 -468
View File
File diff suppressed because it is too large Load Diff
+20 -13
View File
@@ -20,6 +20,7 @@
#include "SurfTriMesh.h"
#include "SurfFlatRegion.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkGeoCollection.h"
//----------------------------------------------------------------------------
@@ -115,18 +116,17 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
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 ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 10 * EPS_SMALL, bool bUpdateEdges = false) 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 GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined = false) 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
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 = IntLineTriaType::ILTT_IN) 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
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev = P_INVALID, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
// 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).
@@ -136,17 +136,26 @@ 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 non è trimmata restituisce un vettore di 4 elementi. Se la superficie è chiusa lungo un parametro i lati algi estremi di quel parametro saranno null.
// restituisce un vettore con i loop della superficie ( più di uno solo se è trimmata con un parametrico con buchi o più di un chunk)
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const override ;
// restituisce il singolo edge della superficie non trimmata
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const override ;
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 CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr) 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 ;
PNTVECTOR GetAllControlPoints( void) const ;
PNTVECTOR GetAllControlPoints( void) const override ;
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
bool RemoveCollapsedSpans( void) override ;
bool SwapParameters( void) ;
bool LimitSurfToTrimmedRegion( void) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -200,8 +209,6 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
// 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 ;
// funzione che calcola se gli edge sono collassati in poli
bool CalcPoles( void) const ;
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ;
@@ -220,8 +227,8 @@ 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 ( gli edge a V=0 e V=1 coincidono)
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V ( gli edge a U=0 e U=1 coincidono)
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
+189 -35
View File
@@ -28,6 +28,13 @@
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#define SAVECLASSCRV 0
#define SAVEADJUSTCRV 0
#if SAVECLASSCRV || SAVEADJUSTCRV
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ;
//----------------------------------------------------------------------------
@@ -56,6 +63,7 @@ SurfFlatRegion::Clear( void)
for ( auto& pLoop : m_vpLoop)
delete pLoop ;
m_vpLoop.clear() ;
m_vExtInd.clear() ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
@@ -106,8 +114,20 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
pMyCrv->SetThickness( 0) ;
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
ICURVEPLIST CrvLst ;
#if SAVEADJUSTCRV
SaveGeoObj( pMyCrv->Clone(), "D:\\Temp\\inters\\CrvCrvInters\\before_adjust.nge") ;
#endif
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
return false ;
#if SAVEADJUSTCRV
for ( auto& pSingCrv : CrvLst)
vGeo.push_back( pSingCrv->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\after_adjust.nge") ;
#endif
// aggiungo le singole curve
int nExtAdded = 0 ;
bool bOk = true ;
@@ -168,14 +188,18 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
Vector3d vtExtr ;
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
pMyCrv->SetExtrusion( Z_AX) ;
// verifico non abbia auto-intersezioni che si attraversano o si sovrappongano
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// verifico che sia esterna alle curve esterne degli altri chunk
bool bOk = true ;
CRVCVECTOR ccClass ;
for ( auto i : m_vExtInd) {
#if SAVEADJUSTCRV
vGeo.clear() ;
vGeo.push_back( pMyCrv->Clone()) ;
vGeo.push_back( m_vpLoop[i]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\during_add_simpleExt.nge") ;
#endif
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
@@ -215,14 +239,9 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
bool
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
{
try {
m_vpLoop.push_back( pCrv) ;
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
m_nStatus = OK ;
}
catch (...) {
return false ;
}
m_vpLoop.push_back( pCrv) ;
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
m_nStatus = OK ;
return true ;
}
@@ -303,10 +322,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
// sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0)
if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
pMyCrv->Invert() ;
// verifico non abbia auto-intersezioni
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// ricerca del chunk in cui andrebbe inserito
int nChunk = -1 ;
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
@@ -353,23 +369,18 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
bool
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
{
try {
// se da aggiungere all'ultimo chunk
if ( nChunk == -1)
m_vpLoop.push_back( pCrv) ;
// altrimenti aggiungo al chunck indicato
else {
int nLoopCnt = GetLoopCount( nChunk) ;
if ( nLoopCnt == 0)
return false ;
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
++ m_vExtInd[i] ;
}
}
catch (...) {
return false ;
//se da aggiungere all'ultimo chunk
if ( nChunk == -1)
m_vpLoop.push_back( pCrv) ;
//altrimenti aggiungo al chunck indicato
else {
int nLoopCnt = GetLoopCount( nChunk) ;
if ( nLoopCnt == 0)
return false ;
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
++ m_vExtInd[i] ;
}
return true ;
@@ -1373,6 +1384,15 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
// intersezione
#if SAVECLASSCRV
//debug
vector<IGeoObj*> vGeo ;
vGeo.push_back( Crv.Clone()) ;
vGeo.push_back( pLoop->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\crv_and_loop.nge") ;
#endif
IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione
CRVCVECTOR ccPart ;
@@ -1536,7 +1556,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
int nClass = ccInt.GetRegionCurveClassification() ;
switch ( nClass){
switch ( nClass) {
default : // CCREGC_NULL
return REGC_NULL ;
case CCREGC_IN1 :
@@ -1549,7 +1569,141 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
return REGC_OUT ;
case CCREGC_INTERS :
return REGC_INTERS ;
}
}
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const
{
bInterference = false ;
// verifico lo stato e il numero di chunk
if ( m_nStatus != OK || m_vpLoop.empty() || nChunk >= GetChunkCount())
return false ;
// recupero rappresentazione base dell'altra regione
const SurfFlatRegion& Reg2 = *GetBasicSurfFlatRegion( &Other) ;
// verifico lo stato e il numero di chunk dell'altra regione
if ( Reg2.m_nStatus != OK || Reg2.m_vpLoop.empty() || nOthChunk >= Reg2.GetChunkCount())
return false ;
// verifico che le due regioni giacciano in piani paralleli
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
return false ;
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
int nClass = GetChunkSimpleClassification( nChunk, Other, nOthChunk) ;
if ( nClass == REGC_NULL)
return false ;
// se le regioni non hanno isole, allora ho già identificato se i Chunks fanno interferenza
int nLoopCnt = GetLoopCount( nChunk) ;
int nOtherLoopCnt = Other.GetLoopCount( nOthChunk) ;
if ( nLoopCnt == 1 && nOtherLoopCnt == 1) {
bInterference = ( nClass != REGC_OUT) ;
return true ;
}
// --- a prescindere dalle isole presenti nei 2 Chunks in esame :
// se i due loop esterni si intersecano tra loro o sono gli stessi, allora fanno per forza interferenza
if ( nClass == REGC_INTERS || nClass == CCREGC_SAME) {
bInterference = true ;
return true ;
}
// se invece sono esterni tra loro, allora non c'è interferenza
else if ( nClass == REGC_OUT)
return true ;
// --- Analisi del loop interni :
// se la curva esterna corrente è interna alla curva esterna dell'altro chunk
else if ( nClass == REGC_IN1) {
// se l'altro chunk non ha isole, c'è interferenza (a prescinere da numero di loop interni del primo chunk)
if ( nOtherLoopCnt == 1) {
bInterference = true ;
return true ;
}
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
// per ogni loop interno (isole)
for ( int i = 1 ; i < nOtherLoopCnt ; ++ i) {
const ICurve* pCrv2Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_frF, Reg2.m_frF))
pCrv2Loc = Reg2.GetMyLoop( nOthChunk, i) ;
else {
pCopyCrv.Set( Reg2.GetMyLoop( nOthChunk, i)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( Reg2.m_frF, m_frF) ;
pCrv2Loc = pCopyCrv ;
}
// classifico il loop esterno del chunk della prima regione rispetto all'interno corrente del chunk della seconda
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
int nInternalClass = ccInt.GetRegionCurveClassification() ;
// se le curve non sono classificabili, errore
if ( nInternalClass == REGC_NULL)
return false ;
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
else if ( nInternalClass == REGC_IN1)
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
else if ( nInternalClass == REGC_OUT)
return true ;
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
bInterference = true ;
return true ;
}
// negli altri casi ho un orientamento errato dei loop o delle regioni
else
return false ;
}
}
// se la curva esterna dell'altro chunk è interna alla curva esterna corrente
else if ( nClass == REGC_IN2) {
// se l'altro chunk non ha isole, c'è interferenza
if ( nLoopCnt == 1) {
bInterference = true ;
return true ;
}
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv2Loc = Reg2.GetMyLoop( nChunk, 0) ;
// per ogni loop interno (isole)
for ( int i = 1 ; i < nLoopCnt ; ++ i) {
const ICurve* pCrv1Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( Reg2.m_frF, m_frF))
pCrv1Loc = GetMyLoop( nOthChunk, i) ;
else {
pCopyCrv.Set( GetMyLoop( nOthChunk, i)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( m_frF, Reg2.m_frF) ;
pCrv1Loc = pCopyCrv ;
}
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
IntersCurveCurve ccInt( *pCrv2Loc, *pCrv1Loc) ;
int nInternalClass = ccInt.GetRegionCurveClassification() ;
// se le curve non sono classificabili, errore
if ( nInternalClass == REGC_NULL)
return false ;
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
else if ( nInternalClass == REGC_IN1)
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
else if ( nInternalClass == REGC_OUT)
return true ;
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
bInterference = true ;
return true ;
}
// negli altri casi ho un orientamento errato dei loop o delle regioni
else
return false ;
}
}
// in questo la curva di bordo è interna ad ogni isola ma interna anche al loop esterno, quindi esiste interferenza
bInterference = true ;
return true ;
}
//----------------------------------------------------------------------------
+2
View File
@@ -107,6 +107,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
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 CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const override ; // compare alls
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
int GetLoopCount( int nChunk) const override ;
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
@@ -139,6 +140,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ;
friend class MyCAvSimpleSurfFrMove ;
friend class MyCAvSurfFrMove ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
+13
View File
@@ -20,6 +20,12 @@
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#define SAVELOOPS 0
#if SAVELOOPS
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ;
//----------------------------------------------------------------------------
@@ -172,6 +178,13 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
pSfr.Set( new( nothrow) SurfFlatRegion) ;
else
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
#if SAVELOOPS
for (int i = 0 ; i < ssize( vpLoop) ; ++i)
vGeo.push_back( vpLoop[i]) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\NewLoops.nge") ;
#endif
if ( IsNull( pSfr)) {
MyTestAndDelete( vpCurve) ;
MyTestAndDelete( vpLoop) ;
+85 -9
View File
@@ -517,9 +517,9 @@ SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const
// verifico esistenza del vertice
if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL)
return false ;
// recupero i dati
dU = m_vVert[nId].dU ;
dV = m_vVert[nId].dV ;
// recupero i dati (verso l'esterno sempre in 0..1..2..3..)
dU = m_vVert[nId].dU / PREC_SCALE_COEFF ;
dV = m_vVert[nId].dV / PREC_SCALE_COEFF ;
return true ;
}
@@ -870,15 +870,21 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
if ( nPos == -1)
return false ;
// medio le normali, finch non incontro degli spigoli
vtN = m_vTria[nT].vtN ;
// medio le normali, finchè non incontro degli spigoli
double dAngW = 1 ;
GetTriangleVertexAngle( nT, nV, dAngW) ;
vtN = dAngW * m_vTria[nT].vtN ;
// parto dal triangolo e vado in direzione positiva
int nLim = nPos ;
for ( int i = NextIndAroundVertex( nPos, nTria, bCirc) ;
i != nPos && i < int( vT.size()) ;
i = NextIndAroundVertex( i, nTria, bCirc)) {
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng)
vtN += m_vTria[vT[i]].vtN ;
if ( m_vTria[nT].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) {
int nK ; double dAngW = 1 ;
if ( FindVertexInTria( m_vTria[nT].nIdVert[nV], vT[i], nK) &&
GetTriangleVertexAngle( vT[i], nK, dAngW))
vtN += dAngW * m_vTria[vT[i]].vtN ;
}
else
break ;
nLim = i ;
@@ -887,8 +893,12 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
for ( int i = PrevIndAroundVertex( nPos, nTria, bCirc) ;
i != nLim && i >= 0 ;
i = PrevIndAroundVertex( i, nTria, bCirc)) {
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng)
vtN += m_vTria[vT[i]].vtN ;
if ( m_vTria[nT].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) {
int nK ; double dAngW = 1 ;
if ( FindVertexInTria( m_vTria[nT].nIdVert[nV], vT[i], nK) &&
GetTriangleVertexAngle( vT[i], nK, dAngW))
vtN += dAngW * m_vTria[vT[i]].vtN ;
}
else
break ;
}
@@ -897,6 +907,23 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetTriangleVertexAngle( int nT, int nV, double& dAng) const
{
// verifico esistenza del triangolo e validità vertice
if ( nT < 0 || nT >= GetTriangleSize() || m_vTria[nT].nIdVert[0] == SVT_DEL || nV < 0 || nV > 2)
return false ;
// determino i vettori dei due lati che partono dal vertice
Point3d ptVert = m_vVert[ m_vTria[nT].nIdVert[nV]].ptP ;
Point3d ptPrev = m_vVert[ m_vTria[nT].nIdVert[Prev( nV)]].ptP ;
Point3d ptNext = m_vVert[ m_vTria[nT].nIdVert[Next( nV)]].ptP ;
Vector3d vtPrev = ptPrev - ptVert ;
Vector3d vtNext = ptNext - ptVert ;
// determino l'angolo tra i due lati
return vtPrev.GetAngle( vtNext, dAng) ;
}
//----------------------------------------------------------------------------
SurfTriMesh*
SurfTriMesh::CloneTriangle( int nT) const
@@ -1340,6 +1367,8 @@ SurfTriMesh::GetTitle( void) const
bool
SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const
{
// visualizzazione spigoli
sOut += "ShowEdges=" + ToString( GetShowEdges()) + szNewLine ;
// area
double dArea ;
GetArea( dArea) ;
@@ -4386,6 +4415,35 @@ SurfTriMesh::ClonePart( int nPart) const
return Release( pSurfTM) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const
{
// l'indice della faccia deve essere nei limiti
if ( nFacet < 0 || nFacet >= int( m_vFacet.size()))
return false ;
// mi assicuro che siano calcolate il numero di parti e di shell
int nParts = GetPartCount() ;
int nTria = m_vFacet[nFacet] ;
nShell = m_vTria[nTria].nShell ;
// scopro in quale part è la shell
int nPartTemp = 0 ;
nPart = - 1 ;
while ( nPartTemp < nParts && nPart == - 1) {
for ( int i : m_vPart[nPartTemp].vShell) {
if ( i == nShell) {
nPart = nPartTemp ;
break ;
}
}
++nPartTemp ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::ResetTFlags( void)
@@ -4512,3 +4570,21 @@ SurfTriMesh::AdjustTopologyFromZMap( void)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetTriaFromFace( int nF, int& nT) const
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico stato sfaccettatura
if ( ! VerifyFaceting())
return false ;
// l'indice della faccia deve essere nei limiti
if ( nF < 0 || nF >= int( m_vFacet.size()))
return false ;
// recupero la normale di un triangolo della faccetta
nT = m_vFacet[nF] ;
return true ;
}
+5
View File
@@ -322,6 +322,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetEdge( int nInd, int& nV1, int& nV2, int& nFl, int& nFr, double& dAng) const override ;
bool GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) const override ;
bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ;
bool GetCurvature( int nV,
double& dMinK, Vector3d& vtMinK, double& dMaxK, Vector3d& vtMaxK, bool& bPlanar, Vector3d& vtNorm) const override ;
bool Cut( const Plane3d& plPlane, bool bSaveOnEq) override ;
bool GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) override ;
bool Add( const ISurfTriMesh& Other) override ;
@@ -345,6 +347,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetPartVolume( int nPart, double& dVolume) const override ;
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
SurfTriMesh* ClonePart( int nPart) const override ;
bool GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const override ;
bool SetTFlag( int nId, int nTFlag) override ;
bool GetTFlag( int nId, int& nFlag) const override ;
int GetMaxTFlag( void) const override
@@ -378,6 +381,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool SetTempInt( int nId, int nTempInt) const ;
bool AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol = 2 * EPS_SMALL) ;
bool AdjustTopologyFromZMap( void) ;
bool GetTriaFromFace( int nF, int& nT) const ;
private :
typedef std::vector<StmVert> VERTVECTOR ;
@@ -411,6 +415,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
int NextIndAroundVertex( int nInd, int nSize, bool bCirc) const ;
int PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const ;
bool GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const ;
bool GetTriangleVertexAngle( int nT, int nV, double& dAng) const ;
bool MarchAlongLoop( int nT, int nV, int nTimeStamp, PolyLine& PL) const ;
bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ;
+1 -1
View File
@@ -41,7 +41,7 @@
using namespace std ;
//----------------------------------------------------------------------------
const double BOOLEAN_SCALE = 1024 ;
const double BOOLEAN_SCALE = PREC_SCALE_COEFF ;
//----------------------------------------------------------------------------
bool
+1 -1
View File
@@ -26,7 +26,7 @@
using namespace std ;
//----------------------------------------------------------------------------
const double CUT_SCALE = 1024 ;
const double CUT_SCALE = PREC_SCALE_COEFF ;
//----------------------------------------------------------------------------
bool
+167 -19
View File
@@ -21,6 +21,8 @@
#include <array>
#include <set>
#include <unordered_map>
#define EIGEN_NO_IO
#include "/EgtDev/Extern/Eigen/Dense"
using namespace std ;
@@ -54,7 +56,7 @@ SurfTriMesh::UpdateFaceting( void)
bool bOk = true ;
for ( int j = 0 ; j < int( vOldFacet.size()) ; ++ j) {
int i = vOldFacet[j] ;
// salto triangoli inesistenti o già assegnati
// salto triangoli inesistenti o già assegnati
if ( i >= int( m_vTria.size()) ||
m_vTria[i].nIdVert[0] == SVT_DEL ||
m_vTria[i].nIdFacet != SVT_NULL)
@@ -69,7 +71,7 @@ SurfTriMesh::UpdateFaceting( void)
// ricostruisco le altre sfaccettature
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
m_vTria[i].nIdFacet != SVT_NULL)
continue ;
@@ -103,7 +105,7 @@ SurfTriMesh::UpdateOneFace( int nFacet, int nT)
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( nT) ;
// finchè set non vuoto
// finchè set non vuoto
bool bOk = true ;
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
@@ -421,7 +423,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 0 è di contorno
// se il lato 0 è di contorno
else if ( nAdjF[0] != nF) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
@@ -433,7 +435,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 1 è di contorno
// se il lato 1 è di contorno
else if ( nAdjF[1] != nF) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
@@ -445,7 +447,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
if ( ! MarchAlongFacetLoop( nF, nT, 2, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 2 è di contorno
// se il lato 2 è di contorno
else if ( nAdjF[2] != nF) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
@@ -457,7 +459,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
if ( ! MarchAlongFacetLoop( nF, nT, 0, m_nTimeStamp, vPL.back()))
return false ;
}
// altrimenti non c'è contorno
// altrimenti non c'è contorno
else {
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
@@ -476,7 +478,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
return false ;
// se loop esterno
if ( vtN * plPlane.GetVersN() > 0) {
// se non c'è ancora loop esterno in prima posizione
// se non c'è ancora loop esterno in prima posizione
if ( ! bOutFirst) {
// lo sposto in prima posizione
if ( i != 0)
@@ -517,7 +519,7 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
// verifico appartenga alla stessa faccia
if ( m_vTria[nAdjT].nIdFacet != nF)
return false ;
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
int nAdjS = SVT_NULL ;
for ( int i = 0 ; i < 3 ; ++ i) {
if ( m_vTria[nAdjT].nIdAdjac[i] == nT) {
@@ -531,11 +533,11 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
return false ;
// vertice di fine adiacenza e indice del successivo lato
int nAdjV = Next( nAdjS) ;
// verifico se il lato successivo è un bordo
// verifico se il lato successivo è un bordo
int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
int nNextF = ( nNextT != SVT_NULL ? m_vTria[nNextT].nIdFacet : SVT_NULL) ;
if ( nNextF != nF) {
// se già recuperato
// se già recuperato
if ( m_vTria[nAdjT].nTemp == nTimeStamp) {
bEnd = true ;
return true ;
@@ -593,7 +595,7 @@ SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Po
// verifico esistenza seconda faccia
if ( nF2 < 0 || nF2 >= int( m_vFacet.size()))
return false ;
// verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto
// verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto
bAdjac = false ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
double dUs, dUe ;
@@ -606,7 +608,7 @@ SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Po
ptP2 = ptPe ;
}
else {
// parametri del segmento già definito
// parametri del segmento già definito
Vector3d vtT ;
double dLen ;
DirDist( ptP1, ptP2, vtT, dLen) ;
@@ -646,7 +648,7 @@ SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
POLYLINEVECTOR vPL ;
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
return false ;
// calcolo il centro del loop esterno (è il primo)
// calcolo il centro del loop esterno (è il primo)
PolygonPlane PolyPlane ;
Point3d ptP ;
for ( bool bFound = vPL[0].GetFirstPoint( ptP) ; bFound ; bFound = vPL[0].GetNextPoint( ptP))
@@ -730,7 +732,7 @@ SurfTriMesh::CloneFacet( int nF) const
// ciclo sui tre vertici
int nIdV[3] ;
for ( int j = 0 ; j < 3 ; ++ j) {
// verifico se vertice già presente
// verifico se vertice già presente
const auto it = PntMap.find( m_vTria[nT].nIdVert[j]) ;
if ( it == PntMap.end()) {
// aggiungo il vertice
@@ -773,7 +775,7 @@ SurfTriMesh::RemoveFacet( int nF)
if ( ! DoCompacting())
return false ;
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
@@ -878,7 +880,7 @@ SurfTriMesh::UpdateFacetEdging( void)
m_bFacEdged = false ;
m_vFacEdge.clear() ;
// verifico validità sfaccettatura
// verifico validità sfaccettatura
if ( ! VerifyFaceting())
return false ;
@@ -957,7 +959,7 @@ SurfTriMesh::GetEdge( int nInd, int& nV1, int& nV2, int& nFl, int& nFr, double&
// verifico stato bordi sfaccettatura
if ( ! VerifyFacetEdging())
return false ;
// verifico la validità dell'indice
// verifico la validità dell'indice
if ( nInd < 0 || nInd > int( m_vFacEdge.size()))
return SVT_NULL ;
// recupero i dati
@@ -980,7 +982,7 @@ SurfTriMesh::GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) cons
// verifico stato bordi sfaccettatura
if ( ! VerifyFacetEdging())
return false ;
// verifico la validità dell'indice
// verifico la validità dell'indice
if ( nInd < 0 || nInd > int( m_vFacEdge.size()))
return SVT_NULL ;
// recupero i dati
@@ -1015,3 +1017,149 @@ SurfTriMesh::GetEdges( ICURVEPOVECTOR& vpCurve) const
}
return true ;
}
//-----------------------------------------------------------------------------
// Funzione per il calcolo della curvatura massima e minima in un vertice della superficie TriMesh
// dMinK : curvatura minima
// vtMinK : versore direzione curvatura minima
// dMaxK : curvatura massima
// vtMaxK : versore direzione curvatura massima
// bPlanar : Flag per indicare le superficie localmente piana
// vtNorm : versore normale del piano tangente alla supericie nel vertice
bool
SurfTriMesh::GetCurvature( int nV,
double& dMinK, Vector3d& vtMinK, double& dMaxK, Vector3d& vtMaxK, bool& bPlanar, Vector3d& vtNorm) const
{
// Controllo la validità della TriMesh e del Vertice
if ( ! IsValid())
return false ;
Point3d ptCurr ;
if ( ! GetVertex( nV, ptCurr))
return false ;
bPlanar = false ;
// Recupero tutti i vertici attorno al vertice corrente ( se presenza di lato libero, allora errore)
INTVECTOR vT ;
bool bCirc ;
if ( ! GetAllTriaAroundVertex( nV, vT, bCirc) || ! bCirc)
return false ;
// Calcolo la normale del vertice pesata mediante angolo sotteso e distanza baricentrica
// ["Estimation Normal Vector of Triangular Mesh Vertex by Angle and Centroid Weights"]
// Controllo anche di non essere in presenza di uno spigolo vivo
INTSET setIndTriaNeightbors ;
bool bFirstTria = true ;
Vector3d vtNFirstTria = V_NULL ;
for ( const int& nT : vT) {
// Recupero il triangolo corrente
Triangle3d Tria ;
int nIdVert[3] ;
if ( ! GetTriangle( nT, Tria) || ! GetTriangle( nT, nIdVert))
return false ;
// Se il triangolo ha area troppo piccola, lo scarto
if ( Tria.GetArea() < EPS_SMALL)
continue ;
// Se primo triangolo salvo la sua normale di riferimento per successivi confronti
if ( bFirstTria) {
vtNFirstTria = Tria.GetN() ;
bFirstTria = false ;
}
else {
// Se spigolo vivo, la curvatura non può esistere
if ( Tria.GetN() * vtNFirstTria < m_dCosSmAng - EPS_SMALL)
return false ;
}
// Recupero le direzioni delle semirette per l'angolo al vertice corrente
Vector3d vtDir0 = V_NULL, vtDir1 = V_NULL ;
for ( int i = 0 ; i < 3 ; ++ i) {
if ( AreSamePointApprox( Tria.GetP( i), ptCurr)) {
vtDir0 = Tria.GetP( ( i + 1) % 3) - Tria.GetP( i) ;
vtDir0.Normalize() ;
vtDir1 = Tria.GetP( ( i + 2) % 3) - Tria.GetP( i) ;
vtDir1.Normalize() ;
break ;
}
}
for ( int i = 0 ; i < 3 ; ++ i) {
if ( nV == nIdVert[i]) {
setIndTriaNeightbors.insert( nIdVert[( i + 1) % 3]) ;
setIndTriaNeightbors.insert( nIdVert[( i + 2) % 3]) ;
break ;
}
}
// Calcolo l'angolo sotteso
double dCosTheta = max( -1., min( 1., ( vtDir0 * vtDir1))) ;
double dTheta = acos( dCosTheta) ;
// Calcolo la distanza baricentrica
double dSqBarDist = max( EPS_SMALL, ( ptCurr - Tria.GetCentroid()).SqLen()) ;
// Aggiorno il contributo della normale al vertice
vtNorm += ( ( dTheta / dSqBarDist) * Tria.GetN()) ;
}
vtNorm.Normalize() ;
// [ESTIMATING CURVATURE ON TRIANGULAR MESHES, cap. 2.1. Fitting Methods,
// par. 2.1.2. Quadric Fitting]
// [https://people.eecs.berkeley.edu/~jrs/meshpapers/GatzkeGrimm.pdf]
// Definisco il piano tangente al vertice corrente
Plane3d plTan ;
if ( ! plTan.Set( ptCurr, vtNorm))
return false ;
// Proietto i punti Neightbors(1) sul piano tangete ( senza ripeterli)
BIPNTVECTOR vPtPtProj ; vPtPtProj.reserve( setIndTriaNeightbors.size()) ;
for ( auto nIter = setIndTriaNeightbors.begin() ; nIter != setIndTriaNeightbors.end() ; ++ nIter) {
Point3d ptNeightbors ;
if ( ! GetVertex( *nIter, ptNeightbors))
return false ;
vPtPtProj.emplace_back( make_pair( ptNeightbors, ProjectPointOnPlane( ptNeightbors, plTan))) ;
}
// Recupero due versori perpendicolari nel piano definito
Vector3d vtTan1 = V_NULL ;
if ( abs( vtNorm.x) < 1./64. && abs( vtNorm.y) < 1./64.)
vtTan1 = Y_AX ^ vtNorm ;
else
vtTan1 = Z_AX ^ vtNorm ;
vtTan1.Normalize() ;
Vector3d vtTan2 = vtNorm ^ vtTan1 ;
vtTan2.Normalize() ;
// Sistema da risolvere mediante minimi quadrati : z(u,v) = Au^2 + Buv + Cv^2
// Questo sistema è molto più semplice e robusto rispetto a z(u,v) = Au^2 + Buv + Cv^2 + Du + Ev + F
// per il fatto che ora le coordinate sono in locale al piano tangente alla superficie ( mettendo
// quindi a 0 i coefficienti del primo ordine e il termine noto F)
// Definizione della matrice A(Nx3)
const int nPts = int( vPtPtProj.size()) ;
Eigen::MatrixXd mat_A( nPts, 3) ;
Eigen::VectorXd vec_b( nPts) ;
for ( int i = 0 ; i < nPts ; ++ i) {
Vector3d vtEdgeProj = vPtPtProj[i].second - ptCurr ;
Vector3d vtEdge = ( vPtPtProj[i].first - vPtPtProj[i].second) ;
double dU = vtEdgeProj * vtTan1 ;
double dV = vtEdgeProj * vtTan2 ;
double dW = vtEdge * vtNorm ;
mat_A( i, 0) = dU * dU ;
mat_A( i, 1) = dU * dV ;
mat_A( i, 2) = dV * dV ;
vec_b( i) = dW ;
}
// Risoluzione del sistema
Eigen::VectorXd vec_x = mat_A.colPivHouseholderQr().solve( vec_b) ;
// Costruzione della matrice hessiana
Eigen::Matrix2d mat_H {{ 2. * vec_x( 0), vec_x( 1)},
{ vec_x( 1), 2. * vec_x( 2)}} ;
// Calcolo gli autovalori ( quindi le curvature principali) e restituisco i risultati
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> Solver( mat_H) ;
dMinK = Solver.eigenvalues()( 0) ;
dMaxK = Solver.eigenvalues()( 1) ;
Eigen::Vector2d dir_Min = Solver.eigenvectors().col( 0) ;
Eigen::Vector2d dir_Max = Solver.eigenvectors().col( 1) ;
vtMinK = dir_Min( 0) * vtTan1 + dir_Min( 1) * vtTan2 ;
vtMaxK = dir_Max( 0) * vtTan1 + dir_Max( 1) * vtTan2 ;
bPlanar = ( abs( dMinK) < EPS_SMALL && abs( dMaxK) < EPS_SMALL) ;
return true ;
}
+642 -93
View File
@@ -9,6 +9,7 @@
// Modifiche : 10.06.25 RE Creazione modulo.
// 10.06.25 RE Offset di superfici chiuse.
// 04.07.25 RE Thickening Offset di superfici generiche.
// 10.12.25 RE Creazione superfici Shell.
//
//----------------------------------------------------------------------------
@@ -16,11 +17,17 @@
#include "stdafx.h"
#include "VolZmap.h"
#include "SurfTriMesh.h"
#include "EgtDev/Include/EGkDistPointSurfTm.h"
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointTria.h"
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include <future>
#define DEBUG 0
#if DEBUG
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
@@ -58,6 +65,255 @@ SumStm( const CISURFTMPVECTOR& vStm)
return ( Release( pStmAdd)) ;
}
//----------------------------------------------------------------------------
// Funzioni per la distanza tra punto e superficie TriMesh in parallelo
//----------------------------------------------------------------------------
static bool
BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff)
{
// svuoto il risultato
vBoxDiff.clear() ;
// se box A vuoto, risultato vuoto
if ( boxA.IsEmpty())
return false ;
// 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) ;
return true ;
}
// recupero i punti estremi dei box A e Intersezione
Point3d ptMinA, ptMaxA ; boxA.GetMinMax( ptMinA, ptMaxA) ;
Point3d ptMinInt, ptMaxInt ; boxInt.GetMinMax( ptMinInt, ptMaxInt) ;
// sotto
if ( ptMinInt.z - ptMinA.z > EPS_SMALL) {
BBox3d boxD( ptMinA, Point3d( ptMaxA.x, ptMaxA.y, ptMinInt.z)) ;
vBoxDiff.emplace_back( boxD) ;
}
// sopra
if ( ptMaxA.z - ptMaxInt.z > EPS_SMALL) {
BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMaxInt.z), ptMaxA) ;
vBoxDiff.emplace_back( boxD) ;
}
// davanti
if ( ptMinInt.y - ptMinA.y > EPS_SMALL) {
BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMinInt.z), Point3d( ptMaxA.x, ptMinInt.y, ptMaxInt.z)) ;
vBoxDiff.emplace_back( boxD) ;
}
// dietro
if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) {
BBox3d boxD( Point3d( ptMinA.x, ptMaxInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxA.y, ptMaxInt.z)) ;
vBoxDiff.emplace_back( boxD) ;
}
// sinistra
if ( ptMinInt.x - ptMinA.x > EPS_SMALL) {
BBox3d boxD( Point3d( ptMinA.x, ptMinInt.y, ptMinInt.z), Point3d( ptMinInt.x, ptMaxInt.y, ptMaxInt.z)) ;
vBoxDiff.emplace_back( boxD) ;
}
// destra
if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) {
BBox3d boxD( Point3d( ptMaxInt.x, ptMinInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxInt.y, ptMaxInt.z)) ;
vBoxDiff.emplace_back( boxD) ;
}
// risultato
return ( ! vBoxDiff.empty()) ;
}
//----------------------------------------------------------------------------
static bool
DistPointSurfTmMultiThread( const Point3d& ptP, const SurfTriMesh& SurfTm, double& dDist,
bool& bIsInside, INTVECTOR& vIndClosestTria)
{
// verifico che la supercicie sia valida
if ( ! SurfTm.IsValid())
return false ;
// inizializzo distanza non calcolata
dDist = - 1. ;
// vettore di indici dei triangoli più vicini inizialmente vuoto
vIndClosestTria.clear() ;
// vettore dei flag temporanei inizialmente tutto a 0
INTVECTOR vIntFlags( SurfTm.GetTriangleCount(), 0) ;
// recupero e verifico il box locale della superficie
BBox3d b3Stm = SurfTm.GetAllTriaBox() ;
if ( b3Stm.IsEmpty())
return false ;
// 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 ;
double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ;
double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ;
// considero anche il box precedente per poter analizzare solo il volume differenza tra i due
BBox3d boxPPrev( ptP) ;
BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ;
// variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima
double dMinDist = DBL_MAX ;
int nMinDistTriaIndex = SVT_NULL ;
Point3d ptMinDistPoint ;
// finché non si verifica la condizione di terminazione ingrandisco il box.
bool bContinue = true ;
// 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
BOXVECTOR vBox ;
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
// Ciclo sui box differenza
bool bCollide = false ;
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.DistFromPoint( ptP) > dMinDist)
continue ;
// ricerca sui triangoli nel box
bCollide = true ;
INTVECTOR vnIds ;
if ( SurfTm.GetAllTriaOverlapBox( b3Int, vnIds)) {
// ciclo sui triangoli del sotto-box corrente
for ( auto nT : vnIds) {
Triangle3d trCurTria ;
if ( vIntFlags[nT] == 0 && SurfTm.GetTriangle( nT, trCurTria)) {
vIntFlags[nT] = 1 ;
DistPointTriangle distPT( ptP, trCurTria) ;
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) ;
// aggiungo il triangolo
vTria.emplace_back( make_pair( nT, trCurTria)) ;
}
}
}
}
}
}
// se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
if ( ! bCollide || dMinDist < EPS_SMALL)
bContinue = false ;
else {
boxPPrev = boxP ;
boxP.Expand( dDeltaLen) ;
}
}
// se non ho trovato nessun triangolo, errore
if ( nMinDistTriaIndex == SVT_NULL)
return false ;
// riempio il vettore dei triangoli a minima distanza
for ( auto& Tria : vTria)
vIndClosestTria.emplace_back( Tria.first) ;
// salvo la distanza
dDist = dMinDist ;
// determino il Side
if ( dDist < EPS_SMALL) {
bIsInside = false ;
return true ;
}
// se ho solo un triangolo
else if ( int( vTria.size()) == 1) {
bIsInside = ( ( ptP - ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ;
return true ;
}
// controllo se tutti i triangoli a minima distanza forniscono la stessa informazione
// ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito )
bool bInside = false ;
bool bOutside = false ;
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) {
if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL)
bInside = true ;
else
bOutside = true ;
}
bIsInside = false ;
if ( bOutside == bInside) {
Point3d ptBar_tot ;
for ( const auto& Tria : vTria)
ptBar_tot += Tria.second.GetCentroid() ;
for ( const auto& Tria : vTria) {
Point3d ptInters1, ptInters2 ;
int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ;
if ( nType == ILTT_IN) {
DistPointTriangle( ptP, Tria.second).GetMinDistPoint( ptMinDistPoint) ;
bIsInside = ( ( ptP - ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ;
nMinDistTriaIndex = Tria.first ;
break ;
}
}
}
else
bIsInside = bInside ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ClassifyTrianglesMultiThread( const TRIA3DEXVECTOR& vTria, int nIndS, int nIndE,
const SurfTriMesh& SurfTm, double dOffs, double dPrec,
bool bSaveInside, BOOLVECTOR& vbSafe)
{
// verifico che la superficie sia valida
if ( ! SurfTm.IsValid())
return false ;
// verifico la validità degli indici
if ( nIndS < 0 || nIndE >= int( vTria.size()))
return false ;
// verifico la dimensione dei vettori
if ( vTria.size() != vbSafe.size())
return false ;
// scorro gli indici dei triangoli da classificare
for ( int k = nIndS ; k <= nIndE ; ++ k) {
// recupero il triangolo corrente
const Triangle3dEx& Tria = vTria[k] ;
// preparo gli elementi di classificazione
DBLVECTOR vDists ; vDists.resize( 3) ;
INTMATRIX matIndClosestTria ; matIndClosestTria.resize( 3) ;
// verifico che i suoi punti siano distanti almeno |dOffs| - dTol dalla superficie
vbSafe[k] = true ;
for ( int i = 0 ; vbSafe[k] && i < 3 ; ++ i) {
bool bIsInside = false ;
DistPointSurfTmMultiThread( Tria.GetP( i), SurfTm, vDists[i], bIsInside, matIndClosestTria[i]) ;
vbSafe[k] = ( ( vDists[i] > abs( dOffs) - 0.25 * dPrec) &&
( vDists[i] < abs( dOffs) + 0.25 * dPrec) &&
( bIsInside == bSaveInside)) ;
}
// se tutti sufficientemente distanti
if ( vbSafe[k]) {
// i triangoli a minima distanza devono avere normale simile
bool bPerp = true ;
for ( int i = 0 ; bPerp && i < 3 ; ++ i) {
for ( int j = 0 ; bPerp && j < int( matIndClosestTria[i].size()) ; ++ j) {
Triangle3d TriaCloser ;
SurfTm.GetTriangle( matIndClosestTria[i][j], TriaCloser) ;
bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < cos( 30. * DEGTORAD)) ;
}
}
vbSafe[k] = ( ! bPerp) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione che crea l'Offset di una superficie TriMesh
//----------------------------------------------------------------------------
@@ -94,123 +350,138 @@ CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPr
return SumStm( vStm) ;
// creo lo Zmap associato alle superfici TriMesh
VolZmap OneVolZmap ;
if ( ! OneVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
VolZmap myVolZmap ;
if ( ! myVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
return nullptr ;
if ( ! OneVolZmap.IsValid())
if ( ! myVolZmap.IsValid())
return nullptr ;
// recupero le superfici aperte
CISURFTMPVECTOR vStmOpen ;
for ( const ISurfTriMesh* pStm : vStm) {
if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed())
if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed())
vStmOpen.emplace_back( pStm) ;
}
// --- se non ho superfici aperte
if ( vStmOpen.empty()) {
// restituisco la superficie TriMesh di Offset
return ( OneVolZmap.GetSurfTriMesh()) ;
return ( myVolZmap.GetSurfTriMesh()) ;
}
// --- se ho delle superfici aperte
// lo Zmap creato è orientato e definisce una superficie chiusa; devo rimuovere i triangoli in eccesso
// anzitutto controllo che lo Zmap sia valido
if ( ! OneVolZmap.IsValid())
return nullptr ;
// inzializzo la superficie TriMesh da restituire
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->Init( 3, 1))
return nullptr ;
PointGrid3d VertGrid ; VertGrid.Init( 50000) ;
// tolleranza di vicinanza alla superficie
double dTolDist = 30. * EPS_SMALL ;
#if DEBUG
VT.emplace_back( OneVolZmap.Clone()) ;
VC.emplace_back( BLACK) ;
#endif
// ciclo lungo i blocchi dello ZMap
for ( int nB = 0 ; nB < OneVolZmap.GetBlockCount() ; ++ nB) {
// recupero i triangoli
// --- se ho delle superfici chiuse
TRIA3DEXVECTOR vAllTria, vTriaOffs ;
for ( int nB = 0 ; nB < myVolZmap.GetBlockCount() ; ++ nB) {
TRIA3DEXVECTOR vTria, vTriaSafe ;
OneVolZmap.GetBlockTriangles( nB, vTria) ;
// un triangolo viene ritenuto valido se è non è troppo vicino ( dOffs) alle superfici aperte
myVolZmap.GetBlockTriangles( nB, vTria) ;
#if DEBUG
TRIA3DVECTOR vTriaUnsafe ;
#endif
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
// recupero il triangolo
Triangle3dEx& Tria = vTria[nT] ;
// scorro le superficie aperte
bool bInsert = true ;
for ( int nS = 0 ; bInsert && nS < int( vStm.size()) ; ++ nS) {
// controllo se posso inserirlo
vector<DistPointSurfTm> vDistPtStm ;
for ( int i = 0 ; i < 3 && bInsert ; ++ i) {
double dDist = 0. ;
vDistPtStm.emplace_back( DistPointSurfTm( Tria.GetP( i), *vStm[nS])) ;
bInsert = ( vDistPtStm.back().GetDist( dDist) && dDist > abs( dOffs) - dTolDist) ;
}
// se il triangolo è al più a distanza di |dOffs| - dTolDist
if ( bInsert) {
// recupero i triangoli a distanza minima dai vertici del triangolo corrente
bool bPerp = true ;
for ( int i = 0 ; i < 3 && bPerp ; ++ i) {
INTVECTOR vTria ;
vDistPtStm[i].GetMinDistTriaIndices( vTria) ;
for ( int j = 0 ; j < int( vTria.size()) && bPerp ; ++ j) {
Triangle3d TriaCloser ;
vStm[nS]->GetTriangle( vTria[j], TriaCloser) ;
bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < dTolDist) ;
}
}
// se tutti i triangoli a distanza minima sono perpendicolari, allora non lo inserisco
bInsert = ( ! bPerp) ;
BBox3d BBoxTria ;
Tria.GetLocalBBox( BBoxTria) ;
// azzero flag di colore
vAllTria.push_back( Tria) ;
}
}
// classifico i triangoli
PtrOwner<const SurfTriMesh> pStmBasic( nullptr) ;
if ( int( vStmOpen.size() == 1))
pStmBasic.Set( GetBasicSurfTriMesh( CloneSurfTriMesh( vStmOpen[0]))) ;
else {
StmFromTriangleSoup AllOpenStmSoup ; AllOpenStmSoup.Start() ;
for ( const ISurfTriMesh* pStmOpen : vStmOpen) {
if ( pStmOpen != nullptr && pStmOpen->IsValid()) {
for ( int nT = 0 ; nT < pStmOpen->GetTriangleCount() ; ++ nT) {
Triangle3d Tria ;
if ( pStmOpen->GetTriangle( nT, Tria))
AllOpenStmSoup.AddTriangle( Tria) ;
}
}
// se triangolo da inserire
if ( bInsert)
vTriaSafe.emplace_back( Tria) ;
#if DEBUG
ICurveComposite* pCompo = CreateCurveComposite() ;
pCompo->AddPoint( Tria.GetP( 0)) ;
pCompo->AddLine( Tria.GetP( 1)) ;
pCompo->AddLine( Tria.GetP( 2)) ;
pCompo->Close() ;
Color myCol = ( bInsert ? Color( 0., 1., 0., .5) : Color( 1., 0., 0., .5)) ;
VT.emplace_back( CloneCurveComposite( pCompo)) ;
VC.emplace_back( myCol) ;
ISurfFlatRegion* pSfrTria = CreateSurfFlatRegion() ;
pSfrTria->AddExtLoop( pCompo) ;
VT.emplace_back( pSfrTria) ;
VC.emplace_back( myCol) ;
#endif
}
// inserisco tutti i triangoli validi
if ( ! pStm->AddTriaFromZMap( vTriaSafe, VertGrid))
return nullptr ;
AllOpenStmSoup.End() ;
pStmBasic.Set( GetBasicSurfTriMesh( AllOpenStmSoup.GetSurf())) ;
}
if ( pStmBasic == nullptr)
return nullptr ;
BBox3d b3Stm = pStmBasic->GetAllTriaBox() ;
if ( b3Stm.IsEmpty())
return nullptr ;
// numero di triangoli da analizzare
int nTriaCnt = int( vAllTria.size()) ;
// definisco un vettore di Flag per i triangoli già visitati
INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ;
// numero massimo di thread concorrenti
int nThreadMax = thread::hardware_concurrency() ;
bool bOk = true ;
BOOLVECTOR vbSafeTria( vAllTria.size(), true) ;
if ( nThreadMax <= 1 || nTriaCnt < 50)
ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, abs( dOffs), dPrec, ( dOffs < 0.), vbSafeTria) ;
else {
const int MAX_PARTS = 32 ;
INTINTVECTOR vFstLst( MAX_PARTS) ;
// calcolo le parti del vettore
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
int nPartDim = nTriaCnt / nPartCnt + 1 ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
vFstLst[i].first = i * nPartDim ;
vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ;
}
// processo le parti
future<bool> vRes[MAX_PARTS] ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first,
vFstLst[i].second, cref( *pStmBasic), abs( dOffs), dPrec, ( dOffs < 0.), ref( vbSafeTria)) ;
}
// attendo i risultati
int nFin = 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 ( ! bOk)
return nullptr ;
TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ;
#if DEBUG
TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ;
#endif
for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) {
if ( vbSafeTria[i])
vTriaSafe.emplace_back( vAllTria[i]) ;
#if DEBUG
if ( ! vbSafeTria[i])
vTriaUnSafe.emplace_back( vAllTria[i]) ;
#endif
}
// definisco la superficie con i soli triangoli validi
StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ;
for ( const Triangle3d& SafeTria : vTriaSafe)
TriaSoup.AddTriangle( SafeTria) ;
TriaSoup.End() ;
PtrOwner<ISurfTriMesh> pStmOffs( TriaSoup.GetSurf()) ;
if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0)
return nullptr ;
#if DEBUG
StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ;
for ( const Triangle3d& _unsafeTria : vTriaUnSafe)
_invalidSoup.AddTriangle( _unsafeTria) ;
_invalidSoup.End() ;
VT.emplace_back( pStmOffs->Clone()) ;
VC.emplace_back( LIME) ;
VT.emplace_back( _invalidSoup.GetSurf()) ;
VC.emplace_back( RED) ;
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
#endif
// sistemo la topologia
if ( ! pStm->AdjustTopologyFromZMap())
return nullptr ;
return ( Release( pStm)) ;
return ( Release( pStmOffs)) ;
}
//----------------------------------------------------------------------------
@@ -240,3 +511,281 @@ CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs,
// restituisco la superficie TriMesh
return ( OneVolZmap.GetSurfTriMesh()) ;
}
//----------------------------------------------------------------------------
// Funzione per creare la Superficie TriMesh Shell da una Trimesh aperta
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshShell( const ISurfTriMesh* pStm, double dThick, double dPrec)
{
// verifico che la superficie sia valida ed aperta
if ( pStm == nullptr || ! pStm->IsValid() || pStm->IsClosed())
return nullptr ;
// lo spessore deve essere sempre positivo, il verso è sempre dato dalla normale dei triangoli
dThick = - max( 10. * EPS_SMALL, abs( dThick)) ;
// creo il suo Offset ( salvandomi lo Zmap per l'orientamento)
#if DEBUG
PerformanceCounter PC ; PC.Start() ;
#endif
VolZmap myVolZMap ;
if ( ! myVolZMap.CreateFromTriMeshOffset( { pStm}, dThick, dPrec))
return nullptr ;
if ( ! myVolZMap.IsValid())
return nullptr ;
#if DEBUG
LOG_INFO( GetEGkLogger(), ( string{ "Tria Time : "} + ToString( PC.Stop())).c_str()) ;
VT.clear() ; VC.clear() ;
VT.emplace_back( myVolZMap.Clone()) ;
VC.emplace_back( BLACK) ;
VT.emplace_back( pStm->Clone()) ;
VC.emplace_back( YELLOW) ;
SaveGeoObj( VT, VC, "C:\\Temp\\VolZMapOffs.nge") ;
#endif
#if DEBUG
VT.clear() ; VC.clear() ;
PC.Start() ;
#endif
// recupero i triangoli dallo ZMap creato
TRIA3DEXVECTOR vAllTria, vTriaOffs ;
for ( int nB = 0 ; nB < myVolZMap.GetBlockCount() ; ++ nB) {
TRIA3DEXVECTOR vTria, vTriaSafe ;
myVolZMap.GetBlockTriangles( nB, vTria) ;
#if DEBUG
TRIA3DVECTOR vTriaUnsafe ;
#endif
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
Triangle3dEx& Tria = vTria[nT] ;
BBox3d BBoxTria ;
Tria.GetLocalBBox( BBoxTria) ;
// azzero flag di colore
vAllTria.push_back( Tria) ;
}
}
// classifico i triangoli
const SurfTriMesh* pStmBasic = GetBasicSurfTriMesh( pStm) ;
if ( pStmBasic == nullptr)
return nullptr ;
BBox3d b3Stm = pStmBasic->GetAllTriaBox() ;
if ( b3Stm.IsEmpty())
return nullptr ;
// numero di triangoli da analizzare
int nTriaCnt = int( vAllTria.size()) ;
// definisco un vettore di Flag per i triangoli già visitati
INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ;
// numero massimo di thread concorrenti
int nThreadMax = thread::hardware_concurrency() ;
bool bOk = true ;
BOOLVECTOR vbSafeTria( vAllTria.size(), true) ;
if ( nThreadMax <= 1 || nTriaCnt < 50)
ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, dThick, dPrec, true, vbSafeTria) ;
else {
const int MAX_PARTS = 32 ;
INTINTVECTOR vFstLst( MAX_PARTS) ;
// calcolo le parti del vettore
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
int nPartDim = nTriaCnt / nPartCnt + 1 ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
vFstLst[i].first = i * nPartDim ;
vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ;
}
// processo le parti
future<bool> vRes[MAX_PARTS] ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first,
vFstLst[i].second, cref( *pStmBasic), dThick, dPrec, true, ref( vbSafeTria)) ;
}
// attendo i risultati
int nFin = 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 ( ! bOk)
return nullptr ;
TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ;
#if DEBUG
TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ;
#endif
for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) {
if ( vbSafeTria[i])
vTriaSafe.emplace_back( vAllTria[i]) ;
#if DEBUG
if ( ! vbSafeTria[i])
vTriaUnSafe.emplace_back( vAllTria[i]) ;
#endif
}
// definisco la superficie con i soli triangoli validi
StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ;
for ( const Triangle3d& SafeTria : vTriaSafe)
TriaSoup.AddTriangle( SafeTria) ;
TriaSoup.End() ;
PtrOwner<ISurfTriMesh> pStmOffs( TriaSoup.GetSurf()) ;
if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0)
return nullptr ;
#if DEBUG
LOG_INFO( GetEGkLogger(), ( string{ "Tria Time ( exceed Approx) : "} + ToString( PC.Stop())).c_str()) ;
StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ;
for ( const Triangle3d& _unsafeTria : vTriaUnSafe)
_invalidSoup.AddTriangle( _unsafeTria) ;
_invalidSoup.End() ;
VT.emplace_back( pStmOffs->Clone()) ;
VC.emplace_back( LIME) ;
VT.emplace_back( _invalidSoup.GetSurf()) ;
VC.emplace_back( RED) ;
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
VT.clear() ; VC.clear() ;
PC.Start() ;
#endif
// recupero i loops della superficie originaria e del suo Offset orientato ( non devono essere diminuiti)
POLYLINEVECTOR vPL, vPLOffs ;
if ( ! pStm->GetLoops( vPL) || ! pStmOffs->GetLoops( vPLOffs))
return nullptr ;
// trasformo ogni loop in curve composite ( devono essere chiuse)
ICRVCOMPOPOVECTOR vCompoLoops ; vCompoLoops.reserve( vPL.size()) ;
for ( const PolyLine& PL : vPL) {
if ( PL.IsClosed()) {
if ( ! vCompoLoops.emplace_back( CreateCurveComposite()) ||
! vCompoLoops.back()->FromPolyLine( PL) ||
! vCompoLoops.back()->IsValid())
return nullptr ;
}
}
ICRVCOMPOPOVECTOR vCompoOffsLoops ; vCompoOffsLoops.reserve( vPLOffs.size()) ;
for ( const PolyLine& PLOffs : vPLOffs) {
if ( PLOffs.IsClosed()) {
if ( ! vCompoOffsLoops.emplace_back( CreateCurveComposite()) ||
! vCompoOffsLoops.back()->FromPolyLine( PLOffs) ||
! vCompoOffsLoops.back()->IsValid())
return nullptr ;
}
}
#if DEBUG
VT.emplace_back( pStmOffs->Clone()) ;
VC.emplace_back( YELLOW) ;
for ( ICurveComposite* pCompo : vCompoLoops) {
VT.emplace_back( pCompo->Clone()) ;
VC.emplace_back( AQUA) ;
}
for ( ICurveComposite* pCompoOffs : vCompoOffsLoops) {
VT.emplace_back( pCompoOffs->Clone()) ;
VC.emplace_back( ORANGE) ;
}
SaveGeoObj( VT, VC, "C:\\Temp\\myCurve.nge") ;
VT.clear() ; VC.clear() ;
#endif
// per ogni curva della superficie originale cerco la sua associata
// NB. per la creazione della superficie ruled la prima curva è quellla che determina il verso
// dei triangoli associati. Per un corretto ed automatico orientamento della superficie
// la prima curva deve essere sempre definita dalla superficie originale ed invertita ( le
// curve nella rigata devono seguire lo stesso orientamento
ISURFTMPOVECTOR vStmRuled ; vStmRuled.reserve( vCompoLoops.size()) ;
BOOLVECTOR vIndMatched( vCompoOffsLoops.size(), false) ;
for ( ICurveComposite* pCompoLoop : vCompoLoops) {
// sposto il punto iniziale della curva nel tratto più lungo
double dMaxLen = - INFINITO ;
int nIndCrv = 0 ;
for ( int nCrv = 0 ; nCrv < pCompoLoop->GetCurveCount() ; ++ nCrv) {
const ICurve* pCurve = pCompoLoop->GetCurve( nCrv) ;
if ( pCurve != nullptr && pCurve->IsValid()) {
double dCurrLen = 0. ;
pCurve->GetLength( dCurrLen) ;
if ( dCurrLen > dMaxLen) {
dMaxLen = dCurrLen ;
nIndCrv = nCrv ;
}
}
}
pCompoLoop->ChangeStartPoint( nIndCrv + 0.5) ;
Point3d ptStart ; pCompoLoop->GetStartPoint( ptStart) ;
// dalle altre curve derivanti dalla superficie di Offset cerco quella più vicina al punto inziale
double dMinSqDist = INFINITO ;
int nIndOffsCrv = -1 ;
Point3d ptMinDist ;
for ( int nOffsCrv = 0 ; nOffsCrv < int( vCompoOffsLoops.size()) ; ++ nOffsCrv) {
if ( vIndMatched[nOffsCrv])
continue ;
// recupero la curva e calcolo la distanza
const ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nOffsCrv] ;
int nFlag = 0 ;
Point3d ptCurrMinDist ;
if ( DistPointCurve( ptStart, *pCompoOffsLoop).GetMinDistPoint( 0., ptCurrMinDist, nFlag)) {
double dCurrSqDist = SqDist( ptStart, ptCurrMinDist) ;
if ( dCurrSqDist < dMinSqDist) {
dMinSqDist = dCurrSqDist ;
nIndOffsCrv = nOffsCrv ;
ptMinDist = ptCurrMinDist ;
}
}
}
if ( nIndOffsCrv == -1)
return nullptr ;
vIndMatched[ nIndOffsCrv] = true ;
// associo le due curve
ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nIndOffsCrv] ;
double dParMinDist = 0. ;
pCompoOffsLoop->GetParamAtPoint( ptMinDist, dParMinDist, 10. * EPS_SMALL) ;
pCompoOffsLoop->ChangeStartPoint( dParMinDist) ;
#if DEBUG
Color _cCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ;
VT.emplace_back( pCompoLoop->Clone()) ;
VC.emplace_back( _cCol) ;
VT.emplace_back( pCompoOffsLoop->Clone()) ;
VC.emplace_back( _cCol) ;
#endif
// creo la superficie tra queste due curve e la oriento in modo da definire un volume
pCompoLoop->Invert() ;
PtrOwner<ISurfTriMesh> pStmRuled( GetSurfTriMeshRuled( pCompoLoop, pCompoOffsLoop, ISurfTriMesh::RuledType::RLT_MINDIST)) ;
if ( IsNull( pStmRuled) || ! pStmRuled->IsValid() ||
! vStmRuled.emplace_back( Release( pStmRuled)))
return nullptr ;
#if DEBUG
LOG_INFO( GetEGkLogger(), ( string{ "Strip generation : "} + ToString( PC.Stop())).c_str()) ;
VT.emplace_back( vStmRuled.back()->Clone()) ;
VC.emplace_back( _cCol) ;
_cCol.SetAlpha( .5) ;
#endif
}
#if DEBUG
SaveGeoObj( VT, VC, "C:\\Temp\\Strips.nge") ;
PC.Start() ;
#endif
// compongo la superficie finale
PtrOwner<ISurfTriMesh> pStmOrig( CloneSurfTriMesh( pStm)) ;
if ( IsNull( pStmOrig) || ! pStmOrig->IsValid())
return nullptr ;
PtrOwner<ISurfTriMesh> pStmRef( Release( pStmOrig)) ;
if ( IsNull( pStmRef) || ! pStmRef->IsValid())
return nullptr ;
for ( int nStrip = 0 ; nStrip < int( vStmRuled.size()) ; ++ nStrip) {
if ( ! pStmRef->DoSewing( *vStmRuled[nStrip]))
return nullptr ;
}
if ( ! pStmRef->DoSewing( *pStmOffs))
return nullptr ;
pStmRef->Repair() ;
#if DEBUG
LOG_INFO( GetEGkLogger(), ( string{ "Sewing : "} + ToString( PC.Stop())).c_str()) ;
#endif
return ( ( ! IsNull( pStmRef) && pStmRef->IsValid()) ? Release( pStmRef) : nullptr) ;
}
+10 -10
View File
@@ -36,25 +36,25 @@ class Tool
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; }
int GetType() const
int GetType( void) const
{ return m_nType ; }
int GetToolNum() const
int GetToolNum( void) const
{ return m_nCurrentNum ; }
double GetHeigth() const
double GetHeigth( void) const
{ return m_dHeight ; }
double GetTipHeigth() const
double GetTipHeigth( void) const
{ return m_dTipHeight ; }
double GetRadius() const
double GetRadius( void) const
{ return m_dRadius ; }
double GetTipRadius() const
double GetTipRadius( void) const
{ return m_dTipRadius ; }
double GetCornRadius() const
double GetCornRadius( void) const
{ return m_dRCorner ; }
double GetRefRadius() const
double GetRefRadius( void) const
{ return m_dRefRadius ; }
double GetMrtChsWidth() const
double GetMrtChsWidth( void) const
{ return m_dMrtChsWidth ; }
double GetMrtChsThickness() const
double GetMrtChsThickness( void) const
{ return m_dMrtChsThickness ; }
const CurveComposite& GetOutline( void) const
{ return ( m_Outline) ; }
+355 -136
View File
File diff suppressed because it is too large Load Diff
+38 -24
View File
@@ -20,12 +20,11 @@
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include <map>
#include "/EgtDev/Extern/abseil/Include/absl/algorithm/container.h"
#include "/EgtDev/Extern/abseil/Include/absl/container/flat_hash_map.h"
#include <utility>
struct PairHashInt64 {
size_t operator()(const std::pair<int64_t, int64_t>& key) const {
size_t
operator()( const std::pair<int64_t, int64_t>& key) const {
size_t h1 = std::hash<int64_t>{}(key.first) ;
size_t h2 = std::hash<int64_t>{}(key.second) ;
return h1 ^ (h2 << 1); // Combine hashes
@@ -35,14 +34,20 @@ struct PairHashInt64 {
//----------------------------------------------------------------------------
struct Inters {
int nIn ;
PNTVECTOR vpt ;
int nOut ;
PNTVECTOR vpt ;
bool bCCW ;
int nChunk ;
bool bSortedbyStart ;
// riordino le intersezioni per lato in senso antiorario dal top
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool operator < ( Inters& b)
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
// riordino le intersezioni per lato in senso antiorario dal top
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool
operator < ( Inters& b)
{
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
@@ -77,7 +82,8 @@ struct Inters {
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
}
static bool FirstEncounter( Inters& a, Inters& b)
static bool
FirstEncounter( Inters& a, Inters& b)
{
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
@@ -137,18 +143,18 @@ struct Inters {
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
}
bool operator == ( Inters& b)
bool
operator == ( Inters& b)
{
return AreSamePointExact( vpt[0], b.vpt[0]) ;
}
bool operator != ( Inters& b)
bool
operator != ( Inters& b)
{
return ! AreSamePointExact( vpt[0], b.vpt[0]) ;
}
} ;
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
//----------------------------------------------------------------------------
class Cell
@@ -162,17 +168,24 @@ class Cell
// | |
// |_________________|
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
public :
enum Collapsed { TO_VERIFY = -1, // da verificare
NO_COLLAPSE = 0, // non ho coppie di lati collassati
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
public :
~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_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( false), m_nRightEdgeIn( -1),
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ORIG),
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_nCollapsed( -1), m_ptPbl( ORIG),
m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) {}
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_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( 0), m_nRightEdgeIn( -1),
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ptBL),
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_nCollapsed( -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) ; }
@@ -233,6 +246,7 @@ class Cell
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
int m_nCollapsed ; // flag che indica se la coppia di lati verticali (1) o orizzontali(2) sono collassati
private :
Point3d m_ptPbl ; // punto bottom left
@@ -253,7 +267,7 @@ class Tree
bool BuildTree( double dLinTol = LIN_TOL_STD,
double dSideMin = 1, // è la minima lunghezza del lato di una cella
double dSideMax = INFINITO) ; // è la massima dimensione di un triangolo della trimesh
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, std::vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops) ;
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, std::vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops, bool bUpdateEdges) ;
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
@@ -278,10 +292,10 @@ class Tree
bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
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
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato top ( la coppia di double è per dare un intervallo diverso su cui limitare i vicini)
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato left
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato right
void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario
void 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
@@ -314,7 +328,7 @@ class Tree
private :
const SurfBezier* m_pSrfBz ; // superficie di bezier
bool m_bTrimmed ; // superficie trimmata
absl::flat_hash_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch
@@ -325,10 +339,10 @@ 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
absl::flat_hash_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
mutable absl::flat_hash_map<std::pair<int64_t,int64_t>,Point3d,PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
mutable std::unordered_map<std::pair<int64_t,int64_t>,Point3d,PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
INTVECTOR m_vnLeaves ; // vettore delle foglie
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo 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.
} ;
} ;
+5398
View File
File diff suppressed because it is too large Load Diff
+424 -119
View File
@@ -1,4 +1,4 @@
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// EgalTech 2015-2016
//----------------------------------------------------------------------------
// File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4
@@ -29,8 +29,21 @@
#include <thread>
#include <future>
#define DEBUG_REMOVE_FINS 0
#if DEBUG_REMOVE_FINS
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
std::vector<IGeoObj*> VT ;
std::vector<Color> VC ;
#endif
using namespace std ;
#if !defined(_WIN64)
int VolZmap::m_nDexelNbr = 0 ;
#endif
//----------------------------------------------------------------------------
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
@@ -55,6 +68,13 @@ VolZmap::VolZmap(void)
//----------------------------------------------------------------------------
VolZmap::~VolZmap( void)
{
// Se versione 32-bit aggiorno il numero di Dexel complessivi rimuovendo il numero dei correnti
#if !defined(_WIN64)
int nDexelNbr = 0 ;
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
nDexelNbr += m_nDim[i] ;
m_nDexelNbr = max( 0, m_nDexelNbr - nDexelNbr) ;
#endif
}
//----------------------------------------------------------------------------
@@ -75,6 +95,13 @@ VolZmap::Clear( void)
m_nNumBlock = 0 ;
m_nConnectedCompoCount = 0 ;
m_MapFrame.Reset() ;
// Se versione 32-bit aggiorno il numero di Dexel complessivi rimuovendo il numero dei correnti
#if !defined(_WIN64)
int nDexelNbr = 0 ;
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
nDexelNbr += m_nDim[i] ;
m_nDexelNbr = max( 0, m_nDexelNbr - nDexelNbr) ;
#endif
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
m_nNy[i] = 0 ;
@@ -133,6 +160,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
m_nFracLin[0] = vzmSrc.m_nFracLin[0] ;
m_nFracLin[1] = vzmSrc.m_nFracLin[1] ;
m_nFracLin[2] = vzmSrc.m_nFracLin[2] ;
m_nDexVoxRatio = vzmSrc.m_nDexVoxRatio ;
m_nConnectedCompoCount = vzmSrc.m_nConnectedCompoCount ;
m_MapFrame = vzmSrc.m_MapFrame ;
@@ -208,6 +236,10 @@ VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const
{
// tipo
sOut += "Type=" + string( m_nMapNum == 1 ? "dexel" : "tridexel") + szNewLine ;
// visualizzazione spigoli
sOut += "ShowEdges=" + ToString( GetShowEdges()) + szNewLine ;
// dexel per voxel (DexToVoxRatio)
sOut += "DexVoxRat=" + ToString( m_nDexVoxRatio) + szNewLine ;
// forma
switch ( m_nShape) {
default : sOut += "Shape=generic" ; break ;
@@ -229,8 +261,6 @@ VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const
// numero di blocchi
sOut += "Blocks=" + ToString( m_nNumBlock) + " (" + ToString( m_nFracLin[0]) + "x" +
ToString( m_nFracLin[1]) + "x" + ToString( m_nFracLin[2]) + ")" + szNewLine ;
// dexel per voxel (DexToVoxRatio)
sOut += "DexVoxRat=" + ToString( m_nDexVoxRatio) + szNewLine ;
return true ;
}
@@ -504,11 +534,15 @@ VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
}
// passo al punto successivo
dX += m_dStep ;
if ( m_nMapNum == N_MAPS)
dX = min( dX, m_dMaxZ[1]) ;
}
// passo alla riga successiva
dY += m_dStep ;
if ( m_nMapNum == N_MAPS)
dY = min( dY, m_dMaxZ[2]) ;
}
//
return true ;
}
@@ -548,9 +582,13 @@ VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
}
// passo al punto successivo
dX += m_dStep ;
if ( m_nMapNum == N_MAPS)
dX = min( dX, m_dMaxZ[1]) ;
}
// passo alla riga successiva
dY += m_dStep ;
if ( m_nMapNum == N_MAPS)
dY = min( dY, m_dMaxZ[2]) ;
}
return true ;
@@ -563,10 +601,10 @@ VolZmap::GetPartLocalBBox( int nPart, BBox3d& b3Loc, int nFlag) const
// Verifico lo stato.
if ( m_nStatus != OK)
return false ;
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1)
return false ;
// Se la componente richiesta non esiste, vi è un errore.
// Se la componente richiesta non esiste, vi è un errore.
if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1)
return false ;
// Calcolo Bounding-box
@@ -614,10 +652,10 @@ VolZmap::GetPartBBox( int nPart, const Frame3d& frRef, BBox3d& b3Ref, int nFlag)
// Verifico lo stato.
if ( m_nStatus != OK)
return false ;
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1)
return false ;
// Se la componente richiesta non esiste, vi è un errore.
// Se la componente richiesta non esiste, vi è un errore.
if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1)
return false ;
// Calcolo Bounding-box
@@ -689,7 +727,7 @@ VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità dell'asse di rotazione
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
@@ -722,7 +760,7 @@ VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del piano di specchiatura
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
@@ -736,7 +774,7 @@ VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità dei parametri
// verifico validità dei parametri
if ( vtNorm.IsSmall() || vtDir.IsSmall())
return false ;
@@ -750,11 +788,11 @@ VolZmap::ToGlob( const Frame3d& frRef)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
@@ -773,11 +811,11 @@ VolZmap::ToLoc( const Frame3d& frRef)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
@@ -796,11 +834,11 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità dei frame
// verifico validità dei frame
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
return false ;
// se i due riferimenti coincidono, non devo fare alcunché
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
@@ -816,10 +854,10 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
int
VolZmap::GetPartCount( void) const
{
// Se mono-dexel la connessione è incalcolabile.
// Se mono-dexel la connessione è incalcolabile.
if ( m_nMapNum == 1)
return - 1 ;
// Se il numero delle componenti è indefinito
// Se il numero delle componenti è indefinito
// lo ricalcolo e restituisco il risultato.
if ( m_nConnectedCompoCount == - 1) {
const_cast<VolZmap*>(this)->CheckMapConnection() ;
@@ -870,7 +908,7 @@ VolZmap::CheckMapConnection( void)
IntervalsToProcessStackVec.resize( nThreadMax) ;
// Mi espando dal primo intervallo mettendo gli intervalli che intersecano nei vari thread
FirstExpansionFromZ( nThreadMax, NewInt, IntervalsToProcessStackVec) ;
// Lancio in parallelo più ricerche
// Lancio in parallelo più ricerche
int nActiveThread = 0 ;
vector<future<bool>> vRes ;
vRes.resize( nThreadMax) ;
@@ -891,7 +929,7 @@ VolZmap::CheckMapConnection( void)
}
}
}
// Se l'intervallo non attraversa un nodo o ha già
// Se l'intervallo non attraversa un nodo o ha già
// un indice assegnato salto questa iterazione.
else
continue ;
@@ -935,7 +973,7 @@ VolZmap::ExpandFromXInterval( IntContainer& IntCont)
double dZmin = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMin ;
double dZmax = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dZmin - 2 * EPS_SMALL < dZ &&
dZmax + 2 * EPS_SMALL > dZ &&
@@ -955,7 +993,7 @@ VolZmap::ExpandFromXInterval( IntContainer& IntCont)
double dYmin = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMin ;
double dYmax = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dYmin - 2 * EPS_SMALL < dY &&
dYmax + 2 * EPS_SMALL > dY &&
@@ -1006,7 +1044,7 @@ VolZmap::ExpandFromYInterval( IntContainer& IntCont)
double dZmin = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMin ;
double dZmax = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dZmin - 2 * EPS_SMALL < dZ &&
dZmax + 2 * EPS_SMALL > dZ &&
@@ -1026,7 +1064,7 @@ VolZmap::ExpandFromYInterval( IntContainer& IntCont)
double dXmin = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMin ;
double dXmax = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dXmin - 2 * EPS_SMALL < dX &&
dXmax + 2 * EPS_SMALL > dX &&
@@ -1077,7 +1115,7 @@ VolZmap::ExpandFromZInterval( IntContainer& IntCont)
double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ;
double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dXmin - 2 * EPS_SMALL < dX &&
dXmax + 2 * EPS_SMALL > dX &&
@@ -1097,7 +1135,7 @@ VolZmap::ExpandFromZInterval( IntContainer& IntCont)
double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ;
double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dYmin - 2 * EPS_SMALL < dY &&
dYmax + 2 * EPS_SMALL > dY &&
@@ -1146,7 +1184,7 @@ VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContaine
double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ;
double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dXmin - 2 * EPS_SMALL < dX &&
dXmax + 2 * EPS_SMALL > dX &&
@@ -1167,7 +1205,7 @@ VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContaine
double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ;
double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha già un indice assegnato, assegno l'indice e
// ha già un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dYmin - 2 * EPS_SMALL < dY &&
dYmax + 2 * EPS_SMALL > dY &&
@@ -1214,13 +1252,13 @@ VolZmap::ClonePart( int nPart) const
// verifico lo stato
if ( m_nStatus != OK)
return nullptr ;
// Se è definita una sola griglia non sono definibili le parti, errore
// Se è definita una sola griglia non sono definibili le parti, errore
if ( m_nMapNum == 1)
return nullptr ;
// Se è richiesta una componente fuori intervallo, errore
// Se è richiesta una componente fuori intervallo, errore
if ( nPart < 0 || nPart >= m_nConnectedCompoCount)
return nullptr ;
// Se il numero di componenti è indefinito, lo ricalcolo.
// Se il numero di componenti è indefinito, lo ricalcolo.
if ( m_nConnectedCompoCount == - 1)
const_cast<VolZmap*>(this)->CheckMapConnection() ;
// Se non vi sono componenti, errore
@@ -1291,7 +1329,7 @@ VolZmap::ClonePart( int nPart) const
pVolume->m_Values[nMap].resize( pVolume->m_nDim[nMap]) ;
}
// Se almeno una griglia è nulla, non ha senso Zmap
// Se almeno una griglia è nulla, non ha senso Zmap
if ( pVolume->m_nDim[0] == 0 ||
pVolume->m_nDim[1] == 0 ||
pVolume->m_nDim[2] == 0)
@@ -1343,8 +1381,8 @@ VolZmap::ClonePart( int nPart) const
dNewOy = nMinIndJ[0] * m_dStep ;
dNewOz = nMinIndJ[1] * m_dStep ;
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
// Quote estreme Z
switch ( nMap) {
@@ -1407,10 +1445,10 @@ VolZmap::RemovePart( int nPart)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// Se è definita una sola griglia non sono definibili le parti, errore
// Se è definita una sola griglia non sono definibili le parti, errore
if ( m_nMapNum == 1)
return false ;
// Se il numero di componenti è indefinito, lo ricalcolo
// Se il numero di componenti è indefinito, lo ricalcolo
if ( m_nConnectedCompoCount == - 1)
CheckMapConnection() ;
// Se non vi sono componenti, abbiamo finito
@@ -1452,7 +1490,7 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
// Verifico lo stato e che siano definibili le componenti connesse
if ( m_nStatus != OK || m_nMapNum == 1)
return - 1 ;
// Se il numero di componenti è indefinito, lo ricalcolo
// Se il numero di componenti è indefinito, lo ricalcolo
if ( m_nConnectedCompoCount == -1)
const_cast<VolZmap*>( this)->CheckMapConnection() ;
// Se non vi sono componenti, abbiamo finito
@@ -1485,7 +1523,7 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
swap( ptEn.y, ptEn.z) ;
swap( ptEn.x, ptEn.z) ;
}
// Calcolo la distanza del punto dal segmento corrente. Se è minore della minima distanza aggiorno quest'ultima
// Calcolo la distanza del punto dal segmento corrente. Se è minore della minima distanza aggiorno quest'ultima
// e la corrispondente componente connessa di minima distanza con la distanza e la componente connessa correnti.
double dDist ;
DistPointLine DistCalc( ptPL, ptSt, ptEn) ;
@@ -1677,88 +1715,356 @@ VolZmap::SubtractSurfTm( const ISurfTriMesh* pStm)
//----------------------------------------------------------------------------
bool
VolZmap::MakeUniform( double dToler)
VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
{
// controllo validità dello Zmap
// Controllo validità dello Zmap
if ( ! IsValid())
return false ;
// la tolleranza deve essere minore dello step
dToler = min( dToler, 0.95 * m_dStep) ;
// creo lo Zmpa che andrà a sostituire il corrente
PtrOwner<VolZmap> pOldVolZmap( CloneBasicVolZmap( this)) ;
if ( IsNull( pOldVolZmap))
// Creo lo ZMap per i riferimenti degli intervalli sulle griglie
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
return false ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// salvo lo Zmap prima di modificare gli spilloni
PtrOwner<VolZmap> pVolZMapCurrGrid( CloneBasicVolZmap( this)) ;
if ( IsNull( pVolZMapCurrGrid))
// Creo uno ZMap per gli intervalli da aggiungere o da rimuovere
PtrOwner<VolZmap> pZMapExtra( CreateBasicVolZmap()) ;
if ( IsNull( pZMapExtra) ||
! pZMapExtra->CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
m_dStep, IsTriDexel()))
return false ;
// ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
// se il dexel corrente non ha sotto-intervalli passo al successivo
if ( int( m_Values[nGrid][nDex].size()) == 0)
// Dovendo effettuare estensioni, allargo gli ingobri nelle direzioni principali
m_dMinZ[0] -= dToler ;
m_dMinZ[1] -= dToler ;
m_dMinZ[2] -= dToler ;
m_dMaxZ[0] += dToler ;
m_dMaxZ[1] += dToler ;
m_dMaxZ[2] += dToler ;
// NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente
// Ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti nella Copia
for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) {
// Se il dexel corrente non ha sotto-intervalli passo al successivo
if ( pZMapCopy->m_Values[nGrid][nDex].empty())
continue ;
// indici del dexel
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// salvo le informazioni dei sotto-intervalli del dexel corrente
vector<Data> vInfo ;
for ( int nExtr = 0 ; nExtr < int( m_Values[nGrid][nDex].size()) ; ++ nExtr)
vInfo.push_back( m_Values[nGrid][nDex][nExtr]) ;
// per ogni sotto-intervallo, estendo a destra e a sinistra della tolleranza
int nSub_intervals = int( vInfo.size()) ;
// scorro gli intervalli
for ( int nInfo = 0 ; nInfo < int( pVolZMapCurrGrid->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// estremo inferiore
if ( vInfo[nInfo].dMin - dToler > m_dMinZ[nGrid]) {
AddIntervals( nGrid, nI, nJ,
vInfo[nInfo].dMin - dToler,
vInfo[nInfo].dMin + dToler,
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, vInfo[nInfo].nToolMin,
true) ;
// se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due
// direzioni nel voxel corrispondente
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
// l'intervallo corrente si è unito con il precedente...
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMin, dToler,
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN,
vInfo[nInfo].nToolMin) ;
// Recupero il numero di intervalli presenti nel Dexel corrente
int nIntervals = ssize( pZMapCopy->m_Values[nGrid][nDex]) ;
// Scorro gli intervalli presenti
for ( int nInfo = 0 ; nInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nInfo) {
// Recupero l'intervallo corrente
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
// --- Se richiesta prima estensione
if ( bIsExtensionFirst) {
// *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ]
// Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler,
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) {
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente)
// ( lascio invariato lo ZMapCopy)
nIntervals = ssize( m_Values[nGrid][nDex]) ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax, Interval.dMin,
dToler, true, nToolNum, V_INVALID, V_INVALID) ;
}
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ]
// Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler,
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) {
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo)
// ( lascio invariato lo ZMapCopy)
nIntervals = ssize( m_Values[nGrid][nDex]) ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
Interval.dMax, pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin,
dToler, true, nToolNum, V_INVALID, V_INVALID) ;
}
}
// estremo superiore
if ( vInfo[nInfo].dMax + dToler < m_dMaxZ[nGrid]) {
AddIntervals( nGrid, nI, nJ,
vInfo[nInfo].dMax - dToler,
vInfo[nInfo].dMax + dToler,
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, vInfo[nInfo].nToolMax,
true) ;
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMax, dToler,
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN,
vInfo[nInfo].nToolMax) ;
// --- Se richiesta prima restrizione
else {
// Se la lunghezza dell'intervallo non è almeno il doppio della tolleranza
double dLen = Interval.dMax - Interval.dMin ;
if ( dLen < 2. * ( dToler + EPS_SMALL)) {
// L'intervallo sparisce completamente
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL,
Interval.vtMinN, Interval.vtMaxN, nToolNum, true) ;
// Rimuovo le parti di spillone nelle altre dimensioni
if ( IsTriDexel()) {
-- nIntervals ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
Interval.dMin, Interval.dMax,
dToler, true, Tool::UNDEF, V_INVALID, V_INVALID) ;
}
}
// Se sufficientemente lungo, allora
else {
// *** Estremo inferiore -> Intervallo : [ dMin, dMin + dToler ]
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMin + dToler,
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax ]
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + EPS_SMALL,
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
}
}
}
// per ogni sotto-intervallo ricavato fino ad ora, restringo della tolleranza
// ( NB. avendo aggiunto intervalli, il dexel può modificare la sua struttura interna )
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// ( NB. la rimozione di un intervallo ora va definita per intervalli a destra e a sinistra,
// altrimenti rimuovo parti in eccesso )
if ( ! pVolZMapCurrGrid->m_Values[nGrid][nDex].empty()) {
if ( nInfo != 0 ||
pVolZMapCurrGrid->m_Values[nGrid][nDex][0].dMin - dToler > m_dMinZ[nGrid])
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
if ( nInfo != int( m_Values[nGrid][nDex].size()) - 1 ||
pVolZMapCurrGrid->m_Values[nGrid][nDex].back().dMax + dToler < m_dMaxZ[nGrid])
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
}
}
// Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy)
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla
if ( m_Values[nGrid][nDex].empty())
continue ;
// Per ogni intervallo ricavato fino ad ora, restringo della tolleranza
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
// --- Se richiesta prima estensione
if ( bIsExtensionFirst) {
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
}
// --- Se richiesta prima restrizione
else {
m_Values[nGrid][nDex][nInfo].dMin -= dToler ;
m_Values[nGrid][nDex][nInfo].dMax += dToler ;
}
// Definisco il colore
for ( int nOrigInfo = 0 ; nOrigInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nOrigInfo) {
if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMin - m_Values[nGrid][nDex][nInfo].dMin < EPS_SMALL)
m_Values[nGrid][nDex][nInfo].nToolMin = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMin ;
if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMax - m_Values[nGrid][nDex][nInfo].dMax < EPS_SMALL)
m_Values[nGrid][nDex][nInfo].nToolMax = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMax ;
}
}
}
}
// Gestisco le parti Extra ricavate
// Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy)
for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( pZMapExtra->m_Values[nGrid]) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla
if ( pZMapExtra->m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Per ogni intervallo ricavato fino ad ora...
for ( int nInfo = 0 ; nInfo < ssize( pZMapExtra->m_Values[nGrid][nDex]) ; ++ nInfo) {
double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ;
double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ;
Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ;
Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ;
// --- Se richiesta prima estensione
if ( bIsExtensionFirst) {
// Aggiungo i contributi
AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
}
// --- Se richiesta prima restrizione
else {
// Sottraggo i contributi
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
}
}
}
}
// Restringo gli ingombri espensi in precedenza
m_dMinZ[0] += dToler ;
m_dMinZ[1] += dToler ;
m_dMinZ[2] += dToler ;
m_dMaxZ[0] -= dToler ;
m_dMaxZ[1] -= dToler ;
m_dMaxZ[2] -= dToler ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::RemoveFins( const Vector3d& vtDir, double dThick)
{
// Verifico la Validità dello ZMap
if ( ! IsValid())
return false ;
// Per sicurezza normalizzo la direzione
Vector3d vtMyDir = vtDir ;
if ( ! vtMyDir.Normalize())
return false ;
double dMyThick = max( 10. * EPS_SMALL, dThick) ;
// Creo lo ZMap per i riferimenti degli intervalli sulle griglie
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
return false ;
// Creo uno ZMap per gli intervalli da aggiungere e successivamente da rimuovere
VolZmap ZMapExtra ;
if ( ! ZMapExtra.CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
m_dStep, IsTriDexel()))
return false ;
const double FIN_ANG_DEG_TOL = 55. ; // Approssimazione per eccesso dell'angolo massimo possibile tra una direzione generica
// e un versore della terna globale ( arccos( 1 / sqrt( 3) ~ 54.375)
const double COS_FIN_ANG_DEG_TOL = cos( FIN_ANG_DEG_TOL * DEGTORAD) ;
const int NUM_TOOL = 1000 ; // Identificativo Utensile per riconoscere le parti rimosse
// NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente
// Ciclo sulle griglie
DBLVECTOR vdThicks ;
if ( IsTriDexel())
vdThicks = { dThick, dThick, dThick} ;
else
vdThicks = { dThick} ;
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
// Verifico se l'angolo tra la direzione degli spilloni della griglia corrente è sotto alla tolleranza rispetto alla direzione
double dCosDir = ( nGrid == 0 ? vtMyDir.z :
( nGrid == 1 ? vtMyDir.x :
vtMyDir.y)) ;
if ( abs( dCosDir) < COS_FIN_ANG_DEG_TOL + EPS_ANG_SMALL)
continue ;
// Aggiorno l'effettivo valore dello spessore da considerare
double dCurrThick = dMyThick / abs( dCosDir) ; // (sicuramente esiste, essendo 55deg il limite)
vdThicks[nGrid] = dCurrThick ;
// Ciclo sul numero di dexel presenti nella Copia
for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) {
// Se il dexel corrente non ha sotto-intervalli passo al successivo
if ( pZMapCopy->m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Scorro gli intervalli presenti
for ( int nInfo = 0 ; nInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nInfo) {
// Recupero l'intervallo corrente
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
// Se entrambi gli estremi dell'intervallo non sono stati toccati dall'utensile, allora passo al successivo
bool bAnalyze = ( ( Interval.nToolMin == 1 && Interval.nToolMax == 1) ||
( Interval.dMax > m_dMaxZ[nGrid] - EPS_SMALL || Interval.dMin < m_dMinZ[nGrid] + EPS_SMALL)) ;
if ( ! bAnalyze)
continue ;
// Se la lunghezza dell'intervallo è superiore allo spessore richiesto, non faccio nulla
double dLen = Interval.dMax - Interval.dMin ;
if ( dLen > dCurrThick + EPS_ZERO)
continue ;
// Se ZMap composto da una sola griglia, elimino il contributo lungo la direzione corrente
if ( ! IsTriDexel()) {
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL,
- Interval.vtMinN, - Interval.vtMaxN, NUM_TOOL, true) ;
}
// Se Tridexel, aggiungo il contributo del cubetto corrente allo ZMap Extra
else
ZMapExtra.AddStripInterval( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL, NUM_TOOL) ;
}
}
}
// Se non ho aggiunto alcun elemento allo ZMap Extra, non devo fare nulla
if ( ! ZMapExtra.IsValid())
return true ;
#if DEBUG_REMOVE_FINS
SaveGeoObj( ZMapExtra.Clone(), "C:\\Temp\\VolZMapSubt0.nge") ;
#endif
// Ciclo sulle griglie dello ZMap Extra
for ( int nGrid = 0 ; nGrid < ZMapExtra.m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( ZMapExtra.m_Values[nGrid]) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla
if ( ZMapExtra.m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Scorro i gli Intervalli dello Spillone corrente
for ( int nInfo = 0 ; nInfo < ssize( ZMapExtra.m_Values[nGrid][nDex]) ; ++ nInfo) {
double dMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMin ;
double dMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMax ;
Vector3d vtNMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMinN ;
Vector3d vtNMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMaxN ;
// sottraggo tali contributi
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, - vtNMin, - vtNMax, NUM_TOOL, true) ;
}
}
}
if ( ! IsValid())
return true ;
#if DEBUG_REMOVE_FINS
SaveGeoObj( this->Clone(), "C:\\Temp\\VolZMapSubt1.nge") ;
#endif
// Sistemo le Normali sullo ZMap ricavato
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
// Se l'Intervallo è vuoto non faccio nulla
if ( m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Scorro gli intervalli dello spillone corrente
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
// Se intervallo con estremo minimo derivante dalla sottrazione con ZMapExtra, medio le normali
int nToolMin = m_Values[nGrid][nDex][nInfo].nToolMin ;
if ( nToolMin == NUM_TOOL) {
// Recupero il valore minimo, se sul bordo dello ZMap corrente non faccio nulla
double dMin = m_Values[nGrid][nDex][nInfo].dMin ;
if ( dMin > m_dMinZ[nGrid] + EPS_SMALL) {
Vector3d vtMinN = V_NULL ;
double dZMin = INFINITO ;
if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMin, vtMyDir, dThick, true, 1, vtMinN, dZMin)) {
vtMinN = - ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ;
dZMin = dMin ;
}
m_Values[nGrid][nDex][nInfo].vtMinN = vtMinN ;
m_Values[nGrid][nDex][nInfo].dMin = dZMin ;
}
}
// Se intervallo con estremo massimo derivante dalla sottrazione con ZMapExtra, medio le normali
int nToolMax = m_Values[nGrid][nDex][nInfo].nToolMax ;
if ( nToolMax == NUM_TOOL) {
// Recupero il valore massimo, se sul bordo dello ZMap corrente non faccio nulla
double dMax = m_Values[nGrid][nDex][nInfo].dMax ;
if ( dMax < m_dMaxZ[nGrid] - EPS_SMALL) {
Vector3d vtMaxN = V_NULL ;
double dZMax = INFINITO ;
if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMax, vtMyDir, dThick, false, 1, vtMaxN, dZMax)) {
vtMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ;
dZMax = dMax ;
}
m_Values[nGrid][nDex][nInfo].vtMaxN = vtMaxN ;
m_Values[nGrid][nDex][nInfo].dMax = dZMax ;
}
}
}
}
}
// Riassegno il Tool dell'utensile alle nuove parti
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
// Se l'Intervallo è vuoto non faccio nulla
if ( m_Values[nGrid][nDex].empty())
continue ;
// Scorro gli intervalli dello spillone corrente
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
if ( m_Values[nGrid][nDex][nInfo].nToolMin == NUM_TOOL)
m_Values[nGrid][nDex][nInfo].nToolMin = 1 ;
if ( m_Values[nGrid][nDex][nInfo].nToolMax == NUM_TOOL)
m_Values[nGrid][nDex][nInfo].nToolMax = 1 ;
}
}
}
@@ -1766,18 +2072,17 @@ VolZmap::MakeUniform( double dToler)
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
{
// Controllo sulla validità della griglia
// Controllo sulla validità della griglia
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo sulla validità del dexel
// Controllo sulla validità del dexel
if ( nDex <= - 1 || nDex >= int( m_Values[nGrid].size()))
return false ;
// Controllo sulla validità dell'intervallo
// Controllo sulla validità dell'intervallo
if ( nInt <= - 1 || nInt >= int( m_Values[nGrid][nDex].size()))
return false ;
@@ -1957,7 +2262,7 @@ VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, do
bool
VolZmap::IsBox( void)
{
// Se non tridexel, non posso stabilire con il metodo seguente se è un box
// Se non tridexel, non posso stabilire con il metodo seguente se è un box
// Verifico solo che gli spilloni di una mappa o sono nulli o hanno gli stessi estremi
if ( m_nMapNum == 1)
return false ;
@@ -1976,7 +2281,7 @@ VolZmap::IsBox( void)
return true ;
}
// Caso di più thread
// Caso di più thread
m_bIsBox = true ;
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
vector< future<bool>> vRes ;
@@ -2021,7 +2326,7 @@ VolZmap::IsBox( void)
}
}
}
// Se uno dei thread trova che la sua porzione non è un box, non lo può essere il solido intero.
// Se uno dei thread trova che la sua porzione non è un box, non lo può essere il solido intero.
if ( ! m_bIsBox)
return false ;
// Controllo che gli estremi Z siano uguali.
@@ -2058,7 +2363,7 @@ VolZmap::Cut( const Plane3d& plPlane)
}
// Ciclo sui dexel della mappa
for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) {
// Se spillone già vuoto, passo al successivo
// Se spillone già vuoto, passo al successivo
if ( m_Values[nMap][nD].empty())
continue ;
// Indici di spillone
@@ -2074,20 +2379,20 @@ VolZmap::Cut( const Plane3d& plPlane)
double dEnDist = DistPointPlane( ptEn, plMyPlane) ;
// Se entrambi sotto il piano
if ( dStDist < EPS_SMALL && dEnDist < EPS_SMALL)
// Non devo fare alcunché
// Non devo fare alcunché
;
// se altrimenti entrambi gli estremi sono oltre il piano
else if ( dStDist > -EPS_SMALL && dEnDist > -EPS_SMALL) {
// Si elimina tutto
SubtractIntervals( nMap, nI, nJ, dMin, dMax, V_NULL, V_NULL, 1) ;
}
// se altrimenti è da tenere il punto iniziale
// se altrimenti è da tenere il punto iniziale
else if ( dStDist < 0) {
// Si elimina la parte tra intersezione e punto finale
double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ;
SubtractIntervals( nMap, nI, nJ, dInt, dMax, plMyPlane.GetVersN(), V_NULL, 1) ;
}
// se altrimenti è da tenere il punto finale
// se altrimenti è da tenere il punto finale
else if (dEnDist < 0) {
// Si elimina la parte tra punto iniziale e intersezione
double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ;
@@ -2177,7 +2482,7 @@ VolZmap::Compact( void)
}
}
// Se non vi è materiale
// Se non vi è materiale
if ( ! bNotEmptyGrid) {
m_nStatus = TO_VERIFY ;
m_nNumBlock = 0 ;
@@ -2199,8 +2504,8 @@ VolZmap::Compact( void)
double dNewOy = nMinJ[0] * m_dStep ;
double dNewOz = nMinJ[1] * m_dStep ;
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
// Quote estreme Z
switch ( nMap) {
+35 -16
View File
@@ -21,9 +21,8 @@
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include <unordered_map>
#include <stack>
#include <mutex>
#include <atomic>
#include <tuple>
#include <atomic>
typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
@@ -82,10 +81,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
public : // IVolZmap
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
bool Clear( void) override ;
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0) override ;
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ;
int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
@@ -151,7 +150,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
int GetPartMinDistFromPoint( const Point3d& ptP) const override ;
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
bool MakeUniform( double dToler) override ;
bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ;
bool RemoveFins( const Vector3d& vtDir, double dThick) override ;
bool Offset( double dOffs, int nType) override ;
public : // IGeoObjRW
@@ -227,7 +227,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
typedef std::unordered_map<int, Voxel> VoxelContainer ;
// Unordered map per la coerenza topologica
typedef std::unordered_map<int, bool> InterVoxMatter ;
#if !defined(_WIN64)
// Numero massimo approssimativo di Dexel per versione 32-bit per evitare Crash con memoria
#if defined(_DEBUG)
static const int MAX_DEXEL_32_BIT = 3000000 + 1 ;
#else
static const int MAX_DEXEL_32_BIT = 5000000 + 1 ;
#endif
static int m_nDexelNbr ; // numero corrente di Dexel presenti
#endif
private :
bool CopyFrom( const VolZmap& clSrc) ;
bool ResetGraphics( void) ;
@@ -260,10 +269,12 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool AddIntervals( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap = false) ;
bool AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler,
Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) ;
bool AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
Vector3d& vtMin, Vector3d& vtMax) ;
bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax,
double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
const Vector3d& vtToolMax) ;
bool AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum) ;
bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
Vector3d& vtMin, Vector3d& vtMax) ;
// Spostamenti utensile
bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ;
bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
@@ -471,18 +482,26 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool UpdateVolZMapBySurfThickeningSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
bool CreateOffsetSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
bool CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
bool CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle) ;
bool CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle, int nTool = 0) ;
bool CreateOrientedOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs) ;
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap = false) ;
bool AddIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap = false) ;
int nToolMin, int nToolMax, bool bSkipSwap = false) ;
bool CutByPlaneForOffset( const Plane3d& plCut) ;
bool AddSurfTmForOffset( const ISurfTriMesh* pStm, int nTool) ;
bool AddMapPartForOffset( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, int nTool, IntersParLinesSurfTm& intPLSTM) ;
// Funzioni per Offset di Zmap
bool OffsetFillet( double dOffs) ;
bool OffsetSharped( double dOffs, int nType) ;
// Funzione analisi punti/Normali per Alette
bool GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc) ;
bool ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
Vector3d& vtN, double& dNewZ) ;
private :
enum Move5Axis {
@@ -553,9 +572,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable std::vector<InterVoxMatter> m_SliceXY ;
mutable std::vector<InterVoxMatter> m_SliceXZ ;
mutable std::vector<InterVoxMatter> m_SliceYZ ;
mutable std::mutex m_SliceMutex ;
mutable std::atomic_flag m_SliceFlag ;
std::atomic<bool> m_bIsBox ;
bool m_bIsBox ;
int m_nCurrTool ;
std::vector<Tool> m_vTool ;
+24 -22
View File
@@ -2294,7 +2294,7 @@ VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir,
vtN1.Normalize() ;
}
// altrimenti piano inferiore
else if( nBasInt == 1) {
else if ( nBasInt == 1) {
// Punto di intersezione
ptInt2 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cono verso l'interno
@@ -3080,17 +3080,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
// ciclo sui voxel del blocco.
for ( int nV = 0 ; nV < ssize( m_BlockSmoothTria[nB]) ; ++ nV) {
// Box del voxel
BBox3d b3Vox ;
GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
// ciclo sui triangoli del voxel
for ( int nT = 0 ; nT < ssize( m_BlockSmoothTria[nB][nV].vTria) ; ++ nT) {
const Triangle3d& trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
@@ -3102,18 +3103,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
}
}
// Triangoli sharp interni al blocco
for ( int nV = 0 ; nV < int( m_BlockSharpTria[nB].size()) ; ++ nV) {
// ciclo sui voxel del blocco.
for ( int nV = 0 ; nV < ssize( m_BlockSharpTria[nB]) ; ++ nV) {
// Box del voxel
BBox3d b3Vox ;
GetVoxelBox( m_BlockSharpTria[nB][nV].i, m_BlockSharpTria[nB][nV].j, m_BlockSharpTria[nB][nV].k, b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
// Ciclo sulle componenti connesse
for ( int nC = 0 ; nC < int( m_BlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
for ( int nT = 0 ; nT < int( m_BlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
Triangle3d trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
for ( int nC = 0 ; nC < ssize( m_BlockSharpTria[nB][nV].vCompoTria) ; ++ nC) {
for ( int nT = 0 ; nT < ssize( m_BlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) {
const Triangle3d& trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
if (nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
// Costruisco il tratto di curva
CurveLine cvLine ;
if ( cvLine.Set(ptSt, ptEn))
@@ -3123,10 +3124,10 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
}
}
// Triangoli grandi del blocco
for ( int nT = 0 ; nT < int( m_BlockBigTria[nB].size()) ; ++ nT) {
Triangle3d trTria = m_BlockBigTria[nB][nT] ;
for ( int nT = 0 ; nT < ssize( m_BlockBigTria[nB]) ; ++ nT) {
const Triangle3d& trTria = m_BlockBigTria[nB][nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
// Costruisco il tratto di curva
CurveLine cvLine ;
@@ -3136,11 +3137,11 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
}
}
// In ogni caso valuto i triangoli sharp fra blocchi
for ( int nV = 0 ; nV < int( m_InterBlockSharpTria[nB].size()) ; ++ nV) {
for ( int nV = 0 ; nV < ssize( m_InterBlockSharpTria[nB]) ; ++ nV) {
// Ciclo sulle componenti connesse
for ( int nC = 0 ; nC < int( m_InterBlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
for ( int nT = 0 ; nT < int( m_InterBlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
Triangle3d trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
for ( int nC = 0 ; nC < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria) ; ++ nC) {
for ( int nT = 0 ; nT < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) {
const Triangle3d& trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
@@ -3156,9 +3157,9 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
// Creo i loop
ChainCurves LoopCreator ;
LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ;
LoopCreator.Init( false, EPS_SMALL, ssize( vLine)) ;
// Carico le curve per concatenarle
for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) {
for ( int nCv = 0 ; nCv < ssize( vLine) ; ++ nCv) {
Point3d ptSt = vLine[nCv].GetStart() ;
Point3d ptEn = vLine[nCv].GetEnd() ;
Vector3d vtDir; vLine[nCv].GetStartDir(vtDir) ;
@@ -3176,6 +3177,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
if ( ! pLoop->AddCurve( vLine[i - 1], true, 10 * EPS_SMALL))
return false ;
}
pLoop->TestClosure( 10 * EPS_SMALL) ;
pLoop->SetExtrusion( plPlane.GetVersN()) ;
pLoop->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
// Inserisco la curva composita nella raccolta da ritornare
+79 -14
View File
@@ -27,8 +27,8 @@ using namespace std ;
// ------------------------- CREAZIONE MAPPA --------------------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
bool
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
{
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
@@ -51,7 +51,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
m_nNx[0] = max( int( ( dDimX + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNy[0] = max( int( ( dDimY + EPS_SMALL) / m_dStep + 0.5), 1) ;
// Numero di componenti connesse
// Numero di componenti connesse
m_nConnectedCompoCount = 1 ;
// Se tridexel
@@ -67,7 +67,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
m_nNx[1] = 0 ;
m_nNy[1] = 0 ;
m_nNx[2] = 0 ;
m_nNy[2] = 0 ;
m_nNy[2] = 0 ;
}
// Definisco il numero di blocchi lungo x,y e z
@@ -81,12 +81,24 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
// Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ;
// Riempimento delle celle
for ( int i = 0 ; i < m_nMapNum ; ++ i)
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
// Aggiungo il tratto al dexel vuoto
@@ -98,7 +110,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
switch ( i) {
case 0 :
m_Values[i][j][0].vtMinN = - Z_AX ;
m_Values[i][j][0].dMax = dDimZ ;
m_Values[i][j][0].dMax = dDimZ ;
m_Values[i][j][0].vtMaxN = Z_AX ;
m_Values[i][j][0].nToolMax = 0 ;
break ;
@@ -113,9 +125,10 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
m_Values[i][j][0].dMax = dDimY ;
m_Values[i][j][0].vtMaxN = Y_AX ;
m_Values[i][j][0].nToolMax = 0 ;
break ;
break ;
}
}
}
// Definizione delle limitazioni iniziali in Z per ogni mappa
m_dMinZ[0] = 0 ;
@@ -136,7 +149,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
//----------------------------------------------------------------------------
bool
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
{
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
@@ -187,6 +200,18 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
// Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ;
@@ -210,7 +235,7 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError)
{
// Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ;
@@ -250,14 +275,35 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
m_nNx[1] = m_nNy[0] ;
m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ;
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
m_Values[1].resize( m_nDim[1]) ;
m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ;
m_nDim[2] = m_nNx[2] * m_nNy[2] ;
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_Values[1].resize( m_nDim[1]) ;
m_Values[2].resize( m_nDim[2]) ;
}
// Se dimensione singola
else {
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
m_nDexelNbr += m_nDim[0] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_nNx[1] = 0 ;
m_nNy[1] = 0 ;
m_nDim[1] = 0 ;
@@ -788,7 +834,7 @@ VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ,
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox)
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError)
{
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
double dVol ;
@@ -838,14 +884,33 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
m_nNx[1] = m_nNy[0] ;
m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ;
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
m_Values[1].resize( m_nDim[1]) ;
m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ;
m_nDim[2] = m_nNx[2] * m_nNy[2] ;
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_Values[1].resize( m_nDim[1]) ;
m_Values[2].resize( m_nDim[2]) ;
}
// Se a dimensione singola
else {
#if !defined(_WIN64)
m_nDexelNbr += m_nDim[0] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_nNx[1] = 0 ;
m_nNy[1] = 0 ;
m_nDim[1] = 0 ;
+26 -13
View File
@@ -24,6 +24,7 @@
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#define EIGEN_NO_IO
#include "/EgtDev/Extern/Eigen/Core"
#include "/EgtDev/Extern/Eigen/SVD"
#include <thread>
@@ -950,7 +951,7 @@ VolZmap::UpdateTripleMapGraphics( void) const
}
}
// Standarda è multithread
// Standard è multithread
constexpr bool MULTITHREAD = true ;
if ( MULTITHREAD) {
@@ -1270,13 +1271,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ;
}
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
m_SliceMutex.lock() ;
while ( m_SliceFlag.test_and_set( memory_order_acquire))
m_SliceFlag.wait( true, memory_order_relaxed) ;
auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceYZ[nSlBlockN].end()) {
bMatOnSlice = it->second ;
bDefTopology = true ;
}
m_SliceMutex.unlock() ;
m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
}
}
else if ( abs( nAdjVox3[nCount]) == 2) {
@@ -1286,13 +1289,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ;
}
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
m_SliceMutex.lock() ;
while ( m_SliceFlag.test_and_set( memory_order_acquire))
m_SliceFlag.wait( true, memory_order_relaxed) ;
auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceXZ[nSlBlockN].end()) {
bMatOnSlice = it->second ;
bDefTopology = true ;
}
m_SliceMutex.unlock() ;
m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
}
}
else if ( abs( nAdjVox3[nCount]) == 3) {
@@ -1302,13 +1307,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ;
}
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
m_SliceMutex.lock() ;
while ( m_SliceFlag.test_and_set( memory_order_acquire))
m_SliceFlag.wait( true, memory_order_relaxed) ;
auto it = m_SliceXY[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceXY[nSlBlockN].end()) {
bMatOnSlice = it->second ;
bDefTopology = true ;
}
m_SliceMutex.unlock() ;
m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
}
}
}
@@ -1373,27 +1380,33 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
if ( nSlBlockN == nBlock)
SliceYZ.emplace( nSliceN, bMatOnSlice) ;
else {
m_SliceMutex.lock() ;
while ( m_SliceFlag.test_and_set( memory_order_acquire))
m_SliceFlag.wait( true, memory_order_relaxed) ;
m_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceMutex.unlock() ;
m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
}
}
else if ( abs(nAdjVox3[nCount]) == 2) {
if ( nSlBlockN == nBlock)
SliceXZ.emplace( nSliceN, bMatOnSlice) ;
else {
m_SliceMutex.lock() ;
while ( m_SliceFlag.test_and_set( memory_order_acquire))
m_SliceFlag.wait( true, memory_order_relaxed) ;
m_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceMutex.unlock() ;
m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
}
}
else if ( abs(nAdjVox3[nCount]) == 3) {
if ( nSlBlockN == nBlock)
SliceXY.emplace(nSliceN, bMatOnSlice) ;
else {
m_SliceMutex.lock() ;
while ( m_SliceFlag.test_and_set( memory_order_acquire))
m_SliceFlag.wait( true, memory_order_relaxed) ;
m_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceMutex.unlock() ;
m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
}
}
}
+747 -196
View File
File diff suppressed because it is too large Load Diff
+1180 -842
View File
File diff suppressed because it is too large Load Diff
+12 -2
View File
@@ -21,6 +21,7 @@
#include "Voronoi.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Extern/vroni/Include/vroni_object.h"
using namespace std ;
@@ -1013,8 +1014,17 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
// aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) {
// forzo chiusura
if ( ! pCrvOffs->IsClosed()) {
Point3d ptS ; pCrvOffs->GetStartPoint( ptS) ;
Point3d ptE ; pCrvOffs->GetEndPoint( ptE) ;
if ( SqDist( ptS, ptE) > 100. * SQ_EPS_SMALL)
return false ;
pCrvOffs->Close() ;
}
OffsList.push_back( Release( pCrvOffs)) ;
}
}
// libero la memoria di vroni dedicata agli offset
@@ -1154,7 +1164,7 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
//---------------------------------------------------------------------------
bool
Voronoi::Translate( const Vector3d & vtMove)
Voronoi::Translate( const Vector3d& vtMove)
{
if ( ! IsValid())
return false ;
+6 -6
View File
@@ -19,17 +19,17 @@
#include "/EgtDev/Include/EGkCurveBezier.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Extern/vroni/Include/vroni_object.h"
//----------------------------------------------------------------------------
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 ;
static constexpr bool USE_VORONOI = true ;
static constexpr int VORONOI_STD_BOUND = 3 ;
static constexpr double VRONI_OFFS_TOL = 1e-9 ;
static constexpr double VRONI_JUNCTION_OPEN = 1.0 ;
static constexpr double VRONI_JUNCTION_CLOSED = 2.0 ;
//-------------------------- Forward Definitions -------------------------------
class ISurfFlatRegion ;
class vroniObject ;
//----------------------------------------------------------------------------
class Voronoi
-1
View File
@@ -34,4 +34,3 @@
#pragma comment(lib, EGTLIBDIR "EgtGeneral" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "abseil" EGTLIBVER ".lib")