Compare commits

...

227 Commits

Author SHA1 Message Date
Daniele Bariletti 1cfd283f26 EgtGeomKernel :
- prima versione dell'offset 3d (da correggere).
2026-06-11 18:05:15 +02:00
Daniele Bariletti 1f47402215 EgtGeomKernel :
- piccola correzione.
2026-06-09 16:50:20 +02:00
Daniele Bariletti 55e2983991 EgtGeomKernel :
- correzione alla gestione delle normali in IntersLineCyl.
- modifiche alla chiamata della funzione IntesLineCyl in VolZMap.
2026-06-09 15:51:46 +02:00
Riccardo Elitropi 7c85ea2d43 EgtGeomKernel :
- in CalcPocketing modifiche stilistiche.
2026-06-09 15:22:55 +02:00
Daniele Bariletti 1c49379ee1 EgtGeomKernel 3.1f2 :
- aggiunta modalità per IntersLineCyl
- spostate funzioni relative
- cambiuo versione.
2026-06-09 12:28:39 +02:00
Riccardo Elitropi 481d81a8d2 EgtGeomKernel :
- in CalcPocketing piccola correzione.
2026-06-09 09:51:46 +02:00
Daniele Bariletti 68e25e10e8 EgtGeomKernel :
- controllo più fine e piccolo miglioramento per identificaizone zone concave smooth.
2026-06-08 12:38:18 +02:00
Riccardo Elitropi 88410333e9 EgtGeomKernel :
- in SurfTriMesh::GetSilhouette aggiunti controlli.
2026-06-08 12:22:25 +02:00
Daniele Bariletti 6bbedc812f EgtGeomKernel 3.1f1 :
- cambio versione.
2026-06-05 14:20:19 +02:00
Daniele Bariletti 4e6dd05aa9 EgtGeomKernel :
- miglioria nella gestione degli angoli interni per lavorazioni a 5 assi.
2026-06-05 10:08:16 +02:00
Riccardo Elitropi a5684b2bf3 EgtGeomKernel :
- piccola correzione in CalcPocketing.
2026-05-29 13:25:47 +02:00
SaraP 119bbe0bcb EgtGeomKernel :
- prime migliorie nella creazione di solidi swept con sezione rettangolare e bevel ( prima versione, da sistemare caps flat e none)
- correzione in Voronoi.
2026-05-28 15:30:41 +02:00
Riccardo Elitropi 35b903e8a0 EgtGeomKernel 3.1e5 :
- in CalcPocketing piccole migliorie e correzioni per ZigZag.
2026-05-27 17:28:50 +02:00
Daniele Bariletti 979597084d EgtGeomKernel :
- migliorie e correzioni a RuledSmooth.
2026-05-26 11:27:27 +02:00
Daniele Bariletti 02742ee80f Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-05-22 10:41:25 +02:00
Daniele Bariletti a2bcc4d682 EgtGeomKernel :
- migliorata funzione per l'interpolazione di direzioni per la lavorazione di trimming.
2026-05-22 10:41:09 +02:00
Dario Sassi cbd487e4ff EgtGeomKernel 3.1e4 :
- modifiche a VerifyConnection di TriMesh per renderla abbastanza veloce con superfici patologiche.
2026-05-21 12:47:21 +02:00
Riccardo Elitropi 37aaa98df6 EgtGeomKernel 3.1e3 :
- in CalcPocketing aggiunta gestione per ToolCompensation.
2026-05-14 15:24:47 +02:00
Dario Sassi 2dcaa57aa3 EgtGeomKernel :
- modifiche a RMF per avere la tangente media sul punto di calcolo (utile solo se la curva non è G1)
- modifiche a GetSurfTriMeshSwept per avere RMF anche con curve piane garantendo la retrocompatibilità.
2026-05-14 13:02:47 +02:00
Riccardo Elitropi ba7379e752 EgtGeomKernel :
- In CalcPocketing aggiunto flag per Conventional Milling.
2026-05-12 09:34:56 +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
Riccardo Elitropi b3ebb35d01 EgtGeomKernel :
- aggiunte prime funzioni di Trimming.
2025-12-22 17:15:02 +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
63 changed files with 11679 additions and 3779 deletions
+1 -1
View File
@@ -151,7 +151,7 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
else { else {
double dParA = vIccInfo[i].IciA[0].dU ; double dParA = vIccInfo[i].IciA[0].dU ;
double dParB = vIccInfo[i].IciB[0].dU ; double dParB = vIccInfo[i].IciB[0].dU ;
if ( abs( dParA - dEnd) < EPS_SMALL) if ( dParA > dParB)
swap( dParA, dParB) ; swap( dParA, dParB) ;
// verifico se uno dei due intervalli dà origine ad un tratto trascurabile // verifico se uno dei due intervalli dà origine ad un tratto trascurabile
PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ; PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ;
+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) { if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) {
m_SCollInfo = scInfoCurr ; m_SCollInfo = scInfoCurr ;
m_SCollInfo.nChunkM = j ; m_SCollInfo.nChunkM = j ;
m_SCollInfo.nLoopM = 0 ;
m_SCollInfo.nCrvM = k ; m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = i ; m_SCollInfo.nChunkF = i ;
m_SCollInfo.nLoopF = 0 ;
m_SCollInfo.nCrvF = l ; m_SCollInfo.nCrvF = l ;
} }
} }
else if ( dNewLenXY < dPrevLenXY) { else if ( dNewLenXY < dPrevLenXY) {
m_SCollInfo = scInfoCurr ; m_SCollInfo = scInfoCurr ;
m_SCollInfo.nChunkM = j ; m_SCollInfo.nChunkM = j ;
m_SCollInfo.nLoopM = 0 ;
m_SCollInfo.nCrvM = k ; m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = i ; m_SCollInfo.nChunkF = i ;
m_SCollInfo.nLoopF = 0 ;
m_SCollInfo.nCrvF = l ; m_SCollInfo.nCrvF = l ;
} }
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ; pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
+2 -2
View File
@@ -30,7 +30,7 @@ class MyCAvSimpleSurfFrMove
const SCollInfo& GetSCollInfo() const SCollInfo& GetSCollInfo()
{ return m_SCollInfo ;} { return m_SCollInfo ;}
private : protected :
bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2, bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2,
const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ; const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ;
bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
@@ -40,7 +40,7 @@ class MyCAvSimpleSurfFrMove
bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
const Point3d& ptCen, double& dAng) ; const Point3d& ptCen, double& dAng) ;
private : protected :
const SurfFlatRegion* m_pRegM ; const SurfFlatRegion* m_pRegM ;
const SurfFlatRegion* m_pRegF ; const SurfFlatRegion* m_pRegF ;
SCollInfo m_SCollInfo ; 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 // Allontanamento dall'interno
double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ; double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ;
// Allontanamento dalla frontiera // Allontanamento dalla frontiera
Vector3d vtMoveOrt = vtMove - vtMove * vtDiskAx * vtDiskAx ; Vector3d vtMoveOrt = OrthoCompo( vtMove, vtDiskAx) ;
vtMoveOrt.Normalize() ; vtMoveOrt.Normalize() ;
Frame3d DiskFrame ; Frame3d DiskFrame ;
Vector3d vtJ = vtDiskAx ^ vtMoveOrt ; DiskFrame.Set( ptDiskCen, vtDiskAx, vtMoveOrt) ;
vtJ.Normalize() ;
DiskFrame.Set( ptDiskCen, vtMoveOrt, vtJ, vtDiskAx) ;
Triangle3d trTriaLoc = trTria ; Triangle3d trTriaLoc = trTria ;
Vector3d vtMoveLoc = vtMove ; Vector3d vtMoveLoc = vtMove ;
trTriaLoc.ToLoc( DiskFrame) ; 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 // Contenuto : Implementazione funzione verifica collisione tra
// SurfTm e SurfTm. // SurfTm e SurfTm.
// //
// Modifiche : 13.11.20 LM Creazione modulo. // Modifiche : 13.11.20 LM Creazione modulo.
// 24.03.24 DS Aggiunta TestSurfTmSurfTm. // 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 ; BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ; pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ; 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) if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ; 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)) if ( ! b3BoxA.Overlaps( b3BoxB))
return false ; return false ;
// Recupero i triangoli di A che interferiscono col box di B // Recupero i triangoli di A che interferiscono col box di B
@@ -61,13 +62,13 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
continue ; continue ;
BBox3d b3BoxTriaA ; BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( 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) if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ; b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A // Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, 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. // Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ; pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. // 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. // Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) { for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge // 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 ; int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ; 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)) if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ; 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) ; Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ; double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ; vtEdgeV /= dEdgeLen ;
@@ -111,10 +112,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
} }
} }
// Non ho trovato collisioni fra triangoli delle superfici. // 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)) if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA))
return false ; return false ;
// La collisione c'è se una superficie è dentro l'altra. // La collisione c'è se una superficie è dentro l'altra.
Point3d ptPointA, ptPointB ; Point3d ptPointA, ptPointB ;
pSrfA->GetFirstVertex( ptPointA) ; pSrfA->GetFirstVertex( ptPointA) ;
pSrfB->GetFirstVertex( ptPointB) ; 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. // Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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 // Recupero le superfici base
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ; const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
@@ -140,10 +141,10 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
BBox3d b3BoxA, b3BoxB ; BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ; pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ; 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) if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ; 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)) if ( ! b3BoxA.Overlaps( b3BoxB))
return false ; return false ;
// Recupero i triangoli di A che interferiscono col box di B // 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 ; continue ;
BBox3d b3BoxTriaA ; BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( 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) if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ; b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A // Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, 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. // Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ; pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. // 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. // Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) { for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge // 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 ; int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ; 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)) if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ; 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) ; Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ; double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ; vtEdgeV /= dEdgeLen ;
@@ -205,6 +206,25 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
pSrfB->SetTempInt( nTB, 1) ; 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 ; 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 #pragma once
#include "/EgtDev/Include/EGkPoint3d.h" #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()) ; 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) ;
+1200 -511
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/EGkChainCurves.h"
#include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkGeomDB.h"
#include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkCurve.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include <algorithm> #include <algorithm>
using namespace std ; 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 ; ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ; vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
// verifico se sono arrivato al punto di chiusura // verifico se sono arrivato al punto di chiusura
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) { if ( AreSamePointEpsilon( ptCurr, ptStop, 0.5 * EPS_SMALL)) {
bStopped = true ; bStopped = true ;
break ; break ;
} }
+2 -1
View File
@@ -45,7 +45,8 @@ static const NamedColor StdColor[] = {
{ "FUCHSIA", FUCHSIA}, { "FUCHSIA", FUCHSIA},
{ "PURPLE", PURPLE}, { "PURPLE", PURPLE},
{ "ORANGE", ORANGE}, { "ORANGE", ORANGE},
{ "BROWN", BROWN} { "BROWN", BROWN},
{ "INVISIBLE", INVISIBLE}
} ; } ;
static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ; static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ;
+583 -54
View File
@@ -13,6 +13,8 @@
//--------------------------- Include ---------------------------------------- //--------------------------- Include ----------------------------------------
#include "stdafx.h" #include "stdafx.h"
#include "CalcDerivate.h"
#include "Bernstein.h"
#include "CurveAux.h" #include "CurveAux.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "CurveLine.h" #include "CurveLine.h"
@@ -24,11 +26,26 @@
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EGkUiUnits.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EGkIntersCurvePlane.h"
#include "/EgtDev/Include/EGkCurveByInterp.h" #include "/EgtDev/Include/EGkCurveByInterp.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#define EIGEN_NO_IO #define EIGEN_NO_IO
#include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Extern/Eigen/Dense"
#define SAVEAPPROX 0
#define SAVECURVEPASSED 0
#define SAVELINEARAPPROX 0
#define SAVESYNCLINES 0
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX || SAVESYNCLINES
#include "/EgtDev/Include/EGkGeoPoint3d.h"
static int nCrvPassed = 0 ;
std::vector<IGeoObj*> VT ;
std::vector<Color> VC ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ; static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ;
@@ -522,9 +539,9 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot)
return nullptr ; return nullptr ;
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ; PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali pCrvBezier->Init( nDeg, false) ;
pCrvBezier->Init( nDeg, true) ; if ( ! pCrvBezier->FromLine( *pCrvLine))
pCrvBezier->FromLine( *pCrvLine) ; return nullptr ;
if ( bMakeRatOrNot) if ( bMakeRatOrNot)
pCrvBezier->MakeRational() ; pCrvBezier->MakeRational() ;
return Release( pCrvBezier) ; return Release( pCrvBezier) ;
@@ -577,6 +594,13 @@ ArcToBezierCurve( const ICurveArc* pArc, int nDeg, bool bMakeRatOrNot)
PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ; PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc)) if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc))
return nullptr ; return nullptr ;
if ( ! bMakeRatOrNot) {
Point3d ptCen = pArc->GetCenter() ;
Vector3d vtN = pArc->GetNormVersor() ;
pCrvBez.Set( ApproxArcCurveBezierWithSingleCubic( pCrvBez, ptCen, vtN)) ;
}
if ( IsNull( pCrvBez))
return nullptr ;
// aumento il grado della curva come richiesto // aumento il grado della curva come richiesto
while ( pCrvBez->GetDegree() < nDeg) while ( pCrvBez->GetDegree() < nDeg)
pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ;
@@ -1135,7 +1159,7 @@ FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
return true ; return true ;
} }
// trovo a quale span appartiene il parametro dU // trovo a quale span appartiene il parametro dU
int nKnots = int( vKnots.size()) ; int nKnots = ssize( vKnots) ;
if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) { if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
nSpan = nKnots - 1 - nDeg ; nSpan = nKnots - 1 - nDeg ;
return true ; return true ;
@@ -1161,7 +1185,7 @@ static bool
CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis) CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
{ {
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1 // mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
if ( vBasis.size() != nDeg + 1) if ( ssize( vBasis) != nDeg + 1)
return false ; return false ;
vBasis[0] = 1 ; vBasis[0] = 1 ;
@@ -1186,7 +1210,8 @@ CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTO
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nEnd, int nDeg, const DBLVECTOR& vLen, double dLenTot) InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nEnd, int nDeg, const DBLVECTOR& vLen, double dLenTot,
const Vector3d& vtStartDir = V_NULL, const Vector3d& vtEndDir = V_NULL)
{ {
PtrOwner<ICurve> pCrvInt ; PtrOwner<ICurve> pCrvInt ;
@@ -1215,6 +1240,8 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
return nullptr ; return nullptr ;
} }
bool bUseStartEndDir = vtStartDir.IsValid() && vtEndDir.IsValid() ;
DBLVECTOR vPntParam ; DBLVECTOR vPntParam ;
vPntParam.resize( nPoints) ; vPntParam.resize( nPoints) ;
vPntParam[0] = 0 ; vPntParam[0] = 0 ;
@@ -1223,13 +1250,15 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ; vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ;
DBLVECTOR vKnots ; DBLVECTOR vKnots ;
vKnots.resize( nPoints + nDeg - 1) ; int nKnots = bUseStartEndDir ? nPoints + nDeg - 1 + 2 : nPoints + nDeg - 1 ;
vKnots.resize( nKnots) ;
for ( int i = 0 ; i < nDeg ; ++i) { for ( int i = 0 ; i < nDeg ; ++i) {
vKnots[i] = 0 ; vKnots[i] = 0 ;
vKnots.end()[-i-1] = 1 ; vKnots.end()[-i-1] = 1 ;
} }
for ( int i = nDeg ; i < nPoints - 1 ; ++i) { int nKnotsToEdit = bUseStartEndDir ? nPoints + 1 : nPoints - 1 ;
for ( int i = nDeg ; i < nKnotsToEdit ; ++i) {
double dKnot = 0 ; double dKnot = 0 ;
for ( int j = i + 1 ; j < i + nDeg + 1 ; ++j) for ( int j = i + 1 ; j < i + nDeg + 1 ; ++j)
dKnot += vPntParam[j - nDeg] ; dKnot += vPntParam[j - nDeg] ;
@@ -1237,13 +1266,14 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
vKnots[i] = dKnot ; vKnots[i] = dKnot ;
} }
Eigen::MatrixXd mA( nPoints, nPoints) ; int nEq = bUseStartEndDir ? nPoints + 2 : nPoints ;
Eigen::MatrixXd mA( nEq, nEq) ;
mA.fill( 0) ; mA.fill( 0) ;
for ( int i = 0 ; i < nPoints ; ++i) { for ( int i = 0 ; i < nEq ; ++i) {
if ( i == 0) if ( i == 0)
mA.row(0).col(0) << 1 ; mA.row(0).col(0) << 1 ;
else if ( i == nPoints - 1) else if ( i == nEq - 1)
mA.row(i).col(nPoints - 1) << 1 ; mA.row(i).col( nEq - 1) << 1 ;
else { else {
int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ; int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ;
DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ; DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ;
@@ -1294,7 +1324,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
int nItCount = 0 ; int nItCount = 0 ;
while ( dErr > dLinTol && nItCount < 10) { while ( dErr > dLinTol && nItCount < 10) {
pCrvInt->Clear() ; pCrvInt->Clear() ;
int nPoints = int( vPnt.size()) ; int nPoints = ssize( vPnt) ;
int nDeg = 3 ; int nDeg = 3 ;
if ( nPoints < 2) if ( nPoints < 2)
return nullptr ; return nullptr ;
@@ -1310,7 +1340,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
else if ( nPoints == 3) { else if ( nPoints == 3) {
// se ho solo tre punti uso un altro algoritmo // se ho solo tre punti uso un altro algoritmo
CurveByInterp cbi ; CurveByInterp cbi ;
for ( int i = 0 ; i < int( vPnt.size()) ; ++i) for ( int i = 0 ; i < ssize( vPnt) ; ++i)
cbi.AddPoint( vPnt[i]) ; cbi.AddPoint( vPnt[i]) ;
pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ; pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ;
if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) if ( ! IsNull( pCrvInt) && pCrvInt->IsValid())
@@ -1342,10 +1372,16 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
} }
} }
if ( vLen.size() != 0) { if ( ! vLen.empty()) {
if ( nEnd == 0) if ( nEnd == 0)
nEnd = nPoints - 1 ; nEnd = nPoints - 1 ;
pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot)) ; Vector3d vtStartDir = V_INVALID ;
Vector3d vtEndDir = V_INVALID ;
//if ( nStart != 0 && nEnd != nPoints - 1) {
// pCrvInt->GetEndDir( vtStartDir) ;
// vtEndDir =
//}
pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot, vtStartDir, vtEndDir)) ;
} }
if ( bFoundLine) { if ( bFoundLine) {
@@ -1357,6 +1393,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
nStart = nEnd ; nStart = nEnd ;
} }
//dErr = 0 ;
CalcApproxError( pCrvOri, pCrvInt, dErr) ; CalcApproxError( pCrvOri, pCrvInt, dErr) ;
if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL) if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL)
dMaxLen /= 2 ; dMaxLen /= 2 ;
@@ -1371,46 +1408,332 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* static bool
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
{ {
PolyLine plApprox ; int nPoints = nLast - nFirst + 1 ;
double dAngTolFine = 2 ; if ( nPoints < 2)
pCrv->ApproxWithLines( dTol, dAngTolFine, ICurve::APL_STD, plApprox) ; return false ;
if ( vParam.empty())
vParam.resize( nPoints) ;
if ( vParam[nFirst] == 0 && vParam[nLast] == 1)
return true ;
vParam[nFirst] = 0 ;
for ( int i = nFirst + 1 ; i <= nLast ; ++i) {
double dDist = Dist( vPnt[i], vPnt[i-1]) ;
vParam[i] = vParam[i- 1] + dDist ;
}
for ( int i = nFirst + 1 ; i < nLast ; ++i)
vParam[i] /= vParam[nLast] ;
vParam[nLast] = 1 ;
PNTVECTOR vPnt ; return true ;
Point3d pt ; plApprox.GetFirstPoint( pt) ; }
do {
vPnt.push_back( pt) ;
} while ( plApprox.GetNextPoint( pt)) ;
// campiono punti lungo la curva e poi li interpolo //----------------------------------------------------------------------------
ICurveBezier*
ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast,
const Vector3d& vtStartDir, const Vector3d& vtEndDir, const DBLVECTOR& vParam)
{
// cerco di approssimare un set di punti con una sola bezier cubica non razionale
int nPoints = nLast - nFirst + 1 ;
// se ho solo quattro punti allora costruisco direttamente la curva
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
int nDeg = 3 ;
bool bRat = false ;
pCrvBez->Init( nDeg, bRat) ;
const Point3d& pt0 = vPnt[nFirst] ;
const Point3d& pt3 = vPnt[nLast] ;
pCrvBez->SetControlPoint( 0, pt0) ;
pCrvBez->SetControlPoint( 3, pt3) ;
Eigen::Vector2d mA ;
if ( nPoints > 4) {
// risoluzione sistema
Eigen::Matrix2d mC ; mC.setZero() ;
Eigen::Vector2d mX ; mX.setZero() ;
for ( int i = nFirst ; i <= nLast ; ++i) {
double dU = vParam[i] ;
DBLVECTOR vBern(4) ;
GetAllBernstein( dU, 3, vBern) ;
PtrOwner<ICurve> pCC( InterpolatePointSetWithBezier( vPnt, dTol, 100)) ; Vector3d A1 = vtStartDir * vBern[1] ;
if ( ! IsNull( pCC) && pCC->IsValid()) Vector3d A2 = vtEndDir * vBern[2] ;
return Release( pCC) ;
else Vector3d tmp = vPnt[i] - ( pt0 * ( vBern[0] + vBern[1])) - (( pt3 * ( vBern[2] + vBern[3])) - ORIG) ; // ORIG serve solo per trasformare l'ultimo termine in un vettore
return nullptr ;
mC(0,0) += A1 * A1 ;
mC(0,1) += A1 * A2 ;
mC(1,0) += A1 * A2 ;
mC(1,1) += A2 * A2 ;
mX(0) += A1 * tmp ;
mX(1) += A2 * tmp ;
}
mA = mC.fullPivLu().solve(mX) ;
}
// l'algoritmo è fatto in modo che alpha1 e alpha2 siano positivi ( se tutto va bene)
// io invece ho tenuto le tangenti con la direzione originale, quindi il primo dovrebbe essere positivo e il secondo negativo
if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) {
if ( mA(0) < 0 || mA(1) > 0)
LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti")
double dDistCorr = Dist( pt3, pt0) / 3 ;
mA(0) = dDistCorr ;
mA(1) = - dDistCorr ;
}
Point3d pt1 = pt0 + vtStartDir * mA(0) ;
Point3d pt2 = pt3 + vtEndDir * mA(1) ;
pCrvBez->SetControlPoint( 1, pt1) ;
pCrvBez->SetControlPoint( 2, pt2) ;
return Release( pCrvBez) ;
}
//----------------------------------------------------------------------------
bool
CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam,
int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr)
{
dErr = 0 ;
// calcolo l'errore di approssimazione
for ( int i = nFirst ; i <= nLast ; ++i) {
Point3d ptBez ; pCrvNew->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez) ;
double dErrTemp = Dist( vPntOrig[i], ptBez) ;
if ( dErrTemp > dErr) {
dErr = dErrTemp ;
nPointMaxErr = i ;
}
}
return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
ApproxPointSetWithBezier( const ICurve* pCrv, double dTol) FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol, bool bLimitSplit = false)
{ {
// campiono punti lungo la curva e poi li interpolo ParamByLen( vPnt, vParam, nFirst, nLast) ;
PtrOwner<ICurveComposite> pCrvFit( CreateCurveComposite()) ;
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
double dErr = INFINITO ;
double dErrPrec = INFINITO ;
double dErrSplit = dTol * 25 ;
int nIter = 0 ;
while ( dErr > dTol && nIter < 10) {
if ( dErr < INFINITO) {
// riparametrizzo i punti
for ( int i = nFirst + 1 ; i < nLast ; ++i) {
// questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione
double dCorr = 1 ;
do {
Vector3d vtDer1, vtDer2 ;
Point3d ptBez ; pCrvBez->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez, &vtDer1, &vtDer2) ;
Vector3d vtLink = ptBez - vPnt[i] ;
double dNum = vtLink * vtDer1 ;
double dDen = vtLink * vtDer2 + vtDer1 * vtDer1 ;
dCorr = dDen > EPS_ZERO ? dNum / dDen : 0 ;
vParam[i] = vParam[i] - dCorr ;
} while ( abs( dCorr) > EPS_ZERO) ;
Clamp( vParam[i], 0., 1.) ;
}
}
PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ; // fit della curva
return Release( pCC) ; Vector3d vtStartDir, vtEndDir ;
if ( bLimitSplit) {
vtStartDir = vNextDer[nFirst / 3] ;
vtEndDir = vPrevDer[nLast / 3] ;
}
else {
vtStartDir = vNextDer[nFirst] ;
vtEndDir = vPrevDer[nLast] ;
}
pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vtStartDir, vtEndDir, vParam)) ;
if ( IsNull( pCrvBez) || ! pCrvBez->IsValid())
return nullptr ;
#if SAVEAPPROX
SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\"+ToString(nCrvPassed) + "first_approx.nge") ;
#endif
int nPointMaxErr = 0 ;
CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ;
// se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti
if ( ((nLast - nFirst == 1) || ( bLimitSplit && nLast - nFirst == 3)) && dErr > dTol) {
CurveLine CL ; CL.Set( vPnt[nFirst], vPnt[nLast]) ;
pCrvBez.Set( GetCurveBezier( CurveToBezierCurve( &CL))) ;
dErr = 0 ;
}
if ( bLimitSplit && nPointMaxErr % 3 != 0) {
nPointMaxErr = 3 * int( round( nPointMaxErr / 3.)) ;
if ( nPointMaxErr == nFirst)
nPointMaxErr += 3 ;
else if( nPointMaxErr == nLast)
nPointMaxErr -= 3 ;
}
++nIter ;
bool bSplit = false ;
if ( ( nIter == 10 && dErr > dTol) || dErr > dErrPrec || dErrPrec - dErr < dErrPrec / 20)
bSplit = true ;
dErrPrec = dErr ;
// se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due
if ( dErr > dErrSplit || bSplit) {
if ( nLast - nFirst > 1 && nPointMaxErr - nFirst > 1 && nLast - nPointMaxErr > 1) {
if ( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol, bLimitSplit)) ||
! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol, bLimitSplit)))
return nullptr ;
break ;
}
else
return nullptr ;
}
}
if ( pCrvFit->GetCurveCount() > 0)
return Release( pCrvFit) ;
else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid())
return Release( pCrvBez) ;
else
return nullptr ;
}
//----------------------------------------------------------------------------
ICurve*
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, const Vector3d& vtStart, const Vector3d& vtEnd)
{
if ( pCrv == nullptr || ! pCrv->IsValid())
return nullptr ;
#if SAVECURVEPASSED
SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ;
++nCrvPassed ;
#endif
//// uso l'algoritmo di Schneider in Grafic Gems I
// mi aspetto che non ci siano angoli ( discontinuità della derivata prima) nel risultato desiderato
PolyLine plApprox ;
double dAngTolFine = 1 ;
double dLinTolFine = 0.05 ;
pCrv->ApproxWithLines( dLinTolFine, dAngTolFine, ICurve::APL_STD, plApprox) ;
#if SAVELINEARAPPROX
CurveComposite CC ; CC.FromPolyLine(plApprox) ;
SaveGeoObj( CC.Clone(), "D:\\Temp\\bezier\\approxWithBezier\\approssimazione_lineare.nge") ;
#endif
PNTVECTOR vPnt ;
PNTVECTOR vPntOverSampling ;
Point3d pt ; plApprox.GetFirstPoint( pt) ;
do {
if ( ! vPntOverSampling.empty()) {
vPntOverSampling.push_back( Media( vPnt.back(), pt,1./3.)) ;
vPntOverSampling.push_back( Media( vPnt.back(), pt,2./3.)) ;
}
vPntOverSampling.push_back( pt) ;
vPnt.push_back( pt) ;
} while ( plApprox.GetNextPoint( pt)) ;
// calcolo la curvatura nei vari punti per identificare zone a curvatura costante
DBLVECTOR vRad ( ssize( vPnt)) ;
for ( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) {
Vector3d vtA = vPnt[i] - vPnt[i-1] ;
Vector3d vtB = vPnt[i+1] - vPnt[i-1] ;
double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * ( vtA ^ vtB).Len()) ;
vRad[i] = dR ;
}
vRad[0] = vRad[1] ;
vRad.back() = vRad.end()[-2] ;
// identifico le zone a curvatura costante // primo e ultimo punto degli intervalli non devono avere curvatura uguale agli altri perché sono di frontiera
INTINTVECTOR vConstCurv ;
double dRadPrec = vRad[0] ;
int nStart = 0 ;
int nEnd = 1 ;
double dRatio = 1.5 ;
while ( nStart < ssize( vPnt) - 1) {
double dRadTol = max( max( vRad[nEnd], dRadPrec) / 10 , 1.) ;
if ( dRadPrec > dRatio * vRad[nEnd] || dRatio * dRadPrec < vRad[nEnd])
dRadTol = 0 ;
while ( nEnd < ssize( vPnt) - 1 && abs( vRad[nEnd] - dRadPrec) < dRadTol) {
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
vConstCurv.emplace_back( nStart * 3, nEnd * 3) ;
nStart = nEnd ;
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
if ( vConstCurv.empty())
vConstCurv.emplace_back( 0, ssize( vPnt) - 1) ;
int nPoints = ssize( vPnt) ;
DBLVECTOR vParam( nPoints) ;
int nFirst = 0 ;
int nLast = ssize( vPnt) - 1 ;
ParamByLen( vPnt, vParam, nFirst, nLast) ;
VCT3DVECTOR vPrevDer ;
VCT3DVECTOR vNextDer ;
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ;
if ( ! AreSameVectorExact(vtStart, V_NULL)) {
vNextDer[0] = vtStart ;
vPrevDer.back() = vtEnd ;
}
int nOverSampling = ssize( vPntOverSampling) ;
vParam.resize( nOverSampling) ;
nFirst = 0 ;
nLast = nOverSampling - 1 ;
ParamByLen( vPntOverSampling, vParam, nFirst, nLast) ;
//normalizzo tutte le derivate
for ( int i = 0 ; i < ssize( vPrevDer) ; ++i) {
vPrevDer[i].Normalize() ;
vNextDer[i].Normalize() ;
}
// potrei verificare prima se un tratto è retto e aggiustare le tangenti del tratto precedente e successivo prima di approssimare
PtrOwner<ICurveComposite> pCCApproxTot( CreateCurveComposite()) ;
for ( INTINT iiSE : vConstCurv) {
nFirst = iiSE.first ;
nLast = iiSE.second ;
// riconosco se ho un tratto retto
int nPnt = nFirst / 3 ;
if ( nLast - nFirst == 3 && ( nPnt > 0 && vRad[nPnt] > dRatio * vRad[nPnt - 1]) && ( nPnt < ssize( vRad) && vRad[nPnt]> dRatio * vRad[nPnt + 1])) {
CurveLine CL ; CL.Set( vPntOverSampling[nFirst], vPntOverSampling[nLast]) ;
PtrOwner<ICurveBezier> pCApprox( LineToBezierCurve( &CL, 3, false)) ;
if ( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
}
else {
//definisco la bezier che vado a raffinare iterativamente
PtrOwner<ICurve> pCApprox( FitWithBezier( pCrv, vPntOverSampling, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol, true)) ;
if ( IsNull( pCApprox) || ! pCApprox->IsValid())
return nullptr ;
if ( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
}
}
return Release( pCCApproxTot) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints) CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints)
{ {
if ( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){
dErr = INFINITO ;
return false ;
}
// controllo l'errore effettivo campionando più finemente // controllo l'errore effettivo campionando più finemente
double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ; double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ;
double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ; double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ;
dErr = 0 ; Point3d ptStart0 ; pCrvOri->GetStartPoint( ptStart0) ;
Point3d ptStart1 ; pCrvNew->GetStartPoint( ptStart1) ;
Point3d ptEnd0 ; pCrvOri->GetEndPoint( ptEnd0) ;
Point3d ptEnd1 ; pCrvNew->GetEndPoint( ptEnd1) ;
dErr = max( Dist( ptStart1, ptStart0), Dist( ptEnd1, ptEnd0)) ;
for ( int i = 1 ; i < nPoints ; ++i) { for ( int i = 1 ; i < nPoints ; ++i) {
Point3d ptOri, ptNew ; Point3d ptOri, ptNew ;
double dParOri, dParNew ; double dParOri, dParNew ;
@@ -1488,7 +1811,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
{ {
// se con nodi extra // se con nodi extra
if ( cnData.bExtraKnotes) { if ( cnData.bExtraKnotes) {
int nKnotesNbr = int( cnData.vU.size()) ; int nKnotesNbr = ssize( cnData.vU) ;
if ( nKnotesNbr < 4) if ( nKnotesNbr < 4)
return false ; return false ;
cnData.bExtraKnotes = false ; cnData.bExtraKnotes = false ;
@@ -1502,7 +1825,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
bool bAlreadyChecked = false ; bool bAlreadyChecked = false ;
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva // se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
// wrap della curva su se stessa // wrap della curva su se stessa
if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) { if ( cnData.bPeriodic && ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1)) {
bool bRepeated = true ; bool bRepeated = true ;
for ( int i = 0 ; i < cnData.nDeg ; ++i) { for ( int i = 0 ; i < cnData.nDeg ; ++i) {
if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) { if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) {
@@ -1511,11 +1834,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
} }
} }
bool bFirstAddedAtEnd = false ; bool bFirstAddedAtEnd = false ;
if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){ if ( ! bRepeated || ( bRepeated && AreSamePointApprox( cnData.vCP[0], cnData.vCP[cnData.nDeg]))) {
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
DBLVECTOR vU = cnData.vU ; DBLVECTOR vU = cnData.vU ;
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo // se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) { if ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1 ) {
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo // se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) { if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
bFirstAddedAtEnd = true ; bFirstAddedAtEnd = true ;
@@ -1527,11 +1850,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ; cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
// controllo eventualmente anche i nodi extra // controllo eventualmente anche i nodi extra
// se ne ho due in più ne tolgo uno in cima e uno in fondo // se ne ho due in più ne tolgo uno in cima e uno in fondo
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
} }
// se ne ho solo uno in più lo tolgo in cima // se ne ho solo uno in più lo tolgo in cima
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) { else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) {
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
} }
} }
@@ -1558,7 +1881,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// recupero il vettore dei nodi // recupero il vettore dei nodi
cnData.vU = vU ; cnData.vU = vU ;
// verifico se ho nodi extra // verifico se ho nodi extra
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1 ) {
// significa che ci sono due nodi extra: // significa che ci sono due nodi extra:
// se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli // se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli
if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) { if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) {
@@ -1569,7 +1892,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
} }
// se ne ho solo uno in più lo tolgo in cima // se ne ho solo uno in più lo tolgo in cima
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
} }
bAlreadyChecked = true ; bAlreadyChecked = true ;
@@ -1594,7 +1917,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare // qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
bool bCollapsed = true ; bool bCollapsed = true ;
Point3d ptFirst = cnData.vCP.front() ; Point3d ptFirst = cnData.vCP.front() ;
for ( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) { for ( int i = 1 ; i < ssize( cnData.vCP) ; ++i) {
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) { if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
bCollapsed = false ; bCollapsed = false ;
break ; break ;
@@ -1611,7 +1934,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p // agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
// comincio ad aumentare la molteplictià del nodo u_m-p+1 // comincio ad aumentare la molteplictià del nodo u_m-p+1
int nCP = int( cnData.vCP.size()) ; int nCP = ssize( cnData.vCP) ;
int nU = nCP + cnData.nDeg - 1 ; int nU = nCP + cnData.nDeg - 1 ;
int nDeg = cnData.nDeg ; int nDeg = cnData.nDeg ;
PNTVECTOR vBC ; PNTVECTOR vBC ;
@@ -1807,9 +2130,9 @@ NurbsToBezierCurve( const CNurbsData& cnData)
if ( cnData.bPeriodic || cnData.bExtraKnotes) if ( cnData.bPeriodic || cnData.bExtraKnotes)
return nullptr ; return nullptr ;
// numero dei nodi // numero dei nodi
int nU = int( cnData.vCP.size()) + cnData.nDeg - 1 ; int nU = ssize( cnData.vCP) + cnData.nDeg - 1 ;
// controllo relazione nodi - punti di controllo // controllo relazione nodi - punti di controllo
if ( nU != int( cnData.vU.size())) if ( nU != ssize( cnData.vU))
return nullptr ; return nullptr ;
// numero degli intervalli // numero degli intervalli
int nInt = nU - 2 * cnData.nDeg + 1 ; int nInt = nU - 2 * cnData.nDeg + 1 ;
@@ -2179,7 +2502,7 @@ CalcCurvesVoronoiDiagram( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, in
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) { for ( int i = 0 ; i < ssize( vCrvC) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vCrvC[i])) if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
return false ; return false ;
} }
@@ -2206,7 +2529,7 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) { for ( int i = 0 ; i < ssize( vCrvC) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vCrvC[i])) if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
return false ; return false ;
} }
@@ -2267,7 +2590,7 @@ bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, doubl
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) { for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i])) if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ; return false ;
} }
@@ -2297,7 +2620,7 @@ bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, do
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) { for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i])) if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ; return false ;
} }
@@ -2326,3 +2649,209 @@ ResetCurveVoronoi( const ICurve& crvC)
break ; break ;
} }
} }
//----------------------------------------------------------------------------
bool
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
{
if ( ssize( vCrv) == 1)
return true ;
ChainCurves chainCrv ;
// modifico direttamente le curve passate in input
chainCrv.Init( bAllowInvert, dChainTol, ssize( vCrv)) ;
for ( int c = 0 ; c < ssize( vCrv) ; ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vCrv[c]->GetStartPoint( ptStart) ;
vCrv[c]->GetEndPoint( ptEnd) ;
vCrv[c]->GetStartDir( vtStart) ;
vCrv[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
INTVECTOR vIds ;
Point3d ptStart = ORIG ;
while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) {
int nFirst = vIds[0] ;
bool bInvert = false ;
if ( nFirst < 0)
bInvert = true ;
nFirst = abs( nFirst) - 1 ;
if ( bInvert)
vCrv[nFirst]->Invert() ;
ICurveComposite* pFirstCrv = vCrv[nFirst] ;
for ( int nId : vIds) {
bInvert = false ;
if ( nId < 0)
bInvert = true ;
nId = abs( nId) - 1 ;
if ( nId == nFirst)
continue ;
if ( bInvert)
vCrv[nId]->Invert() ;
if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol))
return false ;
}
pFirstCrv->GetEndPoint( ptStart) ;
}
// elimino gli elementi del vettore che non contengono più curve
int c = ssize( vCrv) - 1 ;
while ( c > -1) {
if ( IsNull( vCrv[c]))
vCrv.erase( vCrv.begin() + c) ;
--c ;
}
return true ;
}
//----------------------------------------------------------------------------
double
CalcWeightVal( double dLen, const ICurve* pCrv, const Vector3d vtCurr1, const Point3d& ptCurr1, double dCoeff, double dMyDist, double& dUStep2)
{
pCrv->GetParamAtLength( dLen, dUStep2) ;
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
pCrv->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
double dStepCos2 = vtCurr1 * vtStep2 ;
double dDist = Dist( ptCurr1, ptStep2) ;
return (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
}
//----------------------------------------------------------------------------
bool
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
double dLenPrev2, double& dLenCurr2, double dLen2)
{
Point3d ptCurr1 ;
Vector3d vtCurr1 ;
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
vtCurr1.Normalize() ;
// --- Piano di taglio per punto a minima distanza
IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ;
int nIndParCloser = - 1, nIndPointCloser = -1 ;
double dSqMinDist = INFINITO ;
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
IntCrvPlnInfo aInfo ;
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo) && aInfo.Ici[0].dU > dUPrev2) {
if ( nIndParCloser == -1)
nIndParCloser = nInfo ;
double dSqDist = SqDist( ptCurr1, aInfo.Ici[0].ptI) ;
if ( dSqDist < dSqMinDist) {
dSqMinDist = dSqDist ;
nIndPointCloser = nInfo ;
}
}
}
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
if ( bOkPlane) {
// Se gli indici sono tra loro coerenti allora ho individuato il punto
if ( nIndParCloser == nIndPointCloser) {
IntCrvPlnInfo aInfo ;
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
dUCurr2 = aInfo.Ici[0].dU ;
}
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
else {
// scelgo il punto più vicino al corrente
IntCrvPlnInfo aInfoPt, aInfoPar ;
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
dUCurr2 = ( SqDist( ptCurr1, aInfoPt.Ici[0].ptI) < SqDist( ptCurr1, aInfoPar.Ici[0].ptI) ?
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
#if SAVESYNCLINES
VT.clear() ; VC.clear() ;
VT.emplace_back( pCrvEdge1->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
VT.emplace_back( pCrvEdge2->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
PtrOwner<IGeoPoint3d> ptCurr1Geo( CreateGeoPoint3d()) ; ptCurr1Geo->Set( ptCurr1) ;
VT.emplace_back( Release( ptCurr1Geo)) ; VC.emplace_back( BLUE) ;
PtrOwner<IGeoPoint3d> ptPar( CreateGeoPoint3d()) ; ptPar->Set( aInfoPar.Ici[0].ptI) ;
PtrOwner<IGeoPoint3d> ptPt( CreateGeoPoint3d()) ; ptPt->Set( aInfoPt.Ici[0].ptI) ;
VT.emplace_back( Release( ptPar)) ; VC.emplace_back( LIME) ;
VT.emplace_back( Release( ptPt)) ; VC.emplace_back( FUCHSIA) ;
SaveGeoObj( VT, VC, "C:\\Temp\\bezier\\ruled\\TestTrimmingPlane.nge") ;
#endif
}
// Verifico di non essermi allontanato troppo
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
bOkPlane = ( dLen < dLenPrev2 + 2. * dMyDist) ;
}
if ( ! bOkPlane) {
// --- Altrimenti, cerco il punto a minima distanza
DistPointCurve DPC( ptCurr1, *pCrvEdge2) ;
int nFlag ;
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrev2, dUCurr2, nFlag) && dUCurr2 > dUPrev2) ;
// Verifico di non essermi allontanato troppo
if ( bOkMinDist) {
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
bOkMinDist = ( dLen < dLenPrev2 + 2. * dMyDist) ;
}
if ( ! bOkMinDist) {
// --- Aumento la distanza corrente del passo di campionamento
double dLen = Clamp( dLenPrev2 + dMyDist, 0., dLen2) ;
pCrvEdge2->GetParamAtLength( dLen, dUCurr2) ;
}
}
// Recupero il punto corrente e la direzione tangente sul secondo bordo
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
Point3d ptCurr2 ;
Vector3d vtCurr2 ;
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
vtCurr2.Normalize() ;
// Verifico se le direzioni tangenti sono tra di loro circa parallele
const double COS_ANG_TOL = cos( 15. * DEGTORAD) ;
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
double dSearchLen = dMyDist / 2 ;
int NUM_STEP = 10 ;
const double dCoeff = 0.1 ;
double dCos = vtCurr1 * vtCurr2 ;
double dDistCurr = Dist( ptCurr1, ptCurr2) ;
double dMin = (1 - dCos) + dCoeff * dDistCurr / dMyDist ;
double bUpdated = false ;
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
dSearchLen = dMyDist ;
NUM_STEP = 20 ;
}
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
// faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi
DBLVECTOR vVal ;
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
double dUStep2 ;
vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ;
if ( vVal.back() < dMin) {
dMin = vVal.back() ;
dUCurr2 = dUStep2 ;
}
}
DBLDBLVECTOR vInterv ;
for ( int i = 1 ; i < ssize(vVal) - 1 ; ++i) {
if ( vVal[i] < vVal[i-1] && vVal[i] < vVal[i+1])
vInterv.emplace_back( dLimInfLen2 + ( i - 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP,
dLimInfLen2 + ( i + 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP) ;
}
if ( ssize( vInterv) != 0) {
for ( int j = 0 ; j < ssize( vInterv) ; ++j) {
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
double dLen = vInterv[j].first + i * ( vInterv[j].second - vInterv[j].first) / NUM_STEP ;
double dUStep2 ;
double dVal = CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2) ;
if ( dVal < dMin) {
dUCurr2 = dUStep2 ;
dMin = dVal ;
bUpdated = true ;
}
}
}
}
}
// se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita
if ( bUpdated)
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
return true ;
}
+1
View File
@@ -35,3 +35,4 @@ bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ; bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ; ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ; Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
+3 -4
View File
@@ -275,20 +275,19 @@ CurveBezier::FromLine( const ICurveLine& crLine)
{ {
if ( m_nStatus != OK || ! crLine.IsValid()) if ( m_nStatus != OK || ! crLine.IsValid())
return false ; return false ;
double dWeight = 1 ;
int nCount = 0 ; int nCount = 0 ;
Point3d ptStart ; crLine.GetStartPoint( ptStart) ; Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
SetControlPoint( nCount, ptStart, dWeight) ; SetControlPoint( nCount, ptStart) ;
++nCount ; ++nCount ;
double dPart = 1. / m_nDeg ; double dPart = 1. / m_nDeg ;
for ( int i = 1 ; i < m_nDeg ; ++i) { for ( int i = 1 ; i < m_nDeg ; ++i) {
double dU = i * dPart ; double dU = i * dPart ;
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ; Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
SetControlPoint( nCount, ptMid, dWeight) ; SetControlPoint( nCount, ptMid) ;
++nCount ; ++nCount ;
} }
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ; Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
SetControlPoint( nCount, ptEnd, dWeight) ; SetControlPoint( nCount, ptEnd) ;
++nCount ; ++nCount ;
return true ; return true ;
} }
+2 -201
View File
@@ -202,213 +202,14 @@ CurveByApprox::CalcParameterization( void)
bool bool
CurveByApprox::CalcAkimaTangents( bool bDetectCorner) CurveByApprox::CalcAkimaTangents( bool bDetectCorner)
{ {
// pulisco i vettori delle tangenti return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
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 ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CurveByApprox::CalcBesselTangents( void) CurveByApprox::CalcBesselTangents( void)
{ {
// pulisco i vettori delle tangenti return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
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 ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+34 -235
View File
@@ -50,12 +50,42 @@ CurveByInterp::AddPoint( const Point3d& ptP)
ICurve* ICurve*
CurveByInterp::GetCurve( int nMethod, int nType) 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 ( nMethod == BESSEL) {
if ( ! CalcBesselTangents()) if ( ! CalcBesselTangents())
return nullptr ; return nullptr ;
} }
else if ( nType != CUBIC_BEZIERS_LONG) { else {
if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER)) if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER))
return nullptr ; return nullptr ;
} }
@@ -103,16 +133,6 @@ CurveByInterp::GetCurve( int nMethod, int nType)
return ::Release( pCrvCompo) ; return ::Release( pCrvCompo) ;
} }
// 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)) ;
if ( IsNull(pCrv) || ! pCrv->IsValid())
return nullptr ;
return Release( pCrv) ;
}
return nullptr ; return nullptr ;
} }
@@ -120,233 +140,12 @@ CurveByInterp::GetCurve( int nMethod, int nType)
bool bool
CurveByInterp::CalcAkimaTangents( bool bDetectCorner) CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
{ {
// pulisco i vettori dei parametri e delle tangenti return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
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 ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CurveByInterp::CalcBesselTangents( void) CurveByInterp::CalcBesselTangents( void)
{ {
// pulisco i vettori dei parametri e delle tangenti return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
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 ;
} }
+166 -1
View File
@@ -1967,7 +1967,120 @@ CurveComposite::AddJoint( double dU)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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 // verifico lo stato
if ( m_nStatus != OK) if ( m_nStatus != OK)
@@ -1977,6 +2090,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
// verifico l'indice della giunzione // verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount) if ( nU < 0 || nU > nCrvCount)
return false ; return false ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::NONE ;
// recupero l'indice e il puntatore alla curva precedente (se esiste) // recupero l'indice e il puntatore alla curva precedente (se esiste)
int nPrevCrv = -1 ; int nPrevCrv = -1 ;
if ( nU > 0) if ( nU > 0)
@@ -2005,6 +2120,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
if ( AreSamePointApprox( ptStart, ptNewJoint)) { if ( AreSamePointApprox( ptStart, ptNewJoint)) {
delete pPrevCrv ; delete pPrevCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ; m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::PREV ;
} }
// altrimenti diventa un segmento di retta // altrimenti diventa un segmento di retta
else { else {
@@ -2024,6 +2141,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
if ( AreSamePointApprox( ptNewJoint, ptEnd)) { if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
delete pNextCrv ; delete pNextCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ; m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::NEXT ;
} }
// altrimenti diventa un segmento di retta // altrimenti diventa un segmento di retta
else { else {
@@ -3858,3 +3977,49 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
ptStart = m_ptStart ; ptStart = m_ptStart ;
return true ; 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 ;
}
+8 -1
View File
@@ -26,6 +26,9 @@ class Voronoi ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class CurveComposite : public ICurveComposite, public IGeoObjRW class CurveComposite : public ICurveComposite, public IGeoObjRW
{ {
public :
enum DeletedCurve { NONE = 0, PREV = 1, NEXT = 2 } ;
public : // IGeoObj public : // IGeoObj
~CurveComposite( void) override ; ~CurveComposite( void) override ;
CurveComposite* Clone( void) const override ; CurveComposite* Clone( void) const override ;
@@ -156,7 +159,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ; bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ; bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddJoint( double dU) 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 RemoveJoint( int nU) override ;
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ; bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) 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 SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ; bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
bool GetOnlyPoint( Point3d& ptStart) const override ; bool GetOnlyPoint( Point3d& ptStart) const override ;
bool ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
@@ -211,6 +217,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ; bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ; bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
bool CalcVoronoiObject( void) const ; bool CalcVoronoiObject( void) const ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel) ;
private : private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ; enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
+15 -2
View File
@@ -116,6 +116,7 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
vtDiff = ptQ - ptP ; vtDiff = ptQ - ptP ;
// angolo tra vettore e tangente // angolo tra vettore e tangente
dTemp = vtDer1 * vtDiff ; dTemp = vtDer1 * vtDiff ;
bool bEquiverse = dTemp > 0 ;
if ( abs( dTemp) > EPS_ZERO) if ( abs( dTemp) > EPS_ZERO)
dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ; dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ;
else else
@@ -123,8 +124,20 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
// stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U)) // stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U))
dPrevPar = dPar ; dPrevPar = dPar ;
dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ; 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 // clipping parametro
if ( dPar < approxMin.dParMin) { if ( dPar < approxMin.dParMin) {
if ( approxMin.bParMinSing && ! bClampedFromSing) { if ( approxMin.bParMinSing && ! bClampedFromSing) {
+12 -1
View File
@@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
// distanza non calcolata // distanza non calcolata
m_dDist = - 1 ; m_dDist = - 1 ;
if ( &CrvBez == nullptr || ! CrvBez.IsValid()) if ( ! CrvBez.IsValid())
return ; return ;
// determino tolleranza di approssimazione in base a ingombro curva // 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)) if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
return ; 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 // cerco la minima distanza per la polilinea
MDCVECTOR vApproxMin ; MDCVECTOR vApproxMin ;
if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin)) if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin))
+5 -5
View File
@@ -211,13 +211,13 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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()) if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size())
return false ; return false ;
// se distanza nulla, il punto giace sulla curva // se distanza nulla, il punto giace sulla curva
if ( m_dDist <= EPS_SMALL) { if ( m_dDist <= dTol) {
nSide = MDS_ON ; nSide = MDS_ON ;
return true ; return true ;
} }
@@ -259,7 +259,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
// determino il lato di giacitura del punto // determino il lato di giacitura del punto
double dSide = vtRef * ( m_ptP - ptQ) ; double dSide = vtRef * ( m_ptP - ptQ) ;
if ( abs( dSide) < EPS_SMALL) if ( abs( dSide) < dTol)
nSide = MDS_ON ; nSide = MDS_ON ;
else if ( dSide > 0) else if ( dSide > 0)
nSide = MDS_LEFT ; nSide = MDS_LEFT ;
@@ -270,7 +270,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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()) if ( m_dDist < 0 || m_Info.empty())
return false ; return false ;
@@ -286,7 +286,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
} }
} }
// mi sono ricondotto al caso precedente // mi sono ricondotto al caso precedente
return GetSideAtMinDistPoint( nInd, vtN, nSide) ; return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+10 -9
View File
@@ -23,10 +23,10 @@ using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz) DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
: m_dDist( -1), m_bIsInside( false) : m_dDist( -1), m_bIsInside( false), m_bIsSurfClosed( false)
{ {
// Bezier non valida // Bezier non valida
if ( &pSrfBz == nullptr || ! pSrfBz.IsValid()) if ( ! pSrfBz.IsValid())
return ; return ;
// Calcolo la distanza // Calcolo la distanza
Calculate( ptP, pSrfBz) ; Calculate( ptP, pSrfBz) ;
@@ -37,9 +37,9 @@ void
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz) DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
{ {
// Inizializzo distanza non calcolata // Inizializzo distanza non calcolata
m_dDist = - 1. ; m_dDist = -1 ;
// Controllo se la superficie è chiusa // Controllo se la superficie è chiusa
m_bIsSurfClosed = srfBz.IsClosed() ; m_bIsSurfClosed = srfBz.IsClosed() ;
// Lavoro con l'oggetto superficie trimesh di base // Lavoro con l'oggetto superficie trimesh di base
@@ -49,17 +49,17 @@ DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
DistPointSurfTm dpst( ptP, *pStmRef) ; DistPointSurfTm dpst( ptP, *pStmRef) ;
//recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo // recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo
Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ; Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ;
int nT ; dpst.GetMinDistTriaIndex( nT) ; int nT ; dpst.GetMinDistTriaIndex( nT) ;
//salvo il punto corrispondente nel parametrico // salvo il punto corrispondente nel parametrico
srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ; srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ;
// salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto // 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) ; srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ;
// salvo la distanza minima // salvo la distanza minima
m_dDist = Dist( ptP, m_ptMinDistPoint) ; m_dDist = Dist( ptP, m_ptMinDistPoint) ;
// se il punto è sulla superficie // se il punto è sulla superficie
if ( m_dDist < EPS_SMALL) { if ( m_dDist < EPS_SMALL) {
m_bIsInside = false ; m_bIsInside = false ;
return ; return ;
@@ -96,13 +96,14 @@ DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const DistPointSurfBz::GetParamsAtMinDistPoint( double& dU, double& dV) const
{ {
// Distanza non valida // Distanza non valida
if ( m_dDist < -EPS_ZERO) if ( m_dDist < -EPS_ZERO)
return false ; return false ;
// Distanza valida // Distanza valida
ptParamPoint = m_ptParam ; dU = m_ptParam.x ;
dV = m_ptParam.y ;
return true ; return true ;
} }
BIN
View File
Binary file not shown.
+4
View File
@@ -281,8 +281,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="BBox3d.cpp" /> <ClCompile Include="BBox3d.cpp" />
<ClCompile Include="BiArcs.cpp" /> <ClCompile Include="BiArcs.cpp" />
<ClCompile Include="CalcPocketing.cpp" /> <ClCompile Include="CalcPocketing.cpp" />
<ClCompile Include="CalcDerivate.cpp" />
<ClCompile Include="CAvSilhouetteSurfTm.cpp" /> <ClCompile Include="CAvSilhouetteSurfTm.cpp" />
<ClCompile Include="CAvSimpleSurfFrMove.cpp" /> <ClCompile Include="CAvSimpleSurfFrMove.cpp" />
<ClCompile Include="CAvSurfFrMove.cpp" />
<ClCompile Include="CAvToolSurfTm.cpp" /> <ClCompile Include="CAvToolSurfTm.cpp" />
<ClCompile Include="CAvToolTriangle.cpp" /> <ClCompile Include="CAvToolTriangle.cpp" />
<ClCompile Include="CDeBoxClosedSurfTm.cpp" /> <ClCompile Include="CDeBoxClosedSurfTm.cpp" />
@@ -322,6 +324,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersLineVolZmap.cpp" /> <ClCompile Include="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" /> <ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" /> <ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="OffsetCurve3d.cpp" />
<ClCompile Include="Trimming.cpp" /> <ClCompile Include="Trimming.cpp" />
<ClCompile Include="MultiGeomDB.cpp" /> <ClCompile Include="MultiGeomDB.cpp" />
<ClCompile Include="SurfTriMeshOffset.cpp" /> <ClCompile Include="SurfTriMeshOffset.cpp" />
@@ -352,6 +355,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" /> <ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" /> <ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
<ClInclude Include="CAvSilhouetteSurfTm.h" /> <ClInclude Include="CAvSilhouetteSurfTm.h" />
<ClInclude Include="CAvSurfFrMove.h" />
<ClInclude Include="CDeBoxTria.h" /> <ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" /> <ClInclude Include="CDeCapsTria.h" />
<ClInclude Include="CDeConeFrustumTria.h" /> <ClInclude Include="CDeConeFrustumTria.h" />
+15
View File
@@ -567,6 +567,18 @@
<ClCompile Include="Trimming.cpp"> <ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter> <Filter>File di origine\GeoStriping</Filter>
</ClCompile> </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>
<ClCompile Include="OffsetCurve3d.cpp">
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
@@ -1253,6 +1265,9 @@
<ClInclude Include="..\Include\EGkMultiGeomDB.h"> <ClInclude Include="..\Include\EGkMultiGeomDB.h">
<Filter>File di intestazione\Include</Filter> <Filter>File di intestazione\Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="CAvSurfFrMove.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc"> <ResourceCompile Include="EgtGeomKernel.rc">
+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 bAutoInters, bool bClosed, int nCurvesNbr) ;
bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ; bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ;
bool EraseOtherInfo( 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 : private :
bool m_bOverlaps ; bool m_bOverlaps ;
+66 -22
View File
@@ -47,7 +47,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
// ciclo sulle curve per verificare se da approssimare // ciclo sulle curve per verificare se da approssimare
for ( int i = 0 ; i < 2 ; ++ i) { 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])) || if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) ||
m_pCurve[i]->GetType() == CRV_BEZIER) { m_pCurve[i]->GetType() == CRV_BEZIER) {
// approssimo con rette // approssimo con rette
@@ -127,7 +127,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve)
const CurveArc* pArc = GetBasicCurveArc( &Curve) ; const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
if ( pArc == nullptr) if ( pArc == nullptr)
return false ; 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()) || return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ; abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
} }
@@ -252,10 +252,10 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
bool bool
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB) 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()) if ( m_Info.empty())
return true ; 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) if ( ! bAdjCrvA && ! bAdjCrvB)
return true ; return true ;
// procedo ad aggiustare // procedo ad aggiustare
@@ -296,8 +296,8 @@ int
IntersCurveCurve::GetInters3DCount( void) IntersCurveCurve::GetInters3DCount( void)
{ {
int nCount = 0 ; int nCount = 0 ;
for( int i = 0 ; i < m_nIntersCount ; ++i) { for ( int i = 0 ; i < m_nIntersCount ; ++i) {
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { 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) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ; ++nCount ;
} }
@@ -365,8 +365,8 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
if ( nInd < 0 || nInd >= GetInters3DCount()) if ( nInd < 0 || nInd >= GetInters3DCount())
return false ; return false ;
int nCount = - 1 ; int nCount = - 1 ;
for( int i = 0 ; i < m_nIntersCount ; ++i) { for ( int i = 0 ; i < m_nIntersCount ; ++i) {
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { 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) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ; ++nCount ;
} }
@@ -374,7 +374,7 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
++nCount ; ++nCount ;
} }
if( nCount == nInd) { if ( nCount == nInd) {
aInfo = m_Info[nInd] ; aInfo = m_Info[nInd] ;
return true ; return true ;
} }
@@ -389,11 +389,11 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1) if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
return false ; return false ;
// ricerca del punto più vicino tra le intersezioni singole // ricerca del punto più vicino tra le intersezioni singole
bool bFound = false ; bool bFound = false ;
double dMinSqDist = SQ_INFINITO ; double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < m_nIntersCount ; ++ i) { for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// se è un'intersezione singola // se è un'intersezione singola
if ( ! m_Info[i].bOverlap) { if ( ! m_Info[i].bOverlap) {
// faccio la verifica sul punto // faccio la verifica sul punto
Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ; Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ;
@@ -458,7 +458,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
// se esiste almeno una intersezione // se esiste almeno una intersezione
if ( m_nIntersCount >= 1) if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ; 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 else
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ; return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
} }
@@ -475,7 +475,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
// se esiste almeno una intersezione // se esiste almeno una intersezione
if ( m_nIntersCount >= 1) if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ; 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 else
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ; return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
} }
@@ -540,7 +540,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dU2 = Info[j].IciA[1].dU ; double dU2 = Info[j].IciA[1].dU ;
if ( dU2 < dU1 && pCurve->IsClosed()) if ( dU2 < dU1 && pCurve->IsClosed())
dU2 += dEndPar ; 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) { if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) {
bToSkip = true ; bToSkip = true ;
break ; break ;
@@ -559,7 +559,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dCurrPar = dStartPar ; double dCurrPar = dStartPar ;
double dCurrLen = 0 ; double dCurrLen = 0 ;
double dEndLen ; pCurve->GetLength( dEndLen) ; double dEndLen ; pCurve->GetLength( dEndLen) ;
// se è chiusa, recupero come finisce // se è chiusa, recupero come finisce
if ( pCurve->IsClosed()) { if ( pCurve->IsClosed()) {
if ( ! InfoCorr[nNumInters-1].bOverlap) if ( ! InfoCorr[nNumInters-1].bOverlap)
nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ; nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ;
@@ -577,8 +577,24 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
} }
// costruisco il vettore delle classificazioni // costruisco il vettore delle classificazioni
for ( int i = 0 ; i < nNumInters ; ++ i) { for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente // se è definito un tratto precedente
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ; 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) { if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia omogenea e valida // verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ; int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
@@ -599,7 +615,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
// altrimenti, salvo il tipo // altrimenti, salvo il tipo
else else
nLastTy = InfoCorr[i].IciA[0].nNextTy ; nLastTy = InfoCorr[i].IciA[0].nNextTy ;
// se è definito un tratto in sovrapposizione // se è definito un tratto in sovrapposizione
if ( InfoCorr[i].bOverlap) { if ( InfoCorr[i].bOverlap) {
// assegno i dati // assegno i dati
CrvClass segClass ; CrvClass segClass ;
@@ -610,7 +626,11 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
// salvo dati correnti // salvo dati correnti
dCurrPar = InfoCorr[i].IciA[1].dU ; dCurrPar = InfoCorr[i].IciA[1].dU ;
dCurrLen = dLenU ; 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 // eventuale tratto finale rimasto
@@ -639,7 +659,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
double dStartParB, dEndParB ; double dStartParB, dEndParB ;
if ( ! pCurveB->GetDomain( dStartParB, dEndParB)) if ( ! pCurveB->GetDomain( dStartParB, dEndParB))
return false ; 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 ; BBox3d boxCrvA, boxCrvB ;
if ( ! pCurveA->GetLocalBBox( boxCrvA) || if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
! pCurveB->GetLocalBBox( boxCrvB)) ! pCurveB->GetLocalBBox( boxCrvB))
@@ -682,13 +702,37 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
IntersCurveCurve iCC( clLine, *pCurveB) ; IntersCurveCurve iCC( clLine, *pCurveB) ;
// dichiaro la classe della curva per default // dichiaro la classe della curva per default
int nClass = CRVC_OUT ; int nClass = CRVC_OUT ;
// se c'è almeno una intersezione // se c'è almeno una intersezione
if ( iCC.GetIntersCount() > 0) { 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 ; IntCrvCrvInfo aInfo ;
iCC.GetIntCrvCrvInfo( 0, aInfo) ; iCC.GetIntCrvCrvInfo( 0, aInfo) ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN) if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nClass = CRVC_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 // altrimenti sono esterni tra loro
else { else {
@@ -712,7 +756,7 @@ IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
double dArea ; double dArea ;
if ( ! pCurve->GetAreaXY( dArea)) if ( ! pCurve->GetAreaXY( dArea))
return false ; return false ;
nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ; nClass = (( dArea >= 0) ? CRVC_OUT : CRVC_IN) ;
return true ; return true ;
} }
+10 -2
View File
@@ -139,8 +139,6 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur
void void
IntersCurvePlane::OrderAndCompleteIntersections() IntersCurvePlane::OrderAndCompleteIntersections()
{ {
if ( m_Info.size() < 2)
return ;
// cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione // cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione
// riempio le info PrevTy e NexyTy // 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 ;}) ; sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ;
@@ -237,6 +235,16 @@ IntersCurvePlane::GetIntersCount( void)
return m_nIntersCount ; 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 bool
IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam) IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam)
+158 -40
View File
@@ -15,6 +15,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "IntersLineCyl.h" #include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkFrame3d.h" #include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkIntersLineCylinder.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h" #include "/EgtDev/Include/ENkPolynomialRoots.h"
using namespace std ; using namespace std ;
@@ -25,99 +26,176 @@ using namespace std ;
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. // In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
double dRad, double dHeight, double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
double& dU1, double& dU2)
{ {
// Verifico il versore dU1 = NAN ;
if ( vtL.IsSmall()) dU2 = NAN ;
// Verifico il versore
if ( vtV.IsSmall())
return false ; return false ;
// Verifico il cilindro // Verifico il cilindro
if ( dRad < EPS_SMALL || dHeight < EPS_SMALL) if ( dRad < EPS_SMALL || dH < EPS_SMALL)
return false ; return false ;
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse) // Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
int nBasInt = 0 ; int nBasInt = 0 ;
if ( abs( vtL.z) > EPS_ZERO) { if ( abs( vtV.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti // le linee tangenti al cilindro non sono considerate intersecanti
double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ; double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ; if ( bIgnoreTap)
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) { dEpsRad = 0. ;
dU1 = ( ptInt1 - ptL) * vtL ; ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 1 ; nBasInt += 1 ;
vtN1 = - Z_AX ;
dU1 = ( ( 0 - ptP.z) / vtV.z) ;
} }
Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ; ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) { if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
dU2 = ( ptInt2 - ptL) * vtL ;
nBasInt += 2 ; nBasInt += 2 ;
vtN2 = Z_AX ;
dU2 = ( ( dH - ptP.z) / vtV.z) ;
} }
} }
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni // Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
if ( nBasInt == 3) { if ( nBasInt == 3) {
if ( dU1 > dU2) if ( dU1 > dU2) {
swap( dU1, dU2) ; swap( dU1, dU2) ;
// Trovate intersezioni swap( ptInt1, ptInt2) ;
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
return true ; return true ;
} }
// Determino le intersezioni con la superficie laterale del cilindro // Determino le intersezioni con la superficie laterale del cilindro
DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad, DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
2 * ( ptL.x * vtL.x + ptL.y * vtL.y), 2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
vtL.x * vtL.x + vtL.y * vtL.y} ; vtV.x * vtV.x + vtV.y * vtV.y} ;
DBLVECTOR vdRoots ; DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ; int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro // Epsilon per piani di tappo
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
if ( bIgnoreTap) {
dEpsLow = 0. ;
dEpsUp = 0. ;
}
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
if ( nRoot == 2) { if ( nRoot == 2) {
double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ; double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL) if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
-- nRoot ; -- nRoot ;
} }
if ( nRoot >= 1) { if ( nRoot >= 1) {
double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ; double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) { if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
if ( nRoot == 2) if ( nRoot == 2)
vdRoots[0] = vdRoots[1] ; vdRoots[0] = vdRoots[1] ;
-- nRoot ; -- nRoot ;
} }
} }
// Due soluzioni: la retta interseca due volte la superficie laterale // Due soluzioni: la retta interseca due volte la superficie laterale
if ( nRoot == 2) { if ( nRoot == 2) {
// Punti di intersezione con la superficie del cilindro
ptInt1 = ptP + vdRoots[0] * vtV ;
ptInt2 = ptP + vdRoots[1] * vtV ;
dU1 = vdRoots[0] ; dU1 = vdRoots[0] ;
dU2 = vdRoots[1] ; dU2 = vdRoots[1] ;
if ( dU1 > dU2) // Determino le normali
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
vtN1.Normalize() ;
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
vtN2.Normalize() ;
if ( dU1 > dU2) {
swap( dU1, dU2) ; swap( dU1, dU2) ;
// Trovate intersezioni swap( ptInt1, ptInt2) ;
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
return true ; return true ;
} }
// Una soluzione : la retta interseca la superficie laterale e un piano // Una soluzione : la retta interseca la superficie laterale e un piano
else if ( nRoot == 1) { else if ( nRoot == 1) {
// Se piano superiore // Se piano superiore
if ( nBasInt == 2) { if ( nBasInt == 2) {
// Punto di intersezione
dU1 = vdRoots[0] ; dU1 = vdRoots[0] ;
ptInt1 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
vtN1.Normalize() ;
} }
// altrimenti piano inferiore // altrimenti piano inferiore
else if ( nBasInt == 1) { else if ( nBasInt == 1) {
// Punto di intersezione
dU2 = vdRoots[0] ; dU2 = vdRoots[0] ;
ptInt2 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
vtN2.Normalize() ;
} }
// altrimenti niente // altrimenti niente
else else
return false ; return false ;
if ( dU1 > dU2) if ( dU1 > dU2) {
swap( dU1, dU2) ; swap( dU1, dU2) ;
// Trovate intersezioni swap( ptInt1, ptInt2) ;
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
return true ; return true ;
} }
// Nessuna soluzione : nessuna intersezione // Nessuna soluzione : nessuna intersezione
else else
return false ; return false ;
} }
//----------------------------------------------------------------------------
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
// La funzione restituisce true in caso di intersezione, false altrimenti.
//----------------------------------------------------------------------------
bool
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
if ( IntersLineCyl( ptP, vtV, dH, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap, bInvertNormals))
{
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
return true ;
}
return false ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Linea e cilindro sono nel medesimo riferimento. // Linea e cilindro sono nel medesimo riferimento.
// Il cilindro è definito con centro della base, asse, raggio e altezza. // Il cilindro è definito con centro della base, asse, raggio e altezza.
@@ -133,7 +211,13 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
if ( ! frCyl.Set( ptCyl, vtCyl)) if ( ! frCyl.Set( ptCyl, vtCyl))
return false ; return false ;
// Ora eseguo i conti nel riferimento intrinseco // Ora eseguo i conti nel riferimento intrinseco
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ; bool bTapLow = false ;
bool bTapUp = false ;
bool bIgnoreTap = true ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -157,5 +241,39 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
if ( ! frCyl.Set( ptCyl1, vtCyl)) if ( ! frCyl.Set( ptCyl1, vtCyl))
return false ; return false ;
// Ora eseguo i conti nel riferimento intrinseco // Ora eseguo i conti nel riferimento intrinseco
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ; bool bTapLow = false ;
bool bTapUp = false ;
bool bIgnoreTap = true ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
}
//----------------------------------------------------------------------------
// linea già nel riferimento intrinseco del cilindro
//----------------------------------------------------------------------------
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight,
double& dU1, double& dU2)
{
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
bool bTapLow = false, bTapUp = false ;
bool bIgnoreTap = true ;
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
}
//----------------------------------------------------------------------------
// funzione esposta per altre dll
//----------------------------------------------------------------------------
bool
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2)
{
return IntersLineCyl( ptLineSt, vtLineDir, CylFrame, dH, dRad, false, false,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true, false) ;
} }
+23 -4
View File
@@ -20,17 +20,27 @@
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY. // Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
// Con intersezione viene restituito true e i parametri in dU1 e dU2. // Con intersezione viene restituito true e i parametri in dU1 e dU2.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, bool
double dRad, double dHeight, IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
double& dU1, double& dU2) ; double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
// come sopra ma passo il riferimento intrinseco del cilindro in cui portare la linea
bool
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline bool inline bool
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL, TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight) double dRad, double dHeight)
{ {
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ; double dU1, dU2 ;
return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ; bool bTapLow = false, bTapUp = false ;
bool bIgnoreTap = true ;
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -50,3 +60,12 @@ bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad, const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
double& dU1, double& dU2) ; double& dU1, double& dU2) ;
//----------------------------------------------------------------------------
// // Linea e cilindro sono nel medesimo riferimento.
// Il cilindro è definito con raggio e altezza. ( la linea è già nel riferimento intrinseco del cilindro)
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight,
double& dU1, double& dU2) ;
+24 -4
View File
@@ -158,12 +158,32 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ; bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
// flag per segmenti che si allontanano significativamente // flag per segmenti che si allontanano significativamente
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ; bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
// analisi casi speciali di quasi parallelismo // 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 ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) {
if (( nS1Side == 0 && nS2Side == 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) || if (( nS1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
( nS1Side == 0 && nE2Side == 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) || ( nS1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
( nE1Side == 0 && nS2Side == 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) || ( nE1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
( nE1Side == 0 && nE2Side == 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) { ( nE1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
bParallel = true ; bParallel = true ;
bFarEnds = false ; bFarEnds = false ;
} }
+357 -19
View File
@@ -72,14 +72,28 @@ static void
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos, 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) 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) { if ( nILT == ILTA_IN || nILT == ILTA_EDGE || nILT == ILTA_VERT || nILT == ILTA_NO_TRIA) {
double dU = ( ptIBz - ptL) * vtDir ; 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) { else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) {
double dU = ( ptIBz - ptL) * vtDir ; double dU = ( ptIBz - ptL) * vtDir ;
double dU2 = ( ptIBz2 - 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) ;
} }
} }
@@ -93,9 +107,7 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea // ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(), sort( vInfo.begin(), vInfo.end(),
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b) []( 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) ; { return ( a.dU < b.dU) ; }) ;
double dUb = ( ( b.nILTA == ILTA_SEGM || b.nILTA == ILTA_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
return ( dUa < dUb) ; }) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -181,19 +193,9 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
// ciclo sulle intersezioni // ciclo sulle intersezioni
for ( const auto& Info : vInfo) { for ( const auto& Info : vInfo) {
// se intersezione puntuale // se intersezione puntuale
if ( Info.nILTA == ILTA_VERT || Info.nILTA == ILTA_EDGE || Info.nILTA == ILTA_IN) { vInters.emplace_back( Info.nILSB, Info.dU) ;
int nFlag = LSBT_TOUCH ; // se intersezione sovrapposta
if ( Info.dCosDN > EPS_ZERO) // da sviluppare
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) ;
}
} }
// elimino intersezioni ripetute // elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) { for ( size_t j = 1 ; j < vInters.size() ; ) {
@@ -239,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 bool
IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz, IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
+464
View File
@@ -0,0 +1,464 @@
//----------------------------------------------------------------------------
// EgalTech 2026
//----------------------------------------------------------------------------
// File : OffsetCurve3d.cpp Data : 10.06.26 Versione : 3.1f1
// Contenuto : Classe per offset di Curve 3d.
//
//
//
// Modifiche : 10.06.26 DB Creazione modulo.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "CurveLine.h"
#include "CurveComposite.h"
#include "RemoveCurveDefects.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkOffsetCurve3d.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
using namespace std ;
#define SAVECVRORIG 1
#define SAVEOFFDIR 1
#define SAVECYL 1
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
#include "/EgtDev/Include/EGkColor.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
vector<IGeoObj*> vGeo ;
vector<Color> vCol ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
//----------------------------------------------------------------------------
bool AdjustConcavePartsInPath( const ICurveComposite* pCrv, ICURVEPOVECTOR& vOffsetCrvs, const INTVECTOR& vFlag, double dRad) ;
//----------------------------------------------------------------------------
OffsetCurve3d::~OffsetCurve3d( void)
{
Reset() ;
}
//----------------------------------------------------------------------------
bool
OffsetCurve3d::Reset( void)
{
for ( auto& pCrv : m_CrvLst) {
if ( pCrv != nullptr) {
delete pCrv ;
pCrv = nullptr ;
}
}
m_CrvLst.clear() ;
return true ;
}
//----------------------------------------------------------------------------
bool
OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOffDist, int nType)
{
// pulisco tutto
Reset() ;
PtrOwner<CurveComposite> pCrv( CreateBasicCurveComposite()) ;
if ( ! pCrv->FromPolyLine( PL))
return false ;
#if SAVECVRORIG
vGeo.push_back( pCrv->Clone()) ;
vCol.push_back( AQUA) ;
Point3d ptBase ; PL.GetFirstPoint( ptBase) ;
for ( int i = 0 ; i < ssize( vOffDir) ; ++i) {
IGeoVector3d* pVec = CreateGeoVector3d() ;
pVec->Set( vOffDir[i] * dOffDist, ptBase) ;
PL.GetNextPoint( ptBase) ;
vGeo.push_back( pVec) ;
vCol.push_back( BLUE) ;
}
#endif
// verifico se la curva è un segmento di retta
bool bIsLine = PL.GetPointNbr() == 2 ;
if ( bIsLine) {
// faccio l'offset di una linea
return true ;
}
// se offset nullo, copio la curva ed esco
if ( abs( dOffDist) < 10 * EPS_SMALL) {
PtrOwner<CurveComposite> pCopy( CreateBasicCurveComposite()) ;
if ( IsNull( pCopy) || ! pCopy->CopyFrom( pCrv))
return false ;
// unisco parti allineate (tranne gli estremi)
pCopy->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, false) ;
// sposto in lista
m_CrvLst.push_back( Release( pCopy)) ;
return true ;
}
// elimino tratti molto corti
if ( ! RemoveCurveSmallParts( pCrv, m_dLinTol))
return false ;
bool bClosed = pCrv->IsClosed() ;
INTVECTOR vFlag ;
vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ;
const ICurve* pSubCrv = pCrv->GetFirstCurve() ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
pSubCrv = pCrv->GetNextCurve() ;
Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ;
int nFlag = vtDirCurr * vOffDir[i] > 0 ? OffsetCurve3d::AngType::ANG_SMOOTH_CONC : OffsetCurve3d::AngType::ANG_STR ;
vFlag.push_back( nFlag) ;
}
double dRadCorr ;
Point3d ptPrev ; pCrv->GetStartPoint( ptPrev) ;
ptPrev += vOffDir[0] * dOffDist ;
Vector3d vtNormPrev ;
Vector3d vtCorrPrev ;
Vector3d vtTangPrev ;
Vector3d vtDirPrev ; pCrv->GetStartDir( vtDirPrev) ;
const ICurve* pCrvPrev = pCrv->GetFirstCurve() ;
const ICurve* pCrvCurr ;
vector<PtrOwner<ICurve>> vOffsetCrvs ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
pCrvCurr = pCrv->GetNextCurve() ;
Vector3d vtOffDir = vOffDir[i] ;
Vector3d vtDirCurr ; pCrvCurr->GetStartDir( vtDirCurr) ;
pCrvPrev->GetStartDir( vtDirPrev) ;
Vector3d vtTang = Media( vtDirCurr, vtDirPrev) ;
vtTang.Normalize() ;
Vector3d vtNorm = vtOffDir ;
vtNorm.Rotate( vtTang, -90) ;
//Vector3d vtCorr = vtTang ^ vtNorm ; vtCorr.Normalize() ;
// devo invertire vtCorr??? se sì, quando?/////////////////////////////////////////
Vector3d vtCorr = vtOffDir ;
double dCorrK = 1 ;
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CONC) {
double dHalfAlfa = acos( vtTang * vtTangPrev) ;
dCorrK = 1 / sin( 90 - dHalfAlfa) ;
}
Point3d ptP ; pCrvCurr->GetStartPoint( ptP) ;
dRadCorr = dOffDist ;
ptP = ptP + dRadCorr * dCorrK * vtCorr ;
// se secondo punto di angolo esterno di fianco, inserisco movimenti intermedi
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[i-1] == OffsetCurve3d::AngType::ANG_CVEX) {
double dAlfa = acos( vtTang * vtTangPrev) ;
double dDelta = dOffDist * tan( dAlfa / 4) ;
Point3d ptAdd1 = ptPrev + dDelta * vtTangPrev ;
ICurveLine* pCL1 = CreateBasicCurveLine() ;
pCL1->Set( ptPrev, ptAdd1) ;
vOffsetCrvs.emplace_back( pCL1) ;
Point3d ptAdd2 = ptP - dDelta * vtTang ;
ICurveLine* pCL2 = CreateBasicCurveLine() ;
pCL2->Set( ptAdd1, ptAdd2) ;
vOffsetCrvs.emplace_back( pCL2) ;
ptPrev = ptAdd2 ;
}
//// se punto di angolo interno di fianco, elimino eventuali movimenti precedenti invertiti
//if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX == 3) {
// local nLastId = EgtGetLastInGroup( nClPathId)
// while nLastId do
// local vtMlast = ptP - EgtEP( nLastId, GDB_ID.ROOT) ; vtMlast:normalize()
// if vtMlast * vtGpre < 0.5 then
// ptPpre = EgtSP( nLastId, GDB_ID.ROOT)
// EgtErase( nLastId)
// else
// break
// end
// nLastId = EgtGetLastInGroup( nClPathId)
// end
//}
//// se appena dopo angolo interno di fianco, verifico se da aggiungere
//bool bToAdd = true
//if ( nFlpre == 3 and abs( dSideAng) > GEO.EPS_ANG_SMALL) {
// local vtMove = ptP - ptPpre ; vtMove:normalize()
// if vtMove * vtTang < 0.5 then
// bToAdd = false
// end
//}
// aggiungo tratto
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
vOffsetCrvs.emplace_back( pCL) ;
// aggiorno punto precedente
ptPrev = ptP ;
vtNormPrev = vtNorm ;
vtCorrPrev = vtCorr ;
vtTangPrev = vtTang ;
vtDirPrev = vtDirCurr ;
}
//// qui faccio la correzione per gli angoli interni
//AdjustConcavePartsInPath( pCrv, vOffsetCrvs, vFlag, dOffDist) ;
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
#endif
PtrOwner<ICurveComposite> pCrvOffset( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
if ( ! pCrvOffset->AddCurve( Release( vOffsetCrvs[i])))
return false ;
}
m_CrvLst.push_back( Release( pCrvOffset)) ;
return true ;
// raccordi
// angoli interni
// angoli esterni
// auto intersezioni
//// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
//// ottavo passo : concateno i percorsi risultanti (senza cambiare verso)
//// nono passo : se con smusso o estensione, sostituisco i fillet con questi
//// ordino le curve in ordine decrescente di lunghezza
//if ( m_CrvLst.size() > 1) {
// for ( auto pCrv : m_CrvLst) {
// double dLen ;
// if ( pCrv->GetLength( dLen))
// pCrv->SetTempProp( int( 1000 * dLen)) ;
// else
// pCrv->SetTempProp( 0) ;
// }
// m_CrvLst.sort( []( const ICurve* pA, const ICurve* pB) { return ( pA->GetTempProp() > pB->GetTempProp()) ; }) ;
//}
//// se originale era chiusa, verifico le risultanti e se necessario cerco di chiuderle
//if ( bClosed) {
// for ( auto pCrv : m_CrvLst) {
// CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ;
// if ( pCrvCo != nullptr)
// pCrvCo->Close() ;
// }
//}
//return true ;
}
//----------------------------------------------------------------------------
ICurve*
OffsetCurve3d::GetCurve( void)
{
return GetLongerCurve() ;
}
//----------------------------------------------------------------------------
ICurve*
OffsetCurve3d::GetLongerCurve( void)
{
if ( m_CrvLst.empty())
return nullptr ;
// le curve sono ordinate in senso decrescente di lunghezza
ICurve* pCrv = m_CrvLst.front() ;
m_CrvLst.pop_front() ;
return pCrv ;
}
//----------------------------------------------------------------------------
ICurve*
OffsetCurve3d::GetShorterCurve( void)
{
if ( m_CrvLst.empty())
return nullptr ;
// le curve sono ordinate in senso decrescente di lunghezza
ICurve* pCrv = m_CrvLst.back() ;
m_CrvLst.pop_back() ;
return pCrv ;
}
struct Cyl {
Cyl( void): frCyl( GLOB_FRM), dH( 0.), dRad( 0.) {;} ;
Cyl( const Frame3d& _frCyl, double _dH, double _dRad, double _dLinTol) :
frCyl( _frCyl), dH( _dH), dRad( _dRad) { ;}
Cyl( const Point3d& _ptBase, const Vector3d& vtZ, double _dH, double _dRad, double _dLinTol) :
dH( _dH), dRad( _dRad){
frCyl.Set( _ptBase, vtZ); }
public :
Frame3d frCyl ;
public:
double dH ;
double dRad ;
};
typedef vector<Cyl> CYLVECT ;
//----------------------------------------------------------------------------
bool
IsPointInsideCylinder( const Point3d& ptTest, const Cyl& offCyl)
{
Point3d ptTestLoc = ptTest ; ptTestLoc.ToLoc( offCyl.frCyl) ;
if ( ptTestLoc.z > offCyl.dH || ptTestLoc.z < 0)
return false ;
double dDist = ptTestLoc.x * ptTestLoc.x + ptTestLoc.y * ptTestLoc.y ;
double dRadSq = offCyl.dRad * offCyl.dRad ;
if ( dDist > dRadSq)
return false ;
return true ;
}
bool
AdjustConcavePartsInPath( const ICurveComposite* pCrv, ICURVEPOVECTOR& vOffsetCrvs, const INTVECTOR& vFlag, double dRad)
{
const double dLinTol = 5 * EPS_SMALL ;
INTVECTOR vErase ;
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
int nFlag = vFlag[i] ;
if ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
// scorro i prossimi finchè trovo la fine della zona concava
INTVECTOR vLines ;
while ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
vLines.push_back( i) ;
++i ;
nFlag = vFlag[i] ;
}
CYLVECT vCyl ;
// creo un cilindro della dimensione del raggio
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
const ICurve* pSubCrv = pCrv->GetCurve( vLines[j]) ;
Point3d ptStart, ptEnd ;
pSubCrv->GetStartPoint( ptStart) ;
pSubCrv->GetEndPoint( ptEnd) ;
Vector3d vtHeight = ptEnd - ptStart ; vtHeight.Normalize() ;
double dHeight = vtHeight.Len() ;
vCyl.emplace_back( ptStart, vtHeight, dHeight, dRad, dLinTol) ;
}
// controllo l'end di ogni linea per verificare se sta nel cilindro definito da uno degli altri tratti
// controllo tutto i punti
bool bErasedSomePart = false ;
bool bErasedPrev = false ;
INTVECTOR vInters ;
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
Point3d ptStart, ptEnd ;
const ICurve* pSubCrv = pCrv->GetCurve( vLines[j]) ;
if ( pSubCrv == nullptr)
return false ;
pSubCrv->GetEndPoint( ptEnd) ;
pSubCrv->GetStartPoint( ptStart) ;
// se stanno in uno dei cilindri degli altri tratti della zona concava
for ( int k = 0 ; k < ssize( vLines) ; ++k) {
if ( j == k)
continue ;
bool bToErase = IsPointInsideCylinder( ptEnd, vCyl[k]) ;
if ( bErasedPrev && ! bToErase)
bToErase = bToErase || IsPointInsideCylinder( ptStart, vCyl[k]) ;
if ( bToErase) {
bErasedSomePart = true ;
bErasedPrev = true ;
vInters.push_back( vLines[j]) ;
if ( j < ssize( vLines) - 1)
vInters.push_back( vLines[j+1]) ;
++j ;
break ;
}
else
bErasedPrev = false ;
}
}
if ( bErasedSomePart) {
// calcolo le intersezioni effettive del primo e ultimo tratto cancellati con i cilindri che li hanno cancellati
// controllo che effettivamente tutti i tratti cancellati siano consecutivi
for ( int j = 1 ; j < ssize( vInters) ; ++j) {
if ( vInters[j] != vInters[j-1] + 1)
return false ;
}
for ( int j = 0 ; j < ssize( vInters) ; ++j) {
// cancello i tratti intermedi
if ( j > 0 && j < ssize( vInters) - 1) {
vErase.push_back( vInters[j]) ;
continue ;
}
// per il primo e ultimo controllo le intersezioni con tutti i cilindri
ICurve* pCL = vOffsetCrvs[vInters[j]] ;
Point3d ptStart ; pCL->GetStartPoint( ptStart) ;
Vector3d vtStart ; pCL->GetStartDir( vtStart) ;
double dLen ; pCL->GetLength( dLen) ;
double dUTrim = ( j == 0 ? INFINITO : 0) ;
Point3d ptTrim = P_INVALID ;
for ( int k = 0 ; k < ssize( vCyl) ; ++k) {
if ( vInters[j] == k)
continue ;
Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
double dU1, dU2 ;
Vector3d vtN1, vtN2 ;
if ( IntersLineCyl( ptStart, vtStart * dLen, vCyl[k].frCyl, vCyl[k].dH, vCyl[k].dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true)) {
bool bUpdate = ( j == 0 ? dU1 < dUTrim : dU1 > dUTrim) ;
bUpdate = bUpdate && ptInt1.IsValid() && dU1 > 0 && dU1 < 1 ;
bUpdate = bUpdate && vtN1 * vtStart < 0 ;
if ( bUpdate) {
dUTrim = dU1 ;
ptTrim = ptInt1 ;
}
bUpdate = ( j == 0 ? dU2 < dUTrim : dU2 > dUTrim) ;
bUpdate = bUpdate && ptInt2.IsValid() && dU2 > 0 && dU2 < 1 ;
bUpdate = bUpdate && vtN2 * vtStart > 0 ;
if ( bUpdate) {
dUTrim = dU2 ;
ptTrim = ptInt2 ;
}
}
}
if ( ptTrim.IsValid()) {
if ( j == 0) {
pCL->ModifyEnd( ptTrim) ;
double dNewLen ; pCL->GetLength( dNewLen) ;
if ( dNewLen < 0.1 && vInters[0] != 0) { // se fosse il primo allora potrei modificare il successivo
int nPrev = vInters[0] - 1 ;
vErase.push_back( vInters[0]) ;
vInters[0] = nPrev ;
ICurve* pCLPrev = vOffsetCrvs[nPrev] ;
pCLPrev->ModifyEnd( ptTrim) ;
}
}
else {
pCL->ModifyStart( ptTrim) ;
double dNewLen ; pCL->GetLength( dNewLen) ;
if ( dNewLen < 0.1 && vInters[j] != ssize( vOffsetCrvs) - 1) { // se fosse l'ultima curva allora potrei modificare la precedente
int nNext = vInters[j] + 1 ;
vErase.push_back( vInters[j]) ;
vInters[j] = nNext ;
ICurve* pCLNext = vOffsetCrvs[nNext] ;
pCLNext->ModifyStart( ptTrim) ;
}
}
}
}
}
i = vLines.back() ;
}
}
// scorro tutto il vettore delle linee di offset e unisco aggiungendo una linea dove ne ho cancellate
for ( int i = 0 ; i < ssize( vOffsetCrvs) - 1 ; ++i) {
Point3d ptEndCurr, ptStartNext ;
vOffsetCrvs[i]->GetEndPoint( ptEndCurr) ;
vOffsetCrvs[i+1]->GetStartPoint( ptStartNext) ;
if ( ! AreSamePointApprox( ptEndCurr, ptStartNext)) {
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptEndCurr, ptStartNext) ;
PtrOwner<ICurve> pCrvL( pCL) ;
vOffsetCrvs.insert( vOffsetCrvs.begin() + i + 1, std::move(pCrvL)) ;
++i ;
}
}
return true ;
}
+2 -8
View File
@@ -1991,17 +1991,11 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType,
nAddedSpan = 0 ; nAddedSpan = 0 ;
nCrv1 = 0 ; nCrv1 = 0 ;
nCrv2 = 0 ; nCrv2 = 0 ;
bool bLast1 = false ;
bool bLast2 = false ;
while ( nAddedSpan < nPnt) { while ( nAddedSpan < nPnt) {
if ( nCrv1 >= nPnt1) { if ( nCrv1 >= nPnt1)
nCrv1 = nPnt1 - 1 ; nCrv1 = nPnt1 - 1 ;
bLast1 = true ; if ( nCrv2 >= nPnt2)
}
if ( nCrv2 >= nPnt2) {
nCrv2 = nPnt2 - 1 ; nCrv2 = nPnt2 - 1 ;
bLast2 = true ;
}
bool bRep1 = vbRep1[nCrv1] ; bool bRep1 = vbRep1[nCrv1] ;
bool bRep2 = vbRep2[nCrv2] ; bool bRep2 = vbRep2[nCrv2] ;
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ; const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
+1 -1
View File
@@ -173,7 +173,7 @@ Polygon3d::FromPlaneTrimmedWithBox( const Point3d& ptOn, const Vector3d& vtN,
{ {
Plane3d plPlane ; Plane3d plPlane ;
plPlane.Set( ptOn, vtN) ; 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 ; 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) ; 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) ; 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) if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
continue ; continue ;
// calcolo il segmento di linea // calcolo il segmento di linea
CurveLine clLine ; CurveLine clLine ;
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second)) if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
return false ; return false ;
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop // l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
IntersCurveCurve intLL( clLine, ccLoop) ; IntersCurveCurve intLL( clLine, ccLoop) ;
IntCrvCrvInfo aInfo ; if ( intLL.GetIntersCount() == 0) {
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) { Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ;
dElev = max( dElev, aInfo.IciA[0].ptI.z) ; ptM.z = 0 ;
if ( aInfo.bOverlap) if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL))
dElev = max( dElev, aInfo.IciA[1].ptI.z) ; dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.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) else {
dElev = max( dElev, vEdges[i].first.z) ; IntCrvCrvInfo aInfo ;
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice) for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN) dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
dElev = max( dElev, vEdges[i].second.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) ;
}
} }
} }
+312 -132
View File
@@ -19,6 +19,7 @@
#include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h" #include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h"
@@ -39,6 +40,7 @@ const int P5AX_CVEX = 2 ; // su angolo convesso
const int P5AX_CONC = 3 ; // in angolo concavo const int P5AX_CONC = 3 ; // in angolo concavo
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
const int P5AX_SMOOTH_CONC = 6 ; // zona concava curva, senza spigolo netto
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static double static double
@@ -63,6 +65,7 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
static bool static bool
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
{ {
const double dSinSmallAngle = sin( 0 * DEGTORAD) ;
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
// precedente // precedente
int j = i - 1 ; int j = i - 1 ;
@@ -78,20 +81,28 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Point3d ptInt ; Point3d ptInt ;
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
// verifico se spigolo convesso o concavo // verifico se spigolo convesso o concavo
bool bConvex ; bool bConvex = (vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 < 0 ;
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP)) bool bValidInters = true ;
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ; if ( i > 2) {
else int k = i - 2 ;
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ; // verifico la concavità anche tornando indietro lungo la linea
if ( ( ( vPt5ax[k].ptP - vPt5ax[j].ptP) * vPt5ax[i].vtDir1 < 0) != bConvex) {
LOG_WARN( GetEGkLogger(), "La superficie su cui si sta proiettando la curva ha delle normali incoerenti")
return false ;
}
// verifico che l'intersezione sia tra i e j e non prima di j
bValidInters = ( ptInt - vPt5ax[j].ptP) * ( vPt5ax[j].ptP - vPt5ax[k].ptP) > 0 ;
}
// se convesso, metto due punti con direzione appena prima e appena dopo // se convesso, metto due punti con direzione appena prima e appena dopo
if ( bConvex) { if ( bConvex) {
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
if ( dLen1 > 2 * EPS_SMALL) { if ( dLen1 > 10 * EPS_SMALL && bValidInters) {
Point5ax Pt5ax ; Point5ax Pt5ax ;
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ; 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.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ; Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -99,11 +110,18 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
} }
else else
vPt5ax[j].nFlag = P5AX_CVEX ; vPt5ax[j].nFlag = P5AX_CVEX ;
if ( dLen2 > 2 * EPS_SMALL) { if ( dLen2 > 10 * EPS_SMALL) {
Point5ax Pt5ax ; Point5ax Pt5ax ;
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; if ( bValidInters)
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
else {
Vector3d vtNewLine = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtNewLine.Normalize() ;
Pt5ax.ptP = vPt5ax[j].ptP + vtNewLine * 2 * EPS_SMALL ;
}
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ; 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.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ; Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -118,6 +136,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ; 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.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.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ; Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -126,6 +146,21 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
} }
} }
} }
else {
// guardo se la proiezione il tratto successivo, lungo la normale precedente + maggiore di un angolo minimo ( angolo interno smooth)
Vector3d vtDirNext = vPt5ax[i].ptP - vPt5ax[j].ptP ;
vtDirNext.Normalize() ;
if ( vtDirNext * vPt5ax[j].vtDir1 > dSinSmallAngle) {
// se concavo senza spigolo netto segnalo zona concava smooth
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
}
}
}
// riscorro tutto il vettore per vedere se ho creato delle zone concave smooth frammentate (separate solo da un tratto non classificato concavo), che quindi uniformo
for ( int i = 1 ; i < ssize( vPt5ax) - 1 ; ++ i) {
if ( vPt5ax[i].nFlag != P5AX_SMOOTH_CONC && vPt5ax[i-1].nFlag == P5AX_SMOOTH_CONC && vPt5ax[i+1].nFlag == P5AX_SMOOTH_CONC)
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
} }
return true ; return true ;
} }
@@ -233,23 +268,55 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static const SurfTriMesh*
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax) MyGetAuxSurf( const ISurf* pSrf)
{ {
// punto sulle supefici a minima distanza 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 nSurfMin = -1 ;
int nTriaMin ; int nTriaMin = -1 ;
double dUMin = -1, dVMin = -1 ;
Point3d ptMin ; Point3d ptMin ;
double dMinDist ; double dMinDist = NAN ;
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
// punto sulla superficie a minima distanza // punto sulla superficie a minima distanza
DistPointSurfTm dPS( ptP, *vpStm[i]) ; int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ;
double dDist ; if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) { DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ;
nSurfMin = i ; double dDist ;
dPS.GetMinDistPoint( ptMin) ; if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
dPS.GetMinDistTriaIndex ( nTriaMin) ; nSurfMin = i ;
dMinDist = dDist ; 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 ;
}
} }
} }
@@ -257,19 +324,44 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar
if ( nSurfMin >= 0) { if ( nSurfMin >= 0) {
// assegno il punto // assegno il punto
Point3d ptInt = ptMin ; Point3d ptInt = ptMin ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) // calcolo gli altri dati
Triangle3dEx trTria ; int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ;
if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria)) if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
return false ; // recupero superficie trimesh
Vector3d vtN ; const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ;
if ( ! CalcNormal( ptMin, trTria, vtN)) // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
vtN = trTria.GetN() ; Triangle3dEx trTria ;
// assegno valori al punto 5assi if ( ! pSurfTm->GetTriangle( nTriaMin, trTria))
Pt5ax.ptP = ptInt ; return false ;
Pt5ax.vtDir1 = vtN ; Vector3d vtN ;
Pt5ax.vtDir2 = vtN ; if ( ! CalcNormal( ptMin, trTria, vtN))
Pt5ax.dPar = dPar ; vtN = trTria.GetN() ;
Pt5ax.nFlag = P5AX_STD ; // 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 // ritorno con successo
return true ; return true ;
} }
@@ -282,31 +374,6 @@ bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// controllo le tolleranze // controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ; dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
@@ -331,15 +398,17 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
} }
// se richiesto, inserimento punti intermedi in presenza di spigoli // se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) if ( bSharpEdges) {
AddPointsOnCorners( vPt5ax) ; if ( ! AddPointsOnCorners( vPt5ax))
return false ;
}
// rimozione punti in eccesso rispetto alle tolleranze // rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
@@ -354,7 +423,7 @@ typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM, 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) // intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
Point3d ptL = GetToLoc( ptP, frRefLine) ; Point3d ptL = GetToLoc( ptP, frRefLine) ;
@@ -363,23 +432,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) { for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) { if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) // se dalla direzione
int nI = ssize( vIntRes) - 1 ; if ( bFromVsTo) {
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
--nI ; int nI = ssize( vIntRes) - 1 ;
// se trovata while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
if ( nI >= 0) { --nI ;
if ( nInd < 0) { // se trovata
IntRes = vIntRes[nI] ; if ( nI >= 0) {
nInd = i ; if ( nInd < 0) {
}
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] ; IntRes = vIntRes[nI] ;
nInd = i ; 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 ;
}
}
} }
} }
} }
@@ -403,6 +497,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = frRefLine.VersZ() ; Pt5ax.vtDir2 = frRefLine.VersZ() ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -414,7 +510,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -480,7 +576,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -502,7 +598,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool 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 // punto di riferimento
Point3d ptMin = gpRef.GetPoint() ; Point3d ptMin = gpRef.GetPoint() ;
@@ -517,23 +614,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) // se dal punto
int nI = ssize( vIntRes) - 1 ; if ( bFromVsTo) {
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
--nI ; int nI = ssize( vIntRes) - 1 ;
// se trovata while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
if ( nI >= 0) { --nI ;
if ( nInd < 0) { // se trovata
IntRes = vIntRes[nI] ; if ( nI >= 0) {
nInd = i ; if ( nInd < 0) {
}
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] ; IntRes = vIntRes[nI] ;
nInd = i ; 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 ;
}
}
} }
} }
} }
@@ -557,6 +679,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ; Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -569,7 +693,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -620,7 +744,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -638,7 +762,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool 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 // punto a minima distanza
DistPointCurve dPC( ptP, crRef) ; DistPointCurve dPC( ptP, crRef) ;
@@ -656,23 +781,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) // se dalla curva
int nI = ssize( vIntRes) - 1 ; if ( bFromVsTo) {
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
--nI ; int nI = ssize( vIntRes) - 1 ;
// se trovata while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
if ( nI >= 0) { --nI ;
if ( nInd < 0) { // se trovata
IntRes = vIntRes[nI] ; if ( nI >= 0) {
nInd = i ; if ( nInd < 0) {
}
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] ; IntRes = vIntRes[nI] ;
nInd = i ; 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 ;
}
}
} }
} }
} }
@@ -695,7 +845,9 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
// assegno valori al punto 5assi // assegno valori al punto 5assi
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ; Pt5ax.vtDir2 = ( bFromVsTo ? vtLine : -vtLine) ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -709,7 +861,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{ {
// Sistemazioni per tipo di superficie // Sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -760,7 +912,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -778,7 +930,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool 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 // punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, stmRef) ; DistPointSurfTm dPS( ptP, stmRef) ;
@@ -805,23 +958,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) // se dalla superficie
int nI = ssize( vIntRes) - 1 ; if ( bFromVsTo) {
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
--nI ; int nI = ssize( vIntRes) - 1 ;
// se trovata while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
if ( nI >= 0) { --nI ;
if ( nInd < 0) { // se trovata
IntRes = vIntRes[nI] ; if ( nI >= 0) {
nInd = i ; if ( nInd < 0) {
}
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] ; IntRes = vIntRes[nI] ;
nInd = i ; 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 ;
}
}
} }
} }
} }
@@ -852,6 +1030,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ; Pt5ax.vtDir2 = vtN2 ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -864,7 +1044,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -936,7 +1116,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
+10 -3
View File
@@ -92,11 +92,18 @@ RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dPa
Vector3d vtCurrR = frAct.VersX() ; Vector3d vtCurrR = frAct.VersX() ;
Vector3d vtCurrT = frAct.VersZ() ; Vector3d vtCurrT = frAct.VersZ() ;
// punto i-esimo sulla curva e suo vettore tangente // punto i-esimo sulla curva e suo vettore tangente medio
Point3d ptNextM, ptNextP ;
Vector3d vtNextM, vtNextP ;
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNextM, &vtNextM) ||
! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_PLUS, ptNextP, &vtNextP) ||
! vtNextM.Normalize() || ! vtNextP.Normalize())
return false ;
Point3d ptNext ; Point3d ptNext ;
Vector3d vtNextT ; Vector3d vtNextT ;
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) || ptNext = Media( ptNextM, ptNextP) ;
! vtNextT.Normalize()) vtNextT = Media( vtNextM, vtNextP) ;
if ( ! vtNextT.Normalize())
return false ; return false ;
// controllo per casi degeneri // controllo per casi degeneri
+38 -3
View File
@@ -735,8 +735,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfBezier* ISurfBezier*
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv, GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
const INTVECTOR& vShown, const INTINTVECTOR& vNewOrEdited, double dLinTol)
{ {
// verifica parametri // verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr) if ( pCurve1 == nullptr || pCurve2 == nullptr)
@@ -763,7 +762,43 @@ GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const IC
// creo e setto la superficie trimesh // creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv, vNewCrv, vShown, vNewOrEdited)) 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 ; return nullptr ;
// restituisco la superficie // restituisco la superficie
+1121 -542
View File
File diff suppressed because it is too large Load Diff
+14 -7
View File
@@ -76,11 +76,18 @@ FromString( const string& sVal, Frame3d& frFrame)
bool bool
FromString( const string& sVal, Color& cCol) FromString( const string& sVal, Color& cCol)
{ {
// devono essere 4 parametri : Red, Green, Blue, Alpha // dovrebbero essere 4 parametri : Red, Green, Blue, Alpha
int vnVal[4] ; int vnRGBA[4] ;
if ( ! FromString( sVal, vnVal)) if ( FromString( sVal, vnRGBA)) {
return false ; cCol.Set( vnRGBA[0], vnRGBA[1], vnRGBA[2], vnRGBA[3]) ;
// assegno il colore return true ;
cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[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 ;
} }
+310 -68
View File
@@ -24,6 +24,14 @@
#include "/EgtDev/Include/EGkSurfAux.h" #include "/EgtDev/Include/EGkSurfAux.h"
#include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.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 ; using namespace std ;
@@ -530,6 +538,25 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
return Release( pSrfBz) ; 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 bool
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0, MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
@@ -539,36 +566,33 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
bool bRescaledU = false ; bool bRescaledU = false ;
bool bRescaledV = false ; bool bRescaledV = false ;
int nSpanU = 1, nSpanV = 1 ; 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) { for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
// vettore dei nodi // vettore dei nodi
DBLVECTOR vU ; DBLVECTOR& vU = mKnots[nDir] ;
int nExtraKnots = 0 ; int nExtraKnots = 0 ;
// controllo in U // controllo in U
if ( nDir == 0) { if ( nDir == 0) {
if ( nDegU > 1) { for ( int i = nExtraKnots ; i < ssize( vU0) - nExtraKnots ; ++i ) {
nExtraKnots = nDegU - 1 ;
}
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
double dKnot = vU0[i] * SBZ_TREG_COEFF ; double dKnot = vU0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente // 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) ; vU.push_back( dKnot) ;
} }
nSpanU = (int)vU.size() - 1 ; nSpanU = ssize( vU) - 1 ;
} }
// controllo in V // controllo in V
else if ( nDir == 1 ) { else if ( nDir == 1 ) {
if ( nDegV > 1) { for ( int i = nExtraKnots ; i < ssize( vV0) - nExtraKnots ; ++i ) {
nExtraKnots = nDegV - 1 ;
}
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
double dKnot = vV0[i] * SBZ_TREG_COEFF ; double dKnot = vV0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente // 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) ; vU.push_back( dKnot) ;
} }
nSpanV = (int)vU.size() - 1 ; nSpanV = ssize( vU) - 1 ;
} }
// controllo se il vettore dei nodi è uniforme // controllo se il vettore dei nodi è uniforme
@@ -581,76 +605,268 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
if ( b < (int)vU.size()) if ( b < (int)vU.size())
d1 = abs( vU[b] - vU[a]) ; 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 ; nDir == 0 ? bRescaledU = true : bRescaledV = true ;
pRescaledSfr.Set( CreateSurfFlatRegion()) ; // creo il vettore delle curve all'interno di una striscia
if ( IsNull( pRescaledSfr)) ICRVCOMPOPOVECTOR vCrvStrip ;
return false ; for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) {
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
if ( IsNull( pSfr_copy))
return false ;
double dLenStrip = abs( vU[p+1] - vU[p]) ; double dLenStrip = abs( vU[p+1] - vU[p]) ;
if ( dLenStrip < EPS_SMALL) if ( dLenStrip < EPS_SMALL)
continue ; continue ;
// creo la maschera per tagliare la superficie originale e ottenere una striscia // 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 // ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
Vector3d vtTrim ;
if ( nDir == 0) { if ( nDir == 0) {
pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ; Point3d ptStart( abs(vU[p] - vU.front()), - 1, 0) ;
vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ; pTrimMask.Set( GetRectangleCurve( ptStart, dLenStrip, dScaleV + 2)) ;
} }
else{ else{
pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ; Point3d ptStart( - 1, abs(vU[p] - vU.front()), 0) ;
vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ; pTrimMask.Set( GetRectangleCurve( ptStart, dScaleU + 2, dLenStrip)) ;
} }
pSfrTrim->Translate( vtTrim) ;
if ( ! pSfr_copy->Intersect( *pSfrTrim)) // 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)
return false ;
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 ;
// aggiungo la nuova striscia solo se è valida
if ( pSfr_copy->IsValid() ) {
if ( nDir == 0) if ( nDir == 0)
pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ; dCoeffX = SBZ_TREG_COEFF / dLenStrip ;
else else
pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ; dCoeffY = SBZ_TREG_COEFF / dLenStrip ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i) {
// prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo if( ! IsNull( vCrvStrip[i]))
vCrvStrip[i]->Scale( GLOB_FRM, dCoeffX, dCoeffY, 1) ;
Point3d pt ; else
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))
return false ; 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) { if ( nDir == 0) {
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ; dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
if ( pRescaledSfr->IsValid()) { if( ! vbUniform[1]) {
if ( bRetry) vLoop.swap( vUniformedCurves) ;
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET vUniformedCurves.clear() ;
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
} }
} }
else else
@@ -658,12 +874,38 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
} }
} }
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) { if ( ! vUniformedCurves.empty()) {
if ( bRetry) #if SAVEMKUNIF_CRVS
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET //debug
delete pSfr ; vector<IGeoObj*> vGeo ;
pSfr = Release( pRescaledSfr) ; 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) if ( ! bRescaledU && ! bRescaledV)
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ; pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
+1667 -340
View File
File diff suppressed because it is too large Load Diff
+10 -7
View File
@@ -116,9 +116,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ; const SurfTriMesh* GetAuxSurf( void) const override ;
const SurfTriMesh* GetAuxSurfRefined( void) const override ; const SurfTriMesh* GetAuxSurfRefined( void) const override ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) 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. // 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 ; 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 // funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
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 = IntLineTriaType::ILTT_IN) const override ;
@@ -143,16 +143,19 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool IsPlanar( void) const override ; bool IsPlanar( void) const override ;
bool CreateByFlatContour( const PolyLine& PL) override ; bool CreateByFlatContour( const PolyLine& PL) override ;
bool CreateByRegion( const POLYLINEVECTOR& vPL) 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 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 CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ; bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ; bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
PNTVECTOR GetAllControlPoints( void) const ; PNTVECTOR GetAllControlPoints( void) const override ;
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ; bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv, const INTVECTOR& vShown ,const INTINTVECTOR& vNewOrEdited) ; bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
bool RemoveCollapsedSpans() override ; bool RemoveCollapsedSpans( void) override ;
bool SwapParameters() ; 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 public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
+188 -35
View File
@@ -28,6 +28,13 @@
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.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 ; using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -107,8 +114,20 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
pMyCrv->SetThickness( 0) ; pMyCrv->SetThickness( 0) ;
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano) // rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
ICURVEPLIST CrvLst ; ICURVEPLIST CrvLst ;
#if SAVEADJUSTCRV
SaveGeoObj( pMyCrv->Clone(), "D:\\Temp\\inters\\CrvCrvInters\\before_adjust.nge") ;
#endif
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true)) if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
return false ; 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 // aggiungo le singole curve
int nExtAdded = 0 ; int nExtAdded = 0 ;
bool bOk = true ; bool bOk = true ;
@@ -169,14 +188,18 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
Vector3d vtExtr ; Vector3d vtExtr ;
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
pMyCrv->SetExtrusion( Z_AX) ; 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 // verifico che sia esterna alle curve esterne degli altri chunk
bool bOk = true ; bool bOk = true ;
CRVCVECTOR ccClass ; CRVCVECTOR ccClass ;
for ( auto i : m_vExtInd) { 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]) ; IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) || ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
@@ -216,14 +239,9 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
bool bool
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv) SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
{ {
try { m_vpLoop.push_back( pCrv) ;
m_vpLoop.push_back( pCrv) ; m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ; m_nStatus = OK ;
m_nStatus = OK ;
}
catch (...) {
return false ;
}
return true ; return true ;
} }
@@ -304,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) // 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)) if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
pMyCrv->Invert() ; pMyCrv->Invert() ;
// verifico non abbia auto-intersezioni
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// ricerca del chunk in cui andrebbe inserito // ricerca del chunk in cui andrebbe inserito
int nChunk = -1 ; int nChunk = -1 ;
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) { for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
@@ -354,23 +369,18 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
bool bool
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk) SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
{ {
try { //se da aggiungere all'ultimo chunk
// se da aggiungere all'ultimo chunk if ( nChunk == -1)
if ( nChunk == -1) m_vpLoop.push_back( pCrv) ;
m_vpLoop.push_back( pCrv) ; //altrimenti aggiungo al chunck indicato
// altrimenti aggiungo al chunck indicato else {
else { int nLoopCnt = GetLoopCount( nChunk) ;
int nLoopCnt = GetLoopCount( nChunk) ; if ( nLoopCnt == 0)
if ( nLoopCnt == 0) return false ;
return false ; int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
int nOffset = m_vExtInd[nChunk] + nLoopCnt ; m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ; for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i) ++ m_vExtInd[i] ;
++ m_vExtInd[i] ;
}
}
catch (...) {
return false ;
} }
return true ; return true ;
@@ -1374,6 +1384,15 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) { for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ; const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
// intersezione // 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) ; IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione // classificazione
CRVCVECTOR ccPart ; CRVCVECTOR ccPart ;
@@ -1537,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 // classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ; IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
int nClass = ccInt.GetRegionCurveClassification() ; int nClass = ccInt.GetRegionCurveClassification() ;
switch ( nClass){ switch ( nClass) {
default : // CCREGC_NULL default : // CCREGC_NULL
return REGC_NULL ; return REGC_NULL ;
case CCREGC_IN1 : case CCREGC_IN1 :
@@ -1550,7 +1569,141 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
return REGC_OUT ; return REGC_OUT ;
case CCREGC_INTERS : case CCREGC_INTERS :
return REGC_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 GetChunkArea( int nChunk, double& dArea) const override ;
bool GetChunkPerimeter( int nChunk, double& dLen) const override ; bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides 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 ; bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
int GetLoopCount( int nChunk) const override ; int GetLoopCount( int nChunk) const override ;
int GetLoopCurveCount( int nChunk, int nLoop) 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 ; SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ;
friend class MyCAvSimpleSurfFrMove ; friend class MyCAvSimpleSurfFrMove ;
friend class MyCAvSurfFrMove ;
private : private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
+13
View File
@@ -20,6 +20,12 @@
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
#define SAVELOOPS 0
#if SAVELOOPS
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -172,6 +178,13 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
pSfr.Set( new( nothrow) SurfFlatRegion) ; pSfr.Set( new( nothrow) SurfFlatRegion) ;
else else
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ; 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)) { if ( IsNull( pSfr)) {
MyTestAndDelete( vpCurve) ; MyTestAndDelete( vpCurve) ;
MyTestAndDelete( vpLoop) ; MyTestAndDelete( vpLoop) ;
+66 -13
View File
@@ -1188,8 +1188,10 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ; pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr)) if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ; pSfr.Set( pSfrTria) ;
else else {
pSfr->Add( *pSfrTria) ; if ( ! pSfr->Add( *pSfrTria))
return false ;
}
} }
} }
// passo al successivo // passo al successivo
@@ -1201,14 +1203,18 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
return false ; return false ;
// Effettuo contro-offset // Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ; if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
return false ;
// Recupero i contorni della regione // Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) { for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ; PolyLine PL ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
vPL.emplace_back( PL) ; vPL.clear() ;
return false ;
}
vPL.emplace_back( PL) ;
} }
} }
@@ -1259,8 +1265,10 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ; pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr)) if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ; pSfr.Set( pSfrTria) ;
else else {
pSfr->Add( *pSfrTria) ; if ( ! pSfr->Add( *pSfrTria))
return false ;
}
} }
} }
} }
@@ -1274,14 +1282,18 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
return true ; return true ;
// Effettuo contro-offset // Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ; if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
return false ;
// Recupero i contorni della regione // Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) { for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ; PolyLine PL ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
vPL.emplace_back( PL) ; vPL.clear() ;
return false ;
}
vPL.emplace_back( PL) ;
} }
} }
@@ -3810,12 +3822,19 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
BBox3d b3Box ; BBox3d b3Box ;
PtrOwner<ISurfTriMesh> pStmShell ; PtrOwner<ISurfTriMesh> pStmShell ;
} ; } ;
// vettore di shell con vettori dei propri triangoli (per accelerare nei casi degeneri)
INTMATRIX mShellTria( m_nShells) ;
for ( int i = 0 ; i < ssize( m_vTria) ; ++ i) {
if ( m_vTria[i].nShell < m_nShells)
mShellTria[m_vTria[i].nShell].push_back( i) ;
}
// classificazione delle shell
vector<SHELLINFO> vOuterShells ; vector<SHELLINFO> vOuterShells ;
vector<SHELLINFO> vInnerShells ; vector<SHELLINFO> vInnerShells ;
INTVECTOR vOpenShells ; INTVECTOR vOpenShells ;
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) { for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
// se la shell è chiusa // se la shell è chiusa
if ( IsShellClosed( nSh)) { if ( ssize( mShellTria[nSh]) >= 4 && IsShellClosed( nSh)) {
// creo una superficie clonata dalla shell // creo una superficie clonata dalla shell
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ; PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
if ( IsNull( pStmShell) || ! pStmShell->IsValid()) if ( IsNull( pStmShell) || ! pStmShell->IsValid())
@@ -3827,7 +3846,9 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
BBox3d b3Box ; BBox3d b3Box ;
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ; pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
// la inserisco nel vettore opportuno // la inserisco nel vettore opportuno
if ( dVol > 0) if ( abs( dVol) < 1 * 1 * EPS_SMALL)
vOpenShells.push_back( nSh) ;
else if ( dVol > 0)
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ; vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
else else
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ; vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
@@ -3979,6 +4000,7 @@ SurfTriMesh::IsShellClosed( int nShell) const
return false ; return false ;
// ciclo sui triangoli della shell // ciclo sui triangoli della shell
bool bClosed = true ; bool bClosed = true ;
int nTriaCnt = 0 ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// se triangolo non cancellato e della shell // se triangolo non cancellato e della shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) { if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
@@ -3989,10 +4011,12 @@ SurfTriMesh::IsShellClosed( int nShell) const
bClosed = false ; bClosed = false ;
break ; break ;
} }
else
++ nTriaCnt ;
} }
} }
// restituisco il risultato // restituisco il risultato
return bClosed ; return ( bClosed && nTriaCnt >= 4) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -4415,6 +4439,35 @@ SurfTriMesh::ClonePart( int nPart) const
return Release( pSurfTM) ; 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 bool
SurfTriMesh::ResetTFlags( void) SurfTriMesh::ResetTFlags( void)
+1
View File
@@ -347,6 +347,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetPartVolume( int nPart, double& dVolume) const override ; bool GetPartVolume( int nPart, double& dVolume) const override ;
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ; bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
SurfTriMesh* ClonePart( int nPart) 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 SetTFlag( int nId, int nTFlag) override ;
bool GetTFlag( int nId, int& nFlag) const override ; bool GetTFlag( int nId, int& nFlag) const override ;
int GetMaxTFlag( void) const override int GetMaxTFlag( void) const override
+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 SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
bool SetToolNum( int nToolNum) bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; } { m_nCurrentNum = nToolNum ; return true ; }
int GetType() const int GetType( void) const
{ return m_nType ; } { return m_nType ; }
int GetToolNum() const int GetToolNum( void) const
{ return m_nCurrentNum ; } { return m_nCurrentNum ; }
double GetHeigth() const double GetHeigth( void) const
{ return m_dHeight ; } { return m_dHeight ; }
double GetTipHeigth() const double GetTipHeigth( void) const
{ return m_dTipHeight ; } { return m_dTipHeight ; }
double GetRadius() const double GetRadius( void) const
{ return m_dRadius ; } { return m_dRadius ; }
double GetTipRadius() const double GetTipRadius( void) const
{ return m_dTipRadius ; } { return m_dTipRadius ; }
double GetCornRadius() const double GetCornRadius( void) const
{ return m_dRCorner ; } { return m_dRCorner ; }
double GetRefRadius() const double GetRefRadius( void) const
{ return m_dRefRadius ; } { return m_dRefRadius ; }
double GetMrtChsWidth() const double GetMrtChsWidth( void) const
{ return m_dMrtChsWidth ; } { return m_dMrtChsWidth ; }
double GetMrtChsThickness() const double GetMrtChsThickness( void) const
{ return m_dMrtChsThickness ; } { return m_dMrtChsThickness ; }
const CurveComposite& GetOutline( void) const const CurveComposite& GetOutline( void) const
{ return ( m_Outline) ; } { return ( m_Outline) ; }
+109 -25
View File
@@ -177,7 +177,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
int nLoop = 0 ; int nLoop = 0 ;
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk // recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ; PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico double dLinTol = 0.005 ; // questo è riferito allo spazio parametrico
double dAngTolDeg = 5 ; double dAngTolDeg = 5 ;
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ; PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
@@ -185,6 +185,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
// i chunk della falt region sono ancora flat region composte da 1 chunk // i chunk della falt region sono ancora flat region composte da 1 chunk
// rimuovo i difetti dei loop prima di salvarli // rimuovo i difetti dei loop prima di salvarli
PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ; PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ;
if ( IsNull( pLoop))
return false ;
pLoop->MergeCurves( dLinTol, dAngTolDeg) ; pLoop->MergeCurves( dLinTol, dAngTolDeg) ;
pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ; pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ;
pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ; pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ;
@@ -350,10 +352,6 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
} }
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1 // se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
if ( m_mTree.size() == 3 && ! m_mTree.at(-1).IsSplitVert()) { if ( m_mTree.size() == 3 && ! m_mTree.at(-1).IsSplitVert()) {
m_mTree[0].m_nLeft = -1 ;
m_mTree[0].m_nRight = -1 ;
m_mTree[1].m_nLeft = -1 ;
m_mTree[1].m_nRight = -1 ;
m_mTree[0].SetSplitDirVert( true) ; m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ; Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ; m_mTree[1].SetSplitDirVert( true) ;
@@ -461,8 +459,8 @@ Tree::Split( int nId, double dSplitValue)
dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ; dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ;
Point3d ptP00, ptP01, ptP10, ptP11 ; Point3d ptP00, ptP01, ptP10, ptP11 ;
if( bGoodSplitVert) { if ( bGoodSplitVert) {
if( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) { if ( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) {
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ; GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ;
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
@@ -474,12 +472,13 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
} }
if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) && if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL)) ( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL ||
dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitVert = false ; bGoodSplitVert = false ;
} }
if( bGoodSplitHoriz) { if ( bGoodSplitHoriz) {
if( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) { if ( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) {
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ; GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ;
GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ; GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ;
@@ -491,8 +490,9 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
} }
if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) && if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL)) ( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL ||
dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitHoriz = false ; bGoodSplitHoriz = false ;
} }
@@ -662,8 +662,18 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
} }
} }
// calcolo se la parte di superficie nella cella è piatta
PolyLine PL ;
PL.AddUPoint( 0, ptP00) ;
PL.AddUPoint( 1, ptP10) ;
PL.AddUPoint( 2, ptP11) ;
PL.AddUPoint( 3, ptP01) ;
PL.AddUPoint( 4, ptCen) ;
Plane3d plPlane ;
bool bIsFlat = PL.IsFlat( plPlane, dLinTol) ;
// su isoparametriche in U e V // su isoparametriche in U e V
if ( dSagU < dLinTol && dSagV < dLinTol) { if ( dSagU < dLinTol && dSagV < dLinTol && ! bIsFlat) {
// step di verifica in U e in V // step di verifica in U e in V
int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ; int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ;
int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ; int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ;
@@ -724,6 +734,73 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
//{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ; //{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ;
// LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())} // LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())}
} }
else if ( dSagU < dLinTol && dSagV < dLinTol && bIsFlat) {
// se la cella è piatta devo verificare che i bordi siano dei tratti retti, altrimenti potrei commettere un errore di approssimazione
// bordo inferiore e superiore
double dMaxDist = 0 ;
for ( int i = 0 ; i < 2 ; ++i) {
CurveLine clU ;
if ( i == 0)
clU.Set( ptP00, ptP10) ;
else if ( i == 1)
clU.Set( ptP01, ptP11) ;
double dV = 0 ;
if ( i == 0)
dV = pcToSplit->GetBottomLeft().y ;
else if ( i == 1)
dV = pcToSplit->GetTopRight().y ;
int nStepU = 4 ;
for ( int j = 1 ; j < nStepU ; ++ j) {
// parametro U
double dCoeffU = double( j) / nStepU ;
double dU = ( 1 - dCoeffU) * pcToSplit->GetBottomLeft().x + dCoeffU * pcToSplit->GetTopRight().x ;
Point3d ptBez ;
GetPoint( dU, dV, ptBez) ;
DistPointCurve dpc( ptBez, clU) ;
double dDist = 0 ;
dpc.GetDist( dDist) ;
if ( dDist > dMaxDist)
dMaxDist = dDist ;
}
}
if ( dMaxDist > dLinTol)
dSagU = dMaxDist ;
// bordo sinistro e destro
dMaxDist = 0 ;
for ( int i = 0 ; i < 2 ; ++i) {
CurveLine clV ;
if ( i == 0)
clV.Set( ptP00, ptP01) ;
else if ( i == 1)
clV.Set( ptP10, ptP11) ;
double dU = 0 ;
if ( i == 0)
dU = pcToSplit->GetBottomLeft().x ;
else if ( i == 1)
dU = pcToSplit->GetTopRight().x ;
int nStepV = 4 ;
for ( int j = 1 ; j < nStepV ; ++ j) {
// parametro in V
double dCoeffV = double( j) / nStepV ;
double dV = ( 1 - dCoeffV) * pcToSplit->GetBottomLeft().y + dCoeffV * pcToSplit->GetTopRight().y ;
Point3d ptBez ;
GetPoint( dU, dV, ptBez) ;
DistPointCurve dpc( ptBez, clV) ;
double dDist = 0 ;
dpc.GetDist( dDist) ;
if ( dDist > dMaxDist)
dMaxDist = dDist ;
}
}
if ( dMaxDist > dLinTol)
dSagV = dMaxDist ;
}
// per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
// misura approssimativa della curvatura in una direzione // misura approssimativa della curvatura in una direzione
@@ -734,7 +811,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
bVert = false ; bVert = false ;
else else
bVert = ( dSagV <= dSagU) ; bVert = ( dSagV <= dSagU) ;
pcToSplit->SetSplitDirVert( bVert) ; bool bFirstTry = true ;
retry :
// verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
double dSideMinVal = 0 ; double dSideMinVal = 0 ;
double dLengMinVal = 0 ; double dLengMinVal = 0 ;
@@ -776,6 +854,11 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
} }
else if ( dSagV > dLinTol || dSagU > dLinTol) { else if ( dSagV > dLinTol || dSagU > dLinTol) {
bSplit = bDimOk ; bSplit = bDimOk ;
if ( ! bSplit && bFirstTry) {
bFirstTry = false ;
bVert = ! bVert ;
goto retry ;
}
//if ( bSplit) //if ( bSplit)
// LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV") // LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV")
} }
@@ -1455,7 +1538,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
++ nPolyInd ; ++ nPolyInd ;
continue ; continue ;
} }
else if( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE) else if ( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
continue ; continue ;
else { else {
// vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella
@@ -1980,7 +2063,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
nCells.push_back( nCell) ; nCells.push_back( nCell) ;
nEdge = -2 ; nEdge = -2 ;
} }
if( ssize( nCells) == 1) if ( ssize( nCells) == 1)
return nCells ; return nCells ;
Vector3d vtDir ; Vector3d vtDir ;
@@ -2009,14 +2092,14 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 ) if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 )
ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ; ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ;
// altrimenti ruoto a destra // altrimenti ruoto a destra
else if( ( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) || else if (( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) { ( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ; Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
} }
// altrimenti ruoto a sinistra // altrimenti ruoto a sinistra
else /*if( ( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) || else /*if (( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ { ( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ; Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
} }
@@ -2138,7 +2221,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
bool bLoopInside = true ; bool bLoopInside = true ;
Point3d ptCurr ; Point3d ptCurr ;
int nIdPolygon = - 1; int nIdPolygon = - 1;
if( ! pCell->m_vnPolyId.empty()) if ( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ; nIdPolygon = pCell->m_vnPolyId[0] ;
else else
return false ; return false ;
@@ -2178,9 +2261,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
} }
// se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito // se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito
// se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto // se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto
if( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) { if ( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
++ nInfiniteLoopCount ; ++ nInfiniteLoopCount ;
if( nInfiniteLoopCount == 4) { if ( nInfiniteLoopCount == 4) {
LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell") LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell")
return false ; return false ;
} }
@@ -2189,7 +2272,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// aggiorno il puntatore alla cella // aggiorno il puntatore alla cella
pCell = &m_mTree[nId] ; pCell = &m_mTree[nId] ;
// recupero l'indice del poligono base associato alla cella // recupero l'indice del poligono base associato alla cella
if( ! pCell->m_vnPolyId.empty()) if ( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ; nIdPolygon = pCell->m_vnPolyId[0] ;
else else
return false ; return false ;
@@ -4025,7 +4108,8 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
Point3d ptTl ( ptBL.x, ptTR.y) ; Point3d ptTl ( ptBL.x, ptTR.y) ;
Point3d ptBr ( ptTR.x, ptBL.y) ; Point3d ptBr ( ptTR.x, ptBL.y) ;
if( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL) if ( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL ||
ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL)
return false ; return false ;
else if ( AreSamePointXYApprox( ptToAssign, ptTR)) else if ( AreSamePointXYApprox( ptToAssign, ptTR))
nEdge = 7 ; nEdge = 7 ;
+25 -16
View File
@@ -23,7 +23,8 @@
#include <utility> #include <utility>
struct PairHashInt64 { 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 h1 = std::hash<int64_t>{}(key.first) ;
size_t h2 = std::hash<int64_t>{}(key.second) ; size_t h2 = std::hash<int64_t>{}(key.second) ;
return h1 ^ (h2 << 1); // Combine hashes return h1 ^ (h2 << 1); // Combine hashes
@@ -33,14 +34,20 @@ struct PairHashInt64 {
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct Inters { struct Inters {
int nIn ; int nIn ;
PNTVECTOR vpt ;
int nOut ; int nOut ;
PNTVECTOR vpt ;
bool bCCW ; bool bCCW ;
int nChunk ; int nChunk ;
bool bSortedbyStart ; 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 // nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
bool operator < ( Inters& b) // 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 // trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
@@ -75,7 +82,8 @@ struct Inters {
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ; ( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
} }
static bool FirstEncounter( Inters& a, Inters& b) static bool
FirstEncounter( Inters& a, Inters& b)
{ {
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima. // riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso // ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
@@ -135,18 +143,18 @@ struct Inters {
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ; ( 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]) ; return AreSamePointExact( vpt[0], b.vpt[0]) ;
} }
bool operator != ( Inters& b)
bool
operator != ( Inters& b)
{ {
return ! AreSamePointExact( vpt[0], b.vpt[0]) ; 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 class Cell
@@ -160,11 +168,12 @@ class Cell
// | | // | |
// |_________________| // |_________________|
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE) // Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
public:
enum Collapsed { TO_VERIFY = -1, // da verificare public :
NO_COLLAPSE = 0, // non ho coppie di lati collassati enum Collapsed { TO_VERIFY = -1, // da verificare
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati NO_COLLAPSE = 0, // non ho coppie di lati collassati
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
public : public :
~Cell( void) {} ~Cell( void) {}
+2647 -931
View File
File diff suppressed because it is too large Load Diff
+253 -49
View File
@@ -29,8 +29,21 @@
#include <thread> #include <thread>
#include <future> #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 ; using namespace std ;
#if !defined(_WIN64)
int VolZmap::m_nDexelNbr = 0 ;
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ; GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
@@ -55,6 +68,13 @@ VolZmap::VolZmap(void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
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_nNumBlock = 0 ;
m_nConnectedCompoCount = 0 ; m_nConnectedCompoCount = 0 ;
m_MapFrame.Reset() ; 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) { for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ; m_nNx[i] = 0 ;
m_nNy[i] = 0 ; m_nNy[i] = 0 ;
@@ -1694,16 +1721,15 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;
// creo lo ZMap per i riferimenti degli intervalli sulle griglie // Creo lo ZMap per i riferimenti degli intervalli sulle griglie
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ; PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid()) if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
return false ; return false ;
// creo uno ZMap per gli intervalli da aggiungere o da rimuovere // Creo uno ZMap per gli intervalli da aggiungere o da rimuovere
PtrOwner<VolZmap> pZMapExtra( CreateBasicVolZmap()) ; PtrOwner<VolZmap> pZMapExtra( CreateBasicVolZmap()) ;
if ( IsNull( pZMapExtra) || if ( IsNull( pZMapExtra) ||
! pZMapExtra->CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], ! pZMapExtra->CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
m_dStep, IsTriDexel())) m_dStep, IsTriDexel()))
return false ; return false ;
@@ -1719,7 +1745,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
// Ciclo sulle griglie // Ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) { for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti nella Copia // Ciclo sul numero di dexel presenti nella Copia
for ( int nDex = 0 ; nDex < int( pZMapCopy->m_Values[nGrid].size()) ; ++ nDex) { for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) {
// Se il dexel corrente non ha sotto-intervalli passo al successivo // Se il dexel corrente non ha sotto-intervalli passo al successivo
if ( pZMapCopy->m_Values[nGrid][nDex].empty()) if ( pZMapCopy->m_Values[nGrid][nDex].empty())
continue ; continue ;
@@ -1727,9 +1753,9 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
int nI = nDex % m_nNx[nGrid] ; int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ; int nJ = nDex / m_nNx[nGrid] ;
// Recupero il numero di intervalli presenti nel Dexel corrente // Recupero il numero di intervalli presenti nel Dexel corrente
int nIntervals = int( pZMapCopy->m_Values[nGrid][nDex].size()) ; int nIntervals = ssize( pZMapCopy->m_Values[nGrid][nDex]) ;
// Scorro gli intervalli presenti // Scorro gli intervalli presenti
for ( int nInfo = 0 ; nInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nInfo) { for ( int nInfo = 0 ; nInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nInfo) {
// Recupero l'intervallo corrente // Recupero l'intervallo corrente
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ; Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
// --- Se richiesta prima estensione // --- Se richiesta prima estensione
@@ -1739,57 +1765,54 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler, AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler,
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ; Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni // Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) {
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente) // Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente)
// ( lascio invariato lo ZMapCopy) // ( lascio invariato lo ZMapCopy)
nIntervals = int( m_Values[nGrid][nDex].size()) ; nIntervals = ssize( m_Values[nGrid][nDex]) ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax, pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax, Interval.dMin,
Interval.dMin, dToler, true, dToler, true, nToolNum, V_INVALID, V_INVALID) ;
nToolNum, V_INVALID, V_INVALID) ;
} }
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ] // *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ]
// Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) // Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler, AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler,
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ; Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni // Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) {
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo) // Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo)
// ( lascio invariato lo ZMapCopy) // ( lascio invariato lo ZMapCopy)
nIntervals = int( m_Values[nGrid][nDex].size()) ; nIntervals = ssize( m_Values[nGrid][nDex]) ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
Interval.dMax, Interval.dMax, pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin,
pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin, dToler, true, dToler, true, nToolNum, V_INVALID, V_INVALID) ;
nToolNum, V_INVALID, V_INVALID) ;
} }
} }
// --- Se richiesta prima restrizione // --- Se richiesta prima restrizione
else { else {
// *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ] // Se la lunghezza dell'intervallo non è almeno il doppio della tolleranza
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) double dLen = Interval.dMax - Interval.dMin ;
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler, if ( dLen < 2. * ( dToler + EPS_SMALL)) {
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ; // L'intervallo sparisce completamente
// Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL,
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { Interval.vtMinN, Interval.vtMaxN, nToolNum, true) ;
// Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy) // Rimuovo le parti di spillone nelle altre dimensioni
nIntervals = int( m_Values[nGrid][nDex].size()) ; if ( IsTriDexel()) {
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, -- nIntervals ;
Interval.dMin, pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
Interval.dMax, dToler, true, Interval.dMin, Interval.dMax,
Tool::UNDEF, V_INVALID, V_INVALID) ; dToler, true, Tool::UNDEF, V_INVALID, V_INVALID) ;
}
} }
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ] // Se sufficientemente lungo, allora
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) else {
SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler, // *** Estremo inferiore -> Intervallo : [ dMin, dMin + dToler ]
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ; // Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
// Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMin + dToler,
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
// Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy) // *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax ]
nIntervals = int( m_Values[nGrid][nDex].size()) ; // Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + EPS_SMALL,
Interval.dMin, Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
Interval.dMax, dToler, true,
Tool::UNDEF, V_INVALID, V_INVALID) ;
} }
} }
} }
@@ -1799,12 +1822,12 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
// Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy) // Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy)
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) { for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti // Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) { for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla // Se l'intervallo è vuoto, non faccio nulla
if ( m_Values[nGrid][nDex].empty()) if ( m_Values[nGrid][nDex].empty())
continue ; continue ;
// Per ogni intervallo ricavato fino ad ora, restringo della tolleranza // Per ogni intervallo ricavato fino ad ora, restringo della tolleranza
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) { for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
// --- Se richiesta prima estensione // --- Se richiesta prima estensione
if ( bIsExtensionFirst) { if ( bIsExtensionFirst) {
m_Values[nGrid][nDex][nInfo].dMin += dToler ; m_Values[nGrid][nDex][nInfo].dMin += dToler ;
@@ -1816,7 +1839,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
m_Values[nGrid][nDex][nInfo].dMax += dToler ; m_Values[nGrid][nDex][nInfo].dMax += dToler ;
} }
// Definisco il colore // Definisco il colore
for ( int nOrigInfo = 0 ; nOrigInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nOrigInfo) { 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) 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 ; 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) if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMax - m_Values[nGrid][nDex][nInfo].dMax < EPS_SMALL)
@@ -1830,7 +1853,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
// Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy) // Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy)
for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) { for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti // Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < int( pZMapExtra->m_Values[nGrid].size()) ; ++ nDex) { for ( int nDex = 0 ; nDex < ssize( pZMapExtra->m_Values[nGrid]) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla // Se l'intervallo è vuoto, non faccio nulla
if ( pZMapExtra->m_Values[nGrid][nDex].empty()) if ( pZMapExtra->m_Values[nGrid][nDex].empty())
continue ; continue ;
@@ -1838,19 +1861,19 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
int nI = nDex % m_nNx[nGrid] ; int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ; int nJ = nDex / m_nNx[nGrid] ;
// Per ogni intervallo ricavato fino ad ora... // Per ogni intervallo ricavato fino ad ora...
for ( int nInfo = 0 ; nInfo < int( pZMapExtra->m_Values[nGrid][nDex].size()) ; ++ nInfo) { for ( int nInfo = 0 ; nInfo < ssize( pZMapExtra->m_Values[nGrid][nDex]) ; ++ nInfo) {
double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ; double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ;
double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ; double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ;
Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ; Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ;
Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ; Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ;
// --- Se richiesta prima estensione // --- Se richiesta prima estensione
if ( bIsExtensionFirst) { if ( bIsExtensionFirst) {
// ... aggiungo i contributi // Aggiungo i contributi
AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ; AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
} }
// --- Se richiesta prima restrizione // --- Se richiesta prima restrizione
else { else {
// ... sottraggo i contributi // Sottraggo i contributi
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ; SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
} }
} }
@@ -1868,6 +1891,187 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
return true ; 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 ;
}
}
}
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt) VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
+23 -11
View File
@@ -21,9 +21,8 @@
#include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkSurfTriMesh.h"
#include <unordered_map> #include <unordered_map>
#include <stack> #include <stack>
#include <mutex>
#include <atomic>
#include <tuple> #include <tuple>
#include <atomic>
typedef std::pair<Point3d, Vector3d> PNTVEC3D ; typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
@@ -82,10 +81,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
public : // IVolZmap public : // IVolZmap
bool CopyFrom( const IGeoObj* pGObjSrc) override ; bool CopyFrom( const IGeoObj* pGObjSrc) override ;
bool Clear( void) override ; bool Clear( void) override ;
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ; bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ; bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) 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) override ; bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ;
int GetBlockCount( void) const override ; int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ; int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ; bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
@@ -152,6 +151,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool AddSurfTm( const ISurfTriMesh* pStm) override ; bool AddSurfTm( const ISurfTriMesh* pStm) override ;
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ; bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) 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 ; bool Offset( double dOffs, int nType) override ;
public : // IGeoObjRW public : // IGeoObjRW
@@ -227,6 +227,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
typedef std::unordered_map<int, Voxel> VoxelContainer ; typedef std::unordered_map<int, Voxel> VoxelContainer ;
// Unordered map per la coerenza topologica // Unordered map per la coerenza topologica
typedef std::unordered_map<int, bool> InterVoxMatter ; 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 : private :
bool CopyFrom( const VolZmap& clSrc) ; bool CopyFrom( const VolZmap& clSrc) ;
@@ -263,6 +272,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax, bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax,
double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin, double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
const Vector3d& vtToolMax) ; 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, bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
Vector3d& vtMin, Vector3d& vtMax) ; Vector3d& vtMin, Vector3d& vtMax) ;
// Spostamenti utensile // Spostamenti utensile
@@ -383,9 +393,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
double& dU1, double& dU2) const ; double& dU1, double& dU2) const ;
bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ; bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ; bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen, const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
bool bTapLow, bool bTapUp, bool bTapLow, bool bTapUp,
@@ -487,6 +494,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
// Funzioni per Offset di Zmap // Funzioni per Offset di Zmap
bool OffsetFillet( double dOffs) ; bool OffsetFillet( double dOffs) ;
bool OffsetSharped( double dOffs, int nType) ; 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 : private :
enum Move5Axis { enum Move5Axis {
@@ -557,9 +569,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable std::vector<InterVoxMatter> m_SliceXY ; mutable std::vector<InterVoxMatter> m_SliceXY ;
mutable std::vector<InterVoxMatter> m_SliceXZ ; mutable std::vector<InterVoxMatter> m_SliceXZ ;
mutable std::vector<InterVoxMatter> m_SliceYZ ; 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 ; int m_nCurrTool ;
std::vector<Tool> m_vTool ; std::vector<Tool> m_vTool ;
-121
View File
@@ -2071,127 +2071,6 @@ VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise)
return false ; return false ;
} }
//----------------------------------------------------------------------------
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
// La funzione restituisce true in caso di intersezione, false altrimenti.
//----------------------------------------------------------------------------
bool
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
int nBasInt = 0 ;
if ( abs( vtV.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 1 ;
vtN1 = Z_AX ;
}
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 2 ;
vtN2 = - Z_AX ;
}
}
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
if ( nBasInt == 3) {
// Porto i punti e i versori nel riferimento globale
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
// Trovate intersezioni
return true ;
}
// Determino le intersezioni con la superficie laterale del cilindro
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
vtV.x * vtV.x + vtV.y * vtV.y} ;
DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
// Epsilon per piani di tappo
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
if ( nRoot == 2) {
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
-- nRoot ;
}
if ( nRoot >= 1) {
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
if ( nRoot == 2)
vdRoots[0] = vdRoots[1] ;
-- nRoot ;
}
}
// Due soluzioni: la retta interseca due volte la superficie laterale
if ( nRoot == 2) {
// Punti di intersezione con la superficie del cilindro
ptInt1 = ptP + vdRoots[0] * vtV ;
ptInt2 = ptP + vdRoots[1] * vtV ;
// Determino le normali
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
vtN1.Normalize() ;
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
vtN2.Normalize() ;
// Porto i punti e i versori nel riferimento globale
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
// Trovate intersezioni
return true ;
}
// Una soluzione : la retta interseca la superficie laterale e un piano
else if ( nRoot == 1) {
// Se piano superiore
if ( nBasInt == 2) {
// Punto di intersezione
ptInt1 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
vtN1.Normalize() ;
}
// altrimenti piano inferiore
else if ( nBasInt == 1) {
// Punto di intersezione
ptInt2 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
vtN2.Normalize() ;
}
// altrimenti niente
else
return false ;
// Porto i punti e i versori nel riferimento globale
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
// Trovate intersezioni
return true ;
}
// Nessuna soluzione : nessuna intersezione
else
return false ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z. // Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z.
// La funzione restituisce true in caso di intersezione, false altrimenti. // La funzione restituisce true in caso di intersezione, false altrimenti.
+74 -9
View File
@@ -28,7 +28,7 @@ using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) 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 // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL) if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
@@ -81,12 +81,24 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[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 // Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ; m_Values[i].resize( m_nDim[i]) ;
// Riempimento delle celle // 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) { for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
// Aggiungo il tratto al dexel vuoto // Aggiungo il tratto al dexel vuoto
@@ -116,6 +128,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
break ; break ;
} }
} }
}
// Definizione delle limitazioni iniziali in Z per ogni mappa // Definizione delle limitazioni iniziali in Z per ogni mappa
m_dMinZ[0] = 0 ; m_dMinZ[0] = 0 ;
@@ -136,7 +149,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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 // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL) 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) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[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 // Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ; m_Values[i].resize( m_nDim[i]) ;
@@ -210,7 +235,7 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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 // Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ; m_nMapNum = ( bTriDex ? 3 : 1) ;
@@ -250,14 +275,35 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
m_nNx[1] = m_nNy[0] ; m_nNx[1] = m_nNy[0] ;
m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ; m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ;
m_nDim[1] = m_nNx[1] * m_nNy[1] ; m_nDim[1] = m_nNx[1] * m_nNy[1] ;
m_Values[1].resize( m_nDim[1]) ;
m_nNx[2] = m_nNy[1] ; m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ; m_nNy[2] = m_nNx[0] ;
m_nDim[2] = m_nNx[2] * m_nNy[2] ; 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]) ; m_Values[2].resize( m_nDim[2]) ;
} }
// Se dimensione singola
else { 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_nNx[1] = 0 ;
m_nNy[1] = 0 ; m_nNy[1] = 0 ;
m_nDim[1] = 0 ; m_nDim[1] = 0 ;
@@ -788,7 +834,7 @@ VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool 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 // Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
double dVol ; double dVol ;
@@ -838,14 +884,33 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
m_nNx[1] = m_nNy[0] ; m_nNx[1] = m_nNy[0] ;
m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ; m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ;
m_nDim[1] = m_nNx[1] * m_nNy[1] ; m_nDim[1] = m_nNx[1] * m_nNy[1] ;
m_Values[1].resize( m_nDim[1]) ;
m_nNx[2] = m_nNy[1] ; m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ; m_nNy[2] = m_nNx[0] ;
m_nDim[2] = m_nNx[2] * m_nNy[2] ; 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]) ; m_Values[2].resize( m_nDim[2]) ;
} }
// Se a dimensione singola
else { 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_nNx[1] = 0 ;
m_nNy[1] = 0 ; m_nNy[1] = 0 ;
m_nDim[1] = 0 ; m_nDim[1] = 0 ;
+24 -12
View File
@@ -1271,13 +1271,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ; bDefTopology = true ;
} }
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { 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) ; auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceYZ[nSlBlockN].end()) { if ( it != m_SliceYZ[nSlBlockN].end()) {
bMatOnSlice = it->second ; bMatOnSlice = it->second ;
bDefTopology = true ; bDefTopology = true ;
} }
m_SliceMutex.unlock() ; m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs( nAdjVox3[nCount]) == 2) { else if ( abs( nAdjVox3[nCount]) == 2) {
@@ -1287,13 +1289,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ; bDefTopology = true ;
} }
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { 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) ; auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceXZ[nSlBlockN].end()) { if ( it != m_SliceXZ[nSlBlockN].end()) {
bMatOnSlice = it->second ; bMatOnSlice = it->second ;
bDefTopology = true ; bDefTopology = true ;
} }
m_SliceMutex.unlock() ; m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs( nAdjVox3[nCount]) == 3) { else if ( abs( nAdjVox3[nCount]) == 3) {
@@ -1303,13 +1307,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ; bDefTopology = true ;
} }
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { 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) ; auto it = m_SliceXY[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceXY[nSlBlockN].end()) { if ( it != m_SliceXY[nSlBlockN].end()) {
bMatOnSlice = it->second ; bMatOnSlice = it->second ;
bDefTopology = true ; bDefTopology = true ;
} }
m_SliceMutex.unlock() ; m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
} }
} }
} }
@@ -1374,27 +1380,33 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
if ( nSlBlockN == nBlock) if ( nSlBlockN == nBlock)
SliceYZ.emplace( nSliceN, bMatOnSlice) ; SliceYZ.emplace( nSliceN, bMatOnSlice) ;
else { 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_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceMutex.unlock() ; m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs(nAdjVox3[nCount]) == 2) { else if ( abs(nAdjVox3[nCount]) == 2) {
if ( nSlBlockN == nBlock) if ( nSlBlockN == nBlock)
SliceXZ.emplace( nSliceN, bMatOnSlice) ; SliceXZ.emplace( nSliceN, bMatOnSlice) ;
else { 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_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceMutex.unlock() ; m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs(nAdjVox3[nCount]) == 3) { else if ( abs(nAdjVox3[nCount]) == 3) {
if ( nSlBlockN == nBlock) if ( nSlBlockN == nBlock)
SliceXY.emplace(nSliceN, bMatOnSlice) ; SliceXY.emplace(nSliceN, bMatOnSlice) ;
else { 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_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceMutex.unlock() ; m_SliceFlag.clear( memory_order_release) ;
m_SliceFlag.notify_one() ;
} }
} }
} }
+6 -4
View File
@@ -21,6 +21,7 @@
#include "CurveLine.h" #include "CurveLine.h"
#include "CurveArc.h" #include "CurveArc.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtNumUtils.h"
@@ -968,12 +969,13 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true, double dU1, dU2 ;
ptInt1, vtN1, ptInt2, vtN2)) { if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
if ( dOffs > 0.) if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ; AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool, nTool) ;
else else
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ; SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
} }
} }
} }
+430 -104
View File
@@ -21,6 +21,7 @@
#include "VolZmap.h" #include "VolZmap.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "IntersLineBox.h" #include "IntersLineBox.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkSurfBezier.h"
@@ -31,6 +32,13 @@
#include <future> #include <future>
#include <numeric> #include <numeric>
#define SAVETRIMMINGTOOL 0
#if SAVETRIMMINGTOOL
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
// ------------------------- OPERAZIONI SU INTERVALLI -------------------------------------------------------------------------------------- // ------------------------- OPERAZIONI SU INTERVALLI --------------------------------------------------------------------------------------
@@ -838,6 +846,183 @@ VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin,
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum)
{
// Se non Tridex, esco
if ( ! IsTriDexel())
return true ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo che indici nI, nJ siano entro i limiti
if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid])
return false ;
// Numero di voxel contenuti nel dexel corrente ( uguale per ogni dexel di una specifica griglia)
int nVoxNum = int( m_nNy[(( nGrid + 1) % 3)] / m_nDexVoxRatio +
( m_nNy[(( nGrid + 1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
// Scorro i Voxel correnti
for ( int nVox = - 1 ; nVox < nVoxNum - 1 ; ++ nVox) {
// Considero solo i Voxel interni all'intervallo corrente
if ( ( nVox + 1) * m_dStep > dZMin && ( nVox - 1) * m_dStep < dZMax) {
// Recupero gli indici per la griglia successiva
int nMyGrid = ( nGrid + 1) % 3 ;
int nMyI = nJ ;
int nMyJ = nVox ;
int nMyK = nI ;
double dMyMinZ = nMyK * m_dStep ;
double dMyMaxZ = ( nMyK + 1) * m_dStep ;
Vector3d vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
nMyGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY()) ;
Vector3d vtMyMinN = - vtMyMaxN ;
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
// Recupero gli indici della griglia precedente
nMyGrid = ( nGrid + 2) % 3 ;
nMyI = nVox ;
nMyJ = nI ;
nMyK = nJ ;
dMyMinZ = nMyK * m_dStep ;
dMyMaxZ = ( nMyK + 1) * m_dStep ;
vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
nMyGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY()) ;
vtMyMinN = - vtMyMaxN ;
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
}
}
// Aggiungo l'intervallo corrente
Vector3d vtMyMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() :
nGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY()) ;
Vector3d vtMyMinN = - vtMyMaxN ;
AddIntervals( nGrid, nI, nJ, dZMin, dZMax, vtMyMinN, vtMyMaxN, nToolNum, true) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc)
{
// Verifico che lo ZMap corrente sia valido
if ( ! IsValid())
return false ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo che indici nI, nJ siano entro i limiti
if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid])
return false ;
// Calcolo il punto
ptLoc = m_MapFrame.Orig() ;
if ( nGrid == 0)
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersX() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersY() + dZ * m_MapFrame.VersZ()) ;
else if ( nGrid == 1)
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersY() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersZ() + dZ * m_MapFrame.VersX()) ;
else
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersZ() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersX() + dZ * m_MapFrame.VersY()) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
Vector3d& vtN, double& dNewZ)
{
// Verifico che lo ZMap corrente sia valido
if ( ! IsValid())
return false ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Inizializzo il vettore da restituire
vtN = V_NULL ;
dNewZ = INFINITO ;
// Proietto la direzione lungo la mappa della griglia corrente
Vector3d vtDirProj = OrthoCompo( vtDir, ( nGrid == 0 ? m_MapFrame.VersZ() :
nGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY())) ;
// Sposto il punto corrente nella direzione opposta a quella trovata
Point3d ptLoc ;
if ( ! GetLocalPoint( nGrid, nI, nJ, dZ, ptLoc))
return false ;
Point3d ptCenterLoc = ptLoc ;
ptCenterLoc.Translate( - vtDirProj * dThick) ;
// Recupero il Box nel punto
BBox3d BBoxLoc ; BBoxLoc.Add( ptCenterLoc) ;
double dExpandX = ( m_MapFrame.VersX() * X_AX) * dThick * ( vtDirProj * X_AX) ;
double dExpandY = ( m_MapFrame.VersY() * Y_AX) * dThick * ( vtDirProj * Y_AX) ;
double dExpandZ = ( m_MapFrame.VersZ() * Z_AX) * dThick * ( vtDirProj * Z_AX) ;
BBoxLoc.Expand( max( ( m_dStep + EPS_SMALL), dExpandX),
max( ( m_dStep + EPS_SMALL), dExpandY),
max( ( m_dStep + EPS_SMALL), dExpandZ)) ;
// Porto il Box nel Frame della Mappa corrente
BBox3d BBoxInGrid = GetToLoc( BBoxLoc, m_MapFrame) ;
// Recupero i suoi estremi
Point3d ptBoxLocMax = BBoxInGrid.GetMax() ;
Point3d ptBoxLocMin = BBoxInGrid.GetMin() ;
// Determino gli intervalli locali in X e Y locali alla Griglia correnti
double dMinXLoc = ( nGrid == 0 ? ptBoxLocMin.x : nGrid == 1 ? ptBoxLocMin.y : ptBoxLocMin.z) ;
double dMinYLoc = ( nGrid == 0 ? ptBoxLocMin.y : nGrid == 1 ? ptBoxLocMin.z : ptBoxLocMin.x) ;
double dMaxXLoc = ( nGrid == 0 ? ptBoxLocMax.x : nGrid == 1 ? ptBoxLocMax.y : ptBoxLocMax.z) ;
double dMaxYLoc = ( nGrid == 0 ? ptBoxLocMax.y : nGrid == 1 ? ptBoxLocMax.z : ptBoxLocMax.x) ;
// Recupero gli Spilloni coinvolti nel Box
int nStartI = max( 0, int( dMinXLoc / m_dStep)) ;
int nEndI = min( m_nNx[nGrid] - 1, int( dMaxXLoc / m_dStep)) ;
int nStartJ = max( 0, int( dMinYLoc / m_dStep)) ;
int nEndJ = min( m_nNy[nGrid] - 1, int( dMaxYLoc / m_dStep)) ;
double dSqMinDist = INFINITO ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
// Determino la posizione corrente dello Spillone
int nPos = j * m_nNx[nGrid] + i ;
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
// Scorro i suoi Intervalli
for ( int nInterval = 0 ; nInterval < ssize( vDexel) ; ++ nInterval) {
// Se l'Intervallo presenta un indice del Tool da evitare, passo al successivo
if ( ( bMinVsMax && vDexel[nInterval].nToolMin != nTool) ||
( ! bMinVsMax && vDexel[nInterval].nToolMax != nTool))
continue ;
// Recupero l'estremo da analizzare
double dZInterval = ( bMinVsMax ? vDexel[nInterval].dMin : vDexel[nInterval].dMax) ;
// Recupero il punto associato
Point3d ptInterval ;
if ( ! GetLocalPoint( nGrid, i, j, dZInterval, ptInterval))
return false ;
// Se il punto è dentro nel Box, aggiungo il contributo della normale presente
if ( BBoxLoc.Encloses( ptInterval)) {
double dCurrSqDist = ( SqDist( ptInterval, ptLoc)) ;
if ( dCurrSqDist < dSqMinDist) {
dSqMinDist = dCurrSqDist ;
vtN = ( bMinVsMax ? vDexel[nInterval].vtMinN : vDexel[nInterval].vtMaxN) ;
dNewZ = dZInterval ;
}
}
}
}
}
return ( ! vtN.IsSmall() && dZ < INFINITO - 1) ;
}
// ------------------------- BOUNDING BOX -------------------------------------------------------------------------------------- // ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -1569,10 +1754,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
else if ( n5AxisType == Move5Axis::ACROSS) else if ( n5AxisType == Move5Axis::ACROSS)
nTotSurf = 2 + nSub * 4 + nSub * 2 + 16 ; // come sopra nTotSurf = 2 + nSub * 4 + nSub * 2 + 16 ; // come sopra
int nSurfInd = 0 ;
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
double dSide = 0 ;
// punti di riferimento sul tool // punti di riferimento sul tool
// tip del tool // tip del tool
Point3d ptP1T ; Point3d ptP1T ;
@@ -1585,7 +1766,17 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
Vector3d vtDirTip = ptP2T - ptP1T ; Vector3d vtDirTip = ptP2T - ptP1T ;
bool bTopIsPivot = vtDirTop.IsSmall() ; bool bTopIsPivot = vtDirTop.IsSmall() ;
bool bTipIsPivot = vtDirTip.IsSmall() ; bool bTipIsPivot = vtDirTip.IsSmall() ;
bool bTopAndTipAreEquiverse = vtDirTop * vtDirTip > 0 ; bool bSmallMovement = vtDirTop.Len() < 10 * EPS_SMALL && vtDirTip.Len() < 10 * EPS_SMALL ;
bool bInverse = ! (bTopIsPivot || bTipIsPivot) && vtDirTop * vtDirTip < 0 ;
if ( bInverse)
nTotSurf += 4 ;
if ( bSmallMovement)
nTotSurf += 2 ;
int nSurfInd = 0 ;
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
double dSide = 0 ;
// box dell'intero volume spazzato, nel riferimento object oriented // box dell'intero volume spazzato, nel riferimento object oriented
BBox3d bbVol ; BBox3d bbVol ;
@@ -1602,9 +1793,9 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
PNTVECTOR vPntTopStartBack(3) ; PNTVECTOR vPntTopStartBack(3) ;
PNTVECTOR vPntTopEndBack(3) ; PNTVECTOR vPntTopEndBack(3) ;
if ( nSub > 1) { if ( nSub > 1) {
if( bTopIsPivot) if ( bTopIsPivot)
vtDirTop = vtDirTip ; vtDirTop = vtDirTip ;
if( bTipIsPivot) if ( bTipIsPivot)
vtDirTip = vtDirTop ; vtDirTip = vtDirTop ;
// determino in che modo collegare il cilindro iniziale con quello finale // determino in che modo collegare il cilindro iniziale con quello finale
Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ; Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ;
@@ -1618,10 +1809,10 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
dSide = ( ptRefEnd - ptRefStart) * vtLs ; dSide = ( ptRefEnd - ptRefStart) * vtLs ;
// calcolo anche i vettori per le basi inferiori // calcolo anche i vettori per le basi inferiori
Vector3d vtTipBaseStart = -( vtLs ^ vtDirTip) ; Vector3d vtTipBaseStart = bInverse ? ( vtLs ^ vtDirTip) : -( vtLs ^ vtDirTip) ;
vtTipBaseStart.Normalize() ; vtTipBaseStart.Normalize() ;
vtTipBaseStart *= dMinRad ; vtTipBaseStart *= dMinRad ;
Vector3d vtTipBaseEnd = -( vtLe ^ vtDirTip) ; Vector3d vtTipBaseEnd = bInverse ? ( vtLe ^ vtDirTip) : -( vtLe ^ vtDirTip) ;
vtTipBaseEnd.Normalize() ; vtTipBaseEnd.Normalize() ;
vtTipBaseEnd *= dMinRad ; vtTipBaseEnd *= dMinRad ;
// aggiungo il primo punto per ognuno dei gruppi // aggiungo il primo punto per ognuno dei gruppi
@@ -1670,22 +1861,44 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
} }
vector<PNTVECTOR> vvPtCtrl ; vector<PNTVECTOR> vvPtCtrl ;
// superficie laterale sinistra if ( ! bSmallMovement) {
CurveLine cLineLeftStart ; cLineLeftStart.Set( vPntTipStartFront.back(), vPntTopStartFront.back()) ; // superficie laterale sinistra
PtrOwner<CurveBezier> cBezLeftStart( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftStart, nDegU, bRat))) ; CurveLine cLineLeftBottom ; cLineLeftBottom.Set( vPntTipEndFront.back(), vPntTipStartFront.back()) ;
CurveLine cLineLeftEnd ; cLineLeftEnd.Set( vPntTipEndFront.back(), vPntTopEndFront.back()) ; if ( ! cLineLeftBottom.IsValid())
PtrOwner<CurveBezier> cBezLeftEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftEnd, nDegU, bRat))) ; return false ;
vvPtCtrl.emplace_back( cBezLeftStart->GetAllControlPoints()) ; if ( bInverse)
PNTVECTOR vPntLeft = cBezLeftEnd->GetAllControlPoints() ; cLineLeftBottom.Invert() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ; PtrOwner<CurveBezier> cBezLeftBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftBottom, nDegU, bRat))) ;
// superficie laterale destra if ( IsNull( cBezLeftBottom))
CurveLine cLineRightStart ; cLineRightStart.Set( vPntTopStartFront.front(), vPntTipStartFront.front()) ; return false ;
PtrOwner<CurveBezier> cBezRightStart( GetBasicCurveBezier( LineToBezierCurve( &cLineRightStart, nDegU, bRat))) ; CurveLine cLineLeftTop ; cLineLeftTop.Set( vPntTopEndFront.back(), vPntTopStartFront.back()) ;
CurveLine cLineRightEnd ; cLineRightEnd.Set( vPntTopEndFront.front(), vPntTipEndFront.front()) ; if ( ! cLineLeftTop.IsValid())
PtrOwner<CurveBezier> cBezRightEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineRightEnd, nDegU, bRat))) ; return false ;
vvPtCtrl.emplace_back( cBezRightStart->GetAllControlPoints()) ; PtrOwner<CurveBezier> cBezLeftTop( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftTop, nDegU, bRat))) ;
PNTVECTOR vPntRight = cBezRightEnd->GetAllControlPoints() ; if ( IsNull( cBezLeftTop))
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ; return false ;
vvPtCtrl.emplace_back( cBezLeftBottom->GetAllControlPoints()) ;
PNTVECTOR vPntLeft = cBezLeftTop->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
// superficie laterale destra
CurveLine cLineRightBottom ; cLineRightBottom.Set( vPntTipStartFront.front(), vPntTipEndFront.front()) ;
if ( ! cLineRightBottom.IsValid())
return false ;
if ( bInverse)
cLineRightBottom.Invert() ;
PtrOwner<CurveBezier> cBezRightBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineRightBottom, nDegU, bRat))) ;
if ( IsNull( cBezRightBottom))
return false ;
CurveLine cLineRightTop ; cLineRightTop.Set( vPntTopStartFront.front(), vPntTopEndFront.front()) ;
if ( ! cLineRightTop.IsValid())
return false ;
PtrOwner<CurveBezier> cBezRightTop( GetBasicCurveBezier( LineToBezierCurve( &cLineRightTop, nDegU, bRat))) ;
if ( IsNull( cBezRightTop))
return false ;
vvPtCtrl.emplace_back( cBezRightBottom->GetAllControlPoints()) ;
PNTVECTOR vPntRight = cBezRightTop->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
}
if ( nSub == 1) { if ( nSub == 1) {
// superficie inferiore // superficie inferiore
vvPtCtrl.emplace_back( PNTVECTOR( { vPntTipStartFront.front(), vPntTipStartFront.back(), vPntTipEndFront.front(), vPntTipEndFront.back() })) ; vvPtCtrl.emplace_back( PNTVECTOR( { vPntTipStartFront.front(), vPntTipStartFront.back(), vPntTipEndFront.front(), vPntTipEndFront.back() })) ;
@@ -1749,43 +1962,83 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
if ( ! bTipIsPivot) { if ( ! bTipIsPivot) {
// inferiori // inferiori
if ( dSide > 0) { if ( dSide > 0) {
vvPtCtrl.emplace_back(cBezTipStartF1->GetAllControlPoints()); PNTVECTOR vPntTipEnd01 = cBezTipStartF1->GetAllControlPoints() ;
PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints(); if ( ! bInverse)
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()); vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ;
vvPtCtrl.emplace_back(cBezTipStartF2->GetAllControlPoints()); else
PNTVECTOR vPntTipEnd2 = cBezTipEndF2->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()); PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()) ;
PNTVECTOR vPntTipEnd02 = cBezTipStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTipEnd02.begin(), vPntTipEnd02.end()) ;
else
vvPtCtrl.emplace_back( vPntTipEnd02.rbegin(), vPntTipEnd02.rend()) ;
PNTVECTOR vPntTipEnd2 = cBezTipEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()) ;
} }
else { else {
PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints(); PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints() ;
vvPtCtrl.emplace_back(vPntTipEnd01.rbegin(), vPntTipEnd01.rend()); if ( ! bInverse)
PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()); else
PNTVECTOR vPntTipEnd02 = cBezTipStartB2->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ;
vvPtCtrl.emplace_back(vPntTipEnd02.rbegin(), vPntTipEnd02.rend()); PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints() ;
PNTVECTOR vPntTipEnd2 = cBezTipEndB2->GetAllControlPoints(); if ( ! bInverse)
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()); vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ;
PNTVECTOR vPntTipEnd02 = cBezTipStartB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTipEnd02.rbegin(), vPntTipEnd02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTipEnd02.begin(), vPntTipEnd02.end()) ;
PNTVECTOR vPntTipEnd2 = cBezTipEndB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ;
} }
} }
if ( ! bTopIsPivot) { if ( ! bTopIsPivot) {
// superiori // superiori
if ( dSide > 0) { if ( dSide > 0) {
vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints()); PNTVECTOR vPntTopEnd01 = cBezTopStartB1->GetAllControlPoints() ;
PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()); PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints() ;
vvPtCtrl.emplace_back(cBezTopStartB2->GetAllControlPoints()); vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ;
PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints(); PNTVECTOR vPntTopEnd02 = cBezTopStartB2->GetAllControlPoints() ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()); vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ;
PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
} }
else { else {
PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints(); PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints() ;
vvPtCtrl.emplace_back(vPntTopEnd01.rbegin(), vPntTopEnd01.rend()); if ( ! bInverse)
PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTopEnd01.rbegin(), vPntTopEnd01.rend()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.rend()); else
PNTVECTOR vPntTopEnd02 = cBezTopStartF2->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ;
vvPtCtrl.emplace_back(vPntTopEnd02.rbegin(), vPntTopEnd02.rend()); PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints() ;
PNTVECTOR vPntTopEnd2 = cBezTopEndF2->GetAllControlPoints(); if ( ! bInverse)
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd2.rbegin(), vPntTopEnd2.rend()); vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ;
PNTVECTOR vPntTopEnd02 = cBezTopStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTopEnd02.rbegin(), vPntTopEnd02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ;
PNTVECTOR vPntTopEnd2 = cBezTopEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.rbegin(), vPntTopEnd2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
} }
} }
@@ -1794,36 +2047,74 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
if ( ! bTipIsPivot) { if ( ! bTipIsPivot) {
// inferiori // inferiori
if ( dSide > 0) { if ( dSide > 0) {
PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints(); PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints() ;
vvPtCtrl.emplace_back(vPntTip01.rbegin(), vPntTip01.rend()); if ( ! bInverse)
PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()); else
PNTVECTOR vPntTip02 = cBezTipStartB2->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ;
vvPtCtrl.emplace_back(vPntTip02.rbegin(), vPntTip02.rend()); PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints() ;
PNTVECTOR vPntTip2 = cBezTipEndB2->GetAllControlPoints(); if ( ! bInverse)
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()); vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ;
PNTVECTOR vPntTip02 = cBezTipStartB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTip02.rbegin(), vPntTip02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTip02.begin(), vPntTip02.end()) ;
PNTVECTOR vPntTip2 = cBezTipEndB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ;
} }
else { else {
vvPtCtrl.emplace_back(cBezTipStartF1->GetAllControlPoints()); PNTVECTOR vPntTip01 = cBezTipStartF1->GetAllControlPoints() ;
PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints(); if ( ! bInverse)
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()); vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ;
vvPtCtrl.emplace_back(cBezTipStartF2->GetAllControlPoints()); else
PNTVECTOR vPntTip2 = cBezTipEndF2->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()); PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()) ;
PNTVECTOR vPntTip02 = cBezTipStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTip02.begin(), vPntTip02.end()) ;
else
vvPtCtrl.emplace_back( vPntTip02.rbegin(), vPntTip02.rend()) ;
PNTVECTOR vPntTip2 = cBezTipEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()) ;
} }
} }
if( ! bTopIsPivot) { if ( ! bTopIsPivot) {
// superiori // superiori
if ( dSide > 0) { if ( dSide > 0) {
PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints(); PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints() ;
vvPtCtrl.emplace_back(vPntTop01.rbegin(), vPntTop01.rend()); if ( ! bInverse)
PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTop01.rbegin(), vPntTop01.rend()) ;
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.rend()); else
PNTVECTOR vPntTop02 = cBezTopStartF2->GetAllControlPoints(); vvPtCtrl.emplace_back( vPntTop01.begin(), vPntTop01.end()) ;
vvPtCtrl.emplace_back(vPntTop02.rbegin(), vPntTop02.rend()); PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints() ;
PNTVECTOR vPntTop2 = cBezTopEndF2->GetAllControlPoints(); if ( ! bInverse)
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop2.rbegin(), vPntTop2.rend()); vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.begin(), vPntTop1.end()) ;
PNTVECTOR vPntTop02 = cBezTopStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTop02.rbegin(), vPntTop02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTop02.begin(), vPntTop02.end()) ;
PNTVECTOR vPntTop2 = cBezTopEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.rbegin(), vPntTop2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.begin(), vPntTop2.end()) ;
} }
else { else {
vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints()); vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints());
@@ -1839,23 +2130,43 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
// chiudo il volume con le superfici verticali e le basi dei tool // chiudo il volume con le superfici verticali e le basi dei tool
// chiudo il volume con le superici verticali end 1 // chiudo il volume con le superici verticali end front 1
vvPtCtrl.emplace_back( cBezTipEndF1->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipEndF1->GetAllControlPoints()) ;
PNTVECTOR vPntEnd1 = cBezTopEndF1->GetAllControlPoints() ; PNTVECTOR vPntEndF1 = cBezTopEndF1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd1.begin(), vPntEnd1.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF1.begin(), vPntEndF1.end()) ;
// chiudo il volume con le superici verticali end 2 // chiudo il volume con le superici verticali end front 2
vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ;
PNTVECTOR vPntEnd2 = cBezTopEndF2->GetAllControlPoints() ; PNTVECTOR vPntEndF2 = cBezTopEndF2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd2.begin(), vPntEnd2.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF2.begin(), vPntEndF2.end()) ;
if ( bInverse || bSmallMovement) {
// chiudo il volume con le superici verticali end back 1
vvPtCtrl.emplace_back( cBezTipEndB1->GetAllControlPoints()) ;
PNTVECTOR vPntEndB1 = cBezTopEndB1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndB1.begin(), vPntEndB1.end()) ;
// chiudo il volume con le superici verticali end back 2
vvPtCtrl.emplace_back( cBezTipEndB2->GetAllControlPoints()) ;
PNTVECTOR vPntEndB2 = cBezTopEndB2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndB2.begin(), vPntEndB2.end()) ;
}
// chiudo il volume con le superici verticali start 1 // chiudo il volume con le superici verticali start back 1
vvPtCtrl.emplace_back( cBezTipStartB1->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipStartB1->GetAllControlPoints()) ;
PNTVECTOR vPntStart1 = cBezTopStartB1->GetAllControlPoints() ; PNTVECTOR vPntStartB1 = cBezTopStartB1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart1.begin(), vPntStart1.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB1.begin(), vPntStartB1.end()) ;
// chiudo il volume con le superfici verticali start 2 // chiudo il volume con le superfici verticali start back 2
vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ;
PNTVECTOR vPntStart2 = cBezTopStartB2->GetAllControlPoints() ; PNTVECTOR vPntStartB2 = cBezTopStartB2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart2.begin(), vPntStart2.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB2.begin(), vPntStartB2.end()) ;
if ( bInverse || bSmallMovement) {
// chiudo il volume con le superici verticali start front 1
vvPtCtrl.emplace_back( cBezTipStartF1->GetAllControlPoints()) ;
PNTVECTOR vPntStartF1 = cBezTopStartF1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartF1.begin(), vPntStartF1.end()) ;
// chiudo il volume con le superfici verticali start front 2
vvPtCtrl.emplace_back( cBezTipStartF2->GetAllControlPoints()) ;
PNTVECTOR vPntStartF2 = cBezTopStartF2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartF2.begin(), vPntStartF2.end()) ;
}
// superfici di base dei tool // superfici di base dei tool
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) { if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) {
@@ -1926,7 +2237,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
} }
// inizializzo le superfici bilineari e i parametri per le intersezioni // inizializzo le superfici bilineari e i parametri per le intersezioni
for ( int z = 0 ; z < int( vvPtCtrl.size()) ; ++z) { for ( int z = 0 ; z < ssize( vvPtCtrl) ; ++z) {
vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ;
vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ;
@@ -1937,6 +2248,11 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ;
vSurfBez[nSurfInd].sBez.SetControlPoint( 7, vvPtCtrl[z][7]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 7, vvPtCtrl[z][7]) ;
#if SAVETRIMMINGTOOL
if ( nGrid == 0)
vGeo.push_back( vSurfBez[nSurfInd].sBez.Clone()) ;
#endif
Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ; Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ;
Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ; Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ;
Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ; Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ;
@@ -1985,6 +2301,11 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
++ nSurfInd ; ++ nSurfInd ;
} }
#if SAVETRIMMINGTOOL
if ( nGrid == 0)
SaveGeoObj( vGeo, "D:\\Temp\\VirtualMilling\\5axisAdvanced\\marmo sottosquadra\\volume.nge") ;
#endif
// scorro tutti gli spilloni interessati // scorro tutti gli spilloni interessati
int j = 0 ; int j = 0 ;
int nLastForwardJ = -1 ; int nLastForwardJ = -1 ;
@@ -5929,7 +6250,8 @@ VolZmap::CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, co
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
} }
@@ -5974,8 +6296,9 @@ VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
// Cilindro // Cilindro
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT, double dU1, dU2 ;
ptInt1, vtN1, ptInt2, vtN2)) { if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
@@ -6154,7 +6477,8 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
// Cilindro iniziale // Cilindro iniziale
CylFrame.ChangeOrig( ptITip) ; CylFrame.ChangeOrig( ptITip) ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
@@ -6162,7 +6486,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC // del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
// il vettore che congiunge le due origini. // il vettore che congiunge le due origini.
CylFrame.ChangeOrig( ptITip + vtMove) ; CylFrame.ChangeOrig( ptITip + vtMove) ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
@@ -6749,7 +7073,8 @@ VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe,
// Cilindro inviluppo della sfera // Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) { double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
} }
@@ -6897,15 +7222,15 @@ VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, cons
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true, if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
ptInt1, vtN1, ptInt2, vtN2)) { dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ; AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
} }
if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true, if ( IntersLineCyl( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
ptInt1, vtN1, ptInt2, vtN2)) { dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ; AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
} }
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0, if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
@@ -7301,8 +7626,9 @@ VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double
// Cilindro inviluppo della sfera // Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) { double dU1, dU2 ;
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ; if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
} }
} }
} }
+22 -4
View File
@@ -828,10 +828,19 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
Point3d ptTemp ; Point3d ptTemp ;
Vector3d vtDir ; Vector3d vtDir ;
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir)) if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
return false ; continue ;
vtDir.Normalize() ; vtDir.Normalize() ;
vResult.emplace_back( pt, vtDir) ; // verifico che il punto non sia già stato trovato
bool bAdd = true ;
for ( int j = 0 ; j < ssize( vResult) ; j ++) {
if ( AreSamePointApprox( vResult[j].first, pt)) {
bAdd = false ;
break ;
}
}
if ( bAdd)
vResult.emplace_back( pt, vtDir) ;
} }
} }
@@ -1014,8 +1023,17 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ; RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
// aggiungo la curva alla lista degli offset // aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) {
// 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)) ; OffsList.push_back( Release( pCrvOffs)) ;
}
} }
// libero la memoria di vroni dedicata agli offset // libero la memoria di vroni dedicata agli offset
@@ -1155,7 +1173,7 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::Translate( const Vector3d & vtMove) Voronoi::Translate( const Vector3d& vtMove)
{ {
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;