b311480e |
1 | // Created on: 1993-07-12 |
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 | |
17 | #define Debug(expr) cout<<" MAT2d_Tool2d.cxx : expr :"<<expr<<endl; |
873c119f |
18 | //#define OCCT_DEBUG |
19 | //#define DRAW |
7fd59977 |
20 | #ifdef DRAW |
21 | #include <DBRep.hxx> |
22 | #include <DrawTrSurf.hxx> |
23 | #include <stdio.h> |
24 | #endif |
25 | |
26 | #ifdef DRAW |
27 | #include <Draw_Appli.hxx> |
28 | #include <DrawTrSurf_Curve2d.hxx> |
29 | #include <GCE2d_MakeSegment.hxx> |
30 | #include <DrawTrSurf.hxx> |
31 | #endif |
32 | |
33 | #include <MAT2d_Tool2d.ixx> |
34 | #include <MAT2d_MiniPath.hxx> |
35 | #include <MAT2d_Connexion.hxx> |
36 | #include <MAT2d_SequenceOfSequenceOfGeometry.hxx> |
37 | #include <MAT_Edge.hxx> |
38 | #include <Bisector_Curve.hxx> |
39 | #include <Bisector_BisecAna.hxx> |
40 | #include <Bisector_BisecCC.hxx> |
41 | #include <Bisector_Bisec.hxx> |
42 | #include <Bisector_Inter.hxx> |
43 | #include <IntRes2d_Domain.hxx> |
44 | #include <Extrema_ExtPC2d.hxx> |
45 | #include <Geom2dInt_GInter.hxx> |
46 | #include <IntRes2d_IntersectionPoint.hxx> |
47 | #include <IntRes2d_IntersectionSegment.hxx> |
48 | #include <Geom2d_Geometry.hxx> |
49 | #include <Geom2d_Point.hxx> |
50 | #include <Geom2d_Line.hxx> |
51 | #include <Geom2d_Circle.hxx> |
52 | #include <Geom2d_Curve.hxx> |
53 | #include <Geom2d_Parabola.hxx> |
54 | #include <Geom2d_Hyperbola.hxx> |
55 | #include <Geom2d_Ellipse.hxx> |
56 | #include <Geom2d_CartesianPoint.hxx> |
57 | #include <Geom2d_TrimmedCurve.hxx> |
58 | #include <Geom2dAdaptor_Curve.hxx> |
59 | #include <gp_Lin2d.hxx> |
60 | #include <gp_Hypr2d.hxx> |
61 | #include <gp_Parab2d.hxx> |
62 | #include <gp_Elips2d.hxx> |
63 | #include <gp_Circ2d.hxx> |
64 | #include <gp_Vec2d.hxx> |
65 | #include <TColStd_Array1OfReal.hxx> |
66 | #include <ElCLib.hxx> |
67 | #include <StdFail_NotDone.hxx> |
68 | #include <Standard_NotImplemented.hxx> |
69 | #include <Precision.hxx> |
70 | |
71 | #ifdef DRAW |
873c119f |
72 | static Handle(DrawTrSurf_Curve2d) draw; |
73 | static Standard_Integer AffichBis = Standard_False; |
7fd59977 |
74 | #endif |
0797d9d3 |
75 | #ifdef OCCT_DEBUG |
873c119f |
76 | static void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve, |
77 | const Standard_Integer Indice); |
78 | static Standard_Boolean Store = Standard_False; |
79 | static Standard_Boolean AffichDist = Standard_False; |
7fd59977 |
80 | #endif |
81 | |
82 | //===================================================================== |
83 | // static functions |
84 | //===================================================================== |
85 | static IntRes2d_Domain Domain |
86 | (const Handle(Geom2d_TrimmedCurve)& Bisector1, |
873c119f |
87 | const Standard_Real Tolerance); |
7fd59977 |
88 | |
89 | static Handle(Standard_Type) Type (const Handle(Geom2d_Geometry)& acurve); |
90 | |
91 | static Standard_Boolean AreNeighbours(const Standard_Integer IEdge1, |
873c119f |
92 | const Standard_Integer IEdge2, |
93 | const Standard_Integer NbEdge); |
7fd59977 |
94 | |
95 | static void SetTrim(Bisector_Bisec& Bis , Handle(Geom2d_Curve)& Line1); |
873c119f |
96 | static Standard_Boolean CheckEnds (const Handle(Geom2d_Geometry)& Elt , |
97 | const gp_Pnt2d& PCom , |
98 | const Standard_Real Distance, |
99 | const Standard_Real Tol); |
7fd59977 |
100 | |
101 | static Standard_Real MAT2d_TOLCONF = 1.e-7; |
102 | |
103 | //============================================================================ |
104 | //function : |
105 | //purpose : |
106 | //============================================================================ |
107 | MAT2d_Tool2d::MAT2d_Tool2d() |
108 | { |
109 | theDirection = 1.; |
c19dd45e |
110 | theJoinType = GeomAbs_Arc; //default |
7fd59977 |
111 | theNumberOfBisectors = 0; |
112 | theNumberOfVecs = 0; |
113 | theNumberOfPnts = 0; |
114 | } |
115 | |
116 | //============================================================================= |
117 | //function : InitItems |
118 | //purpose : |
119 | //============================================================================= |
120 | void MAT2d_Tool2d::InitItems(const Handle(MAT2d_Circuit)& EquiCircuit) |
121 | { |
122 | theGeomBisectors.Clear(); |
123 | theGeomPnts.Clear(); |
124 | theGeomVecs.Clear(); |
125 | theLinesLength.Clear(); |
126 | theNumberOfBisectors = 0; |
127 | theNumberOfVecs = 0; |
128 | theNumberOfPnts = 0; |
873c119f |
129 | |
7fd59977 |
130 | theCircuit = EquiCircuit; |
131 | } |
873c119f |
132 | |
7fd59977 |
133 | //============================================================================= |
134 | //function : Sense |
135 | //purpose : |
136 | //============================================================================= |
137 | void MAT2d_Tool2d::Sense(const MAT_Side aside) |
138 | { |
139 | if(aside == MAT_Left) theDirection = 1.; |
140 | else theDirection = -1.; |
141 | } |
142 | |
c19dd45e |
143 | //============================================================================= |
144 | //function : SetJoinType |
145 | //purpose : |
146 | //============================================================================= |
147 | void MAT2d_Tool2d::SetJoinType(const GeomAbs_JoinType aJoinType) |
148 | { |
149 | theJoinType = aJoinType; |
150 | } |
151 | |
7fd59977 |
152 | //============================================================================= |
153 | //function : NumberOfItems |
154 | //purpose : |
155 | //============================================================================= |
156 | Standard_Integer MAT2d_Tool2d::NumberOfItems() const |
157 | { |
158 | return theCircuit->NumberOfItems(); |
159 | } |
160 | |
161 | //============================================================================= |
162 | //function : ToleranceOfConfusion |
163 | //purpose : |
164 | //============================================================================= |
165 | Standard_Real MAT2d_Tool2d::ToleranceOfConfusion() const |
166 | { |
167 | return 2*MAT2d_TOLCONF; |
168 | } |
169 | |
170 | //============================================================================= |
171 | //function : FirstPoint |
172 | //purpose : |
173 | //============================================================================= |
174 | Standard_Integer MAT2d_Tool2d::FirstPoint(const Standard_Integer anitem, |
873c119f |
175 | Standard_Real& dist ) |
7fd59977 |
176 | { |
177 | Handle(Geom2d_Curve) curve; |
178 | Handle(Geom2d_Point) point; |
179 | theNumberOfPnts++; |
180 | |
181 | if (theCircuit->ConnexionOn(anitem)){ |
182 | gp_Pnt2d P1 = theCircuit->Connexion(anitem)->PointOnFirst(); |
183 | gp_Pnt2d P2 = theCircuit->Connexion(anitem)->PointOnSecond(); |
184 | theGeomPnts.Bind(theNumberOfPnts,gp_Pnt2d((P1.X() + P2.X())*0.5, |
873c119f |
185 | (P1.Y() + P2.Y())*0.5)); |
7fd59977 |
186 | dist = P1.Distance(P2)*0.5; |
187 | return theNumberOfPnts; |
188 | } |
189 | |
190 | Handle(Standard_Type) type; |
191 | type = theCircuit->Value(anitem)->DynamicType(); |
192 | dist = 0.; |
193 | |
194 | if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){ |
195 | curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem)); |
196 | theGeomPnts.Bind(theNumberOfPnts,curve->Value(curve->FirstParameter())); |
197 | } |
198 | else{ |
199 | point = Handle(Geom2d_Point)::DownCast(theCircuit->Value(anitem)); |
200 | theGeomPnts.Bind(theNumberOfPnts,point->Pnt2d()); |
201 | } |
202 | return theNumberOfPnts; |
203 | } |
204 | |
205 | //============================================================================= |
206 | //function : TangentBefore |
207 | //purpose : |
208 | //============================================================================= |
0e0f7a7c |
209 | Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem, |
210 | const Standard_Boolean IsOpenResult) |
7fd59977 |
211 | { |
212 | Standard_Integer item; |
213 | Handle(Geom2d_Curve) curve; |
214 | theNumberOfVecs++; |
0e0f7a7c |
215 | |
216 | if (!IsOpenResult) |
873c119f |
217 | item = (anitem == theCircuit->NumberOfItems()) ? 1 : (anitem + 1); |
0e0f7a7c |
218 | else |
219 | item = (anitem == theCircuit->NumberOfItems()) ? (anitem - 1) : (anitem + 1); |
7fd59977 |
220 | if (theCircuit->ConnexionOn(item)){ |
221 | Standard_Real x1,y1,x2,y2; |
222 | theCircuit->Connexion(item)->PointOnFirst().Coord(x1,y1); |
223 | theCircuit->Connexion(item)->PointOnSecond().Coord(x2,y2); |
224 | theGeomVecs.Bind(theNumberOfVecs,gp_Vec2d((x2-x1),(y2-y1))); |
225 | return theNumberOfVecs; |
226 | } |
227 | |
228 | Handle(Standard_Type) type; |
229 | type = theCircuit->Value(anitem)->DynamicType(); |
230 | if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){ |
231 | curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem)); |
232 | theGeomVecs.Bind(theNumberOfVecs,curve->DN(curve->LastParameter(),1)); |
233 | } |
234 | else { |
235 | curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item)); |
0e0f7a7c |
236 | Standard_Real param = (IsOpenResult && anitem == theCircuit->NumberOfItems())? |
237 | curve->LastParameter() : curve->FirstParameter(); |
238 | theGeomVecs.Bind(theNumberOfVecs,curve->DN(param,1)); |
7fd59977 |
239 | } |
240 | |
241 | return theNumberOfVecs; |
242 | } |
243 | |
244 | //============================================================================= |
245 | //function : TangentAfter |
246 | //purpose : |
247 | //============================================================================= |
0e0f7a7c |
248 | Standard_Integer MAT2d_Tool2d::TangentAfter(const Standard_Integer anitem, |
249 | const Standard_Boolean IsOpenResult) |
7fd59977 |
250 | { |
251 | Standard_Integer item; |
252 | Handle(Geom2d_Curve) curve; |
253 | gp_Vec2d thevector; |
254 | theNumberOfVecs++; |
255 | |
256 | if (theCircuit->ConnexionOn(anitem)){ |
257 | Standard_Real x1,y1,x2,y2; |
258 | theCircuit->Connexion(anitem)->PointOnFirst().Coord(x1,y1); |
259 | theCircuit->Connexion(anitem)->PointOnSecond().Coord(x2,y2); |
260 | theGeomVecs.Bind(theNumberOfVecs,gp_Vec2d((x1-x2),(y1-y2))); |
261 | return theNumberOfVecs; |
262 | } |
263 | |
264 | Handle(Standard_Type) type; |
265 | type = theCircuit->Value(anitem)->DynamicType(); |
266 | if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){ |
267 | curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem)); |
268 | thevector = curve->DN(curve->FirstParameter(),1); |
269 | } |
270 | else { |
0e0f7a7c |
271 | if (!IsOpenResult) |
873c119f |
272 | item = (anitem == 1) ? theCircuit->NumberOfItems() : (anitem - 1); |
0e0f7a7c |
273 | else |
274 | item = (anitem == 1) ? 2 : (anitem - 1); |
7fd59977 |
275 | curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item)); |
0e0f7a7c |
276 | Standard_Real param = (IsOpenResult && anitem == 1)? |
277 | curve->FirstParameter() : curve->LastParameter(); |
278 | thevector = curve->DN(param,1); |
7fd59977 |
279 | } |
280 | theGeomVecs.Bind(theNumberOfVecs,thevector.Reversed()); |
281 | return theNumberOfVecs; |
282 | } |
283 | |
284 | //============================================================================= |
285 | //function : Tangent |
286 | //purpose : |
287 | //============================================================================= |
288 | Standard_Integer MAT2d_Tool2d::Tangent(const Standard_Integer bisector) |
289 | { |
290 | theNumberOfVecs++; |
291 | theGeomVecs.Bind(theNumberOfVecs,GeomBis(bisector).Value() |
873c119f |
292 | ->DN(GeomBis(bisector).Value() |
293 | ->LastParameter(),1)); |
7fd59977 |
294 | return theNumberOfVecs; |
295 | } |
296 | |
297 | //============================================================================= |
298 | //function : CreateBisector |
299 | //purpose : |
300 | //============================================================================= |
301 | void MAT2d_Tool2d::CreateBisector(const Handle(MAT_Bisector)& abisector) |
302 | { |
303 | Handle(Geom2d_Point) point1,point2; |
304 | Handle(Geom2d_Geometry) elt1,elt2; |
305 | Bisector_Bisec bisector; |
306 | Standard_Real tolerance = MAT2d_TOLCONF ; |
307 | |
308 | Standard_Integer edge1number = abisector->FirstEdge()->EdgeNumber(); |
309 | Standard_Integer edge2number = abisector->SecondEdge()->EdgeNumber(); |
310 | Standard_Boolean ontheline = AreNeighbours(edge1number, |
873c119f |
311 | edge2number, |
312 | NumberOfItems()); |
7fd59977 |
313 | Standard_Boolean InitialNeighbour = ontheline; |
314 | |
315 | if(theCircuit->ConnexionOn(edge2number)) ontheline = Standard_False; |
316 | |
317 | elt1 = theCircuit->Value(edge1number); |
318 | elt2 = theCircuit->Value(edge2number); |
319 | |
320 | Handle(Standard_Type) type1; |
321 | type1 = theCircuit->Value(edge1number)->DynamicType(); |
322 | Handle(Standard_Type) type2; |
323 | type2 = theCircuit->Value(edge2number)->DynamicType(); |
324 | Handle(Geom2d_Curve) item1; |
325 | Handle(Geom2d_Curve) item2; |
326 | |
327 | if ( type1 != STANDARD_TYPE(Geom2d_CartesianPoint)){ |
328 | item1 = Handle(Geom2d_Curve)::DownCast(elt1); |
329 | } |
330 | |
331 | if ( type2 != STANDARD_TYPE(Geom2d_CartesianPoint)){ |
332 | item2 = Handle(Geom2d_Curve)::DownCast(elt2); |
333 | } |
334 | |
0797d9d3 |
335 | #ifdef OCCT_DEBUG |
7fd59977 |
336 | Standard_Boolean Affich = Standard_False; |
337 | if (Affich) { |
338 | cout<<endl; |
339 | cout<<"BISECTOR number : "<<theNumberOfBisectors+1<<endl; |
340 | cout<<" Item 1 : "<<endl; |
341 | cout<<edge1number<<endl; |
342 | cout<<endl; |
873c119f |
343 | // elt1->Dump(1,1); |
7fd59977 |
344 | cout<<endl; |
345 | cout<<" Item 2 : "<<endl; |
346 | cout<<edge2number<<endl; |
347 | cout<<endl; |
873c119f |
348 | // elt2->Dump(1,1); |
7fd59977 |
349 | cout<<endl; |
350 | } |
351 | #endif |
352 | |
353 | if(type1 != STANDARD_TYPE(Geom2d_CartesianPoint) && |
873c119f |
354 | type2 != STANDARD_TYPE(Geom2d_CartesianPoint)) { |
355 | bisector.Perform(item1,item2, |
356 | GeomPnt (abisector->IssuePoint()), |
357 | GeomVec (abisector->FirstVector()), |
358 | GeomVec (abisector->SecondVector()), |
359 | theDirection,tolerance,ontheline); |
7fd59977 |
360 | } |
361 | else if(type1 == STANDARD_TYPE(Geom2d_CartesianPoint) && |
873c119f |
362 | type2 == STANDARD_TYPE(Geom2d_CartesianPoint)) { |
363 | point1 = Handle(Geom2d_Point)::DownCast(elt1); |
364 | point2 = Handle(Geom2d_Point)::DownCast(elt2); |
365 | bisector.Perform(point1,point2, |
366 | GeomPnt (abisector->IssuePoint()), |
367 | GeomVec (abisector->FirstVector()), |
368 | GeomVec (abisector->SecondVector()), |
369 | theDirection,tolerance,ontheline); |
7fd59977 |
370 | } |
371 | else if(type1 == STANDARD_TYPE(Geom2d_CartesianPoint)) { |
372 | point1 = Handle(Geom2d_Point)::DownCast(elt1); |
373 | bisector.Perform(point1,item2, |
873c119f |
374 | GeomPnt (abisector->IssuePoint()), |
375 | GeomVec (abisector->FirstVector()), |
376 | GeomVec (abisector->SecondVector()), |
377 | theDirection,tolerance,ontheline); |
7fd59977 |
378 | } |
379 | else { |
380 | point2 = Handle(Geom2d_Point)::DownCast(elt2); |
381 | bisector.Perform(item1,point2, |
873c119f |
382 | GeomPnt (abisector->IssuePoint()), |
383 | GeomVec (abisector->FirstVector()), |
384 | GeomVec (abisector->SecondVector()), |
385 | theDirection,tolerance,ontheline); |
7fd59977 |
386 | } |
387 | |
388 | //------------------------------ |
389 | // Restriction de la bisectrice. |
390 | //----------------------------- |
391 | TrimBisec(bisector,edge1number,InitialNeighbour,1); |
392 | TrimBisec(bisector,edge2number,InitialNeighbour,2); |
393 | |
394 | theNumberOfBisectors++; |
395 | theGeomBisectors.Bind(theNumberOfBisectors,bisector); |
396 | |
397 | abisector->BisectorNumber(theNumberOfBisectors); |
398 | abisector->Sense(1); |
399 | |
0797d9d3 |
400 | #ifdef OCCT_DEBUG |
7fd59977 |
401 | Standard_Boolean AffichDraw = Standard_False; |
402 | if (AffichDraw) Dump(abisector->BisectorNumber(),1); |
403 | if (Store) { |
404 | Handle(Standard_Type) Type1 = Type(bisector.Value()->BasisCurve()); |
405 | Handle(Geom2d_Curve) BasisCurve; |
406 | if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) { |
407 | BasisCurve = Handle(Bisector_BisecAna) |
873c119f |
408 | ::DownCast(bisector.Value()->BasisCurve())->Geom2dCurve(); |
7fd59977 |
409 | #ifdef DRAW |
410 | char *name = new char[100]; |
411 | sprintf(name,"BISSEC_%d",abisector->BisectorNumber()); |
412 | DrawTrSurf::Set(name,BasisCurve); |
413 | delete [] name; |
414 | #endif |
415 | } |
416 | } |
417 | #endif |
418 | } |
419 | |
420 | //============================================================================= |
421 | //function : TrimBisec |
422 | //purpose : Restriction de la bisectrice. |
423 | // Restriction des bissectrice separant deux elements lies par une |
424 | // connexion ou l un au moins des elements est un cercle. |
425 | // Cette restriction est necessaire a la logique de l algorithme. |
426 | //============================================================================= |
427 | void MAT2d_Tool2d::TrimBisec ( Bisector_Bisec& B1, |
873c119f |
428 | const Standard_Integer IndexEdge, |
429 | const Standard_Boolean InitialNeighbour, |
430 | const Standard_Integer StartOrEnd ) const |
7fd59977 |
431 | { |
432 | Handle(Geom2d_Curve) Curve; |
433 | Handle(Geom2d_TrimmedCurve) LineSupportDomain,Line; |
434 | Handle(Geom2d_Line) Line1,Line2; |
873c119f |
435 | |
7fd59977 |
436 | //gp_Vec2d Tan1,Tan2; |
437 | gp_Pnt2d Ori; //PEdge; |
96a95605 |
438 | Standard_Integer INext; |
7fd59977 |
439 | INext = (IndexEdge == theCircuit->NumberOfItems()) ? 1 : (IndexEdge + 1); |
873c119f |
440 | |
7fd59977 |
441 | Handle(Standard_Type) EdgeType = theCircuit->Value(IndexEdge)->DynamicType(); |
873c119f |
442 | |
7fd59977 |
443 | if (EdgeType != STANDARD_TYPE(Geom2d_CartesianPoint)) { |
444 | if(!InitialNeighbour) { |
445 | Curve = Handle(Geom2d_TrimmedCurve) |
873c119f |
446 | ::DownCast(theCircuit->Value(IndexEdge))->BasisCurve(); |
7fd59977 |
447 | EdgeType = Curve->DynamicType(); |
448 | //------------------------------------------------------------------- |
449 | // si l edge est liee a sa voisine precedente par une connexion. |
450 | //------------------------------------------------------------------- |
451 | if (theCircuit->ConnexionOn(IndexEdge) && StartOrEnd == 1){ |
873c119f |
452 | if (EdgeType == STANDARD_TYPE(Geom2d_Circle)) { |
453 | Ori = Handle(Geom2d_Circle)::DownCast(Curve)->Location(); |
454 | gp_Pnt2d P2 = theCircuit->Connexion(IndexEdge)->PointOnFirst(); |
455 | Line1 = new Geom2d_Line (Ori,gp_Dir2d(P2.X() - Ori.X(), |
456 | P2.Y() - Ori.Y())); |
457 | } |
7fd59977 |
458 | } |
459 | //----------------------------------------------------------------------- |
460 | // Si l edge est liee a sa voisine suivante par une connexion. |
461 | //----------------------------------------------------------------------- |
462 | if (theCircuit->ConnexionOn(INext) && StartOrEnd == 2){ |
873c119f |
463 | if (EdgeType == STANDARD_TYPE(Geom2d_Circle)) { |
464 | Ori = Handle(Geom2d_Circle)::DownCast(Curve)->Location(); |
465 | gp_Pnt2d P2 = theCircuit->Connexion(INext)->PointOnSecond(); |
466 | Line2 = new Geom2d_Line (Ori,gp_Dir2d(P2.X() - Ori.X(), |
467 | P2.Y() - Ori.Y())); |
468 | } |
7fd59977 |
469 | } |
470 | if (Line1.IsNull() && Line2.IsNull()) return; |
471 | |
472 | //----------------------------------------------------------------------- |
473 | // Restriction de la bisectrice par les demi-droites liees aux connexions |
474 | // si elles existent. |
475 | //----------------------------------------------------------------------- |
476 | if (!Line1.IsNull()) { |
873c119f |
477 | Line = new Geom2d_TrimmedCurve(Line1,0.,Precision::Infinite()); |
478 | SetTrim(B1,Line); |
7fd59977 |
479 | } |
480 | if (!Line2.IsNull()) { |
873c119f |
481 | Line = new Geom2d_TrimmedCurve(Line2,0.,Precision::Infinite()); |
482 | SetTrim(B1,Line); |
7fd59977 |
483 | } |
484 | } |
485 | } |
486 | } |
487 | |
488 | //============================================================================= |
489 | //function : TrimBisector |
490 | //purpose : |
491 | //============================================================================= |
492 | Standard_Boolean MAT2d_Tool2d::TrimBisector |
493 | (const Handle(MAT_Bisector)& abisector) |
494 | { |
495 | Standard_Real param = abisector->FirstParameter(); |
496 | |
0797d9d3 |
497 | #ifdef OCCT_DEBUG |
7fd59977 |
498 | Standard_Boolean Affich = Standard_False; |
499 | if (Affich) cout<<"TRIM de "<<abisector->BisectorNumber()<<endl; |
500 | #endif |
501 | |
502 | Handle(Geom2d_TrimmedCurve) |
503 | bisector = Handle(Geom2d_TrimmedCurve) |
873c119f |
504 | ::DownCast(ChangeGeomBis(abisector->BisectorNumber()).ChangeValue()); |
505 | |
7fd59977 |
506 | if(bisector->BasisCurve()->IsPeriodic() && param == Precision::Infinite()) { |
c6541a0c |
507 | param = bisector->FirstParameter() + 2*M_PI; |
7fd59977 |
508 | } |
509 | if (param > bisector->BasisCurve()->LastParameter()) { |
873c119f |
510 | param = bisector->BasisCurve()->LastParameter(); |
7fd59977 |
511 | } |
512 | if(bisector->FirstParameter() == param) return Standard_False; |
513 | |
514 | bisector->SetTrim(bisector->FirstParameter(),param); |
515 | return Standard_True; |
516 | } |
517 | |
518 | //============================================================================= |
519 | //function : TrimBisector |
520 | //purpose : |
521 | //============================================================================= |
522 | Standard_Boolean MAT2d_Tool2d::TrimBisector |
523 | (const Handle(MAT_Bisector)& abisector, |
873c119f |
524 | const Standard_Integer apoint) |
7fd59977 |
525 | { |
526 | Standard_Real Param; |
527 | Handle(Geom2d_TrimmedCurve) |
528 | Bisector = Handle(Geom2d_TrimmedCurve):: |
873c119f |
529 | DownCast(ChangeGeomBis(abisector->BisectorNumber()).ChangeValue()); |
7fd59977 |
530 | |
531 | Handle(Bisector_Curve) Bis = Handle(Bisector_Curve):: |
532 | DownCast(Bisector->BasisCurve()); |
533 | |
873c119f |
534 | // Param = ParameterOnCurve(Bisector,theGeomPnts.Value(apoint)); |
7fd59977 |
535 | Param = Bis->Parameter(GeomPnt (apoint)); |
536 | |
537 | if (Bisector->BasisCurve()->IsPeriodic()) { |
c6541a0c |
538 | if (Bisector->FirstParameter() > Param) Param = Param + 2*M_PI; |
7fd59977 |
539 | } |
540 | if(Bisector->FirstParameter() >= Param)return Standard_False; |
541 | if(Bisector->LastParameter() < Param)return Standard_False; |
542 | Bisector->SetTrim(Bisector->FirstParameter(),Param); |
543 | |
0797d9d3 |
544 | #ifdef OCCT_DEBUG |
7fd59977 |
545 | Standard_Boolean Affich = Standard_False; |
546 | if (Affich) MAT2d_DrawCurve(Bisector,2); |
547 | #endif |
548 | |
549 | return Standard_True; |
550 | } |
551 | |
552 | //============================================================================= |
553 | //function : Projection |
554 | //purpose : |
555 | //============================================================================= |
556 | Standard_Boolean MAT2d_Tool2d::Projection (const Standard_Integer IEdge , |
873c119f |
557 | const gp_Pnt2d& PCom , |
558 | Standard_Real& Distance) |
559 | const |
7fd59977 |
560 | { |
561 | gp_Pnt2d PEdge; |
562 | Handle(Geom2d_Geometry) Elt = theCircuit->Value(IEdge); |
563 | Handle(Standard_Type) Type = Elt->DynamicType(); |
564 | Handle(Geom2d_TrimmedCurve) Curve; |
565 | Standard_Integer INext; |
7fd59977 |
566 | Standard_Real Eps = MAT2d_TOLCONF;//*10.; |
567 | |
568 | if (Type == STANDARD_TYPE(Geom2d_CartesianPoint)) { |
569 | PEdge = Handle(Geom2d_Point)::DownCast(Elt)->Pnt2d(); |
570 | Distance = PCom.Distance(PEdge); |
571 | } |
572 | else { |
573 | Distance = Precision::Infinite(); |
574 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Elt); |
575 | //----------------------------------------------------------------------- |
576 | // Calcul des parametres MinMax sur l edge si celui ci est lies a ses |
577 | // voisins par des connexions la courbe de calcul est limitee par |
578 | // celles_ci. |
579 | //----------------------------------------------------------------------- |
580 | Standard_Real ParamMin = Curve->FirstParameter(); |
581 | Standard_Real ParamMax = Curve->LastParameter(); |
582 | if (theCircuit->ConnexionOn(IEdge)) { |
583 | ParamMin = theCircuit->Connexion(IEdge)->ParameterOnSecond(); |
584 | } |
585 | INext = (IEdge == theCircuit->NumberOfItems()) ? 1 : (IEdge + 1); |
586 | if (theCircuit->ConnexionOn(INext)) { |
587 | ParamMax = theCircuit->Connexion(INext)->ParameterOnFirst(); |
588 | if (Curve->BasisCurve()->IsPeriodic()){ |
873c119f |
589 | ElCLib::AdjustPeriodic(0.,2*M_PI,Eps,ParamMin,ParamMax); |
7fd59977 |
590 | } |
591 | } |
592 | //--------------------------------------------------------------------- |
593 | // Constuction de la courbe pour les extremas et ajustement des bornes. |
594 | //--------------------------------------------------------------------- |
595 | Geom2dAdaptor_Curve C1(Curve); |
596 | GeomAbs_CurveType TypeC1 = C1.GetType(); |
597 | if (TypeC1 == GeomAbs_Circle) { |
598 | Standard_Real R = C1.Circle().Radius(); |
873c119f |
599 | Standard_Real EpsCirc = 100.*Eps; |
7fd59977 |
600 | if ( R < 1.) EpsCirc = Eps/R; |
873c119f |
601 | if (((ParamMax - ParamMin + 2*EpsCirc) < 2*M_PI)) { |
602 | ParamMax = ParamMax + EpsCirc; ParamMin = ParamMin - EpsCirc; |
7fd59977 |
603 | } |
604 | } |
605 | else { |
606 | ParamMax = ParamMax + Eps; ParamMin = ParamMin - Eps; |
607 | } |
608 | //----------------------------------------------------- |
609 | // Calcul des extremas et stockage minimum de distance. |
610 | //----------------------------------------------------- |
611 | Extrema_ExtPC2d Extremas(PCom,C1,ParamMin,ParamMax); |
612 | if (Extremas.IsDone()){ |
873c119f |
613 | Distance = Precision::Infinite(); |
614 | if(Extremas.NbExt() < 1) |
615 | { |
616 | return Standard_False; |
617 | } |
7fd59977 |
618 | for (Standard_Integer i = 1; i <= Extremas.NbExt(); i++) { |
873c119f |
619 | if (Extremas.SquareDistance(i) < Distance) { |
620 | Distance = Extremas.SquareDistance(i); |
621 | } |
7fd59977 |
622 | } |
873c119f |
623 | Distance = Sqrt(Distance); |
7fd59977 |
624 | } |
625 | else { |
626 | if (TypeC1 == GeomAbs_Circle) { |
873c119f |
627 | Distance = C1.Circle().Radius(); |
7fd59977 |
628 | } |
629 | } |
630 | } |
631 | return Standard_True; |
632 | } |
633 | |
634 | //============================================================================= |
635 | //function : IsSameDistance |
636 | // purpose : |
637 | //============================================================================= |
638 | Standard_Boolean MAT2d_Tool2d::IsSameDistance ( |
873c119f |
639 | const Handle(MAT_Bisector)& BisectorOne, |
640 | const Handle(MAT_Bisector)& BisectorTwo, |
641 | const gp_Pnt2d& PCom, |
642 | Standard_Real& Distance) const |
7fd59977 |
643 | { |
644 | TColStd_Array1OfReal Dist(1,4); |
873c119f |
645 | const Standard_Real eps = 1.e-7; |
7fd59977 |
646 | Standard_Integer IEdge1,IEdge2,IEdge3,IEdge4; |
647 | |
648 | IEdge1 = BisectorOne->FirstEdge() ->EdgeNumber(); |
649 | IEdge2 = BisectorOne->SecondEdge()->EdgeNumber(); |
650 | IEdge3 = BisectorTwo->FirstEdge() ->EdgeNumber(); |
651 | IEdge4 = BisectorTwo->SecondEdge()->EdgeNumber(); |
652 | |
873c119f |
653 | Standard_Boolean isDone1 = Projection(IEdge1,PCom,Dist(1)); |
654 | Standard_Boolean isDone2 = Projection(IEdge2,PCom,Dist(2)); |
655 | |
656 | if(isDone1) |
657 | { |
658 | if(!isDone2) |
659 | { |
660 | Handle(Geom2d_Geometry) Elt = theCircuit->Value(IEdge2); |
661 | Standard_Real Tol = Max(Precision::Confusion(), eps*Dist(1)); |
662 | if(CheckEnds (Elt, PCom, Dist(1), Tol)) |
663 | { |
664 | Dist(2) = Dist(1); |
665 | } |
666 | } |
667 | } |
668 | else |
669 | { |
670 | if(isDone2) |
671 | { |
672 | Handle(Geom2d_Geometry) Elt = theCircuit->Value(IEdge1); |
673 | Standard_Real Tol = Max(Precision::Confusion(), eps*Dist(2)); |
674 | if(CheckEnds (Elt, PCom, Dist(2), Tol)) |
675 | { |
676 | Dist(1) = Dist(2); |
677 | } |
678 | } |
679 | } |
7fd59977 |
680 | |
873c119f |
681 | Standard_Boolean isDone3 = Standard_True, isDone4 = Standard_True; |
7fd59977 |
682 | if (IEdge3 == IEdge1) Dist(3) = Dist(1); |
683 | else if (IEdge3 == IEdge2) Dist(3) = Dist(2); |
873c119f |
684 | else isDone3 = Projection(IEdge3,PCom,Dist(3)); |
7fd59977 |
685 | |
686 | if (IEdge4 == IEdge1) Dist(4) = Dist(1); |
687 | else if (IEdge4 == IEdge2) Dist(4) = Dist(2); |
873c119f |
688 | else isDone4 = Projection(IEdge4,PCom,Dist(4)); |
689 | // |
690 | if(isDone3) |
691 | { |
692 | if(!isDone4) |
693 | { |
694 | Handle(Geom2d_Geometry) Elt = theCircuit->Value(IEdge4); |
695 | Standard_Real Tol = Max(Precision::Confusion(), eps*Dist(3)); |
696 | if(CheckEnds (Elt, PCom, Dist(3), Tol)) |
697 | { |
698 | Dist(4) = Dist(3); |
699 | } |
700 | } |
701 | } |
702 | else |
703 | { |
704 | if(isDone4) |
705 | { |
706 | Handle(Geom2d_Geometry) Elt = theCircuit->Value(IEdge3); |
707 | Standard_Real Tol = Max(Precision::Confusion(), eps*Dist(4)); |
708 | if(CheckEnds (Elt, PCom, Dist(4), Tol)) |
709 | { |
710 | Dist(3) = Dist(4); |
711 | } |
712 | } |
713 | } |
7fd59977 |
714 | |
0797d9d3 |
715 | #ifdef OCCT_DEBUG |
873c119f |
716 | if (AffichDist) |
7fd59977 |
717 | for (Standard_Integer j = 1; j <= 4;j++){ |
718 | cout <<"Distance number : "<<j<<" is :"<< Dist(j)<<endl; |
719 | } |
720 | #endif |
721 | |
873c119f |
722 | Standard_Real EpsDist = MAT2d_TOLCONF*300. ; |
723 | Distance = Dist(1); |
724 | for (Standard_Integer i = 1; i <= 4; i++){ |
c19dd45e |
725 | if (theJoinType == GeomAbs_Intersection && |
726 | Precision::IsInfinite(Dist(i))) |
727 | continue; |
873c119f |
728 | if (Abs(Dist(i) - Distance) > EpsDist) { |
729 | Distance = Precision::Infinite(); |
730 | return Standard_False; |
731 | } |
7fd59977 |
732 | } |
873c119f |
733 | return Standard_True; |
7fd59977 |
734 | } |
735 | |
736 | //============================================================================= |
737 | //function : IntersectBisector |
738 | //purpose : |
739 | //============================================================================= |
740 | Standard_Real MAT2d_Tool2d::IntersectBisector ( |
873c119f |
741 | const Handle(MAT_Bisector)& BisectorOne, |
742 | const Handle(MAT_Bisector)& BisectorTwo, |
743 | Standard_Integer& IntPnt) |
7fd59977 |
744 | { |
745 | Standard_Real Tolerance = MAT2d_TOLCONF; |
746 | Standard_Real Param1,Param2; |
747 | Standard_Real Parama,Paramb; |
1d47d8d0 |
748 | Standard_Real Distance = 0.,DistanceMini; |
7fd59977 |
749 | Standard_Boolean SolutionValide; |
750 | gp_Pnt2d PointSolution; |
751 | |
752 | Handle(Geom2d_TrimmedCurve) |
753 | Bisector1 = Handle(Geom2d_TrimmedCurve) |
873c119f |
754 | ::DownCast(ChangeGeomBis(BisectorOne->BisectorNumber()).ChangeValue()); |
7fd59977 |
755 | |
756 | Handle(Geom2d_TrimmedCurve) |
757 | Bisector2 = Handle(Geom2d_TrimmedCurve) |
873c119f |
758 | ::DownCast(ChangeGeomBis(BisectorTwo->BisectorNumber()).ChangeValue()); |
7fd59977 |
759 | |
760 | if(Bisector1.IsNull() || Bisector2.IsNull()) return Precision::Infinite(); |
761 | |
762 | //------------------------------------------------------------------------- |
763 | // Si les deux bissectrices separent des elements consecutifs et qu elles |
764 | // sont issues des connexions C1 et C2. |
765 | // Si C1 est la reverse de C2 ,alors les deux bissectrices sont issues |
766 | // du meme point. Dans ce cas l intersection n est pas validee. |
767 | //------------------------------------------------------------------------- |
768 | Standard_Integer IS1 = BisectorOne->SecondEdge()->EdgeNumber(); |
769 | Standard_Integer IS2 = BisectorTwo->SecondEdge()->EdgeNumber(); |
770 | Standard_Integer IF1 = BisectorOne->FirstEdge() ->EdgeNumber(); |
771 | Standard_Integer IF2 = BisectorTwo->FirstEdge() ->EdgeNumber(); |
873c119f |
772 | |
7fd59977 |
773 | if (AreNeighbours(IF1,IS1,NumberOfItems()) && |
873c119f |
774 | AreNeighbours(IF2,IS2,NumberOfItems()) && |
775 | theCircuit->ConnexionOn(IS2) && |
776 | theCircuit->ConnexionOn(IS1) ) { |
777 | Handle(MAT2d_Connexion) C1,C2; |
778 | C1 = theCircuit->Connexion(IS1); |
779 | C2 = theCircuit->Connexion(IS2); |
780 | if (C2->IndexFirstLine() == C1->IndexSecondLine() && |
781 | C1->IndexFirstLine() == C2->IndexSecondLine() ) |
782 | return Precision::Infinite(); |
7fd59977 |
783 | } |
784 | |
785 | // ----------------------------------------- |
786 | // Construction des domaines d intersection. |
787 | // ----------------------------------------- |
788 | IntRes2d_Domain Domain1 = Domain(Bisector1,Tolerance); |
789 | IntRes2d_Domain Domain2 = Domain(Bisector2,Tolerance); |
790 | |
791 | if (Domain1.LastParameter() - Domain1.FirstParameter() < Tolerance) |
873c119f |
792 | return Precision::Infinite(); |
7fd59977 |
793 | if (Domain2.LastParameter() - Domain2.FirstParameter() < Tolerance) |
873c119f |
794 | return Precision::Infinite(); |
7fd59977 |
795 | |
0797d9d3 |
796 | #ifdef OCCT_DEBUG |
7fd59977 |
797 | Standard_Boolean Affich = Standard_False; |
798 | if (Affich) { |
799 | cout<<endl; |
800 | cout<<"INTERSECTION de "<<BisectorOne->BisectorNumber()<< |
873c119f |
801 | " et de "<<BisectorTwo->BisectorNumber()<<endl; |
7fd59977 |
802 | cout<<" Bisector 1 : "<<endl; |
873c119f |
803 | // (Bisector1->BasisCurve())->Dump(-1,1); |
7fd59977 |
804 | cout<<endl; |
805 | Debug(Domain1.FirstParameter()); |
806 | Debug(Domain1.LastParameter()); |
807 | cout<<"-----------------"<<endl; |
808 | cout<<" Bisector 2 : "<<endl; |
873c119f |
809 | // (Bisector2->BasisCurve())->Dump(-1,1); |
7fd59977 |
810 | cout<<endl; |
811 | Debug(Domain2.FirstParameter()); |
812 | Debug(Domain2.LastParameter()); |
813 | cout<<"-----------------"<<endl; |
814 | } |
815 | #endif |
816 | |
873c119f |
817 | // ------------------------- |
818 | // Calcul de l intersection. |
819 | // ------------------------- |
7fd59977 |
820 | |
821 | Bisector_Inter Intersect; |
822 | Intersect.Perform (GeomBis(BisectorOne->BisectorNumber()),Domain1, |
873c119f |
823 | GeomBis(BisectorTwo->BisectorNumber()),Domain2, |
824 | Tolerance,Tolerance,Standard_True); |
7fd59977 |
825 | |
873c119f |
826 | // Geom2dInt_GInter Intersect; |
827 | // Intersect.Perform(Bisector1,Domain1,Bisector2,Domain2,Tolerance,Tolerance); |
7fd59977 |
828 | |
873c119f |
829 | // ------------------------------------------------------------------------- |
830 | // Exploitation du resultat de l intersection et selection du point solution |
831 | // equidistant des deux edges et le plus proche en parametre de l origine |
832 | // des bissectrices. |
833 | // ------------------------------------------------------------------------- |
7fd59977 |
834 | |
835 | if(!Intersect.IsDone()) return Precision::Infinite(); |
836 | |
837 | if(Intersect.IsEmpty()) return Precision::Infinite(); |
838 | |
839 | DistanceMini = Precision::Infinite(); |
840 | Param1 = Precision::Infinite(); |
841 | Param2 = Precision::Infinite(); |
842 | SolutionValide = Standard_False; |
843 | |
844 | if(Intersect.NbSegments() >= 1) { |
845 | Standard_Real MaxSegmentLength = 10.*Tolerance; |
846 | for (Standard_Integer i=1;i<=Intersect.NbSegments();i++) { |
847 | IntRes2d_IntersectionSegment Segment = Intersect.Segment(i); |
848 | Standard_Boolean PointRetenu = Standard_False; |
849 | gp_Pnt2d PointOnSegment; |
850 | // ---------------------------------------------------------------- |
851 | // Si les segments sont petits, recherche des points sur le segment |
852 | // equidistants des edges. |
853 | // ---------------------------------------------------------------- |
854 | if ((Segment.HasFirstPoint() && Segment.HasLastPoint())) { |
873c119f |
855 | gp_Pnt2d P1,P2; |
856 | Standard_Real SegmentLength; |
857 | P1 = Segment.FirstPoint().Value(); |
858 | P2 = Segment.LastPoint().Value(); |
859 | SegmentLength = P1.Distance(P2); |
860 | if (SegmentLength <= Tolerance) { |
861 | PointOnSegment = P1; |
862 | if(IsSameDistance(BisectorOne,BisectorTwo, |
863 | PointOnSegment,Distance)) |
864 | PointRetenu = Standard_True; |
865 | } |
866 | else if (SegmentLength <= MaxSegmentLength) { |
867 | gp_Dir2d Dir(P2.X()-P1.X(),P2.Y()-P1.Y()); |
868 | Standard_Real Dist = 0.; |
869 | while (Dist <= SegmentLength + Tolerance){ |
870 | PointOnSegment = P1.Translated(Dist*Dir); |
871 | if(IsSameDistance(BisectorOne,BisectorTwo, |
872 | PointOnSegment,Distance)) { |
873 | PointRetenu = Standard_True; |
874 | break; |
875 | } |
876 | Dist = Dist + Tolerance; |
877 | } |
878 | } |
7fd59977 |
879 | } |
880 | |
881 | // ---------------------------------------------------------------- |
882 | // Sauvegarde du point equidistant des edges de plus petit |
883 | // parametre sur les bissectrices. |
884 | // ---------------------------------------------------------------- |
885 | if(PointRetenu) { |
873c119f |
886 | Parama = Handle(Bisector_Curve)::DownCast(Bisector1->BasisCurve()) |
887 | ->Parameter(PointOnSegment); |
888 | Paramb = Handle(Bisector_Curve)::DownCast(Bisector2->BasisCurve()) |
889 | ->Parameter(PointOnSegment); |
890 | if(Parama < Param1 && Paramb < Param2) { |
891 | Param1 = Parama; |
892 | Param2 = Paramb; |
893 | DistanceMini = Distance; |
894 | PointSolution = PointOnSegment; |
895 | SolutionValide = Standard_True; |
896 | } |
7fd59977 |
897 | } |
898 | } |
899 | } |
900 | |
901 | if(Intersect.NbPoints() != 1) { |
902 | for(Standard_Integer i=1; i<=Intersect.NbPoints(); i++) { |
903 | if(IsSameDistance(BisectorOne,BisectorTwo, |
873c119f |
904 | Intersect.Point(i).Value(),Distance) && |
905 | Distance > Tolerance ) { |
906 | Parama = Intersect.Point(i).ParamOnFirst(); |
907 | Paramb = Intersect.Point(i).ParamOnSecond(); |
908 | if (Parama < Param1 && Paramb < Param2) { |
909 | Param1 = Parama; |
910 | Param2 = Paramb; |
911 | DistanceMini = Distance; |
912 | PointSolution = Intersect.Point(i).Value(); |
913 | SolutionValide = Standard_True; |
914 | } |
7fd59977 |
915 | } |
916 | } |
917 | } |
918 | else { |
919 | PointSolution = Intersect.Point(1).Value(); |
920 | Param1 = Intersect.Point(1).ParamOnFirst(); |
921 | Param2 = Intersect.Point(1).ParamOnSecond(); |
922 | SolutionValide = IsSameDistance(BisectorOne,BisectorTwo, |
873c119f |
923 | PointSolution,DistanceMini); |
7fd59977 |
924 | } |
925 | |
926 | if (!SolutionValide) return Precision::Infinite(); |
927 | theNumberOfPnts++; |
928 | theGeomPnts.Bind(theNumberOfPnts,PointSolution); |
929 | IntPnt = theNumberOfPnts; |
930 | |
931 | //----------------------------------------------------------------------- |
932 | // Si le point d intersection est quasi confondue avec une des extremites |
933 | // de l une ou l autre des bisectrices, l intersection n est pas validee. |
934 | // |
935 | // SAUF si une des bisectrices est issue d une connexion et que les |
936 | // edges separes par les bissectrices sont des voisines sur le contour |
937 | // initiales. |
938 | // en effet le milieu de la connexion P qui est l origine d une des |
939 | // bissectrices peut etre sur l autre bissectrice. |
940 | // P est donc point d intersection |
941 | // et la bissectrice issue de la connexion est de longueur nulle. |
942 | // (ex : un rectangle dans un rectangle ou la connexion est entre un coin |
943 | // et un cote). |
944 | //----------------------------------------------------------------------- |
945 | |
946 | Standard_Integer IndexEdge1,IndexEdge2,IndexEdge3,IndexEdge4; |
947 | Standard_Boolean ExtremiteControle = Standard_True; |
948 | |
949 | IndexEdge1 = BisectorOne->FirstEdge() ->EdgeNumber(); |
950 | IndexEdge2 = BisectorOne->SecondEdge()->EdgeNumber(); |
951 | IndexEdge3 = BisectorTwo->FirstEdge() ->EdgeNumber(); |
952 | IndexEdge4 = BisectorTwo->SecondEdge()->EdgeNumber(); |
873c119f |
953 | |
7fd59977 |
954 | if (theCircuit->ConnexionOn(IndexEdge2)){ |
955 | // -------------------------------------- |
956 | // BisectorOne est issue d une connexion. |
957 | // -------------------------------------- |
873c119f |
958 | if (AreNeighbours(IndexEdge1,IndexEdge2,NumberOfItems()) && |
959 | AreNeighbours(IndexEdge3,IndexEdge4,NumberOfItems()) && |
960 | IndexEdge2 == IndexEdge3 ){ |
961 | ExtremiteControle = Standard_False; |
962 | Param1 = Param1 + Tolerance; |
7fd59977 |
963 | } |
964 | } |
873c119f |
965 | |
7fd59977 |
966 | if (theCircuit->ConnexionOn(IndexEdge4)){ |
873c119f |
967 | //-------------------------------------- |
968 | //BisectorTwo est issue d une connexion. |
969 | //-------------------------------------- |
7fd59977 |
970 | if (AreNeighbours(IndexEdge1,IndexEdge2,NumberOfItems()) && |
873c119f |
971 | AreNeighbours(IndexEdge3,IndexEdge4,NumberOfItems()) && |
972 | IndexEdge2 == IndexEdge3 ){ |
973 | ExtremiteControle = Standard_False; |
974 | Param2 = Param2 + Tolerance; |
7fd59977 |
975 | } |
976 | } |
873c119f |
977 | |
978 | //if (ExtremiteControle) { |
979 | // if(Bisector1->StartPoint().Distance(PointSolution) < Tolerance || |
980 | // Bisector2->StartPoint().Distance(PointSolution) < Tolerance ) |
981 | // return Precision::Infinite(); |
982 | //} |
983 | |
984 | if(ExtremiteControle) |
985 | { |
986 | if(Bisector1->StartPoint().Distance(PointSolution) < Tolerance) |
987 | { |
988 | #ifdef DRAW |
989 | if(AffichBis) |
990 | { |
991 | DrawTrSurf::Set("Bis1", Bisector1); |
992 | DrawTrSurf::Set("Bis2", Bisector2); |
993 | } |
994 | #endif |
7fd59977 |
995 | return Precision::Infinite(); |
873c119f |
996 | } |
997 | if(Bisector2->StartPoint().Distance(PointSolution) < Tolerance) |
998 | { |
999 | |
1000 | #ifdef DRAW |
1001 | if(AffichBis) |
1002 | { |
1003 | DrawTrSurf::Set("Bis1", Bisector1); |
1004 | DrawTrSurf::Set("Bis2", Bisector2); |
1005 | } |
1006 | #endif |
1007 | return Precision::Infinite(); |
1008 | } |
7fd59977 |
1009 | } |
1010 | |
873c119f |
1011 | |
1012 | |
7fd59977 |
1013 | if(BisectorOne->SecondParameter() < Precision::Infinite() && |
873c119f |
1014 | BisectorOne->SecondParameter() < Param1*(1. - Tolerance )) |
7fd59977 |
1015 | return Precision::Infinite(); |
873c119f |
1016 | |
7fd59977 |
1017 | if(BisectorTwo->FirstParameter() < Precision::Infinite() && |
873c119f |
1018 | BisectorTwo->FirstParameter() < Param2*(1.- Tolerance)) |
7fd59977 |
1019 | return Precision::Infinite(); |
1020 | |
1021 | BisectorOne->SecondParameter(Param1); |
1022 | BisectorTwo->FirstParameter (Param2); |
873c119f |
1023 | |
7fd59977 |
1024 | |
0797d9d3 |
1025 | #ifdef OCCT_DEBUG |
7fd59977 |
1026 | if (Affich) { |
1027 | cout<<" coordonnees : "<<GeomPnt (IntPnt).X()<<" " |
873c119f |
1028 | <<GeomPnt (IntPnt).Y()<<endl; |
7fd59977 |
1029 | cout<<" parametres : "<<Param1<<" "<<Param2<<endl; |
1030 | cout<<" distancemini : "<<DistanceMini<<endl; |
1031 | } |
1032 | #endif |
873c119f |
1033 | |
7fd59977 |
1034 | return DistanceMini; |
1035 | } |
1036 | |
1037 | //============================================================================= |
1038 | //function : Distance |
1039 | //purpose : |
1040 | //============================================================================= |
1041 | Standard_Real MAT2d_Tool2d::Distance(const Handle(MAT_Bisector)& Bis, |
873c119f |
1042 | const Standard_Real Param1, |
1043 | const Standard_Real Param2) const |
7fd59977 |
1044 | { |
1045 | Standard_Real Dist = Precision::Infinite(); |
1046 | |
1047 | if (Param1 != Precision::Infinite() && Param2 != Precision::Infinite()) { |
1048 | gp_Pnt2d P1 = GeomBis(Bis->BisectorNumber()).Value()->Value(Param1); |
1049 | gp_Pnt2d P2 = GeomBis(Bis->BisectorNumber()).Value()->Value(Param2); |
1050 | Dist = P1.Distance(P2); |
1051 | } |
1052 | return Dist; |
1053 | } |
1054 | |
1055 | //============================================================================= |
1056 | //function : Dump |
1057 | //purpose : |
1058 | //============================================================================= |
0797d9d3 |
1059 | #ifndef OCCT_DEBUG |
7fd59977 |
1060 | void MAT2d_Tool2d::Dump(const Standard_Integer , |
873c119f |
1061 | const Standard_Integer ) const |
7fd59977 |
1062 | { |
1063 | Standard_NotImplemented::Raise(); |
1064 | #else |
1065 | void MAT2d_Tool2d::Dump(const Standard_Integer bisector, |
873c119f |
1066 | const Standard_Integer) const |
7fd59977 |
1067 | { |
1068 | if(bisector == -1) return; |
1069 | if(bisector > theNumberOfBisectors) return; |
1070 | |
1071 | Handle(Geom2d_Curve) thebisector = GeomBis(bisector).Value(); |
1072 | |
1073 | MAT2d_DrawCurve(thebisector,3); |
1074 | |
1075 | #endif |
1076 | } |
1077 | |
1078 | |
1079 | //============================================================================= |
1080 | //function : GeomBis |
1081 | //purpose : |
1082 | //============================================================================= |
1083 | const Bisector_Bisec& MAT2d_Tool2d::GeomBis (const Standard_Integer Index) |
873c119f |
1084 | const |
7fd59977 |
1085 | { |
1086 | return theGeomBisectors.Find(Index); |
1087 | } |
1088 | |
1089 | //============================================================================= |
1090 | //function : ChangeGeomBis |
1091 | //purpose : |
1092 | //============================================================================= |
1093 | Bisector_Bisec& MAT2d_Tool2d::ChangeGeomBis(const Standard_Integer Index) |
1094 | { |
1095 | return theGeomBisectors.ChangeFind(Index); |
1096 | } |
1097 | |
1098 | |
1099 | //============================================================================= |
1100 | //function : GeomElt |
1101 | //purpose : |
1102 | //============================================================================= |
1103 | Handle(Geom2d_Geometry) MAT2d_Tool2d::GeomElt(const Standard_Integer Index) |
873c119f |
1104 | const |
7fd59977 |
1105 | { |
1106 | return theCircuit->Value(Index); |
1107 | } |
1108 | |
1109 | |
1110 | //============================================================================= |
1111 | //function : GeomPnt |
1112 | //purpose : |
1113 | //============================================================================= |
1114 | const gp_Pnt2d& MAT2d_Tool2d::GeomPnt(const Standard_Integer Index) const |
1115 | { |
1116 | return theGeomPnts.Find(Index); |
1117 | } |
1118 | |
1119 | //============================================================================= |
1120 | //function : GeomVec |
1121 | //purpose : |
1122 | //============================================================================= |
1123 | const gp_Vec2d& MAT2d_Tool2d::GeomVec(const Standard_Integer Index)const |
1124 | { |
1125 | return theGeomVecs.Find(Index); |
1126 | } |
1127 | |
1128 | //============================================================================= |
1129 | //function : Circuit |
1130 | //purpose : |
1131 | //============================================================================= |
1132 | Handle(MAT2d_Circuit) MAT2d_Tool2d::Circuit()const |
1133 | { |
1134 | return theCircuit; |
1135 | } |
1136 | |
1137 | //============================================================================= |
1138 | //function : BisecFusion |
1139 | //purpose : |
1140 | //============================================================================= |
1141 | void MAT2d_Tool2d::BisecFusion(const Standard_Integer I1, |
873c119f |
1142 | const Standard_Integer I2) |
7fd59977 |
1143 | { |
1144 | Standard_Real DU,UL1,UF1; |
1145 | Handle(Geom2d_TrimmedCurve) Bisector1; |
1146 | Handle(Geom2d_TrimmedCurve) Bisector2; |
1147 | |
1148 | Bisector1 = Handle(Geom2d_TrimmedCurve)::DownCast(GeomBis(I1).Value()); |
1149 | Bisector2 = Handle(Geom2d_TrimmedCurve)::DownCast(GeomBis(I2).Value()); |
1150 | UF1 = Bisector1->FirstParameter(); |
1151 | UL1 = Bisector1->LastParameter(); |
1152 | |
1153 | Handle(Standard_Type) Type1 = Bisector1->BasisCurve()->DynamicType(); |
1154 | if (Type1 == STANDARD_TYPE(Bisector_BisecCC)) { |
1155 | //------------------------------------------------------------------------------------ |
1156 | // les bissectrice courbe/courbe sont construites avec un point de depart |
1157 | // elles ne peuvent pas etre trimes par un point se trouvant de l autre cote du |
1158 | // point de depart. |
1159 | // pour faire la fusion des deux bissectrices on reconstruit la bissectrice entre les |
1160 | // deux courbes avec comme point de depart le dernier point de la Bisector2. |
1161 | // on trime ensuite la courbe par le dernier point de Bisector1. |
1162 | //------------------------------------------------------------------------------------ |
1163 | Standard_Real Tolerance = MAT2d_TOLCONF; |
1164 | Bisector_Bisec Bis; |
1165 | gp_Vec2d VBid(1,0); |
1166 | gp_Pnt2d P2 = Bisector2->Value(Bisector2->LastParameter()); |
1167 | gp_Pnt2d P1 = Bisector1->Value(Bisector1->LastParameter()); |
1168 | Handle(Bisector_BisecCC) BCC1 = Handle(Bisector_BisecCC)::DownCast(Bisector1->BasisCurve()); |
1169 | |
1170 | Bis.Perform(BCC1->Curve(2), BCC1->Curve(1), P2, VBid, VBid, |
873c119f |
1171 | theDirection, Tolerance, Standard_False); |
7fd59977 |
1172 | |
1173 | Bisector1 = Handle(Geom2d_TrimmedCurve)::DownCast(Bis.Value()); |
1174 | BCC1 = Handle(Bisector_BisecCC) ::DownCast(Bisector1->BasisCurve()); |
1175 | UF1 = BCC1->FirstParameter(); |
1176 | UL1 = BCC1->Parameter(P1); |
1177 | Bisector1->SetTrim(UF1,UL1); |
1178 | theGeomBisectors.Bind(I1,Bis); |
1179 | } |
1180 | else { |
1181 | DU = Bisector2->LastParameter() - Bisector2->FirstParameter(); |
1182 | UF1 = UF1 - DU; |
1183 | |
1184 | Handle(Bisector_BisecAna) BAna = Handle(Bisector_BisecAna)::DownCast(Bisector1->BasisCurve()); |
873c119f |
1185 | //---------------------------- uncomment if new method Bisector_BisecAna::SetTrim(f,l) is not used |
1186 | // Handle(Geom2d_Curve) C2d = BAna->Geom2dCurve(); |
1187 | // Handle(Geom2d_TrimmedCurve) trimC2d = new Geom2d_TrimmedCurve(C2d, UF1, UL1); |
1188 | // BAna->Init(trimC2d); |
1189 | //--------------------------- end |
7fd59977 |
1190 | BAna->SetTrim(UF1,UL1); // put comment if SetTrim(f,l) is not used |
1191 | |
1192 | Bisector1->SetTrim(UF1,UL1); |
1193 | } |
1194 | } |
1195 | |
1196 | //============================================================================= |
1197 | //function : Type |
1198 | //purpose : |
1199 | //============================================================================= |
1200 | static Handle(Standard_Type) Type(const Handle(Geom2d_Geometry)& aGeom) |
1201 | { |
1202 | Handle(Standard_Type) type = aGeom->DynamicType(); |
1203 | Handle(Geom2d_Curve) curve; |
1204 | |
1205 | if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) { |
1206 | curve = Handle(Geom2d_TrimmedCurve)::DownCast(aGeom)->BasisCurve(); |
1207 | type = curve->DynamicType(); |
1208 | } |
1209 | return type; |
1210 | } |
1211 | |
1212 | //========================================================================== |
1213 | //function : AreNeighbours |
1214 | //purpose : Return TRUE si IEdge1 et IEdge2 correspondent a des elements |
1215 | // consecutifs sur un contour ferme de NbEdge elements. |
1216 | //========================================================================== |
1217 | Standard_Boolean AreNeighbours(const Standard_Integer IEdge1, |
873c119f |
1218 | const Standard_Integer IEdge2, |
1219 | const Standard_Integer NbEdge) |
7fd59977 |
1220 | { |
1221 | if (Abs(IEdge1 - IEdge2) == 1) return Standard_True; |
1222 | else if (Abs(IEdge1 - IEdge2) == NbEdge -1) return Standard_True; |
1223 | else return Standard_False; |
1224 | } |
1225 | |
1226 | //========================================================================== |
1227 | //function : SetTrim |
1228 | //purpose : |
1229 | //========================================================================== |
1230 | void SetTrim(Bisector_Bisec& Bis, Handle(Geom2d_Curve)& Line1) |
1231 | { |
1232 | Geom2dInt_GInter Intersect; |
1233 | Standard_Real Distance; |
1234 | Standard_Real Tolerance = MAT2d_TOLCONF; |
1235 | Handle(Geom2d_TrimmedCurve) Bisector = |
1236 | Handle(Geom2d_TrimmedCurve)::DownCast(Bis.ChangeValue()); |
1237 | |
1238 | IntRes2d_Domain Domain1 = Domain(Bisector,Tolerance); |
1239 | Standard_Real UB1 = Bisector->FirstParameter(); |
1240 | Standard_Real UB2 = Bisector->LastParameter(); |
873c119f |
1241 | |
7fd59977 |
1242 | gp_Pnt2d FirstPointBisector = Bisector->Value(UB1); |
1243 | Standard_Real UTrim = Precision::Infinite(); |
1244 | |
1245 | Geom2dAdaptor_Curve AdapBisector(Bisector); |
1246 | Geom2dAdaptor_Curve AdapLine1 (Line1); |
1247 | Intersect.Perform(AdapBisector, Domain1, |
873c119f |
1248 | AdapLine1, Tolerance, Tolerance); |
7fd59977 |
1249 | |
1250 | if (Intersect.IsDone() && !Intersect.IsEmpty()) { |
1251 | for (Standard_Integer i = 1; i <= Intersect.NbPoints(); i++) { |
1252 | gp_Pnt2d PInt = Intersect.Point(i).Value(); |
1253 | Distance = FirstPointBisector.Distance(PInt); |
1254 | if (Distance > 10.*Tolerance && |
873c119f |
1255 | Intersect.Point(i).ParamOnFirst() < UTrim ) { |
1256 | UTrim = Intersect.Point(i).ParamOnFirst(); |
7fd59977 |
1257 | } |
1258 | } |
1259 | } |
1260 | // ------------------------------------------------------------------------ |
1261 | // Restriction de la Bissectrice par le point d intersection de plus petit |
1262 | // parametre. |
1263 | // ------------------------------------------------------------------------ |
1264 | if (UTrim < UB2 && UTrim > UB1) Bisector->SetTrim(UB1,UTrim); |
1265 | } |
1266 | |
1267 | //========================================================================== |
1268 | //function : Domain |
1269 | //purpose : |
1270 | //========================================================================== |
1271 | IntRes2d_Domain Domain(const Handle(Geom2d_TrimmedCurve)& Bisector1, |
873c119f |
1272 | const Standard_Real Tolerance) |
7fd59977 |
1273 | { |
1274 | Standard_Real Param1 = Bisector1->FirstParameter(); |
1275 | Standard_Real Param2 = Bisector1->LastParameter(); |
1276 | if(Param2 > 10000.) { |
1277 | Param2 = 10000.; |
1278 | Handle(Standard_Type) Type1 = Type(Bisector1->BasisCurve()); |
1279 | Handle(Geom2d_Curve) BasisCurve; |
1280 | if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) { |
1281 | BasisCurve = Handle(Bisector_BisecAna) |
873c119f |
1282 | ::DownCast(Bisector1->BasisCurve())->Geom2dCurve(); |
7fd59977 |
1283 | Type1 = BasisCurve->DynamicType(); |
1284 | } |
1285 | gp_Parab2d gpParabola; |
1286 | gp_Hypr2d gpHyperbola; |
1287 | Standard_Real Focus; |
1288 | Standard_Real Limit = 50000.; |
1289 | if (Type1 == STANDARD_TYPE(Geom2d_Parabola)) { |
1290 | gpParabola = Handle(Geom2d_Parabola)::DownCast(BasisCurve)->Parab2d(); |
1291 | Focus = gpParabola.Focal(); |
1292 | Standard_Real Val1 = Sqrt(Limit*Focus); |
1293 | Standard_Real Val2 = Sqrt(Limit*Limit); |
1294 | Param2 = (Val1 <= Val2 ? Val1:Val2); |
1295 | } |
1296 | else if (Type1 == STANDARD_TYPE(Geom2d_Hyperbola)) { |
1297 | gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(BasisCurve)->Hypr2d(); |
1298 | Standard_Real Majr = gpHyperbola.MajorRadius(); |
1299 | Standard_Real Minr = gpHyperbola.MinorRadius(); |
1300 | Standard_Real Valu1 = Limit/Majr; |
1301 | Standard_Real Valu2 = Limit/Minr; |
1302 | Standard_Real Val1 = Log(Valu1+Sqrt(Valu1*Valu1-1)); |
1303 | Standard_Real Val2 = Log(Valu2+Sqrt(Valu2*Valu2+1)); |
1304 | Param2 = (Val1 <= Val2 ? Val1:Val2); |
1305 | } |
1306 | } |
873c119f |
1307 | |
7fd59977 |
1308 | IntRes2d_Domain Domain1(Bisector1->Value(Param1),Param1,Tolerance, |
873c119f |
1309 | Bisector1->Value(Param2),Param2,Tolerance); |
7fd59977 |
1310 | if(Bisector1->BasisCurve()->IsPeriodic()) { |
c6541a0c |
1311 | Domain1.SetEquivalentParameters(0.,2.*M_PI); |
7fd59977 |
1312 | } |
1313 | return Domain1; |
1314 | } |
1315 | |
873c119f |
1316 | //============================================================================= |
1317 | //function : CheckEnds |
1318 | //purpose : |
1319 | //============================================================================= |
1320 | Standard_Boolean CheckEnds (const Handle(Geom2d_Geometry)& Elt , |
1321 | const gp_Pnt2d& PCom , |
1322 | const Standard_Real Distance, |
1323 | const Standard_Real Tol) |
1324 | |
1325 | { |
1326 | Handle(Standard_Type) Type = Elt->DynamicType(); |
1327 | Handle(Geom2d_TrimmedCurve) Curve; |
1328 | |
1329 | if (Type == STANDARD_TYPE(Geom2d_CartesianPoint)) { |
1330 | return Standard_False; |
1331 | } |
1332 | else { |
1333 | Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Elt); |
1334 | gp_Pnt2d aPf = Curve->StartPoint(); |
1335 | gp_Pnt2d aPl = Curve->EndPoint(); |
1336 | Standard_Real df = PCom.Distance(aPf); |
1337 | Standard_Real dl = PCom.Distance(aPl); |
1338 | if(Abs(df - Distance) <= Tol) |
1339 | return Standard_True; |
1340 | if(Abs(dl - Distance) <= Tol) |
1341 | return Standard_True; |
1342 | } |
1343 | return Standard_False; |
1344 | } |
1345 | |
1346 | |
0797d9d3 |
1347 | #ifdef OCCT_DEBUG |
7fd59977 |
1348 | //========================================================================== |
1349 | //function : MAT2d_DrawCurve |
1350 | //purpose : Affichage d une courbe <aCurve> de Geom2d. dans une couleur |
1351 | // definie par <Indice>. |
1352 | // Indice = 1 jaune, |
1353 | // Indice = 2 bleu, |
1354 | // Indice = 3 rouge, |
1355 | // Indice = 4 vert. |
1356 | //========================================================================== |
1357 | void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve, |
873c119f |
1358 | const Standard_Integer /*Indice*/) |
7fd59977 |
1359 | { |
1360 | Handle(Standard_Type) type = aCurve->DynamicType(); |
1361 | Handle(Geom2d_Curve) curve,CurveDraw; |
1362 | #ifdef DRAW |
1363 | Handle(DrawTrSurf_Curve2d) dr; |
1364 | Draw_Color Couleur; |
1365 | #endif |
1366 | |
1367 | if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) { |
1368 | curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve(); |
1369 | type = curve->DynamicType(); |
1370 | // PB de representation des courbes semi_infinies. |
1371 | gp_Parab2d gpParabola; |
1372 | gp_Hypr2d gpHyperbola; |
1373 | Standard_Real Focus; |
1374 | Standard_Real Limit = 50000.; |
1375 | Standard_Real delta = 400; |
1376 | |
1377 | // PB de representation des courbes semi_infinies. |
1378 | if (aCurve->LastParameter() == Precision::Infinite()) { |
873c119f |
1379 | |
7fd59977 |
1380 | if (type == STANDARD_TYPE(Geom2d_Parabola)) { |
873c119f |
1381 | gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d(); |
1382 | Focus = gpParabola.Focal(); |
1383 | Standard_Real Val1 = Sqrt(Limit*Focus); |
1384 | Standard_Real Val2 = Sqrt(Limit*Limit); |
1385 | delta= (Val1 <= Val2 ? Val1:Val2); |
7fd59977 |
1386 | } |
1387 | else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) { |
873c119f |
1388 | gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d(); |
1389 | Standard_Real Majr = gpHyperbola.MajorRadius(); |
1390 | Standard_Real Minr = gpHyperbola.MinorRadius(); |
1391 | Standard_Real Valu1 = Limit/Majr; |
1392 | Standard_Real Valu2 = Limit/Minr; |
1393 | Standard_Real Val1 = Log(Valu1+Sqrt(Valu1*Valu1-1)); |
1394 | Standard_Real Val2 = Log(Valu2+Sqrt(Valu2*Valu2+1)); |
1395 | delta = (Val1 <= Val2 ? Val1:Val2); |
7fd59977 |
1396 | } |
1397 | CurveDraw = new Geom2d_TrimmedCurve(aCurve, |
873c119f |
1398 | aCurve->FirstParameter(), |
1399 | aCurve->FirstParameter() + delta); |
7fd59977 |
1400 | } |
1401 | else { |
1402 | CurveDraw = aCurve; |
1403 | } |
1404 | // fin PB. |
1405 | } |
1406 | else { |
1407 | CurveDraw = aCurve; |
1408 | } |
1409 | |
1410 | #ifdef DRAW |
873c119f |
1411 | Standard_Integer Indice = 1; |
7fd59977 |
1412 | if (Indice == 1) Couleur = Draw_jaune; |
1413 | else if (Indice == 2) Couleur = Draw_bleu; |
1414 | else if (Indice == 3) Couleur = Draw_rouge; |
1415 | else if (Indice == 4) Couleur = Draw_vert; |
1416 | |
1417 | if (type == STANDARD_TYPE(Geom2d_Circle)) |
1418 | dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30); |
1419 | else if (type == STANDARD_TYPE(Geom2d_Line)) |
1420 | dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2); |
1421 | else |
1422 | dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500); |
1423 | |
873c119f |
1424 | //dout << dr; |
1425 | //dout.Flush(); |
7fd59977 |
1426 | #endif |
1427 | } |
1428 | |
1429 | #endif |
1430 | |