b311480e |
1 | // Created on: 1993-11-19 |
2 | // Created by: Yves FRICAUD |
3 | // Copyright (c) 1993-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
5201d3e6 |
17 | #include <Adaptor2d_OffsetCurve.hxx> |
7fd59977 |
18 | #include <Geom2d_CartesianPoint.hxx> |
42cf5bc1 |
19 | #include <Geom2d_Geometry.hxx> |
20 | #include <Geom2d_TrimmedCurve.hxx> |
21 | #include <Geom2dAdaptor_HCurve.hxx> |
22 | #include <Geom2dInt_GInter.hxx> |
23 | #include <IntRes2d_IntersectionPoint.hxx> |
7fd59977 |
24 | #include <MAT2d_BiInt.hxx> |
42cf5bc1 |
25 | #include <MAT2d_Circuit.hxx> |
7fd59977 |
26 | #include <MAT2d_Connexion.hxx> |
42cf5bc1 |
27 | #include <MAT2d_DataMapIteratorOfDataMapOfBiIntSequenceOfInteger.hxx> |
28 | #include <MAT2d_DataMapOfBiIntSequenceOfInteger.hxx> |
29 | #include <MAT2d_DataMapOfIntegerConnexion.hxx> |
30 | #include <MAT2d_MiniPath.hxx> |
7fd59977 |
31 | #include <MAT2d_SequenceOfConnexion.hxx> |
7fd59977 |
32 | #include <MAT2d_SequenceOfSequenceOfGeometry.hxx> |
7fd59977 |
33 | #include <Precision.hxx> |
42cf5bc1 |
34 | #include <Standard_Type.hxx> |
35 | #include <TColStd_Array1OfBoolean.hxx> |
36 | #include <TColStd_Array1OfInteger.hxx> |
37 | #include <TColStd_SequenceOfInteger.hxx> |
7fd59977 |
38 | |
25e59720 |
39 | IMPLEMENT_STANDARD_RTTIEXT(MAT2d_Circuit,Standard_Transient) |
f5f4ebd0 |
40 | |
41 | #ifdef OCCT_DEBUG |
42 | #include <GCE2d_MakeSegment.hxx> |
43 | #include <Geom2d_Curve.hxx> |
44 | #include <Geom2d_Parabola.hxx> |
45 | #include <Geom2d_Hyperbola.hxx> |
46 | #include <Geom2d_TrimmedCurve.hxx> |
47 | #include <Geom2d_CartesianPoint.hxx> |
48 | #include <Geom2d_Line.hxx> |
49 | #include <Geom2d_Circle.hxx> |
50 | #endif |
51 | |
7fd59977 |
52 | #ifdef DRAW |
f5f4ebd0 |
53 | #include <Draw_Appli.hxx> |
54 | #include <DrawTrSurf_Curve2d.hxx> |
55 | #include <Draw_Marker2D.hxx> |
7fd59977 |
56 | static Handle(DrawTrSurf_Curve2d) draw; |
57 | Standard_EXPORT Draw_Viewer dout; |
58 | #endif |
0797d9d3 |
59 | #ifdef OCCT_DEBUG |
7fd59977 |
60 | static void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve, |
61 | const Standard_Integer Indice); |
62 | static Standard_Boolean AffichCircuit = 0; |
63 | #endif |
64 | |
65 | // static functions: |
66 | |
67 | static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1, |
68 | const Handle(Geom2d_Geometry)& Geom2, |
69 | Standard_Real& DotProd); |
70 | |
7fd59977 |
71 | |
72 | //============================================================================= |
73 | //function : Constructor |
74 | //purpose : |
75 | //============================================================================= |
c19dd45e |
76 | MAT2d_Circuit::MAT2d_Circuit(const GeomAbs_JoinType aJoinType, |
77 | const Standard_Boolean IsOpenResult) |
7fd59977 |
78 | { |
c19dd45e |
79 | myJoinType = aJoinType; |
6a442250 |
80 | myIsOpenResult = IsOpenResult; |
7fd59977 |
81 | } |
82 | |
83 | //============================================================================= |
84 | //function : Perform |
85 | //purpose : |
86 | //============================================================================= |
87 | void MAT2d_Circuit::Perform |
88 | ( MAT2d_SequenceOfSequenceOfGeometry& FigItem, |
89 | const TColStd_SequenceOfBoolean & IsClosed, |
90 | const Standard_Integer IndRefLine, |
91 | const Standard_Boolean Trigo) |
92 | { |
93 | Standard_Integer NbLines = FigItem.Length(); |
94 | Standard_Integer i; |
95 | TColStd_Array1OfBoolean Open(1,NbLines); |
96 | MAT2d_SequenceOfConnexion SVide; |
97 | Handle(MAT2d_Connexion) ConnexionNul; |
98 | |
99 | if (Trigo) direction = 1.; else direction = -1.; |
100 | |
101 | //--------------------- |
102 | // Reinitialisation SD. |
103 | //--------------------- |
104 | geomElements.Clear(); |
105 | connexionMap.Clear(); |
106 | linkRefEqui.Clear(); |
107 | linesLength.Clear(); |
108 | |
109 | //---------------------------- |
110 | // Detection Lignes ouvertes. |
111 | //---------------------------- |
112 | for ( i = 1; i <= NbLines; i++) { |
857ffd5e |
113 | Handle(Geom2d_TrimmedCurve) Curve; |
7fd59977 |
114 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(FigItem.Value(i).First()); |
115 | gp_Pnt2d P1 = Curve->StartPoint(); |
116 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(FigItem.Value(i).Last()); |
117 | gp_Pnt2d P2 = Curve->EndPoint(); |
118 | // Modified by Sergey KHROMOV - Wed Mar 6 16:59:01 2002 Begin |
119 | // if ( P1.IsEqual(P2,Precision::Confusion())) Open(i) = Standard_False; |
120 | // else Open(i) = Standard_True; |
121 | if (IsClosed(i)) Open(i) = Standard_False; |
122 | else if (P1.IsEqual(P2,Precision::Confusion())) Open(i) = Standard_False; |
123 | else Open(i) = Standard_True; |
124 | // Modified by Sergey KHROMOV - Wed Mar 6 16:59:04 2002 End |
125 | } |
126 | |
127 | //--------------------------------------------------------------- |
128 | // Insertion des cassures saillantes ou |
129 | // ajout des extremites de chaque courbe si la ligne est ouverte. |
130 | //--------------------------------------------------------------- |
131 | for ( i = 1; i <= NbLines; i++) { |
132 | if (Open(i)) { |
133 | InitOpen(FigItem.ChangeValue(i)); |
134 | linesLength.Append(FigItem.Value(i).Length()); |
135 | } |
136 | else { |
137 | InsertCorner(FigItem.ChangeValue(i)); |
138 | linesLength.Append(FigItem.Value(i).Length()); |
139 | } |
140 | } |
141 | |
142 | //--------------------------------- |
143 | // Une seule ligne => Rien a faire. |
144 | //--------------------------------- |
145 | if (NbLines == 1) { |
146 | if (Open(1)) { |
147 | DoubleLine(FigItem.ChangeValue(1),SVide,ConnexionNul,direction); |
148 | linesLength.SetValue(1,FigItem.Value(1).Length()); |
149 | } |
150 | geomElements = FigItem.Value(1); |
151 | UpDateLink(1,1,1,geomElements.Length()); |
152 | linesLength.Append(FigItem.Value(1).Length()); |
153 | return; |
154 | } |
155 | |
156 | //------------------ |
157 | // Plusieurs lignes. |
158 | //------------------ |
159 | |
160 | //--------------------------------------------------------- |
161 | // Calcul de l ensemble des connexions realisant le chemin. |
162 | //--------------------------------------------------------- |
163 | MAT2d_MiniPath Road; |
164 | Road.Perform(FigItem,IndRefLine,Trigo); |
165 | |
166 | //------------------------ |
167 | // Fermeture ligne ouverte. |
168 | //------------------------- |
169 | for ( i = 1; i <= NbLines; i++) { |
170 | if (Open(i)) { |
171 | Handle(MAT2d_Connexion) CF; |
172 | if (Road.IsRoot(i)) CF = ConnexionNul; else CF = Road.Father(i); |
173 | if (Road.IsConnexionsFrom(i)) { |
174 | DoubleLine(FigItem.ChangeValue(i),Road.ConnexionsFrom(i), |
175 | CF,direction); |
176 | } |
177 | else { |
178 | DoubleLine(FigItem.ChangeValue(i),SVide,CF,direction); |
179 | } |
180 | linesLength.SetValue(i,FigItem.Value(i).Length()); |
181 | } |
182 | } |
183 | |
184 | //------------------------ |
185 | // Construction du chemin. |
186 | //------------------------ |
187 | Road.RunOnConnexions(); |
188 | |
0797d9d3 |
189 | #ifdef OCCT_DEBUG |
7fd59977 |
190 | if (AffichCircuit) { |
191 | Standard_Integer NbConnexions = Road.Path().Length(); |
192 | for (i = 1; i <= NbConnexions; i++) { |
193 | Handle(Geom2d_TrimmedCurve) edge; |
194 | edge = GCE2d_MakeSegment(Road.Path().Value(i)->PointOnFirst(), |
195 | Road.Path().Value(i)->PointOnSecond()); |
196 | MAT2d_DrawCurve(edge,2); |
197 | } |
198 | } |
199 | #endif |
200 | |
201 | //------------------------- |
202 | // Construction du Circuit. |
203 | //------------------------- |
204 | ConstructCircuit(FigItem,IndRefLine,Road); |
205 | } |
206 | |
c19dd45e |
207 | //======================================================================= |
208 | //function : IsSharpCorner |
209 | //purpose : Return True Si le point commun entre <Geom1> et <Geom2> est |
210 | // une cassure saillante par rapport <Direction> |
211 | //======================================================================= |
212 | |
213 | Standard_Boolean MAT2d_Circuit::IsSharpCorner(const Handle(Geom2d_Geometry)& Geom1, |
214 | const Handle(Geom2d_Geometry)& Geom2, |
215 | const Standard_Real Direction) const |
216 | { |
217 | Standard_Real DotProd; |
218 | Standard_Real ProVec = CrossProd (Geom1,Geom2,DotProd); |
219 | Standard_Integer NbTest = 1; |
220 | Standard_Real DU = Precision::Confusion(); |
221 | Handle(Geom2d_TrimmedCurve) C1,C2; |
222 | |
223 | C1= Handle(Geom2d_TrimmedCurve)::DownCast(Geom1); |
224 | C2= Handle(Geom2d_TrimmedCurve)::DownCast(Geom2); |
225 | // Modified by Sergey KHROMOV - Thu Oct 24 19:02:46 2002 Begin |
226 | // Add the same criterion as it is in MAT2d_Circuit::InitOpen(..) |
227 | // Standard_Real TolAng = 1.E-5; |
228 | Standard_Real TolAng = 1.E-8; |
229 | // Modified by Sergey KHROMOV - Thu Oct 24 19:02:47 2002 End |
230 | |
231 | if (myJoinType == GeomAbs_Arc) |
232 | { |
233 | while (NbTest <= 10) { |
234 | if ((ProVec)*Direction < -TolAng) |
235 | return Standard_True; // Saillant. |
236 | if ((ProVec)*Direction > TolAng) |
237 | return Standard_False; // Rentrant. |
238 | else { |
239 | if (DotProd > 0) { |
240 | return Standard_False; // Plat. |
241 | } |
242 | TolAng = 1.E-8; |
243 | Standard_Real U1 = C1->LastParameter() - NbTest*DU; |
244 | Standard_Real U2 = C2->FirstParameter() + NbTest*DU; |
245 | gp_Dir2d Dir1(C1->DN(U1,1)); |
246 | gp_Dir2d Dir2(C2->DN(U2,1)); |
247 | DotProd = Dir1.Dot(Dir2); |
248 | ProVec = Dir1^Dir2; |
249 | NbTest++; |
250 | } |
251 | } |
252 | |
253 | |
254 | |
255 | // Rebroussement. |
256 | // on calculde des paralleles aux deux courbes du cote du domaine |
257 | // de calcul |
258 | // Si pas dintersection => saillant. |
259 | // Sinon => rentrant. |
260 | Standard_Real D ; |
261 | Standard_Real Tol = Precision::Confusion(); |
262 | Standard_Real MilC1 = (C1->LastParameter() + C1->FirstParameter())*0.5; |
263 | Standard_Real MilC2 = (C2->LastParameter() + C2->FirstParameter())*0.5; |
264 | gp_Pnt2d P = C1->Value(C1->LastParameter()); |
265 | gp_Pnt2d P1 = C1->Value(MilC1); |
266 | gp_Pnt2d P2 = C2->Value(MilC2); |
267 | |
268 | D = Min(P1.Distance(P),P2.Distance(P)); |
269 | D /= 10; |
270 | |
271 | if (Direction > 0.) D = -D; |
272 | |
273 | Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C1); |
274 | Handle(Geom2dAdaptor_HCurve) HC2 = new Geom2dAdaptor_HCurve(C2); |
5201d3e6 |
275 | Adaptor2d_OffsetCurve OC1(HC1,D,MilC1,C1->LastParameter()); |
276 | Adaptor2d_OffsetCurve OC2(HC2,D,C2->FirstParameter(),MilC2); |
c19dd45e |
277 | Geom2dInt_GInter Intersect; |
278 | Intersect.Perform(OC1,OC2,Tol,Tol); |
279 | |
0797d9d3 |
280 | #ifdef OCCT_DEBUG |
c19dd45e |
281 | static Standard_Boolean Affich = 0; |
282 | if (Affich) { |
283 | #ifdef DRAW |
284 | Standard_Real DU1 = (OC1.LastParameter() - OC1.FirstParameter())/9.; |
285 | Standard_Real DU2 = (OC2.LastParameter() - OC2.FirstParameter())/9.; |
286 | for (Standard_Integer ki = 0; ki <= 9; ki++) { |
287 | gp_Pnt2d P1 = OC1.Value(OC1.FirstParameter()+ki*DU1); |
288 | gp_Pnt2d P2 = OC2.Value(OC2.FirstParameter()+ki*DU2); |
289 | Handle(Draw_Marker2D) dr1 = new Draw_Marker2D(P1,Draw_Plus,Draw_vert); |
290 | Handle(Draw_Marker2D) dr2 = new Draw_Marker2D(P2,Draw_Plus,Draw_rouge); |
291 | dout << dr1; |
292 | dout << dr2; |
293 | } |
294 | dout.Flush(); |
295 | #endif |
296 | } |
297 | #endif |
298 | |
299 | if (Intersect.IsDone() && !Intersect.IsEmpty()) { |
300 | return Standard_False; |
301 | } |
302 | else { |
303 | return Standard_True; |
304 | } |
305 | } //end of if (myJoinType == GeomAbs_Arc) |
306 | else if (myJoinType == GeomAbs_Intersection) |
307 | { |
308 | if (Abs(ProVec) <= TolAng && |
309 | DotProd < 0) |
310 | { |
311 | while (NbTest <= 10) |
312 | { |
313 | Standard_Real U1 = C1->LastParameter() - NbTest*DU; |
314 | Standard_Real U2 = C2->FirstParameter() + NbTest*DU; |
315 | gp_Dir2d Dir1(C1->DN(U1,1)); |
316 | gp_Dir2d Dir2(C2->DN(U2,1)); |
317 | DotProd = Dir1.Dot(Dir2); |
318 | ProVec = Dir1^Dir2; |
319 | if ((ProVec)*Direction < -TolAng) |
320 | return Standard_True; // Saillant. |
321 | if ((ProVec)*Direction > TolAng) |
322 | return Standard_False; // Rentrant. |
323 | |
324 | NbTest++; |
325 | } |
326 | return Standard_False; |
327 | } |
328 | else |
329 | return Standard_False; |
330 | } |
331 | return Standard_False; |
332 | } |
333 | |
7fd59977 |
334 | //======================================================================= |
335 | //function : SubSequence |
336 | //purpose : |
337 | //======================================================================= |
338 | static void SubSequence(const TColGeom2d_SequenceOfGeometry& S1, |
339 | Standard_Integer IF, |
340 | Standard_Integer IL, |
341 | TColGeom2d_SequenceOfGeometry& S2) |
342 | { |
343 | S2.Clear(); |
344 | for (Standard_Integer i = IF; i<= IL; i++){ |
345 | S2.Append(S1.Value(i)); |
346 | } |
347 | } |
348 | |
349 | |
350 | //============================================================================= |
351 | //function : ConstructCircuit |
352 | //purpose : |
353 | //============================================================================= |
354 | void MAT2d_Circuit::ConstructCircuit |
355 | (const MAT2d_SequenceOfSequenceOfGeometry& FigItem, |
356 | const Standard_Integer IndRefLine, |
357 | const MAT2d_MiniPath& Road) |
358 | { |
359 | Handle(MAT2d_Connexion) PrevC,CurC; |
360 | TColGeom2d_SequenceOfGeometry SetOfItem; |
361 | Standard_Integer NbConnexions; |
362 | Standard_Integer ILastItem; |
363 | Standard_Integer IndLast; |
364 | Standard_Integer i; |
365 | |
366 | NbConnexions = Road.Path().Length(); |
367 | //----------------------------------------------------- |
368 | // Depart du premier element de la ligne de reference. |
369 | //----------------------------------------------------- |
370 | PrevC = Road.Path().Value(1); |
371 | SubSequence(FigItem.Value(IndRefLine), |
372 | 1, |
373 | PrevC->IndexItemOnFirst(), |
374 | geomElements); |
375 | UpDateLink(1,IndRefLine,1,PrevC->IndexItemOnFirst()); |
376 | connexionMap.Bind(geomElements.Length()+1,PrevC); |
377 | ILastItem = geomElements.Length(); |
378 | |
379 | //----------------------------------------------------------------------- |
380 | // Ajout des portion de lignes delimites par deux connexions successives. |
381 | //----------------------------------------------------------------------- |
382 | for ( i = 2; i <= NbConnexions; i++) { |
383 | CurC = Road.Path().Value(i); |
384 | if (PassByLast(PrevC,CurC)) { |
385 | //------------------------------------------------------ |
386 | // La portion passe par le dernier element de la ligne. |
387 | // - ajout de la portion de PrevC au dernier element |
388 | // de la ligne. |
389 | // - Si la ligne contient plus d'un element ajout de la |
390 | // portion du premier element de la ligne a CurC. |
391 | //------------------------------------------------------ |
392 | IndLast = FigItem.Value(CurC->IndexFirstLine()).Length(); |
393 | SubSequence (FigItem.Value(CurC->IndexFirstLine()), |
394 | PrevC->IndexItemOnSecond(), |
395 | IndLast, |
396 | SetOfItem); |
397 | UpDateLink(ILastItem+1,CurC->IndexFirstLine(), |
398 | PrevC->IndexItemOnSecond(),IndLast); |
399 | geomElements.Append(SetOfItem); |
400 | ILastItem = geomElements.Length(); |
401 | |
402 | if (FigItem.Value(CurC->IndexFirstLine()).Length() > 1) { |
403 | SubSequence(FigItem.Value(CurC->IndexFirstLine()), |
404 | 1, |
405 | CurC->IndexItemOnFirst(), |
406 | SetOfItem); |
407 | UpDateLink(ILastItem+1,CurC->IndexFirstLine(), |
408 | 1,CurC->IndexItemOnFirst()); |
409 | geomElements.Append(SetOfItem); |
410 | ILastItem = geomElements.Length(); |
411 | } |
412 | connexionMap.Bind(ILastItem+1,CurC); |
413 | } |
414 | else{ |
415 | |
416 | //------------------------------------------------------ |
417 | // La portion ne passe par le dernier element de la ligne. |
418 | //------------------------------------------------------ |
419 | SubSequence(FigItem.Value(CurC->IndexFirstLine()), |
420 | PrevC->IndexItemOnSecond(), |
421 | CurC ->IndexItemOnFirst(), |
422 | SetOfItem); |
423 | UpDateLink(ILastItem+1,CurC->IndexFirstLine(), |
424 | PrevC->IndexItemOnSecond(),CurC->IndexItemOnFirst()); |
425 | geomElements.Append(SetOfItem); |
426 | ILastItem = geomElements.Length(); |
427 | connexionMap.Bind(ILastItem+1,CurC); |
428 | } |
429 | PrevC = CurC; |
430 | } |
431 | |
432 | //------------------------------------------------------------- |
433 | // Fermeture : de la derniere connexion au dernier element de la |
434 | // ligne de reference. |
435 | //------------------------------------------------------------- |
436 | IndLast = FigItem.Value(IndRefLine).Length(); |
437 | if (IndLast == 1) { |
438 | connexionMap.Bind(1,CurC); |
439 | connexionMap.UnBind(ILastItem+1); |
440 | } |
441 | else { |
442 | SubSequence(FigItem.Value(IndRefLine), |
443 | PrevC->IndexItemOnSecond(), |
444 | IndLast, |
445 | SetOfItem); |
446 | UpDateLink(ILastItem+1,IndRefLine,PrevC->IndexItemOnSecond(),IndLast); |
447 | geomElements.Append(SetOfItem); |
448 | ILastItem = geomElements.Length(); |
449 | } |
450 | |
451 | //-------------------------------------- |
452 | // Tri des RefToEqui pour chaque element. |
453 | //-------------------------------------- |
454 | MAT2d_DataMapIteratorOfDataMapOfBiIntSequenceOfInteger Ite; |
455 | |
456 | for ( Ite.Initialize(linkRefEqui); Ite.More(); Ite.Next()) { |
457 | if (Ite.Value().Length() > 1) { |
458 | SortRefToEqui(Ite.Key()); |
459 | } |
460 | } |
461 | |
0797d9d3 |
462 | #ifdef OCCT_DEBUG |
7fd59977 |
463 | if (AffichCircuit) { |
464 | ILastItem = geomElements.Length(); |
465 | for (i = 1; i <= ILastItem; i++) { |
466 | if (geomElements.Value(i)->DynamicType() != STANDARD_TYPE(Geom2d_CartesianPoint) ){ |
467 | MAT2d_DrawCurve |
468 | (Handle(Geom2d_Curve)::DownCast(geomElements.Value(i)),2); |
469 | } |
470 | } |
471 | } |
472 | #endif |
473 | } |
474 | |
475 | //============================================================================= |
476 | //function : InitOpen |
477 | //purpose : |
478 | //============================================================================= |
479 | void MAT2d_Circuit::InitOpen (TColGeom2d_SequenceOfGeometry& Line) const |
480 | { |
481 | Handle(Geom2d_TrimmedCurve) Curve; |
482 | Standard_Real DotProd; |
7fd59977 |
483 | |
0e0f7a7c |
484 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.First()); |
485 | Line.InsertBefore(1,new Geom2d_CartesianPoint(Curve->StartPoint())); |
486 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Last()); |
487 | Line.Append(new Geom2d_CartesianPoint(Curve->EndPoint())); |
488 | |
489 | for ( Standard_Integer i = 2; i <= Line.Length() - 2; i++) { |
7fd59977 |
490 | if ( Abs(CrossProd(Line.Value(i),Line.Value(i+1),DotProd)) > 1.E-8 || |
491 | DotProd < 0. ) { |
492 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)); |
493 | Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->EndPoint())); |
494 | i++; |
495 | } |
496 | } |
497 | } |
498 | |
499 | //============================================================================= |
500 | //function : DoubleLine |
501 | //purpose : |
502 | //============================================================================= |
503 | void MAT2d_Circuit::DoubleLine |
504 | ( TColGeom2d_SequenceOfGeometry& Line, |
505 | MAT2d_SequenceOfConnexion& ConnexionFrom, |
506 | const Handle(MAT2d_Connexion)& ConnexionFather, |
507 | const Standard_Real SideRef) |
508 | const |
509 | { |
510 | Handle(Standard_Type) Type; |
511 | Handle(Geom2d_TrimmedCurve) Curve; |
512 | Standard_Integer NbItems = Line.Length(); |
513 | Standard_Integer i; |
514 | Standard_Real ProVec,DotProd; |
515 | Handle(MAT2d_Connexion) CC; |
516 | |
517 | //-------------------------- |
518 | // Completion de la ligne. |
519 | //-------------------------- |
6a442250 |
520 | if (!myIsOpenResult) |
521 | { |
522 | for ( i = NbItems - 1; i > 1; i--){ |
523 | Type = Line.Value(i)->DynamicType(); |
524 | if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){ |
525 | Line.Append(Line.Value(i)); |
526 | } |
527 | else { |
528 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)->Copy()); |
529 | Curve->Reverse(); |
530 | Line.Append(Curve); |
531 | } |
7fd59977 |
532 | } |
533 | } |
534 | |
535 | //------------------------------------------ |
536 | // Repartition des connexions sur la ligne |
537 | //------------------------------------------ |
538 | Standard_Integer IAfter = ConnexionFrom.Length(); |
539 | Standard_Integer NbConnexions = IAfter; |
540 | Standard_Integer IndCOF; |
541 | |
542 | for (i = 1; i <= IAfter; i++) { |
543 | CC = ConnexionFrom.Value(i); |
544 | IndCOF = CC->IndexItemOnFirst(); |
545 | Type = Line.Value(IndCOF)->DynamicType(); |
546 | |
547 | if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){ |
548 | if (IndCOF!= NbItems && IndCOF!= 1) { |
549 | ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd); |
550 | if ((ProVec)*SideRef > 0){ |
551 | CC->IndexItemOnFirst(2*NbItems - IndCOF); |
552 | ConnexionFrom.InsertAfter(IAfter,CC); |
553 | ConnexionFrom.Remove(i); |
554 | IAfter--; |
555 | i--; |
556 | } |
557 | } |
558 | } |
559 | else if (Side(CC,Line) != SideRef){ |
560 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF)); |
561 | CC->IndexItemOnFirst(2*NbItems - IndCOF); |
562 | CC->ParameterOnFirst(Curve->ReversedParameter(CC->ParameterOnFirst())); |
563 | ConnexionFrom.InsertAfter(IAfter,CC); |
564 | ConnexionFrom.Remove(i); |
565 | IAfter--; |
566 | i--; |
567 | } |
568 | } |
569 | |
570 | //--------------------------- |
571 | // Mise a jour connexion pere. |
572 | //--------------------------- |
573 | if (!ConnexionFather.IsNull()) { |
574 | CC = ConnexionFather->Reverse(); |
575 | IndCOF = CC->IndexItemOnFirst(); |
576 | Type = Line.Value(IndCOF)->DynamicType(); |
577 | |
578 | if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){ |
579 | if (IndCOF != NbItems && IndCOF != 1) { |
580 | ProVec = CrossProd(Line.Value(IndCOF - 1),Line.Value(IndCOF + 1),DotProd); |
581 | if ((ProVec)*SideRef > 0){ |
582 | ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF); |
583 | } |
584 | } |
585 | } |
586 | else if (Side(CC,Line) != SideRef){ |
587 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(IndCOF)); |
588 | ConnexionFather->IndexItemOnSecond(2*NbItems - IndCOF); |
589 | ConnexionFather->ParameterOnSecond |
590 | (Curve->ReversedParameter(ConnexionFather->ParameterOnSecond())); |
591 | } |
592 | } |
593 | |
594 | //------------------------------------- |
595 | // Suppression des cassures rentrantes. |
596 | //------------------------------------- |
597 | Standard_Integer IndLine = 1; |
598 | Standard_Integer ICorres = 1; |
599 | TColStd_Array1OfInteger Corres(1,Line.Length()); |
600 | |
601 | while (Line.Value(IndLine) != Line.Last()){ |
602 | Corres(ICorres) = IndLine; |
603 | Type = Line.Value(IndLine)->DynamicType(); |
604 | |
605 | if (Type == STANDARD_TYPE(Geom2d_CartesianPoint) && |
606 | ICorres != 1 && ICorres != NbItems) { |
607 | |
608 | if (!IsSharpCorner(Line.Value(IndLine - 1), |
609 | Line.Value(IndLine + 1),SideRef)){ |
610 | Line.Remove(IndLine); |
611 | IndLine--; |
612 | Corres(ICorres) =0; |
613 | } |
614 | } |
615 | IndLine++; |
616 | ICorres++; |
617 | } |
618 | Corres(ICorres) = IndLine; |
7fd59977 |
619 | |
6a442250 |
620 | if (!myIsOpenResult) |
621 | { |
622 | for (i = 1; i < 2*NbItems - 2; i++) { |
623 | if (Corres(i) == 0) |
624 | Corres(i) = Corres(2*NbItems - i); |
625 | } |
626 | |
0797d9d3 |
627 | #ifdef OCCT_DEBUG |
6a442250 |
628 | if (AffichCircuit) { |
629 | for (i = 1; i <= 2*NbItems - 2; i++) { |
04232180 |
630 | std::cout<< "Correspondance "<< i<<" -> "<<Corres(i)<<std::endl; |
6a442250 |
631 | } |
7fd59977 |
632 | } |
7fd59977 |
633 | #endif |
6a442250 |
634 | |
635 | //---------------------------- |
636 | // Mise a jour des Connexions. |
637 | //---------------------------- |
638 | for ( i = 1; i <= NbConnexions; i++){ |
639 | CC = ConnexionFrom.ChangeValue(i); |
640 | CC->IndexItemOnFirst(Corres(CC->IndexItemOnFirst())); |
641 | } |
642 | |
643 | if (!ConnexionFather.IsNull()) { |
644 | ConnexionFather |
645 | ->IndexItemOnSecond(Corres(ConnexionFather->IndexItemOnSecond())); |
646 | } |
7fd59977 |
647 | } |
648 | } |
649 | |
650 | |
651 | //============================================================================= |
652 | //function : InsertCorner |
653 | //purpose : |
654 | //============================================================================= |
655 | void MAT2d_Circuit::InsertCorner (TColGeom2d_SequenceOfGeometry& Line) const |
656 | { |
657 | Standard_Integer i,isuiv; |
658 | Handle(Geom2d_TrimmedCurve) Curve; |
659 | Standard_Boolean Insert; |
660 | |
661 | for ( i = 1; i <= Line.Length(); i++) { |
662 | isuiv = (i == Line.Length()) ? 1 : i + 1; |
663 | Insert = IsSharpCorner(Line.Value(i),Line.Value(isuiv),direction); |
664 | |
0797d9d3 |
665 | #ifdef OCCT_DEBUG |
7fd59977 |
666 | if (AffichCircuit) { |
667 | if (Insert) { |
668 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv)); |
7fd59977 |
669 | #ifdef DRAW |
96a95605 |
670 | gp_Pnt2d P = Curve->StartPoint(); |
7fd59977 |
671 | Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Draw_vert); |
672 | dout << dr; |
673 | dout.Flush(); |
674 | #endif |
675 | } |
676 | } |
677 | #endif |
678 | |
679 | if (Insert) { |
680 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv)); |
681 | Line.InsertAfter(i,new Geom2d_CartesianPoint(Curve->StartPoint())); |
682 | i++; |
683 | } |
684 | } |
685 | } |
686 | |
687 | //============================================================================= |
688 | //function : NumberOfItem |
689 | //purpose : |
690 | //============================================================================= |
691 | Standard_Integer MAT2d_Circuit::NumberOfItems()const |
692 | { |
693 | return geomElements.Length(); |
694 | } |
695 | |
696 | //============================================================================= |
697 | //function : LineLength |
698 | //purpose : |
699 | //============================================================================= |
700 | Standard_Integer MAT2d_Circuit::LineLength(const Standard_Integer I) const |
701 | { |
702 | return linesLength(I); |
703 | } |
704 | |
705 | //============================================================================= |
706 | //function : Value |
707 | //purpose : |
708 | //============================================================================= |
709 | Handle(Geom2d_Geometry) MAT2d_Circuit::Value |
710 | (const Standard_Integer Index)const |
711 | { |
712 | return geomElements.Value(Index); |
713 | } |
714 | |
715 | //============================================================================= |
716 | //function : RefToEqui |
717 | //purpose : |
718 | //============================================================================= |
719 | const TColStd_SequenceOfInteger& MAT2d_Circuit::RefToEqui |
720 | (const Standard_Integer IndLine, |
721 | const Standard_Integer IndCurve) const |
722 | { |
723 | MAT2d_BiInt Key(IndLine,IndCurve); |
724 | return linkRefEqui(Key); |
725 | } |
726 | |
727 | //============================================================================= |
728 | //function : SortRefToEqui |
729 | //purpose : |
730 | //============================================================================= |
731 | void MAT2d_Circuit::SortRefToEqui (const MAT2d_BiInt& BiRef) |
732 | { |
733 | Standard_Integer i; |
734 | TColStd_SequenceOfInteger& S = linkRefEqui.ChangeFind(BiRef); |
735 | TColStd_SequenceOfInteger SFin; |
736 | |
737 | for( i = 1; i <= S.Length(); i++){ |
738 | if (!ConnexionOn(S.Value(i))) break; |
739 | } |
740 | if ( i > 1 && i <= S.Length()) { |
741 | SFin = S; |
742 | SFin.Split(i,S); |
743 | S.Append(SFin); |
744 | } |
745 | } |
746 | |
747 | //============================================================================= |
748 | //function : Connexion |
749 | //purpose : |
750 | //============================================================================= |
751 | Handle(MAT2d_Connexion) MAT2d_Circuit::Connexion(const Standard_Integer I)const |
752 | { |
753 | return connexionMap(I); |
754 | } |
755 | |
756 | //============================================================================= |
757 | //function : ConnexionOn |
758 | //purpose : |
759 | //============================================================================= |
760 | Standard_Boolean MAT2d_Circuit::ConnexionOn(const Standard_Integer I)const |
761 | { |
762 | return connexionMap.IsBound(I); |
763 | } |
764 | |
765 | //============================================================================= |
766 | //function : Side |
767 | //purpose : |
768 | //============================================================================= |
769 | Standard_Real MAT2d_Circuit::Side |
770 | (const Handle(MAT2d_Connexion)& C1, |
771 | const TColGeom2d_SequenceOfGeometry& Line) |
772 | const |
773 | { |
774 | Handle(Geom2d_TrimmedCurve) Curve; |
775 | |
776 | gp_Vec2d Vect1(C1->PointOnSecond().X() - C1->PointOnFirst().X(), |
777 | C1->PointOnSecond().Y() - C1->PointOnFirst().Y()); |
778 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast |
779 | (Line.Value(C1->IndexItemOnFirst())); |
780 | gp_Vec2d Vect2 = Curve->DN(C1->ParameterOnFirst(),1); |
781 | if ( (Vect1^Vect2) > 0.) return - 1.; else return 1.; |
782 | } |
783 | |
784 | //============================================================================= |
785 | //function : PassByLast |
786 | //purpose : |
787 | //============================================================================= |
788 | Standard_Boolean MAT2d_Circuit::PassByLast |
789 | (const Handle(MAT2d_Connexion)& C1, |
790 | const Handle(MAT2d_Connexion)& C2) const |
791 | { |
792 | if (C2->IndexFirstLine() == C1->IndexSecondLine()){ |
793 | if (C2->IndexItemOnFirst() < C1->IndexItemOnSecond()) { |
794 | return Standard_True; |
795 | } |
796 | else if (C2->IndexItemOnFirst() == C1->IndexItemOnSecond()) { |
797 | if (C1->IndexFirstLine() == C2->IndexSecondLine()) { |
798 | return Standard_True; |
799 | } |
800 | if (C2->ParameterOnFirst() == C1->ParameterOnSecond()) { |
801 | gp_Vec2d Vect1(C1->PointOnSecond(),C1->PointOnFirst()); |
802 | gp_Vec2d Vect2(C2->PointOnFirst(),C2->PointOnSecond()); |
803 | if ((Vect1^Vect2)*direction > 0) { |
804 | return Standard_True; |
805 | } |
806 | } |
807 | else if (C2->ParameterOnFirst() < C1->ParameterOnSecond()) { |
808 | return Standard_True; |
809 | } |
810 | } |
811 | } |
812 | return Standard_False; |
813 | } |
814 | |
815 | //============================================================================= |
816 | //function : UpDateLink |
817 | //purpose : |
818 | //============================================================================= |
819 | void MAT2d_Circuit::UpDateLink(const Standard_Integer IFirst, |
820 | const Standard_Integer ILine, |
821 | const Standard_Integer ICurveFirst, |
822 | const Standard_Integer ICurveLast) |
823 | { |
824 | Standard_Integer IEqui = IFirst; |
825 | Standard_Integer i; |
826 | |
827 | for (i = ICurveFirst; i <= ICurveLast; i++) { |
828 | MAT2d_BiInt Key(ILine,i); |
829 | if (linkRefEqui.IsBound(Key)) { |
830 | linkRefEqui(Key).Append(IEqui); |
831 | } |
832 | else { |
833 | TColStd_SequenceOfInteger L; |
834 | linkRefEqui.Bind(Key,L); |
835 | linkRefEqui(Key).Append(IEqui); |
836 | } |
837 | IEqui++; |
838 | } |
839 | } |
840 | |
841 | //========================================================================== |
842 | //function : CrossProd |
843 | //purpose : Calcul le produit vectoriel et scalaire entre les directions des |
844 | // tangentes a la fin de Geom1 et au debut de Geom2. |
845 | // Geom1 et Geom2 doivent etre des courbes. |
846 | //========================================================================== |
847 | static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1, |
848 | const Handle(Geom2d_Geometry)& Geom2, |
849 | Standard_Real& DotProd) |
850 | { |
851 | Handle(Geom2d_TrimmedCurve) Curve; |
852 | |
853 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom1); |
854 | gp_Dir2d Dir1(Curve->DN(Curve->LastParameter(),1)); |
855 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Geom2); |
856 | gp_Dir2d Dir2(Curve->DN(Curve->FirstParameter(),1)); |
857 | DotProd = Dir1.Dot(Dir2); |
858 | return Dir1^Dir2; |
859 | } |
860 | |
861 | |
7fd59977 |
862 | |
863 | |
864 | |
0797d9d3 |
865 | #ifdef OCCT_DEBUG |
7fd59977 |
866 | //========================================================================== |
867 | //function : MAT2d_DrawCurve |
868 | //purpose : Affichage d une courbe <aCurve> de Geom2d. dans une couleur |
869 | // definie par <Indice>. |
870 | // Indice = 1 jaune, |
871 | // Indice = 2 bleu, |
872 | // Indice = 3 rouge, |
873 | // Indice = 4 vert. |
874 | //========================================================================== |
875 | void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve, |
35e08fe8 |
876 | const Standard_Integer /*Indice*/) |
7fd59977 |
877 | { |
878 | Handle(Standard_Type) type = aCurve->DynamicType(); |
879 | Handle(Geom2d_Curve) curve,CurveDraw; |
880 | #ifdef DRAW |
881 | Handle(DrawTrSurf_Curve2d) dr; |
882 | Draw_Color Couleur; |
883 | #endif |
884 | |
885 | if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) { |
886 | curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve(); |
887 | type = curve->DynamicType(); |
888 | // PB de representation des courbes semi_infinies. |
889 | gp_Parab2d gpParabola; |
890 | gp_Hypr2d gpHyperbola; |
891 | Standard_Real Focus; |
892 | Standard_Real Limit = 50000.; |
893 | Standard_Real delta = 400; |
894 | |
895 | // PB de representation des courbes semi_infinies. |
896 | if (aCurve->LastParameter() == Precision::Infinite()) { |
897 | |
898 | if (type == STANDARD_TYPE(Geom2d_Parabola)) { |
899 | gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d(); |
900 | Focus = gpParabola.Focal(); |
901 | Standard_Real Val1 = Sqrt(Limit*Focus); |
902 | Standard_Real Val2 = Sqrt(Limit*Limit); |
903 | delta= (Val1 <= Val2 ? Val1:Val2); |
904 | } |
905 | else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) { |
906 | gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d(); |
907 | Standard_Real Majr = gpHyperbola.MajorRadius(); |
908 | Standard_Real Minr = gpHyperbola.MinorRadius(); |
909 | Standard_Real Valu1 = Limit/Majr; |
910 | Standard_Real Valu2 = Limit/Minr; |
911 | Standard_Real Val1 = Log(Valu1+Sqrt(Valu1*Valu1-1)); |
912 | Standard_Real Val2 = Log(Valu2+Sqrt(Valu2*Valu2+1)); |
913 | delta = (Val1 <= Val2 ? Val1:Val2); |
914 | } |
915 | CurveDraw = new Geom2d_TrimmedCurve(aCurve, |
916 | aCurve->FirstParameter(), |
917 | aCurve->FirstParameter() + delta); |
918 | } |
919 | else { |
920 | CurveDraw = aCurve; |
921 | } |
922 | // fin PB. |
923 | } |
924 | else { |
925 | CurveDraw = aCurve; |
926 | } |
927 | |
928 | #ifdef DRAW |
929 | if (Indice == 1) Couleur = Draw_jaune; |
930 | else if (Indice == 2) Couleur = Draw_bleu; |
931 | else if (Indice == 3) Couleur = Draw_rouge; |
932 | else if (Indice == 4) Couleur = Draw_vert; |
933 | |
934 | if (type == STANDARD_TYPE(Geom2d_Circle)) |
935 | dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30); |
936 | else if (type == STANDARD_TYPE(Geom2d_Line)) |
937 | dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2); |
938 | else |
939 | dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500); |
940 | |
941 | dout << dr; |
942 | dout.Flush(); |
943 | #endif |
944 | } |
945 | |
946 | #endif |
947 | |