1 // Copyright (C) 2007-2011 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
22 // GEOM SKETCHER : basic sketcher
23 // File : Sketcher_Profile.cxx
24 // Author : Damien COQUERET
27 #include <Standard_Stream.hxx>
29 #include <Sketcher_Profile.hxx>
31 #include <TopoDS_Vertex.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <BRepLib.hxx>
34 #include <BRepBuilderAPI_MakeVertex.hxx>
35 #include <BRepBuilderAPI_MakeEdge.hxx>
36 #include <BRepBuilderAPI_MakeWire.hxx>
37 #include <BRepBuilderAPI_MakeFace.hxx>
39 #include <GeomAPI.hxx>
40 #include <Geom2d_Line.hxx>
41 #include <Geom2d_Circle.hxx>
42 #include <Geom_Surface.hxx>
44 #include <Precision.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <TColStd_Array1OfAsciiString.hxx>
51 #include "utilities.h"
53 //=======================================================================
55 // command to build a profile
56 //=======================================================================
57 Sketcher_Profile::Sketcher_Profile()
62 //=======================================================================
64 // command to build a profile
65 //=======================================================================
66 Sketcher_Profile::Sketcher_Profile(const char* aCmd)
68 enum {line, circle, point, none} move;
70 Standard_Integer i = 1;
71 Standard_Real x0, y0, x, y, dx, dy;
72 x0 = y0 = x = y = dy = 0;
75 Standard_Boolean first, stayfirst, face, close;
76 first = Standard_True;
77 stayfirst = face = close = Standard_False;
79 Standard_Integer reversed = 0;
80 Standard_Integer control_Tolerance = 0;
84 BRepBuilderAPI_MakeWire MW;
85 gp_Ax3 DummyHP(gp::XOY());
87 TopLoc_Location TheLocation;
88 Handle(Geom_Surface) Surface;
90 myOK = Standard_False;
93 //TCollection_AsciiString aCommand(CORBA::string_dup(aCmd));
94 TCollection_AsciiString aCommand ((char*)aCmd);
95 TCollection_AsciiString aToken = aCommand.Token(":", 1);
98 TColStd_Array1OfAsciiString aTab (0, aCommand.Length() - 1);
99 if ( aCommand.Length() )
101 while(aToken.Length() != 0) {
102 if(aCommand.Token(":", n + 1).Length() > 0)
103 aTab(n) = aCommand.Token(":", n + 1);
104 aToken = aCommand.Token(":", ++n);
108 if ( aTab.Length() && aTab(0).Length() )
110 Standard_Real length = 0, radius = 0, angle = 0;
114 TColStd_Array1OfAsciiString a (0, aTab(0).Length());
115 aToken = aTab(i).Token(" ", 1);
116 while (aToken.Length() != 0) {
117 if (aTab(i).Token(" ", n1 + 1).Length() > 0)
118 a(n1) = aTab(i).Token(" ", n1 + 1);
119 aToken = aTab(i).Token(" ", ++n1);
123 switch(a(0).Value(1))
127 if (n1 != 3) goto badargs;
129 MESSAGE("profile : The F instruction must precede all moves");
132 x0 = x = a(1).RealValue();
133 y0 = y = a(2).RealValue();
134 stayfirst = Standard_True;
139 if (n1 != 4) goto badargs;
140 P.SetLocation(gp_Pnt(a(1).RealValue(), a(2).RealValue(), a(3).RealValue()));
141 stayfirst = Standard_True;
146 if (n1 != 7) goto badargs;
147 gp_Vec vn(a(1).RealValue(), a(2).RealValue(), a(3).RealValue());
148 gp_Vec vx(a(4).RealValue(), a(5).RealValue(), a(6).RealValue());
149 if (vn.Magnitude() <= Precision::Confusion() || vx.Magnitude() <= Precision::Confusion()) {
150 MESSAGE("profile : null direction");
153 gp_Ax2 ax(P.Location(), vn, vx);
155 stayfirst = Standard_True;
160 if (n1 != 2) goto badargs;
161 length = a(1).RealValue();
170 if (n1 != 2) goto badargs;
171 length = a(1).RealValue();
180 if (n1 != 2) goto badargs;
181 length = a(1).RealValue();
182 if (Abs(length) > Precision::Confusion())
190 if (n1 != 3) goto badargs;
191 Standard_Real vx = a(1).RealValue();
192 Standard_Real vy = a(2).RealValue();
197 length = Sqrt(vx * vx + vy * vy);
198 if (length > Precision::Confusion()) {
209 if (n1 != 2) goto badargs;
210 angle = a(1).RealValue() * M_PI / 180.;
216 Standard_Real c = Cos(angle);
217 Standard_Real s = Sin(angle);
218 Standard_Real t = c * dx - s * dy;
219 dy = s * dx + c * dy;
226 if (n1 != 3) goto badargs;
227 Standard_Real vx = a(1).RealValue();
228 Standard_Real vy = a(2).RealValue();
229 length = Sqrt(vx * vx + vy * vy);
230 if (length > Precision::Confusion()) {
240 if (n1 != 3) goto badargs;
241 radius = a(1).RealValue();
242 if (Abs(radius) > Precision::Confusion()) {
243 angle = a(2).RealValue() * M_PI / 180.;
250 case 'A': // TAngential arc by end point
252 if (n1 != 3) goto badargs;
253 Standard_Real vx = a(1).RealValue();
254 Standard_Real vy = a(2).RealValue();
259 Standard_Real det = dx * vy - dy * vx;
260 if ( Abs(det) > Precision::Confusion()) {
261 // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
262 Standard_Real c = (dx * vx + dy * vy) / Sqrt((dx * dx + dy * dy) * (vx * vx + vy * vy));
263 // radius = distance between start and end point / 2 * sin(alpha)
264 // radius is > 0 or < 0
265 radius = (vx * vx + vy * vy)* Sqrt(dx * dx + dy * dy) / (2.0 * det);
266 if (Abs(radius) > Precision::Confusion()) {
267 angle = 2.0 * acos(c); // angle in [0,2Pi]
278 case 'U': // Arc by end point and radiUs
280 if (n1 != 5) goto badargs;
281 Standard_Real vx = a(1).RealValue();
282 Standard_Real vy = a(2).RealValue();
283 radius = a(3).RealValue();
284 reversed = a(4).IntegerValue();
285 if (a(0) == "UU") { // Absolute
289 Standard_Real length = Sqrt(vx * vx + vy * vy);
290 if ( (4.0 - (vx * vx + vy * vy) / (radius * radius) >= 0.0 ) && (length > Precision::Confusion()) ) {
291 // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
292 Standard_Real c = 0.5 * Sqrt(4.0 - (vx * vx + vy * vy) / (radius * radius));
293 angle = 2.0 * acos(c); // angle in [0,Pi]
295 angle = angle - 2 * M_PI;
296 dx = 0.5 * ( vy * 1.0/radius
297 + vx * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
298 dy = - 0.5 * ( vx * 1.0/radius
299 - vy * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
307 case 'E': // Arc by end point and cEnter
309 if (n1 != 7) goto badargs;
310 Standard_Real vx = a(1).RealValue();
311 Standard_Real vy = a(2).RealValue();
312 Standard_Real vxc = a(3).RealValue();
313 Standard_Real vyc = a(4).RealValue();
314 reversed = a(5).IntegerValue();
315 control_Tolerance = a(6).IntegerValue();
317 if (a(0) == "EE") { // Absolute
323 radius = Sqrt( vxc * vxc + vyc * vyc );
324 Standard_Real det = vx * vyc - vy * vxc;
325 Standard_Real length = Sqrt(vx * vx + vy * vy);
326 Standard_Real length2 = Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc));
327 Standard_Real length3 = Sqrt(vxc * vxc + vyc * vyc);
328 Standard_Real error = Abs(length2 - radius);
330 if ( error > Precision::Confusion() ){
331 MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
333 if ( error > Precision::Confusion() && control_Tolerance == 1) // Don't create the arc if the end point
334 move = none; // is too far from it
335 else if ( (length > Precision::Confusion()) &&
336 (length2 > Precision::Confusion()) &&
337 (length3 > Precision::Confusion()) ) {
338 Standard_Real c = ( radius * radius - (vx * vxc + vy * vyc) )
339 / ( radius * Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc)) ) ; // Cosine of arc angle
340 angle = acos(c); // angle in [0,Pi]
342 angle = angle - 2 * M_PI;
356 if (n1 != 2) goto badargs;
357 length = a(1).RealValue();
359 if (Abs(dx) < Precision::Confusion()) {
360 MESSAGE("profile : cannot intersect, arg "<<i-1);
363 length = (length - x) / dx;
365 else if (a(0) == "IY") {
366 if (Abs(dy) < Precision::Confusion()) {
367 MESSAGE("profile : cannot intersect, arg "<<i-1);
370 length = (length - y) / dy;
372 if (Abs(length) > Precision::Confusion())
381 close = Standard_True;
382 else if(a(0) == "WF") {
383 close = Standard_True;
384 face = Standard_True;
391 MESSAGE("profile : unknown code " << a(i));
406 Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
407 BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(l,P),0,length);
417 Standard_Boolean sense = Standard_True;
424 gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
429 Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
430 BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(c,P),0,angle);
445 MP = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, 0.0));
457 stayfirst = Standard_False;
459 if(!(dx == 0 && dy == 0))
460 myLastDir.SetCoord(dx, dy, 0.0);
468 if ((i == n) && close) {
469 // the closing segment
472 length = Sqrt(dx * dx + dy * dy);
474 if (length > Precision::Confusion()) {
482 // get the result, face or wire
485 } else if (move == point) {
491 BRepBuilderAPI_MakeFace MF (P, MW.Wire());
503 if(!TheLocation.IsIdentity())
511 MESSAGE("profile : bad number of arguments");