1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // GEOM SKETCHER : basic sketcher
24 // File : Sketcher_Profile.cxx
25 // Author : Damien COQUERET
28 #include <Standard_Stream.hxx>
30 #include <Sketcher_Profile.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopoDS_Face.hxx>
34 #include <BRepLib.hxx>
35 #include <BRepBuilderAPI_MakeVertex.hxx>
36 #include <BRepBuilderAPI_MakeEdge.hxx>
37 #include <BRepBuilderAPI_MakeWire.hxx>
38 #include <BRepBuilderAPI_MakeFace.hxx>
40 #include <GeomAPI.hxx>
41 #include <Geom2d_Line.hxx>
42 #include <Geom2d_Circle.hxx>
43 #include <Geom_Surface.hxx>
45 #include <Precision.hxx>
49 #include <TCollection_AsciiString.hxx>
50 #include <TColStd_Array1OfAsciiString.hxx>
52 #include "utilities.h"
54 //=======================================================================
56 // command to build a profile
57 //=======================================================================
58 Sketcher_Profile::Sketcher_Profile()
63 //=======================================================================
65 // command to build a profile
66 //=======================================================================
67 Sketcher_Profile::Sketcher_Profile(const char* aCmd)
69 enum {line, circle, point, none} move;
71 Standard_Integer i = 1;
72 Standard_Real x0, y0, x, y, dx, dy;
73 x0 = y0 = x = y = dy = 0;
76 Standard_Boolean first, stayfirst, face, close;
77 first = Standard_True;
78 stayfirst = face = close = Standard_False;
80 Standard_Integer reversed = 0;
81 Standard_Integer control_Tolerance = 0;
85 BRepBuilderAPI_MakeWire MW;
86 gp_Ax3 DummyHP(gp::XOY());
88 TopLoc_Location TheLocation;
89 Handle(Geom_Surface) Surface;
91 myOK = Standard_False;
94 //TCollection_AsciiString aCommand(CORBA::string_dup(aCmd));
95 TCollection_AsciiString aCommand ((char*)aCmd);
96 TCollection_AsciiString aToken = aCommand.Token(":", 1);
99 TColStd_Array1OfAsciiString aTab (0, aCommand.Length() - 1);
100 if ( aCommand.Length() )
102 while(aToken.Length() != 0) {
103 if(aCommand.Token(":", n + 1).Length() > 0)
104 aTab(n) = aCommand.Token(":", n + 1);
105 aToken = aCommand.Token(":", ++n);
109 if ( aTab.Length() && aTab(0).Length() )
111 Standard_Real length = 0, radius = 0, angle = 0;
115 TColStd_Array1OfAsciiString a (0, aTab(0).Length());
116 aToken = aTab(i).Token(" ", 1);
117 while (aToken.Length() != 0) {
118 if (aTab(i).Token(" ", n1 + 1).Length() > 0)
119 a(n1) = aTab(i).Token(" ", n1 + 1);
120 aToken = aTab(i).Token(" ", ++n1);
124 switch(a(0).Value(1))
128 if (n1 != 3) goto badargs;
130 MESSAGE("profile : The F instruction must precede all moves");
133 x0 = x = a(1).RealValue();
134 y0 = y = a(2).RealValue();
135 stayfirst = Standard_True;
140 if (n1 != 4) goto badargs;
141 P.SetLocation(gp_Pnt(a(1).RealValue(), a(2).RealValue(), a(3).RealValue()));
142 stayfirst = Standard_True;
147 if (n1 != 7) goto badargs;
148 gp_Vec vn(a(1).RealValue(), a(2).RealValue(), a(3).RealValue());
149 gp_Vec vx(a(4).RealValue(), a(5).RealValue(), a(6).RealValue());
150 if (vn.Magnitude() <= Precision::Confusion() || vx.Magnitude() <= Precision::Confusion()) {
151 MESSAGE("profile : null direction");
154 gp_Ax2 ax(P.Location(), vn, vx);
156 stayfirst = Standard_True;
161 if (n1 != 2) goto badargs;
162 length = a(1).RealValue();
171 if (n1 != 2) goto badargs;
172 length = a(1).RealValue();
181 if (n1 != 2) goto badargs;
182 length = a(1).RealValue();
183 if (Abs(length) > Precision::Confusion())
191 if (n1 != 3) goto badargs;
192 Standard_Real vx = a(1).RealValue();
193 Standard_Real vy = a(2).RealValue();
198 length = Sqrt(vx * vx + vy * vy);
199 if (length > Precision::Confusion()) {
210 if (n1 != 2) goto badargs;
211 angle = a(1).RealValue() * M_PI / 180.;
217 Standard_Real c = Cos(angle);
218 Standard_Real s = Sin(angle);
219 Standard_Real t = c * dx - s * dy;
220 dy = s * dx + c * dy;
227 if (n1 != 3) goto badargs;
228 Standard_Real vx = a(1).RealValue();
229 Standard_Real vy = a(2).RealValue();
230 length = Sqrt(vx * vx + vy * vy);
231 if (length > Precision::Confusion()) {
241 if (n1 != 3) goto badargs;
242 radius = a(1).RealValue();
243 if (Abs(radius) > Precision::Confusion()) {
244 angle = a(2).RealValue() * M_PI / 180.;
251 case 'A': // TAngential arc by end point
253 if (n1 != 3) goto badargs;
254 Standard_Real vx = a(1).RealValue();
255 Standard_Real vy = a(2).RealValue();
260 Standard_Real det = dx * vy - dy * vx;
261 if ( Abs(det) > Precision::Confusion()) {
262 // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
263 Standard_Real c = (dx * vx + dy * vy) / Sqrt((dx * dx + dy * dy) * (vx * vx + vy * vy));
264 // radius = distance between start and end point / 2 * sin(alpha)
265 // radius is > 0 or < 0
266 radius = (vx * vx + vy * vy)* Sqrt(dx * dx + dy * dy) / (2.0 * det);
267 if (Abs(radius) > Precision::Confusion()) {
268 angle = 2.0 * acos(c); // angle in [0,2Pi]
279 case 'U': // Arc by end point and radiUs
281 if (n1 != 5) goto badargs;
282 Standard_Real vx = a(1).RealValue();
283 Standard_Real vy = a(2).RealValue();
284 radius = a(3).RealValue();
285 reversed = a(4).IntegerValue();
286 if (a(0) == "UU") { // Absolute
290 Standard_Real length = Sqrt(vx * vx + vy * vy);
291 if ( (4.0 - (vx * vx + vy * vy) / (radius * radius) >= 0.0 ) && (length > Precision::Confusion()) ) {
292 // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
293 Standard_Real c = 0.5 * Sqrt(4.0 - (vx * vx + vy * vy) / (radius * radius));
294 angle = 2.0 * acos(c); // angle in [0,Pi]
296 angle = angle - 2 * M_PI;
297 dx = 0.5 * ( vy * 1.0/radius
298 + vx * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
299 dy = - 0.5 * ( vx * 1.0/radius
300 - vy * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
308 case 'E': // Arc by end point and cEnter
310 if (n1 != 7) goto badargs;
311 Standard_Real vx = a(1).RealValue();
312 Standard_Real vy = a(2).RealValue();
313 Standard_Real vxc = a(3).RealValue();
314 Standard_Real vyc = a(4).RealValue();
315 reversed = a(5).IntegerValue();
316 control_Tolerance = a(6).IntegerValue();
318 if (a(0) == "EE") { // Absolute
324 radius = Sqrt( vxc * vxc + vyc * vyc );
325 Standard_Real det = vx * vyc - vy * vxc;
326 Standard_Real length = Sqrt(vx * vx + vy * vy);
327 Standard_Real length2 = Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc));
328 Standard_Real length3 = Sqrt(vxc * vxc + vyc * vyc);
329 Standard_Real error = Abs(length2 - radius);
331 if ( error > Precision::Confusion() ){
332 MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
334 if ( error > Precision::Confusion() && control_Tolerance == 1) // Don't create the arc if the end point
335 move = none; // is too far from it
336 else if ( (length > Precision::Confusion()) &&
337 (length2 > Precision::Confusion()) &&
338 (length3 > Precision::Confusion()) ) {
339 Standard_Real c = ( radius * radius - (vx * vxc + vy * vyc) )
340 / ( radius * Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc)) ) ; // Cosine of arc angle
341 angle = acos(c); // angle in [0,Pi]
343 angle = angle - 2 * M_PI;
357 if (n1 != 2) goto badargs;
358 length = a(1).RealValue();
360 if (Abs(dx) < Precision::Confusion()) {
361 MESSAGE("profile : cannot intersect, arg "<<i-1);
364 length = (length - x) / dx;
366 else if (a(0) == "IY") {
367 if (Abs(dy) < Precision::Confusion()) {
368 MESSAGE("profile : cannot intersect, arg "<<i-1);
371 length = (length - y) / dy;
373 if (Abs(length) > Precision::Confusion())
382 close = Standard_True;
383 else if(a(0) == "WF") {
384 close = Standard_True;
385 face = Standard_True;
392 MESSAGE("profile : unknown code " << a(i));
407 Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
408 BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(l,P),0,length);
418 Standard_Boolean sense = Standard_True;
425 gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
430 Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
431 BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(c,P),0,angle);
446 MP = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, 0.0));
458 stayfirst = Standard_False;
460 if(!(dx == 0 && dy == 0))
461 myLastDir.SetCoord(dx, dy, 0.0);
469 if ((i == n) && close) {
470 // the closing segment
473 length = Sqrt(dx * dx + dy * dy);
475 if (length > Precision::Confusion()) {
483 // get the result, face or wire
486 } else if (move == point) {
492 BRepBuilderAPI_MakeFace MF (P, MW.Wire());
504 if(!TheLocation.IsIdentity())
512 MESSAGE("profile : bad number of arguments");