Compare commits

...

153 Commits

Author SHA1 Message Date
Daniele Bariletti b7b05fb3e1 EgtGeomKernel :
- correzione e miglioria dell'offset 3d delle curve.
2026-06-12 16:48:00 +02:00
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 98c576afe0 Merge branch 'master' into NewRuled 2026-02-23 09:12:05 +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 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
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 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 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
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
47 changed files with 7682 additions and 2029 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) ;
+968 -471
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -169,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]) ) ;
+185 -8
View File
@@ -25,19 +25,24 @@
#include "IntersLineLine.h" #include "IntersLineLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.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/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 SAVEAPPROX 0
#define SAVECURVEPASSED 0 #define SAVECURVEPASSED 0
#define SAVELINEARAPPROX 0 #define SAVELINEARAPPROX 0
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX #define SAVESYNCLINES 0
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX || SAVESYNCLINES
#include "/EgtDev/Include/EGkGeoPoint3d.h"
static int nCrvPassed = 0 ; static int nCrvPassed = 0 ;
std::vector<IGeoObj*> VT ;
std::vector<Color> VC ;
#include "/EgtDev/Include/EGkGeoObjSave.h" #include "/EgtDev/Include/EGkGeoObjSave.h"
#endif #endif
@@ -1595,8 +1600,10 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
ApproxCurveWithBezier( const ICurve* pCrv , double dTol) ApproxCurveWithBezier( const ICurve* pCrv , double dTol, const Vector3d& vtStart, const Vector3d& vtEnd)
{ {
if ( pCrv == nullptr || ! pCrv->IsValid())
return nullptr ;
#if SAVECURVEPASSED #if SAVECURVEPASSED
SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ; SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ;
@@ -1668,6 +1675,10 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
VCT3DVECTOR vPrevDer ; VCT3DVECTOR vPrevDer ;
VCT3DVECTOR vNextDer ; VCT3DVECTOR vNextDer ;
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ; ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ;
if ( ! AreSameVectorExact(vtStart, V_NULL)) {
vNextDer[0] = vtStart ;
vPrevDer.back() = vtEnd ;
}
int nOverSampling = ssize( vPntOverSampling) ; int nOverSampling = ssize( vPntOverSampling) ;
vParam.resize( nOverSampling) ; vParam.resize( nOverSampling) ;
@@ -1718,7 +1729,11 @@ CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int
// 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 ;
@@ -2656,12 +2671,21 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
INTVECTOR vIds ; INTVECTOR vIds ;
Point3d ptStart = ORIG ; Point3d ptStart = ORIG ;
while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) { while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) {
ICurveComposite* pFirstCrv = vCrv[abs(vIds[0]) - 1] ; 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) { for ( int nId : vIds) {
bool bInvert = false ; bInvert = false ;
if ( nId < 0) if ( nId < 0)
bInvert = true ; bInvert = true ;
nId = abs( nId) - 1 ; nId = abs( nId) - 1 ;
if ( nId == nFirst)
continue ;
if ( bInvert) if ( bInvert)
vCrv[nId]->Invert() ; vCrv[nId]->Invert() ;
if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol)) if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol))
@@ -2670,7 +2694,7 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
pFirstCrv->GetEndPoint( ptStart) ; pFirstCrv->GetEndPoint( ptStart) ;
} }
// elimino gli elementi del vettore che non contengono più curve // elimino gli elementi del vettore che non contengono più curve
int c = ssize( vCrv) ; int c = ssize( vCrv) - 1 ;
while ( c > -1) { while ( c > -1) {
if ( IsNull( vCrv[c])) if ( IsNull( vCrv[c]))
vCrv.erase( vCrv.begin() + c) ; vCrv.erase( vCrv.begin() + c) ;
@@ -2678,3 +2702,156 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
} }
return true ; 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 ;
}
+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} ;
+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) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
BIN
View File
Binary file not shown.
+3
View File
@@ -284,6 +284,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="CalcDerivate.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" />
@@ -323,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" />
@@ -353,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" />
+12
View File
@@ -570,6 +570,15 @@
<ClCompile Include="CalcDerivate.cpp"> <ClCompile Include="CalcDerivate.cpp">
<Filter>File di origine\Geo</Filter> <Filter>File di origine\Geo</Filter>
</ClCompile> </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">
@@ -1256,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">
+326 -88
View File
@@ -19,14 +19,15 @@
#include "/EgtDev/Include/EGkAngle.h" #include "/EgtDev/Include/EGkAngle.h"
#include "/EgtDev/Include/EGkHashGrids2d.h" #include "/EgtDev/Include/EGkHashGrids2d.h"
#include <algorithm> #include <algorithm>
#include <ranges>
using namespace std ; using namespace std ;
//--------------------------- Local functions -------------------------------- //--------------------------- Local functions --------------------------------
static bool CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, static bool CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
bool bCrvAClosed, double dCrvASpan) ; bool bCrvAClosed, double dCrvASpan, bool bOrderedOnB = false) ;
static bool CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, static bool CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
bool bCrvBClosed, double dCrvBSpan) ; bool bCrvBClosed, double dCrvBSpan, bool bOrderedOnB = false) ;
static void MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crvCompo) ; static void MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crvCompo) ;
static int GetCrvBDirAPrev( IntCrvCrvInfo& Icci) ; static int GetCrvBDirAPrev( IntCrvCrvInfo& Icci) ;
static int GetCrvBDirANext( IntCrvCrvInfo& Icci) ; static int GetCrvBDirANext( IntCrvCrvInfo& Icci) ;
@@ -34,7 +35,6 @@ static bool CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nS
const ICurve& CurveB, double dUB, int& nType) ; const ICurve& CurveB, double dUB, int& nType) ;
static bool CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA, static bool CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
const ICurve& CurveB, double dUB1, double dUB2, int& nType) ; const ICurve& CurveB, double dUB1, double dUB2, int& nType) ;
static bool CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
@@ -198,13 +198,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// se coincidono U e ptInt tra A e B // se coincidono U e ptInt tra A e B
if ( abs( m_Info[i].IciA[0].dU - m_Info[j].IciB[0].dU) < EPS_SMALL && if ( abs( m_Info[i].IciA[0].dU - m_Info[j].IciB[0].dU) < EPS_SMALL &&
AreSamePointXYEpsilon( m_Info[i].IciA[0].ptI, m_Info[j].IciB[0].ptI, 10 * EPS_SMALL)) { AreSamePointXYEpsilon( m_Info[i].IciA[0].ptI, m_Info[j].IciB[0].ptI, 10 * EPS_SMALL)) {
// se non è alla fine di curva chiusa // se j è alla fine di curva chiusa
if ( ! bCrvAClosed || abs( m_Info[j].IciA[0].dU - dCrvBSpan) > EPS_SMALL) // se j è alla fine di curva chiusa e la prima intersezione è di overlap con partenza dall'inizio ( compreso nel caso precedente)
// elimino la seconda // oppure se i è all'inizio di curva chiusa e l'intersezione successiva a j è di overlap con lo stesso parametro
EraseOtherInfo( i, j) ; if ( bCrvAClosed && (( abs( m_Info[j].IciA[0].dU - dCrvBSpan) < EPS_SMALL) ||
else ( i == 0 && ssize(m_Info) > 2 && m_Info[i].IciA[0].dU < EPS_SMALL && m_Info[j+1].bOverlap && abs( m_Info[j].IciA[0].dU - m_Info[j+1].IciA[0].dU) < EPS_SMALL)))
// elimino la prima // elimino la prima
EraseCurrentInfo( i, j) ; EraseCurrentInfo( i, j) ;
else
// elimino la seconda
EraseOtherInfo( i, j) ;
break ; break ;
} }
} }
@@ -262,8 +265,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM && abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM &&
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM) { abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM) {
// cancello entrambe // cancello entrambe
EraseOtherInfo( i, j) ; EraseBothInfo( i, j) ;
EraseCurrentInfo( i, j) ;
} }
// caso DET-(NULL) -> (NULL)-DET per prima curva // caso DET-(NULL) -> (NULL)-DET per prima curva
else if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL && else if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
@@ -383,8 +385,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL && m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) { m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
// cancello entrambe // cancello entrambe
EraseOtherInfo( i, j) ; EraseBothInfo( i, j) ;
EraseCurrentInfo( i, j) ;
} }
// caso NULL-DET -> NULL-DET per prima curva con NULL-NULL -> NULL-NULL su seconda curva // caso NULL-DET -> NULL-DET per prima curva con NULL-NULL -> NULL-NULL su seconda curva
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL && else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL &&
@@ -392,12 +393,10 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL && m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) { m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
// cancello entrambe // cancello entrambe
EraseOtherInfo( i, j) ; EraseBothInfo( i, j) ;
EraseCurrentInfo( i, j) ;
} }
// caso NULL-NULL per corrente di prima curva // caso NULL-NULL per corrente di prima curva
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) { else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
m_Info[j].IciA[kj].nNextTy = ICCT_NULL ;
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL) if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ; m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL) if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
@@ -407,7 +406,6 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
} }
// caso NULL-NULL per precedente di prima curva // caso NULL-NULL per precedente di prima curva
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) { else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
m_Info[i].IciA[ki].nPrevTy = ICCT_NULL ;
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL) if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ; m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL) if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
@@ -430,20 +428,19 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
continue ; continue ;
} }
// calcolo sottoindici // calcolo sottoindici
int ki = 0 ; // del successivo si prende sempre il primo int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
// verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL) // verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL)
if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) && if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) &&
AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) && AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) &&
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan) && CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan, true) &&
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan)) { CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan, true)) {
// caso entrambi Overlap ma di tipo opposto e sullo stesso tratto // caso entrambi Overlap ma di tipo opposto e sullo stesso tratto
if ( m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq && if ( m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq &&
abs( m_Info[i].IciB[0].dU - m_Info[j].IciB[0].dU) < EPS_PARAM && abs( m_Info[i].IciB[0].dU - m_Info[j].IciB[0].dU) < EPS_PARAM &&
abs( m_Info[i].IciB[1].dU - m_Info[j].IciB[1].dU) < EPS_PARAM) { abs( m_Info[i].IciB[1].dU - m_Info[j].IciB[1].dU) < EPS_PARAM) {
// cancello entrambe // cancello entrambe
EraseOtherInfo( i, j) ; EraseBothInfo( i, j) ;
EraseCurrentInfo( i, j) ;
} }
// caso DET-(NULL) -> (NULL)-DET per seconda curva // caso DET-(NULL) -> (NULL)-DET per seconda curva
else if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL && else if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
@@ -463,6 +460,12 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ; m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ; m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
} }
else {
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
}
// se overlap equiverso // se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) { if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda // per la prima curva ogni sottotipo è il duale di quello della seconda
@@ -475,6 +478,12 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ; m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ; m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
} }
else {
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
}
// medio parametri e punti separatamente per le due curve // medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ; MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ; MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
@@ -507,6 +516,12 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ; m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ; m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
} }
else {
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
}
// se overlap equiverso // se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) { if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda // per la prima curva ogni sottotipo è il duale di quello della seconda
@@ -519,6 +534,12 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ; m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ; m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
} }
else {
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
}
// medio parametri e punti separatamente per le due curve // medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ; MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ; MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
@@ -539,8 +560,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL && m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) { m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
// cancello entrambe // cancello entrambe
EraseOtherInfo( i, j) ; EraseBothInfo( i, j) ;
EraseCurrentInfo( i, j) ;
} }
// caso NULL-DET -> NULL-DET per seconda curva con NULL-NULL -> NULL-NULL su prima curva // caso NULL-DET -> NULL-DET per seconda curva con NULL-NULL -> NULL-NULL su prima curva
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL && else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL &&
@@ -548,12 +568,10 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL && m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) { m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
// cancello entrambe // cancello entrambe
EraseOtherInfo( i, j) ; EraseBothInfo( i, j) ;
EraseCurrentInfo( i, j) ;
} }
// caso NULL-NULL per corrente di seconda curva // caso NULL-NULL per corrente di seconda curva
else if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) { else if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
m_Info[j].IciB[kj].nNextTy = ICCT_NULL ;
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL) if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ; m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL) if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
@@ -563,7 +581,6 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
} }
// caso NULL-NULL per precedente di seconda curva // caso NULL-NULL per precedente di seconda curva
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL) { else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL) {
m_Info[i].IciB[ki].nPrevTy = ICCT_NULL ;
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL) if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ; m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL) if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
@@ -599,18 +616,19 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ; stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
for ( int i = 0 ; i < m_nNumInters ; ++ i) { for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// se il tipo di accostamento per la curva B non è definito // se il tipo di accostamento per la curva B non è definito
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) { int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL) {
if ( i > 0 || ( bCrvBClosed && ! bAutoInters)) { if ( i > 0 || ( bCrvBClosed && ! bAutoInters)) {
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ; int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
m_Info[i].IciB[0].nPrevTy = ( m_Info[j].bOverlap ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ; m_Info[i].IciB[ki].nPrevTy = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
} }
} }
// se il tipo di allontanamento per la curva B non è definito // se il tipo di allontanamento per la curva B non è definito
int ki = ( m_Info[i].bOverlap ? 1 : 0) ; ki = ( m_Info[i].bOverlap && m_Info[i].bCBOverEq ? 1 : 0) ;
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL) { if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
if ( i < m_nNumInters - 1 || ( bCrvBClosed && ! bAutoInters)) { if ( i < m_nNumInters - 1 || ( bCrvBClosed && ! bAutoInters)) {
int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ; int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ;
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[0].nPrevTy ; m_Info[i].IciB[ki].nNextTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nPrevTy : m_Info[j].IciB[0].nPrevTy) ;
} }
} }
} }
@@ -781,63 +799,109 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
} }
// verifico se una curva ha tutte le info e queste info sono coerenti // verifico se una curva ha tutte le info e queste info sono coerenti
if ( m_nNumInters > 1) { if ( m_nNumInters > 1 && ! bAutoInters) {
bool bCoherent = true ; bool bCoherent = true ;
INTVECTOR vIncoherenceWithPrev ; INTVECTOR vIncoherenceWithPrev ;
INTVECTOR vNewOverlap ;
// salvo eventuali incoerenze col precedente // salvo eventuali incoerenze col precedente
for ( int i = bCrvAClosed ? 0 : 1 ; i < m_nNumInters ; ++i) { for ( int i = bCrvAClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
int kj = m_Info[j].bOverlap ? 1 : 0 ; int kj = ( m_Info[j].bOverlap ? 1 : 0) ;
if ( m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy && bool bSpike = m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq ;
m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) { if ( bSpike) {
vIncoherenceWithPrev.push_back( i) ; bSpike = abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ;
}
if ( (m_Info[j].IciA[kj].nNextTy == ICCT_NULL || m_Info[i].IciA[0].nPrevTy == ICCT_NULL || m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy) &&
m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) {
if ( vIncoherenceWithPrev.empty() || vIncoherenceWithPrev.back() != i)
vIncoherenceWithPrev.push_back( i) ;
if ( bSpike) {
// se ho uno spike sistemo anche il successivo
int k = i == m_nNumInters - 1 ? -1 : i + 1 ;
if ( k == -1 && bCrvAClosed)
k = 0 ;
if ( k != -1)
vIncoherenceWithPrev.push_back( k) ;
}
bCoherent = false ; bCoherent = false ;
} }
} }
// incoerenze sulla curva A // incoerenze sulla curva A
if ( ! bCoherent) { if ( ! bCoherent) {
for ( int i : vIncoherenceWithPrev) { for ( int i : vIncoherenceWithPrev) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
int kj = m_Info[j].bOverlap ? 1 : 0 ; int kj = ( m_Info[j].bOverlap ? 1 : 0) ;
int nType = 0 ; int nType = 0 ;
CalcSide( m_Info[j], m_Info[i], &CCompoA, &CCompoB, true, nType) ; CalcSide( j, i, &CCompoA, &CCompoB, true, nType) ;
if ( nType == MDS_LEFT) if ( nType != ICCT_ON) {
nType = ICCT_IN ; m_Info[i].IciA[0].nPrevTy = nType ;
else if ( nType == MDS_RIGHT) m_Info[j].IciA[kj].nNextTy = nType ;
nType = ICCT_OUT ; }
m_Info[i].IciA[0].nPrevTy = nType ; else
m_Info[j].IciA[kj].nNextTy = nType ; vNewOverlap.push_back( i) ;
} }
} }
// faccio il merge se ho trasformato delle intersezioni in overlap
for ( int i : views::reverse( vNewOverlap))
MergeNewOverlap( i, true) ;
vNewOverlap.clear() ;
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ; stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
bCoherent = true ; bCoherent = true ;
vIncoherenceWithPrev.clear() ; vIncoherenceWithPrev.clear() ;
// salvo eventuali incoerenze col precedente // salvo eventuali incoerenze col precedente
for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) { for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
int kj = m_Info[j].bOverlap ? 1 : 0 ; int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
if ( m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[0].nPrevTy && int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[0].nPrevTy != ICCT_SPK) { bool bSpike = m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq ;
vIncoherenceWithPrev.push_back( i) ; if ( bSpike) {
bSpike = abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ;
}
if ( ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL || m_Info[i].IciB[ki].nPrevTy == ICCT_NULL || m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[ki].nPrevTy) &&
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[ki].nPrevTy != ICCT_SPK) {
if ( vIncoherenceWithPrev.empty() || vIncoherenceWithPrev.back() != i)
vIncoherenceWithPrev.push_back( i) ;
if ( bSpike) {
// se ho uno spike sistemo anche il successivo
int k = ( i == m_nNumInters - 1 ? -1 : i + 1) ;
if ( k == -1 && bCrvBClosed)
k = 0 ;
if ( k != -1)
vIncoherenceWithPrev.push_back( k) ;
}
bCoherent = false ; bCoherent = false ;
} }
} }
// incoerenze sulla curva B // incoerenze sulla curva B
if ( ! bCoherent) { if ( ! bCoherent) {
for ( int i : vIncoherenceWithPrev) { for ( int i : vIncoherenceWithPrev) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
int kj = m_Info[j].bOverlap ? 1 : 0 ; int ki = ( m_Info[i].bOverlap && !m_Info[i].bCBOverEq ? 1 : 0) ;
int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
int nType = 0 ; int nType = 0 ;
CalcSide( m_Info[j], m_Info[i], &CCompoB, &CCompoA, false, nType) ; CalcSide( j, i, &CCompoB, &CCompoA, false, nType) ;
if ( nType == MDS_LEFT) if ( nType != ICCT_ON) {
nType = ICCT_IN ; m_Info[i].IciB[ki].nPrevTy = nType ;
else if ( nType == MDS_RIGHT) m_Info[j].IciB[kj].nNextTy = nType ;
nType = ICCT_OUT ; }
m_Info[i].IciB[0].nPrevTy = nType ; else
m_Info[j].IciB[kj].nNextTy = nType ; vNewOverlap.push_back( i) ;
} }
} }
// faccio il merge se ho trasformato delle intersezioni in overlap
for ( int i : views::reverse( vNewOverlap))
MergeNewOverlap( i, false) ;
} }
else { else {
// posso completare A guardando B e viceversa // posso completare A guardando B e viceversa
@@ -849,34 +913,171 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool bool
CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType)
{ {
const IntCrvCrvInfo& Icci1 = m_Info[j] ;
const IntCrvCrvInfo& Icci2 = m_Info[i] ;
// calcolo tra l'intersezione 1 e 2 se la curva sta dentro o fuori // calcolo tra l'intersezione 1 e 2 se la curva sta dentro o fuori
int kj = Icci1.bOverlap ? 1 : 0 ; int ki = 0 ;
int kj = ( Icci1.bOverlap ? 1 : 0) ;
if ( ! bCrvAOrB) {
ki = ( m_Info[i].bOverlap && !m_Info[i].bCBOverEq ? 1 : 0) ;
kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
}
double dU = 0 ; double dU = 0 ;
bool bPrevIsBefore = true ;
if ( bCrvAOrB) { if ( bCrvAOrB) {
// se precedente minore del successivo faccio la media // se precedente minore del successivo faccio la media
if ( Icci1.IciA[kj].dU < Icci2.IciA[0].dU) if ( Icci1.IciA[kj].dU < Icci2.IciA[ki].dU)
dU = (Icci2.IciA[0].dU + Icci1.IciA[kj].dU) / 2 ; dU = ( Icci2.IciA[ki].dU + Icci1.IciA[kj].dU) / 2 ;
// altrimenti guardo tra lo start e il successivo // altrimenti guardo tra lo start e il successivo
else else {
dU = (Icci2.IciA[0].dU + 0.) / 2 ; bPrevIsBefore = false ;
dU = ( Icci2.IciA[0].dU + 0.) / 2 ;
if ( dU < EPS_SMALL) {
double dStart, dEnd ;
pThisCrv->GetDomain( dStart, dEnd) ;
double dUNew = dEnd - Icci1.IciA[kj].dU / 2 ;
if ( dUNew > dU)
dU = dUNew ;
}
}
} }
else { else {
// se precedente minore del successivo faccio la media // se precedente minore del successivo faccio la media
if ( Icci1.IciB[kj].dU < Icci2.IciB[0].dU) if ( Icci1.IciB[kj].dU < Icci2.IciB[ki].dU)
dU = (Icci2.IciB[0].dU + Icci1.IciB[kj].dU) / 2 ; dU = ( Icci2.IciB[ki].dU + Icci1.IciB[kj].dU) / 2 ;
// altrimenti guardi tra lo start e il successivo // altrimenti guardi tra lo start e il successivo
else else {
dU = (Icci2.IciB[0].dU + 0.) / 2 ; bPrevIsBefore = false ;
dU = ( Icci2.IciB[0].dU + 0.) / 2 ;
if ( dU < EPS_SMALL) {
double dStart, dEnd ;
pThisCrv->GetDomain( dStart, dEnd) ;
double dUNew = dEnd - Icci1.IciB[kj].dU / 2 ;
if ( dUNew > dU)
dU = dUNew ;
}
}
} }
Point3d ptTest ; pThisCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptTest) ; Point3d ptTest ; pThisCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptTest) ;
DistPointCurve dpc( ptTest, *pOtherCrv) ; DistPointCurve dpc( ptTest, *pOtherCrv) ;
dpc.GetSideAtMinDistPoint( 0, Z_AX, nType) ; dpc.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ;
if ( nType == MDS_LEFT)
nType = ICCT_IN ;
else if ( nType == MDS_RIGHT)
nType = ICCT_OUT ;
// se lo trovo sulla curva controllo se posso definire un tratto overlap
if ( nType == MDS_ON) {
double dFactor = 1./3. ;
DBLVECTOR vdU(2) ;
bool bIsOn = false ;
if ( bCrvAOrB) {
if ( bPrevIsBefore) {
vdU[0] = ( 1 - dFactor) * Icci2.IciA[ki].dU + dFactor * Icci1.IciA[kj].dU ;
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[ki].dU + 2 * dFactor * Icci1.IciA[kj].dU ;
}
else if ( Icci2.IciA[ki].dU > 2 * EPS_SMALL){
vdU[0] = ( Icci2.IciA[ki].dU + 0.) * dFactor ;
vdU[1] = ( Icci2.IciA[ki].dU + 0.) * 2 * dFactor ;
}
else
bIsOn = true ;
}
else {
if ( bPrevIsBefore) {
vdU[0] = ( 1 - dFactor) * Icci2.IciB[ki].dU + dFactor * Icci1.IciB[kj].dU ;
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[ki].dU + 2 * dFactor * Icci1.IciB[kj].dU ;
}
else if ( Icci2.IciB[ki].dU > 2 * EPS_SMALL) {
vdU[0] = ( Icci2.IciB[ki].dU + 0.) * dFactor ;
vdU[1] = ( Icci2.IciB[ki].dU + 0.) * 2 * dFactor ;
}
else
bIsOn = true ;
}
if ( ! bIsOn) {
bIsOn = true ;
for ( int k = 0 ; k < ssize(vdU) && bIsOn ; ++k) {
Point3d ptTest2 ; pThisCrv->GetPointD1D2( vdU[k], ICurve::FROM_MINUS, ptTest2) ;
DistPointCurve dpc2( ptTest2, *pOtherCrv) ;
dpc2.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ;
if ( nType != MDS_ON)
bIsOn = false ;
}
}
if ( bIsOn) {
m_Info[i].bOverlap = true ;
Vector3d vtDirThis, vtDirOther ;
Point3d ptCommon ;
double dUThis = 0 ;
if ( bCrvAOrB)
dUThis = m_Info[i].IciA[0].dU ;
else
dUThis = m_Info[i].IciB[0].dU ;
pThisCrv->GetPointD1D2( dUThis, ICurve::Side::FROM_MINUS, ptCommon, &vtDirThis) ;
double dUOther = 0 ; pOtherCrv->GetParamAtPoint( ptCommon, dUOther) ;
pOtherCrv->GetPointD1D2( dUOther, ICurve::Side::FROM_MINUS, ptCommon, &vtDirOther) ;
m_Info[i].bCBOverEq = vtDirThis * vtDirOther > 0 ;
if ( m_Info[i].bCBOverEq) {
m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
m_Info[i].IciA[0].nNextTy = ICCT_ON ;
m_Info[i].IciB[0].nNextTy = ICCT_ON ;
}
else {
if ( bCrvAOrB) {
m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
m_Info[i].IciA[0].nNextTy = ICCT_ON ;
m_Info[i].IciB[1] = m_Info[j].IciB[kj] ;
m_Info[i].IciB[0].nPrevTy = ICCT_ON ;
m_Info[i].IciB[1].nNextTy = ICCT_ON ;
}
else {
m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
m_Info[i].IciB[0].nNextTy = ICCT_ON ;
m_Info[i].IciA[1] = m_Info[j].IciA[kj] ;
m_Info[i].IciA[0].nPrevTy = ICCT_ON ;
m_Info[i].IciA[1].nNextTy = ICCT_ON ;
}
}
nType = ICCT_ON ;
}
}
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
IntersCrvCompoCrvCompo::MergeNewOverlap( int i, bool bCrvAOrB)
{
if ( i >= ssize(m_Info))
return false ;
// faccio il merge col precedente
int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
if ( m_Info[j].bOverlap) {
m_Info[i].IciA[0] = m_Info[j].IciA[0] ;
m_Info[i].IciB[0] = m_Info[j].IciB[0] ;
}
m_Info.erase( m_Info.begin() + j) ;
-- j ;
-- m_nNumInters ;
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IntersCrvCompoCrvCompo::IntersSimpleCurves( const ICurve& CurveA, int nA, const ICurve& CurveB, int nB, IntersCrvCompoCrvCompo::IntersSimpleCurves( const ICurve& CurveA, int nA, const ICurve& CurveB, int nB,
@@ -941,13 +1142,27 @@ bool
IntersCrvCompoCrvCompo::EraseOtherInfo( int& nIndCurr, int& nIndOther) IntersCrvCompoCrvCompo::EraseOtherInfo( int& nIndCurr, int& nIndOther)
{ {
m_Info.erase( m_Info.begin() + nIndOther) ; m_Info.erase( m_Info.begin() + nIndOther) ;
if ( nIndOther < nIndCurr) -- nIndCurr ;
-- nIndCurr ;
-- nIndOther ; -- nIndOther ;
-- m_nNumInters ; -- m_nNumInters ;
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
IntersCrvCompoCrvCompo::EraseBothInfo( int& nIndCurr, int& nIndOther)
{
m_Info.erase( m_Info.begin() + nIndOther) ;
-- nIndCurr ;
-- nIndOther ;
-- m_nNumInters ;
m_Info.erase( m_Info.begin() + nIndCurr) ;
if ( nIndCurr != -1)
-- nIndCurr ;
-- m_nNumInters ;
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Global functions // Global functions
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -990,21 +1205,25 @@ SortGreaterB( const IntCrvCrvInfo& aInfo1, const IntCrvCrvInfo& aInfo2)
dU1 = aInfo1.IciB[0].dU ; dU1 = aInfo1.IciB[0].dU ;
if ( aInfo1.bOverlap) { if ( aInfo1.bOverlap) {
// caso normale // caso normale
if ( aInfo1.IciB[0].dU < aInfo1.IciB[1].dU) if ( ( aInfo1.bCBOverEq && aInfo1.IciB[0].dU < aInfo1.IciB[1].dU) || ( ! aInfo1.bCBOverEq && aInfo1.IciB[0].dU > aInfo1.IciB[1].dU))
dU1 = 0.5 * ( aInfo1.IciB[0].dU + aInfo1.IciB[1].dU) ; dU1 = 0.5 * ( aInfo1.IciB[0].dU + aInfo1.IciB[1].dU) ;
// a cavallo di fine / inizio // a cavallo di fine / inizio
else else if ( aInfo1.bCBOverEq)
dU1 = aInfo1.IciB[0].dU + SPAN_PARAM ; dU1 = aInfo1.IciB[0].dU + SPAN_PARAM ;
else
dU1 = aInfo1.IciB[1].dU + SPAN_PARAM ;
} }
// determino il secondo termine del confronto // determino il secondo termine del confronto
dU2 = aInfo2.IciB[0].dU ; dU2 = aInfo2.IciB[0].dU ;
if ( aInfo2.bOverlap) { if ( aInfo2.bOverlap) {
// caso normale // caso normale
if ( aInfo2.IciB[0].dU < aInfo2.IciB[1].dU) if ( ( aInfo2.bCBOverEq && aInfo2.IciB[0].dU < aInfo2.IciB[1].dU) || ( ! aInfo2.bCBOverEq && aInfo2.IciB[0].dU > aInfo2.IciB[1].dU))
dU2 = 0.5 * ( aInfo2.IciB[0].dU + aInfo2.IciB[1].dU) ; dU2 = 0.5 * ( aInfo2.IciB[0].dU + aInfo2.IciB[1].dU) ;
// a cavallo di fine / inizio // a cavallo di fine / inizio
else else if ( aInfo2.bCBOverEq)
dU2 = aInfo2.IciB[0].dU + SPAN_PARAM ; dU2 = aInfo2.IciB[0].dU + SPAN_PARAM ;
else
dU2 = aInfo2.IciB[1].dU + SPAN_PARAM ;
} }
return ( dU2 > dU1 + EPS_PARAM) ; return ( dU2 > dU1 + EPS_PARAM) ;
@@ -1095,11 +1314,20 @@ OrderNonManifoldInters( ICCIVECTOR& Info, const ICurve& CurveA, const ICurve& Cu
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
bool bCrvAClosed, double dCrvASpan) bool bCrvAClosed, double dCrvASpan, bool bOrderedOnB)
{ {
int k = ( Icci1.bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap int ki = 0 ;
if ( abs( Icci1.IciA[k].dU - Icci2.IciA[0].dU) > 0.1 * SPAN_PARAM && int kj = 0 ;
( ! bCrvAClosed || abs( abs( Icci1.IciA[k].dU - Icci2.IciA[0].dU) - dCrvASpan) > 0.1 * SPAN_PARAM)) if ( ! bOrderedOnB) {
ki = 0 ;
kj = Icci1.bOverlap ? 1 : 0 ;
}
else {
ki = Icci2.bOverlap && ! Icci2.bCBOverEq ? 1 : 0 ;
kj = Icci1.bOverlap && Icci1.bCBOverEq ? 1 : 0 ;
}
if ( abs( Icci1.IciA[kj].dU - Icci2.IciA[ki].dU) > 0.1 * SPAN_PARAM &&
( ! bCrvAClosed || abs( abs( Icci1.IciA[kj].dU - Icci2.IciA[ki].dU) - dCrvASpan) > 0.1 * SPAN_PARAM))
return false ; return false ;
return true ; return true ;
} }
@@ -1107,11 +1335,21 @@ CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
bool bCrvBClosed, double dCrvBSpan) bool bCrvBClosed, double dCrvBSpan, bool bOrderedOnB)
{ {
int k = ( Icci1.bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap int ki = 0 ;
if ( abs( Icci1.IciB[k].dU - Icci2.IciB[0].dU) > 0.1 * SPAN_PARAM && int kj = 0 ;
( ! bCrvBClosed || abs( abs( Icci1.IciB[k].dU - Icci2.IciB[0].dU) - dCrvBSpan) > 0.1 * SPAN_PARAM)) if ( ! bOrderedOnB) {
ki = 0 ;
kj = Icci1.bOverlap ? 1 : 0 ;
}
else {
ki = Icci2.bOverlap && ! Icci2.bCBOverEq ? 1 : 0 ;
kj = Icci1.bOverlap && Icci1.bCBOverEq ? 1 : 0 ;
}
if ( abs( Icci1.IciB[kj].dU - Icci2.IciB[ki].dU) > 0.1 * SPAN_PARAM &&
( ! bCrvBClosed || abs( abs( Icci1.IciB[kj].dU - Icci2.IciB[ki].dU) - dCrvBSpan) > 0.1 * SPAN_PARAM))
return false ; return false ;
return true ; return true ;
} }
+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 ;
+22 -2
View File
@@ -579,6 +579,22 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
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 ;
@@ -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
@@ -736,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
View File
@@ -235,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) ;
+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,
+547
View File
@@ -0,0 +1,547 @@
//----------------------------------------------------------------------------
// 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 0
#define SAVEOFFDIR 0
#define SAVECYL 0
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
#include "/EgtDev/Include/EGkColor.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
vector<IGeoObj*> vGeo ;
vector<Color> vCol ;
#include "CurveArc.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#endif
//----------------------------------------------------------------------------
struct OffsetSegm {
PtrOwner<ICurve> pCrv ;
int nFlag ;
int nParent ;
OffsetSegm( ICurve* _pCrv, int _nFlag, int _nParent) :
nFlag( _nFlag), nParent( _nParent) { pCrv.Set( _pCrv); } ;
} ;
typedef vector<OffsetSegm> vOffsetSeg ;
bool AdjustConcavePartsInPath( const ICurveComposite* pCrv, vOffsetSeg& vOffsetCrvs, 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)
{
// la funzione è pensata per lavorare con il risultato dell'operazione ProjectCurveOnSurf
// vOffDir devono essere normalizzati
// mi aspetto che siano più o meno perpendicolari alla curva
// pulisco tutto
Reset() ;
PtrOwner<CurveComposite> pCrv( CreateBasicCurveComposite()) ;
if ( ! pCrv->FromPolyLine( PL))
return false ;
#if SAVECVRORIG || SAVEOFFDIR
vGeo.clear() ;
vCol.clear() ;
vGeo.push_back( pCrv->Clone()) ;
vCol.push_back( AQUA) ;
#if SAVEOFFDIR
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
#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 ;
}
bool bClosed = pCrv->IsClosed() ;
INTVECTOR vFlag ;
vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ;
const ICurve* pSubCrv = pCrv->GetFirstCurve() ;
const double dSinAngSmall = sin( 1 * DEGTORAD) ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
pSubCrv = pCrv->GetNextCurve() ;
Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ;
vtDirCurr.Normalize() ;
int nFlag ;
double dProj = vtDirCurr * vOffDir[i-1] ;
if ( dProj > dSinAngSmall)
nFlag = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ;
else if ( dProj > - dSinAngSmall)
nFlag = OffsetCurve3d::AngType::ANG_STR ;
else
nFlag = OffsetCurve3d::AngType::ANG_CVEX ;
vFlag.push_back( nFlag) ;
}
for ( int i = 1 ; i < ssize( vFlag) - 1 ; ++i) {
if ( vFlag[i-1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC &&
vFlag[i+1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC &&
vFlag[i] != OffsetCurve3d::AngType::ANG_SMOOTH_CONC)
vFlag[i] = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ;
}
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 ;
vOffsetSeg vOffsetCrvs ;
Vector3d vtDirPrevOff = V_INVALID ;
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 ;
if ( vFlag[i] != OffsetCurve3d::AngType::ANG_CVEX)
vtTang = Media( vtDirCurr, vtDirPrev) ;
else if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[i-1] != OffsetCurve3d::AngType::ANG_CVEX)
vtTang = vtDirPrev ;
else
vtTang = vtDirCurr ;
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, OffsetCurve3d::AngType::ANG_CVEX, -1) ;
Point3d ptAdd2 = ptP - dDelta * vtTang ;
ICurveLine* pCL2 = CreateBasicCurveLine() ;
pCL2->Set( ptAdd1, ptAdd2) ;
vOffsetCrvs.emplace_back( pCL2, OffsetCurve3d::AngType::ANG_CVEX, -1) ;
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
//}
Vector3d vtDirCurrOff = ptP - ptPrev ; vtDirCurrOff.Normalize() ;
double dProj = 1 ;
if ( vtDirPrevOff.IsValid())
dProj = vtDirCurrOff * vtDirPrevOff ;
if ( dProj > - 0.5 || vFlag[i] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
// aggiungo tratto
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
vOffsetCrvs.emplace_back( pCL, vFlag[i], i - 1) ;
// aggiorno punto precedente
ptPrev = ptP ;
vtNormPrev = vtNorm ;
vtCorrPrev = vtCorr ;
vtTangPrev = vtTang ;
vtDirPrev = vtDirCurr ;
pCrvPrev = pCrvCurr ;
vtDirPrevOff = vtDirCurrOff ;
}
}
// se chiusa aggiungo il tratto di chiusura
if ( bClosed) {
Point3d ptP ; vOffsetCrvs.front().pCrv->GetStartPoint( ptP) ;
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ;
}
// qui faccio la correzione per gli angoli interni
if ( ! AdjustConcavePartsInPath( pCrv, vOffsetCrvs, dOffDist))
return false ;
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
vGeo.push_back( vOffsetCrvs[i].pCrv->Clone()) ;
if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC)
vCol.push_back( GREEN) ;
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_STR)
vCol.push_back( PURPLE) ;
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_CVEX)
vCol.push_back( RED) ;
}
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
return true ;
#endif
PtrOwner<ICurveComposite> pCrvOffset( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
if ( ! pCrvOffset->AddCurve( Release( vOffsetCrvs[i].pCrv)))
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, double dLinTol)
{
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 - dLinTol) * ( offCyl.dRad - dLinTol) ;
if ( dDist > dRadSq)
return false ;
return true ;
}
bool
AdjustConcavePartsInPath( const ICurveComposite* pCrv, vOffsetSeg& vOffsetCrvs, double dRad)
{
const double dLinTol = 5 * EPS_SMALL ;
INTVECTOR vErase ;
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
int nFlag = vOffsetCrvs[i].nFlag ;
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 = vOffsetCrvs[i].nFlag ;
}
CYLVECT vCyl ;
// creo un cilindro della dimensione del raggio
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
if ( vOffsetCrvs[vLines[j]].nParent == -1)
continue ;
const ICurve* pSubCrv = pCrv->GetCurve( vOffsetCrvs[vLines[j]].nParent) ;
Point3d ptStart, ptEnd ;
pSubCrv->GetStartPoint( ptStart) ;
pSubCrv->GetEndPoint( ptEnd) ;
Vector3d vtHeight = ptEnd - ptStart ;
double dHeight = vtHeight.Len() ;
vtHeight.Normalize() ;
vCyl.emplace_back( ptStart, vtHeight, dHeight, dRad, dLinTol) ;
#if SAVECYL
CurveArc ca ; ca.Set( ptStart, vtHeight, dRad) ;
ISurfTriMesh* pSurfTm = GetSurfTriMeshByExtrusion( &ca, vtHeight, false, 2 * EPS_SMALL) ;
vGeo.push_back( pSurfTm) ;
vCol.push_back( LGRAY) ;
#endif
}
// 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 = vOffsetCrvs[vLines[j]].pCrv ;
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], dLinTol) ;
if ( bErasedPrev && ! bToErase)
bToErase = bToErase || IsPointInsideCylinder( ptStart, vCyl[k], dLinTol) ;
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]].pCrv ;
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].pCrv ;
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].pCrv ;
pCLNext->ModifyStart( ptTrim) ;
}
}
}
}
}
i = vLines.back() ;
}
}
// cancello le curve indicate in vErase
for ( int i = ssize( vErase) - 1 ; i >= 0 ; --i) {
vOffsetCrvs.erase( vOffsetCrvs.begin() + vErase[i]) ;
}
// 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].pCrv->GetEndPoint( ptEndCurr) ;
vOffsetCrvs[i+1].pCrv->GetStartPoint( ptStartNext) ;
if ( ! AreSamePointApprox( ptEndCurr, ptStartNext)) {
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptEndCurr, ptStartNext) ;
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR,-1) ;
rotate( vOffsetCrvs.begin() + i + 1, vOffsetCrvs.end() - 1, vOffsetCrvs.end()) ;
++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) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+213 -80
View File
@@ -40,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
@@ -64,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 ;
@@ -79,18 +81,24 @@ 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.vtDirU = vPt5ax[j].vtDirU ;
@@ -102,9 +110,14 @@ 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.vtDirU = vPt5ax[i].vtDirU ;
@@ -133,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 ;
} }
@@ -377,8 +405,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
} }
// 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) ;
@@ -393,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) ;
@@ -402,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 ;
}
}
} }
} }
} }
@@ -455,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 ;
@@ -521,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) ;
@@ -543,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() ;
@@ -558,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 ;
}
}
} }
} }
} }
@@ -612,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 ;
@@ -663,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) ;
@@ -681,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) ;
@@ -699,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 ;
}
}
} }
} }
} }
@@ -738,7 +845,7 @@ 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.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ; Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
@@ -754,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 ;
@@ -805,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) ;
@@ -823,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) ;
@@ -850,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 ;
}
}
} }
} }
} }
@@ -911,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 ;
@@ -983,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
+36
View File
@@ -733,6 +733,42 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
return Release( pSbz) ; return Release( pSbz) ;
} }
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfBezier* ISurfBezier*
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol) GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
+1121 -542
View File
File diff suppressed because it is too large Load Diff
+110 -22
View File
@@ -29,6 +29,7 @@
#define SAVEMKUNIF_CRVS 0 #define SAVEMKUNIF_CRVS 0
#if SAVEMKUNIF_CRVS #if SAVEMKUNIF_CRVS
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h" #include "/EgtDev/Include/EGkGeoObjSave.h"
#endif #endif
@@ -618,7 +619,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
#if SAVEMKUNIF_CRVS #if SAVEMKUNIF_CRVS
//debug //debug
vector<IGeoObj*> vGeo ; vGeo.clear() ;
for( int i = 0 ; i < ssize( vLoop); ++i){ for( int i = 0 ; i < ssize( vLoop); ++i){
vGeo.push_back(vLoop[i]->Clone()) ; vGeo.push_back(vLoop[i]->Clone()) ;
} }
@@ -632,7 +633,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
nDir == 0 ? bRescaledU = true : bRescaledV = true ; nDir == 0 ? bRescaledU = true : bRescaledV = true ;
// creo il vettore delle curve all'interno di una striscia // creo il vettore delle curve all'interno di una striscia
ICRVCOMPOPOVECTOR vCrvStrip ; ICRVCOMPOPOVECTOR vCrvStrip ;
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) { for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) {
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 ;
@@ -654,24 +655,85 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
for ( int l = 0 ; l < ssize( vLoop); ++l) { for ( int l = 0 ; l < ssize( vLoop); ++l) {
#if SAVEMKUNIF_CRVS #if SAVEMKUNIF_CRVS
//debug //debug
vector<IGeoObj*> vGeo ; vGeo.clear() ;
vGeo.push_back(pTrimMask->Clone()) ; vGeo.push_back(pTrimMask->Clone()) ;
vGeo.push_back(vLoop[l]->Clone()) ; vGeo.push_back(vLoop[l]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ; SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ;
//debug //debug
#endif #endif
IntersCurveCurve icc( *pTrimMask, *vLoop[l]) ; IntersCurveCurve icc( *vLoop[l], *pTrimMask) ;
CRVCVECTOR vCurveClass ; int nInters = icc.GetIntersCount() ;
icc.GetCurveClassification( 1, 10 * EPS_SMALL, vCurveClass) ; ICCIVECTOR vICCI ;
for( int i = 0 ; i < ssize( vCurveClass); ++i) { for ( int i = 0 ; i < nInters ; ++i) {
if( vCurveClass[i].nClass == CRVC_IN || vCurveClass[i].nClass == CRVC_ON_P) IntCrvCrvInfo icci ; icc.GetIntCrvCrvInfo( i, icci) ;
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCurveClass[i].dParS, vCurveClass[i].dParE))) ; 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 #if SAVEMKUNIF_CRVS
//debug //debug
vector<IGeoObj*> vGeo ; vGeo.clear() ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){ for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ; vGeo.push_back(vCrvStrip[i]->Clone()) ;
} }
@@ -694,25 +756,27 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
return false ; return false ;
} }
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo // 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 ; Point3d pt ;
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
if ( nDir == 0)
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
Vector3d vtJoin ; Vector3d vtJoin ;
if ( nDir == 0) 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) ; vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
else }
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) ; vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
}
for( int i = 0 ; i < ssize( vCrvStrip); ++i) for( int i = 0 ; i < ssize( vCrvStrip); ++i)
vCrvStrip[i]->Translate( vtJoin) ; vCrvStrip[i]->Translate( vtJoin) ;
#if SAVEMKUNIF_CRVS #if SAVEMKUNIF_CRVS
//debug //debug
vector<IGeoObj*> vGeo ; vGeo.clear() ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){ for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ; vGeo.push_back(vCrvStrip[i]->Clone()) ;
} }
@@ -725,7 +789,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) { if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) {
#if SAVEMKUNIF_CRVS #if SAVEMKUNIF_CRVS
//debug //debug
vector<IGeoObj*> vGeo ; vGeo.clear() ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){ for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
vGeo.push_back(vUniformedCurves[i]->Clone()) ; vGeo.push_back(vUniformedCurves[i]->Clone()) ;
} }
@@ -758,6 +822,20 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
ICRVCOMPOPOVECTOR vNewCrv ; ICRVCOMPOPOVECTOR vNewCrv ;
int nCrvPrec = ssize( vUniformedCurves) ; int nCrvPrec = ssize( vUniformedCurves) ;
while ( chainCrv.GetChainFromNear( ORIG, false, vIds)) { 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()) ; vNewCrv.emplace_back( CreateBasicCurveComposite()) ;
for ( int nId : vIds) { for ( int nId : vIds) {
nId -= 1 ; nId -= 1 ;
@@ -767,6 +845,16 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
vNewCrv.back()->AddCurve( Release( vCrvStrip[nId - ssize( vUniformedCurves)]), true, dChainTol) ; 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 // aggiorno le curve
vUniformedCurves.clear() ; vUniformedCurves.clear() ;
vUniformedCurves.swap( vNewCrv) ; vUniformedCurves.swap( vNewCrv) ;
@@ -799,7 +887,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
// controllo che tutte le curve siano chiuse, sennò vuol dire che ho perso qualche pezzo durante le intersezioni // 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) { for ( int i = 0 ; i < ssize( vUniformedCurves); ++i) {
if ( ! vUniformedCurves[i]->IsClosed()) if ( ! vUniformedCurves[i]->IsClosed() && ! vUniformedCurves[i]->Close())
return false ; return false ;
} }
+1323 -289
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -148,11 +148,14 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ; bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ; bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ; bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
PNTVECTOR GetAllControlPoints( void) const ; 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 BIPNTVECTOR& vCrv) ; bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
bool RemoveCollapsedSpans( void) override ; bool RemoveCollapsedSpans( void) override ;
bool SwapParameters( void) ; 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) ;
+37 -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) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
-4
View File
@@ -352,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) ;
+706 -66
View File
@@ -36,13 +36,13 @@
#include "/EgtDev/Include/EGkIntersLineBox.h" #include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EGkIntersCurvePlane.h" #include "/EgtDev/Include/EGkIntersCurvePlane.h"
#include "/EgtDev/Include/EGkSurfTriMeshAux.h" #include "/EgtDev/Include/EGkSurfTriMeshAux.h"
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtNumUtils.h"
#include <thread> #include <thread>
#include <future> #include <future>
#include <numeric> #include <numeric>
// -------------------------- Debug -------------------------------------------- // -------------------------- Debug --------------------------------------------
#define DEBUG 0
#define DEBUG_BASIC_BORDERS 0 #define DEBUG_BASIC_BORDERS 0
#define DEBUG_CHAIN_CURVES 0 #define DEBUG_CHAIN_CURVES 0
#define DEBUG_ANG_APPROX 0 #define DEBUG_ANG_APPROX 0
@@ -63,11 +63,12 @@
#define DEBUG_EDGES 0 #define DEBUG_EDGES 0
#define DEBUG_SHAPE_STM 0 #define DEBUG_SHAPE_STM 0
#define DEBUG_HOLES 0 #define DEBUG_HOLES 0
#define DEBUG_SMOOTH_CURVATURE 0
#if DEBUG_BASIC_BORDERS || DEBUG_CHAIN_CURVES || DEBUG_ANG_APPROX || DEBUG_BEZIER_INTERP || \ #if DEBUG_BASIC_BORDERS || DEBUG_CHAIN_CURVES || DEBUG_ANG_APPROX || DEBUG_BEZIER_INTERP || \
DEBUG_FACE_SEARCH || DEBUG_FACE_SEARCH_TRIA_MODIF || DEBUG_BRK_POINTS || DEBUG_BRK_THICK || \ DEBUG_FACE_SEARCH || DEBUG_FACE_SEARCH_TRIA_MODIF || DEBUG_BRK_POINTS || DEBUG_BRK_THICK || \
DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \ DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \
DEBUG_BEZIER_RULED || DEBUG_CURVATURE || DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || \ DEBUG_BEZIER_RULED || DEBUG_CURVATURE || DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || \
DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG_SMOOTH_CURVATURE
#include "CurveLine.h" #include "CurveLine.h"
#include "/EgtDev/Include/EGkGeoObjSave.h" #include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EgtPerfCounter.h"
@@ -284,6 +285,63 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL)
return true ; return true ;
} }
////-----------------------------------------------------------------------------
//// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
//// Patches di curve di Bezier
//static bool
//ApproxBorder( ICurveComposite* pCrvCompo, double dLinTol, double dAngTol, double dAngTolSplit)
//{
// // N.B.:in futuro bisognerebbe fare l'approssimazione direttamente con le bezier.
//
// // Controllo dei parametri
// if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid())
// return false ;
//
// // splitto la curva considerando la tolleranza angolare
// ICRVCOMPOPOVECTOR vCC ;
// SplitCurveCompoByAngTol( pCrvCompo, dAngTolSplit, vCC) ;
// #if DEBUG_BEZIER_INTERP
// VT.clear() ;
// for( int i = 0 ; i < ssize(vCC) ; ++i)
// VT.push_back( vCC[i]->Clone()) ;
// SaveGeoObj( VT, "D:\\Temp\\trimming\\AngBorderApprox.nge") ;
// VT.clear() ;
// #endif
//
// pCrvCompo->Clear() ;
//
// // Ogni PolyLine ricavata viene approssimata con un tratto di Bezier
// const double MAXLEN = 1.5 ;
// for ( ICurveComposite* pCC : vCC) {
// // Se meno di due curve, non la considero ( non dovrebbe mai capitare )
// if ( pCC->GetCurveCount() < 2)
// continue ;
// PolyArc PA ;
// if ( ! pCC->ApproxWithArcs( dLinTol, dAngTol, PA))
// return false ;
// CurveComposite CrvTemp ;
// if ( ! CrvTemp.FromPolyArc( PA) || ! CrvTemp.MergeCurves( dLinTol, dAngTol))
// return false ;
// #if DEBUG_BEZIER_INTERP
// VT.emplace_back( CrvTemp->Clone()) ;
// #endif
// // Converto in Bezier
// PtrOwner<ICurve> pCrvBz( CurveToBezierCurve( &CrvTemp)) ;
// if ( IsNull( pCrvBz) || ! pCrvBz->IsValid()) {
// LOG_ERROR( GetEGkLogger(), "Error : converrting curve to bezier") ;
// return false ;
// }
// // Aggiungo il tratto approssimato alla curva finale complessiva
// if ( ! pCrvCompo->AddCurve( Release( pCrvBz)))
// return false ;
// }
// #if DEBUG_BEZIER_INTERP
// SaveGeoObj( VT, VC, "D:\\Temp\\trimming\\bezier_edge.nge") ;
// #endif
//
// return ( pCrvCompo->IsValid()) ;
//}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante // Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
// Patches di curve di Bezier // Patches di curve di Bezier
@@ -3475,10 +3533,11 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static bool static bool
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide, InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
const Plane3d& plStart, const Plane3d& plEnd, double dLinTol, const Plane3d& plStart, const Plane3d& plEnd, const Vector3d vtAuxStart, const Vector3d vtAuxEnd,
BIPNTVECTOR& vBiPts) double dLinTol, BIPNTVECTOR& vBiPts)
{ {
vBiPts.clear() ; vBiPts.clear() ;
const double dLinAngTol = 15 * EPS_SMALL ; // tolleranza sulla lunghezza della corda dell'angolo di tolleranza
// Verifico che le curve siano valide // Verifico che le curve siano valide
if ( pGuide == nullptr || ! pGuide->IsValid() || if ( pGuide == nullptr || ! pGuide->IsValid() ||
@@ -3508,52 +3567,134 @@ InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICur
// Interpolo le normali dei piani rispetto a tale valore // Interpolo le normali dei piani rispetto a tale valore
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ; Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
vtN.Normalize() ; vtN.Normalize() ;
Vector3d vtAux = Media( vtAuxStart, vtAuxEnd, dInterPar) ; vtAux.Normalize() ;
// Definisco il piano di intersezione // Definisco il piano di intersezione
Point3d ptCurr ; Point3d ptCurr ;
if ( ! pCrv->GetEndPoint( ptCurr)) if ( ! pCrv->GetEndPoint( ptCurr))
return false ; return false ;
// con i piani
#if DEBUG_SYNC_INTERPOLATION #if DEBUG_SYNC_INTERPOLATION
Frame3d frPl ; frPl.Set( ptCurr, vtN) ; Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ; PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
VT.emplace_back( Release( frCurr)) ; VT.emplace_back( Release( frCurr)) ;
VC.emplace_back( WHITE) ; VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
#endif #endif
// Recupero il parametro di intersezione tra la curva e il piano // Recupero il parametro di intersezione tra la curva e il piano
#if 0
VT.clear() ; VC.clear() ;
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
VT.emplace_back( Release( PT)) ;
VC.emplace_back( AQUA) ;
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
VECT->ChangeBase( ptCurr) ;
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
pSfrPlane->AddExtLoop( Release( pArc)) ;
VT.emplace_back( Release( pSfrPlane)) ;
VC.emplace_back( Color( 0., 0., 0., .5)) ;
VT.emplace_back( Release( VECT)) ;
VC.emplace_back( BLUE) ;
VT.emplace_back( pOtherGuide->Clone()) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
if ( IntCP.GetIntersCount() == 0)
return false ; // ambiguità
// Recupero il punto della prima intersezione trovata
Point3d ptInt ;
double dPar ;
if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar))
return false ;
#if DEBUG_SYNC_INTERPOLATION #if DEBUG_SYNC_INTERPOLATION
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ; if ( false) {
VT.emplace_back( Release( ptG)) ; VT.clear() ; VC.clear() ;
VC.emplace_back( WHITE) ; PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; VT.emplace_back( Release( PT)) ;
VC.emplace_back( AQUA) ;
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
VECT->ChangeBase( ptCurr) ;
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
pSfrPlane->AddExtLoop( Release( pArc)) ;
VT.emplace_back( Release( pSfrPlane)) ;
VC.emplace_back( Color( 0., 0., 0., .5)) ;
VT.emplace_back( Release( VECT)) ;
VC.emplace_back( BLUE) ;
VT.emplace_back( pOtherGuide->Clone()) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
}
#endif #endif
// Memorizzo tale punto
vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ; IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
bool bFound = false ;
if ( IntCP.GetIntersCount() != 0) {
// Recupero il punto della prima intersezione trovata
Point3d ptIntClosest ;
double dPar ;
IntCP.GetIntersPointNearTo( ptCurr, ptIntClosest, dPar) ;
// verifico che sia allineato con la direzione che dovrebbe avere
Vector3d vtDir = ptIntClosest - ptCurr ;
vtDir.Normalize() ;
double dDiff = (vtDir - vtAux).Len() ;
if ( dDiff < dLinAngTol) {
#if DEBUG_SYNC_INTERPOLATION
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptIntClosest) ;
VT.emplace_back( Release( ptG)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
#endif
//Memorizzo tale punto
vBiPts.emplace_back( make_pair( ptCurr, ptIntClosest)) ;
bFound = true ;
}
else if ( IntCP.GetIntersCount() > 1) {
double dMinDiff = INFINITO ;
Point3d ptBest ;
for ( int j = 0 ; j < IntCP.GetIntersCount() ; ++j) {
IntCrvPlnInfo icpi ; IntCP.GetIntCrvPlnInfo( j, icpi) ;
Point3d ptInt = icpi.Ici->ptI ;
double dDiff = ( ptInt - ptCurr).Len() ;
if ( dDiff < dMinDiff) {
dMinDiff = dDiff ;
ptBest = ptInt ;
}
}
if ( dMinDiff < dLinAngTol)
bFound = true ;
}
}
if ( ! bFound) {
// applico la direzione desiderata nel punto corrente della guida
// calcolo la lunghezza dell'isocurva in quella zona
Point3d ptS1, ptS2 ;
pGuide->GetStartPoint( ptS1) ;
pOtherGuide->GetStartPoint( ptS2);
double dDistRef = Dist( ptS1, ptS2) ;
double dParamOther = -1. ;
int nFlag = -1 ;
Point3d ptEnd = ptCurr + (vtAux * dDistRef) ;
if ( ! DistPointCurve( ptEnd, *pOtherGuide).GetParamAtMinDistPoint( 0, dParamOther, nFlag))
return false ;
// nell'intorno del più vicino, cerco l'isocurva più vicina alla direzione desiderata
Point3d ptBest ;
double dMinDiff = INFINITO ;
double dSearchLen = 3. ;
double dStepLen = 0.1 ;
double dCurrLenOther ; pOtherGuide->GetLengthAtParam( dParamOther, dCurrLenOther) ;
double dLenOther ; pOtherGuide->GetLength( dLenOther) ;
dCurrLenOther -= dSearchLen ;
dCurrLenOther = Clamp( dCurrLenOther, 0., dLenOther) ;
for ( int j = 0 ; j < 2 * dSearchLen / dStepLen ; ++j) {
dCurrLenOther += j * dStepLen ;
if ( dCurrLenOther > dLenOther)
break ;
double dCurrParOther = 0 ; pOtherGuide->GetParamAtLength( dCurrLenOther, dCurrParOther) ;
Point3d ptCurrOther ; pOtherGuide->GetPointD1D2( dCurrParOther, ICurve::FROM_MINUS, ptCurrOther) ;
Vector3d vtDir = ptCurrOther - ptCurr ; vtDir.Normalize() ;
double dDiff = ( vtDir - vtAux).Len() ;
if ( dDiff < dMinDiff) {
dMinDiff = dDiff ;
ptBest = ptCurrOther ;
}
#if DEBUG_SYNC_INTERPOLATION
VT.clear() ;
VC.clear() ;
VT.emplace_back( pGuide->Clone()) ;
VC.emplace_back( BLUE) ;
VT.emplace_back( pOtherGuide->Clone()) ;
VC.emplace_back( BLUE) ;
PtrOwner<IGeoVector3d> vtFirst( CreateGeoVector3d()) ; vtFirst->Set( -vtN * 12, ptCurrOther) ;
VT.emplace_back( Release( vtFirst)) ;
VC.emplace_back( AQUA) ;
PtrOwner<IGeoVector3d> vtCurr( CreateGeoVector3d()) ; vtCurr->Set( -vtDir * 12, ptCurrOther) ;
VT.emplace_back( Release( vtCurr)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
#endif
}
if ( dMinDiff < 2 * dLinAngTol)
vBiPts.emplace_back( make_pair( ptCurr, ptBest)) ;
}
} }
return true ; return true ;
@@ -3838,8 +3979,8 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
! pCompoEdge1->IsValid() || ! pCompoEdge2->IsValid()) ! pCompoEdge1->IsValid() || ! pCompoEdge2->IsValid())
return false ; return false ;
// Controllo sulla tolleranza lineare //// Controllo sulla tolleranza lineare
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; //double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
#if DEBUG_SYNC_POINTS #if DEBUG_SYNC_POINTS
VT.clear() ; VC.clear() ; VT.clear() ; VC.clear() ;
@@ -3850,26 +3991,26 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
#endif #endif
// Definisco la superficie di Bezier rigata // Definisco la superficie di Bezier rigata
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuled( pCompoEdge1, pCompoEdge2, ISurfBezier::RLT_B_MINDIST_PLUS, dMyLinTol))) ; PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncPoints, 20.0))) ;
if ( IsNull( pSBzRuled) || ! pSBzRuled->IsValid()) if ( IsNull( pSBzRuled) || ! pSBzRuled->IsValid())
return false ; return false ;
// Recupero i punti di sincronizzazione e li restituisco //// Recupero i punti di sincronizzazione e li restituisco
ICURVEPOVECTOR vCrv ; // ICURVEPOVECTOR vCrv ;
pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ; // pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
vSyncPoints.reserve( vCrv.size()) ; // vSyncPoints.reserve( vCrv.size()) ;
for ( int i = 0 ; i < ssize( vCrv) ; ++ i) { // for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) { // if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
#if DEBUG_SYNC_POINTS // #if DEBUG_SYNC_POINTS
VT.emplace_back( vCrv[i]->Clone()) ; // VT.emplace_back( vCrv[i]->Clone()) ;
VC.emplace_back( LIME) ; // VC.emplace_back( LIME) ;
#endif // #endif
Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ; // Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ; // Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
if ( ! AreSamePointApprox( ptStart, ptEnd)) // if ( ! AreSamePointApprox( ptStart, ptEnd))
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; // vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
} // }
} // }
#if DEBUG_SYNC_POINTS #if DEBUG_SYNC_POINTS
SaveGeoObj( VT, VC, "C:\\Temp\\BorderSyncPoints.nge") ; SaveGeoObj( VT, VC, "C:\\Temp\\BorderSyncPoints.nge") ;
@@ -3900,7 +4041,7 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
// Verifico i valori delle tolleranze // Verifico i valori delle tolleranze
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ; //double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ;
// Verifico le due curve di sincronizzazione abbiano gli estremi sulle due curve di bordo // Verifico le due curve di sincronizzazione abbiano gli estremi sulle due curve di bordo
Point3d ptS1 ; pSync1->GetStartPoint( ptS1) ; Point3d ptS1 ; pSync1->GetStartPoint( ptS1) ;
@@ -4008,18 +4149,18 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
Vector3d vtStart1, vtStart2 ; Vector3d vtStart1, vtStart2 ;
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2)) if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
return false ; return false ;
Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ; Vector3d vtAuxStart = ptE1 - ptS1 ; vtAuxStart.Normalize() ;
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ; Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ; Vector3d vtN = OrthoCompo( vtMTan, vtAuxStart) ; vtN.Normalize() ;
Plane3d plStart ; Plane3d plStart ;
if ( ! plStart.Set( ptS1, vtN)) if ( ! plStart.Set( ptS1, vtN))
return false ; return false ;
Vector3d vtEnd1, vtEnd2 ; Vector3d vtEnd1, vtEnd2 ;
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2)) if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
return false ; return false ;
vtAux = ptE2 - ptS2 ; vtAux.Normalize() ; Vector3d vtAuxEnd = ptE2 - ptS2 ; vtAuxEnd.Normalize() ;
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ; vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ; vtN = OrthoCompo( vtMTan, vtAuxEnd) ; vtN.Normalize() ;
Plane3d plEnd ; Plane3d plEnd ;
if ( ! plEnd.Set( ptS2, vtN)) if ( ! plEnd.Set( ptS2, vtN))
return false ; return false ;
@@ -4038,13 +4179,15 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2 // Curve di Sincronizzazione del Bordo 1 sul Bordo 2
BIPNTVECTOR vBiPts1 ; BIPNTVECTOR vBiPts1 ;
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1)) if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts1))
return false ; return false ;
vtAuxStart *= -1 ;
vtAuxEnd *= -1 ;
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1 // Curve di Sincronizzazione del Bordo 2 sul Bordo 1
BIPNTVECTOR vBiPts2 ; BIPNTVECTOR vBiPts2 ;
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2)) //if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts2))
return false ; // return false ;
// Restituisco le Curve di Sincronizzazione // Restituisco le Curve di Sincronizzazione
// [Da Bordo 1 a Bordo 2 originale] // [Da Bordo 1 a Bordo 2 originale]
@@ -4110,7 +4253,8 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
// Se non ho punti di controllo forzati // Se non ho punti di controllo forzati
if ( vSyncPoints.empty()) { if ( vSyncPoints.empty()) {
pSurfBz.Set( GetSurfBezierRuled( pCompoEdge1, pCompoEdge2, ISurfBezier::RLT_B_MINDIST_PLUS, dMyLinTol)) ; BIPNTVECTOR vSyncLines ;
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncLines, 20.0)) ;
if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) { if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) {
LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ; LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ;
return nullptr ; return nullptr ;
@@ -4746,7 +4890,7 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl
// Scorro le curve successive // Scorro le curve successive
for ( int j = i + 1 ; nIndJ == -1 && j < ssize( vHoles) ; ++ j) { for ( int j = i + 1 ; nIndJ == -1 && j < ssize( vHoles) ; ++ j) {
// Recupero la curva corrente, se non presente allora passo alla successiva // Recupero la curva corrente, se non presente allora passo alla successiva
if ( IsNull( vHoles[i].pCompoHole)) if ( IsNull( vHoles[j].pCompoHole))
continue ; continue ;
// Se il tipo è differente non possono essere in coppia // Se il tipo è differente non possono essere in coppia
if ( vHoles[i].nType != vHoles[j].nType) if ( vHoles[i].nType != vHoles[j].nType)
@@ -4841,3 +4985,499 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl
return true ; return true ;
} }
struct PntInfo{
Point3d pt ;
double dDist ;
Vector3d vtPos ;
PntInfo( const Point3d& _pt, double _dDist, const Vector3d& _vtPos) :
pt( _pt), dDist( _dDist), vtPos( _vtPos) {;}
};
typedef vector<PntInfo> PNTINFOVECTOR ;
//------------------------------------------------------------------------------
static bool
FillPntInfo( const PNTVECTOR& vPnt, const ICurveComposite* pCC, PNTINFOVECTOR& vPntInfo)
{
for ( int i = 0 ; i < ssize( vPnt) - 3 ; i+=3) {
bool bOk = false ;
const ICurveBezier* pSubCrv = GetCurveBezier( pCC->GetCurve( i / 3)) ;
for ( int j = i == 0 ? 0 : 1 ; j <= 3 ; ++j) {
Point3d pt = pSubCrv->GetControlPoint( j, &bOk) ;
double dDist = 0 ;
Vector3d vtPos = V_NULL ;
if ( j > 0 && j < 3){
DistPointCurve dpc( pt, *pSubCrv) ;
dpc.GetDist( dDist) ;
int nFlag = - 1 ;
Point3d ptMinDist ;
dpc.GetMinDistPoint( 0., ptMinDist, nFlag) ;
vtPos = pt - ptMinDist ;
}
vPntInfo.emplace_back( pt, dDist, vtPos) ;
}
}
return true ;
}
//------------------------------------------------------------------------------
static bool
RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& vPntRefInfo)
{
// se trovo tre punti di fila che sono dallo stesso lato, opposto a quello degli altri punti attorno, allora cerco di spostarli lungo la
// normale alla superficie in modo da evitare cambi di concavità
bool bSameSideAsPrev = true ;
double dSmallDist = 5 * EPS_SMALL ;
for ( int i = 2 ; i < ssize( vPntInfo) - 2 ; ++i) {
// se è un punto di split o sta sulla curva vado avanti
if ( vPntInfo[i].dDist < dSmallDist)
continue ;
int nPrev = vPntInfo[i-1].dDist < EPS_ZERO ? i - 2 : i - 1 ;
double dProj = vPntInfo[i].vtPos * vPntInfo[nPrev].vtPos ;
bSameSideAsPrev = dProj > EPS_ZERO ;
if ( abs(dProj) < EPS_ZERO){
int nPrevPrev = nPrev - 1 ;
dProj = vPntInfo[i].vtPos * vPntInfo[nPrevPrev].vtPos ;
bSameSideAsPrev = dProj > EPS_ZERO ;
}
if ( ! bSameSideAsPrev) {
// devo verificare anche che sia diverso anche dal successivo ( o dal quello dopo ancora, se il successivo sta sulla curva)
bool bCurrOrPrev = vPntInfo[i+1].dDist < EPS_ZERO ;
int nFirst, nSecond, nThird ;
if ( bCurrOrPrev) {
nFirst = i ;
nSecond = i + 1 ;
nThird = i + 2 ;
}
else {
nFirst = i - 2 ;
nSecond = i - 1 ;
nThird = i ;
}
int nNext = bCurrOrPrev ? i + 2 : i + 1 ;
// se il successivo è diverso ho un terzetto anomalo da aggiustare
// altrimenti ho un cambio naturale di concavità
if ( vPntInfo[i].vtPos * vPntInfo[nNext].vtPos < 0 || vPntInfo[nNext].dDist < dSmallDist) {
// ruoto il terzetto fino a matchare la tangente sull'altra curva
// ruoto il punto solo se non stava già esattamente sulla SubCrv ( che suppongo essere un tratto rettilineo)
if ( vPntInfo[nFirst].dDist > dSmallDist) {
Vector3d vtCurr = vPntInfo[nSecond].pt - vPntInfo[nFirst].pt ;
Vector3d vtRef = vPntRefInfo[nSecond].pt - vPntRefInfo[nFirst].pt ;
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
bool bDet = false ;
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
if ( abs(dAng) > 170)
dAng = 180 - dAng ;
vPnt[nFirst].Rotate( vPnt[nSecond], vtAx, dAng) ;
}
if ( vPntInfo[nThird].dDist > dSmallDist) {
Vector3d vtCurr = vPntInfo[nThird].pt - vPntInfo[nSecond].pt ;
Vector3d vtRef = vPntRefInfo[nThird].pt - vPntRefInfo[nSecond].pt ;
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
bool bDet = false ;
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
if ( abs(dAng) > 170)
dAng = 180 - dAng ;
vPnt[nThird].Rotate( vPnt[nSecond], vtAx, dAng) ;
}
if ( bCurrOrPrev)
i += 2 ;
}
}
}
return true ;
}
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
// Le curve vengono modificate entro una data tolleranza, in modo che
ISurfBezier*
RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol)
{
#if DEBUG_SMOOTH_CURVATURE
VT.clear() ;
#endif
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
Point3d ptS1 = bpIsoStart.first ;
Point3d ptS2 = bpIsoEnd.first ;
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
if ( nDegU != 3)
return nullptr ;
// individuo quali isocurve sono state indicate come inizio e fine
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
pCrv2->Invert() ;
double dParS1 = -1 ; double dParS2 = -1 ;
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
return nullptr ;
int nUS1 = int ( dParS1) * nDegU ;
int nUS2 = int ( dParS2) * nDegU ;
if ( nUS1 > nUS2) {
swap( nUS1, nUS2) ;
swap( dParS1, dParS2) ;
swap( ptS1, ptS2) ;
swap( vtDir1, vtDir2) ;
}
PtrOwner<ICurveComposite> pCrvOrig1( ConvertCurveToComposite( pCrv1->CopyParamRange( dParS1, dParS2))) ;
PtrOwner<ICurveComposite> pCrvOrig2( ConvertCurveToComposite( pCrv2->CopyParamRange( dParS1, dParS2))) ;
/////////////////////// versione con RMF
// campiono finemente la prima curva e ottengo il punto che dovrebbe stare sull'altra curva
Vector3d vtTang1 ; pCrvOrig1->GetStartDir( vtTang1) ;
Frame3d frStart1 ; frStart1.Set( ptS1, vtTang1, vtDir1) ; // uso la tangente (come z) e l'isocurva in V (come x) per il frame iniziale
RotationMinimizingFrame rmf ; rmf.Set( pCrvOrig1, frStart1) ;
double dLenTot = 0. ; pCrvOrig1->GetLength( dLenTot) ;
double dStep = dLenTot / ceil( dLenTot) ;
FRAME3DVECTOR vRMF ;
rmf.GetFramesByStep( dStep, true, vRMF) ;
PNTVECTOR vPnt1 ;
PolyLine PL2 ;
double dLenCurr = 0. ;
double dWidth = vtDir1.Len() ;
for ( int i = 0 ; i < ssize( vRMF) ; ++i) {
double dPar ; pCrvOrig1->GetParamAtLength( dLenCurr, dPar) ;
Point3d pt0 ; pCrvOrig1->GetPointD1D2( dPar, ICurve::FROM_MINUS, pt0) ;
Point3d pt1 = pt0 + vRMF[i].VersX() * dWidth ;
vPnt1.push_back( pt1) ;
PL2.AddUPoint( i, pt1) ;
dLenCurr += dStep ;
}
CurveComposite CCToApprox2 ; CCToApprox2.FromPolyLine( PL2) ;
Vector3d vtStart2 ; pCrvOrig2->GetStartDir( vtStart2) ;
Vector3d vtEnd2 ; pCrvOrig2->GetEndDir( vtEnd2) ;
PtrOwner<ICurveComposite> pCC2( ConvertCurveToComposite( ApproxCurveWithBezier( &CCToApprox2, 0.05, vtStart2, vtEnd2))) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// dalla seconda ricostruisco la prima
Vector3d vtTang2 ; pCC2->GetStartDir( vtTang2) ;
Frame3d frStart2 ; frStart2.Set( bpIsoStart.second, vtTang2, vtDir1) ; // uso la tangente (come z) e l'isocurva in V (come x) per il frame iniziale
RotationMinimizingFrame rmf2 ; rmf2.Set( pCC2, frStart2) ;
double dLenTot2 = 0. ; pCC2->GetLength( dLenTot2) ;
double dStep2 = dLenTot2 / ceil( dLenTot2) ;
FRAME3DVECTOR vRMF2 ;
rmf2.GetFramesByStep( dStep2, true, vRMF2) ;
PNTVECTOR vPnt0 ;
PolyLine PL1 ;
double dLenCurr2 = 0. ;
for ( int i = 0 ; i < ssize( vRMF2) ; ++i) {
double dPar ; pCC2->GetParamAtLength( dLenCurr2, dPar) ;
Point3d pt1 ; pCC2->GetPointD1D2( dPar, ICurve::FROM_MINUS, pt1) ;
Point3d pt0 = pt1 - vRMF2[i].VersX() * dWidth ;
vPnt0.push_back( pt0) ;
PL1.AddUPoint( i, pt0) ;
dLenCurr2 += dStep2 ;
}
CurveComposite CCToApprox1 ; CCToApprox1.FromPolyLine( PL1) ;
Vector3d vtStart1 ; pCrvOrig1->GetStartDir( vtStart1) ;
Vector3d vtEnd1 ; pCrvOrig1->GetEndDir( vtEnd1) ;
PtrOwner<ICurveComposite> pCC1( ConvertCurveToComposite( ApproxCurveWithBezier( &CCToApprox1, 0.05, vtStart1, vtEnd1))) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
#if DEBUG_SMOOTH_CURVATURE
for( int i = 0 ; i < ssize( vPnt1) ; ++i) {
PtrOwner<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ;
VT.push_back( Release( pPT)) ;
}
for( int i = 0 ; i < ssize( vPnt0) ; ++i) {
PtrOwner<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt0[i]) ;
VT.push_back( Release( pPT)) ;
}
VT.push_back( pCC1->Clone()) ;
VT.push_back( pCC2->Clone()) ;
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_RMF.nge") ;
#endif
// controllo di essere rimasto in tolleranza
double dErr = 0 ;
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
if ( dErr > dTol)
return nullptr ;
dErr = 0 ;
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
if ( dErr > dTol)
return nullptr ;
// creo una surf di bezier uguale a quella di partenza, ma a cui cambio la parte da modificare
PtrOwner<SurfBezier> pNewSurf( CreateBasicSurfBezier()) ;
int nNewCrvs = pCC1->GetCurveCount() ;
if ( pCC2->GetCurveCount() != nNewCrvs)
return nullptr ;
int nDiff = nNewCrvs - pCrvOrig1->GetCurveCount() ;
pNewSurf->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
// copio la parte uguale
for ( int i = 0 ; i < nSpanU * nDegU + 1 ; ++i) {
if ( i > nUS1 && i < nUS2)
continue ;
bool bOk = false ;
Point3d pt = pSurfBz->GetControlPoint( i, 0, &bOk) ;
int nNewI = i ;
if ( i > nUS2)
nNewI = i + nDiff ;
pNewSurf->SetControlPoint( nNewI, 0, pt) ;
pt = pSurfBz->GetControlPoint( i, 1, &bOk) ;
pNewSurf->SetControlPoint( nNewI, 1, pt) ;
}
// aggiungo la parte diversa
for ( int i = 0 ; i < nNewCrvs * nDegU + 1 ; ++i) {
int nSub = i / 3 ;
int nPnt = i % 3 ;
if ( nSub == nNewCrvs) {
--nSub ;
nPnt = 3 ;
}
const ICurveBezier* pSubCrv1 = GetCurveBezier( pCC1->GetCurve( nSub)) ;
Point3d pt = pSubCrv1->GetControlPoint( nPnt) ;
int nNewI = i + nUS1 ;
pNewSurf->SetControlPoint( nNewI, 0, pt) ;
const ICurveBezier* pSubCrv2 = GetCurveBezier( pCC2->GetCurve( nSub)) ;
pt = pSubCrv2->GetControlPoint( nPnt) ;
pNewSurf->SetControlPoint( nNewI, 1, pt) ;
}
return Release( pNewSurf) ;
}
//------------------------------------------------------------------------------
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
// Le curve vengono modificate entro una data tolleranza, in modo che
ISurfBezier*
RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol, int nType)
{
if ( nType == RegolarizeType::RMF)
return RegolarizeBordersLocallyRMF( pSurfBz, bpIsoStart, bpIsoEnd, dTol) ;
#if DEBUG_SMOOTH_CURVATURE
VT.clear() ;
#endif
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
Point3d ptS1 = bpIsoStart.first ;
Point3d ptS2 = bpIsoEnd.first ;
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
//double dInterpolateAngTol = 4 ;
//double dAngInterp = 0 ;
//vtDir1.GetAngle( vtDir2, dAngInterp) ;
//bool bInterpolate = dAngInterp > dInterpolateAngTol ;
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
if ( nDegU != 3)
return nullptr ;
// individuo quali isocurve sono state indicate come inizio e fine
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
pCrv2->Invert() ;
double dParS1 = -1 ; double dParS2 = -1 ;
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
return nullptr ;
int nUS1 = int ( dParS1) * nDegU ;
int nUS2 = int ( dParS2) * nDegU ;
bool bInverted = false ;
if ( nUS1 > nUS2) {
swap( nUS1, nUS2) ;
swap( dParS1, dParS2) ;
swap( ptS1, ptS2) ;
swap( vtDir1, vtDir2) ;
bInverted = true ;
}
PtrOwner<ICurve> pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ;
PtrOwner<ICurve> pCrvOrig2( pCrv2->CopyParamRange( dParS1, dParS2)) ;
double dLen = 0 ; pCrvOrig1->GetLength( dLen) ;
///// versione con correzioni a mano
Point3d ptPrevS = ptS1 ;
Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ;
Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ;
Point3d ptBez ; Vector3d vtNCurr ;
pSurfBz->GetPointNrmD1D2( dParS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNCurr) ;
int nPoints = ( nUS2 - nUS1) * nDegU + 1 ;
PNTVECTOR vPnt0 ; vPnt0.reserve( nPoints) ; vPnt0.push_back( ptPrevS) ;
PNTVECTOR vPnt1 ; vPnt1.reserve( nPoints) ; vPnt1.push_back( ptPrevE) ;
// salvo il secondo punto di controllo della patch
bool bOk = false ;
Point3d ptSecond1Curr = pSurfBz->GetControlPoint( nUS1 + 1, 0, &bOk) ;
vPnt0.push_back( ptSecond1Curr) ;
Point3d ptSecond2Curr = pSurfBz->GetControlPoint( nUS1 + 1, 1, &bOk) ;
vPnt1.push_back( ptSecond2Curr) ;
// scorro le isocurve di separazione tra patch
for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) {
// recupero precedente e successivo
Point3d ptThird1Prev = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ;
Point3d ptThird2Prev = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ;
Point3d ptSecond1Next = pSurfBz->GetControlPoint( i + 1, 0, &bOk) ;
Point3d ptSecond2Next = pSurfBz->GetControlPoint( i + 1, 1, &bOk) ;
// recupero corrente e verifico la torsione
Point3d ptCurr1 = pSurfBz->GetControlPoint( i, 0, &bOk) ;
Point3d ptCurr2 = pSurfBz->GetControlPoint( i, 1, &bOk) ;
Vector3d vtIsoCurr = ptCurr2 - ptCurr1 ;
double dDist = vtIsoCurr.Len() ;
vtIsoCurr.Normalize() ;
//Vector3d vtDirPrev = vtIsoPrev ^ vtNPrev ;
Vector3d vtDirCurr = ptSecond1Next - ptCurr1 ; vtDirCurr.Normalize() ;
double dLenCurr = 0 ; pCrvOrig1->GetLengthAtParam( i, dLenCurr) ;
double dCoeff = dLenCurr / dLen ;
Vector3d vtIsoInterp = Media( vtDir1, vtDir2, dCoeff) ; vtIsoInterp.Normalize() ;
bool bDet = false ;
//double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoPrev, vtDirPrev, dAng, bDet) ;
double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoInterp, vtDirCurr, dAng, bDet) ;
vtNCurr = vtDirCurr ^ vtIsoCurr ; vtNCurr.Rotate( vtDirCurr, dAng) ;
double dSinAngTol = sin( 5 * DEGTORAD) ;
Vector3d vtPrev1 = ptCurr1 - ptThird1Prev ; vtPrev1.Normalize() ;
Vector3d vtNext1 = ptSecond1Next - ptCurr1 ; vtNext1.Normalize() ;
bool bAngularPoint1 = ! AreSameVectorEpsilon( vtPrev1, vtNext1, dSinAngTol) ;
Vector3d vtPrev2 = ptCurr2 - ptThird2Prev ; vtPrev2.Normalize() ;
Vector3d vtNext2 = ptSecond2Next - ptCurr2 ; vtNext2.Normalize() ;
bool bAngularPoint2 = ! AreSameVectorEpsilon( vtPrev2, vtNext2, dSinAngTol) ;
if ( abs( dAng) > 0) {
// se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente
// allora prendo il penultimo punto della curva precedente, il punto di joint e il secondo della prossima e li sposto lungo la normale della superficie
dDist *= dAng * DEGTORAD / 2 ;
if ( ! bAngularPoint1) {
// se non ho un punto angoloso muovo tutto il terzetto insieme
ptThird1Prev -= vtNCurr * dDist ;
ptSecond1Next -= vtNCurr * dDist ;
ptCurr1 -= vtNCurr * dDist ;
}
else {
// altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo
DistPointLine dpl( ptCurr1, ptThird1Prev, ptSecond1Next, true) ;
Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ;
Vector3d vtCorrDir = ptMinDist - ptCurr1 ; vtCorrDir.Normalize() ;
double dProjDir = vtNCurr * vtCorrDir ;
if ( dProjDir < 0)
LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv0 near an angular point") ;
double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr1)) ;
ptCurr1 -= vtCorrDir * dDistCorr ;
}
if ( ! bAngularPoint2) {
ptThird2Prev += vtNCurr * dDist ;
ptSecond2Next += vtNCurr * dDist ;
ptCurr2 += vtNCurr * dDist ;
}
else {
// altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo
DistPointLine dpl( ptCurr2, ptThird2Prev, ptSecond2Next, true) ;
Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ;
Vector3d vtCorrDir = ptMinDist - ptCurr2 ; vtCorrDir.Normalize() ;
double dProjDir = vtNCurr * vtCorrDir ;
if ( dProjDir < 0)
LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv1 near an angular point") ;
double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr2)) ;
ptCurr2 += vtCorrDir * dDistCorr ;
}
}
vPnt0.push_back( ptThird1Prev) ;
vPnt0.push_back( ptCurr1) ;
vPnt0.push_back( ptSecond1Next) ;
vPnt1.push_back( ptThird2Prev) ;
vPnt1.push_back( ptCurr2) ;
vPnt1.push_back( ptSecond2Next) ;
//vtIsoPrev = ptCurr2 - ptCurr1 ; vtIsoPrev.Normalize() ;
//vtNPrev = ( ptSecond1Next - ptCurr1) ^ vtIsoPrev ; vtNPrev.Normalize() ;
}
// aggiungo gli ultimi due punti
Point3d ptThird1Prev = pSurfBz->GetControlPoint( nUS2 - 1, 0, &bOk) ;
vPnt0.push_back( ptThird1Prev) ;
Point3d ptFourth1Curr = pSurfBz->GetControlPoint( nUS2, 0, &bOk) ;
vPnt0.push_back( ptFourth1Curr) ;
Point3d ptThird2Prev = pSurfBz->GetControlPoint( nUS2 - 1, 1, &bOk) ;
vPnt1.push_back( ptThird2Prev) ;
Point3d ptFourth2Curr = pSurfBz->GetControlPoint( nUS2, 1, &bOk) ;
vPnt1.push_back( ptFourth2Curr) ;
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
cb1->SetControlPoint( 0, vPnt0[i]) ;
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
pCC1->AddCurve( Release( cb1)) ;
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
cb2->SetControlPoint( 0, vPnt1[i]) ;
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
pCC2->AddCurve( Release( cb2)) ;
}
////// N.B.:dovrei tener conto anche della patch PRECEDENTE e SUCCESSIVA a quelle indicate, altrimenti non vedo se ho creato flessi al bordo della zona
#if DEBUG_SMOOTH_CURVATURE
VT.push_back( pCC1->Clone()) ;
VT.push_back( pCC2->Clone()) ;
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_first_step.nge") ;
#endif
// ora verifico l'eventuale presenza di cambi di concavità non desiderati
// se ne trovo su una curva e non sull'altra allora ruoto il terzetto di punti della curva con flesso in modo
// da matchare la tangente dell'altra curva
PNTINFOVECTOR vPntInfo1, vPntInfo2 ;
FillPntInfo( vPnt0, pCC1, vPntInfo1) ;
FillPntInfo( vPnt1, pCC2, vPntInfo2) ;
RemoveInflexionPoints( vPnt0, vPntInfo1, vPntInfo2) ;
RemoveInflexionPoints( vPnt1, vPntInfo2, vPntInfo1) ;
pCC1->Clear() ;
pCC2->Clear() ;
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
cb1->SetControlPoint( 0, vPnt0[i]) ;
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
pCC1->AddCurve( Release( cb1)) ;
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
cb2->SetControlPoint( 0, vPnt1[i]) ;
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
pCC2->AddCurve( Release( cb2)) ;
}
// controllo di essere rimasto in tolleranza
double dErr = 0 ;
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
if ( dErr > dTol)
return nullptr ;
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
if ( dErr > dTol)
return nullptr ;
PtrOwner<ISurfBezier> pNewSurf( pSurfBz->Clone()) ;
// aggiorno i punti di controllo della superficie di bezier
for ( int i = 0 ; i < ssize( vPnt0) ; ++i) {
pNewSurf->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ;
pNewSurf->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ;
}
#if DEBUG_SMOOTH_CURVATURE
VT.clear() ;
VT.push_back( Release(pCC1)) ;
VT.push_back( Release(pCC2)) ;
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ;
#endif
return Release( pNewSurf) ;
}
+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)
+20 -7
View File
@@ -81,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 ;
@@ -151,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
@@ -226,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) ;
@@ -262,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
@@ -382,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,
@@ -486,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 {
-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 ;
+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) ;
} }
} }
} }
+427 -100
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,6 +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 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 ;
@@ -1617,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
@@ -1669,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() })) ;
@@ -1748,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()) ;
} }
} }
@@ -1793,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());
@@ -1838,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)) {
@@ -1925,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]) ;
@@ -1936,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] ;
@@ -1984,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 ;
@@ -5928,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) ;
} }
} }
@@ -5973,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) ;
} }
@@ -6153,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) ;
} }
@@ -6161,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) ;
} }
@@ -6748,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) ;
} }
} }
@@ -6896,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,
@@ -7300,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 ;