Back to index

salome-geom  6.5.0
Sketcher_Profile.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  GEOM SKETCHER : basic sketcher
00024 //  File   : Sketcher_Profile.cxx
00025 //  Author : Damien COQUERET
00026 //  Module : GEOM
00027 
00028 #include <Standard_Stream.hxx>
00029 
00030 #include <Sketcher_Profile.hxx>
00031 
00032 #include <TopoDS_Vertex.hxx>
00033 #include <TopoDS_Face.hxx>
00034 #include <BRepLib.hxx>
00035 #include <BRepBuilderAPI_MakeVertex.hxx>
00036 #include <BRepBuilderAPI_MakeEdge.hxx>
00037 #include <BRepBuilderAPI_MakeWire.hxx>
00038 #include <BRepBuilderAPI_MakeFace.hxx>
00039 
00040 #include <GeomAPI.hxx>
00041 #include <Geom2d_Line.hxx>
00042 #include <Geom2d_Circle.hxx>
00043 #include <Geom_Surface.hxx>
00044 
00045 #include <Precision.hxx>
00046 #include <gp_Pln.hxx>
00047 #include <gp_Ax2.hxx>
00048 
00049 #include <TCollection_AsciiString.hxx>
00050 #include <TColStd_Array1OfAsciiString.hxx>
00051 
00052 #include "utilities.h"
00053 
00054 //=======================================================================
00055 // profile
00056 // command to build a profile
00057 //=======================================================================
00058 Sketcher_Profile::Sketcher_Profile()
00059 {
00060 }
00061 
00062 
00063 //=======================================================================
00064 // profile
00065 // command to build a profile
00066 //=======================================================================
00067 Sketcher_Profile::Sketcher_Profile(const char* aCmd)
00068 {
00069   enum {line, circle, point, none} move;
00070 
00071   Standard_Integer i = 1;
00072   Standard_Real x0, y0, x, y, dx, dy;
00073   x0 = y0 = x = y = dy = 0;
00074   dx = 1;
00075 
00076   Standard_Boolean first, stayfirst, face, close;
00077   first = Standard_True;
00078   stayfirst = face = close = Standard_False;
00079 
00080   Standard_Integer reversed = 0;
00081   Standard_Integer control_Tolerance = 0;
00082 
00083   TopoDS_Shape S;
00084   TopoDS_Vertex MP;
00085   BRepBuilderAPI_MakeWire MW;
00086   gp_Ax3 DummyHP(gp::XOY());
00087   gp_Pln P(DummyHP);
00088   TopLoc_Location TheLocation;
00089   Handle(Geom_Surface) Surface;
00090 
00091   myOK = Standard_False;
00092   myError = 0;
00093 
00094   //TCollection_AsciiString aCommand(CORBA::string_dup(aCmd));
00095   TCollection_AsciiString aCommand ((char*)aCmd);
00096   TCollection_AsciiString aToken = aCommand.Token(":", 1);
00097   int n = 0;
00098   // porting to WNT
00099   TColStd_Array1OfAsciiString aTab (0, aCommand.Length() - 1);
00100   if ( aCommand.Length() )
00101   {
00102     while(aToken.Length() != 0) {
00103       if(aCommand.Token(":", n + 1).Length() > 0)
00104         aTab(n) = aCommand.Token(":", n + 1);
00105       aToken = aCommand.Token(":", ++n);
00106     }
00107     n = n - 1;
00108   }
00109   if ( aTab.Length() && aTab(0).Length() )
00110     while(i < n) {
00111       Standard_Real length = 0, radius = 0, angle = 0;
00112       move = point;
00113 
00114       int n1 = 0;
00115       TColStd_Array1OfAsciiString a (0, aTab(0).Length());
00116       aToken = aTab(i).Token(" ", 1);
00117       while (aToken.Length() != 0) {
00118         if (aTab(i).Token(" ", n1 + 1).Length() > 0)
00119           a(n1) = aTab(i).Token(" ", n1 + 1);
00120         aToken = aTab(i).Token(" ", ++n1);
00121       }
00122       n1 = n1 - 1;
00123 
00124       switch(a(0).Value(1))
00125       {
00126       case 'F':
00127         {
00128           if (n1 != 3) goto badargs;
00129           if (!first) {
00130             MESSAGE("profile : The F instruction must precede all moves");
00131             return;
00132           }
00133           x0 = x = a(1).RealValue();
00134           y0 = y = a(2).RealValue();
00135           stayfirst = Standard_True;
00136           break;
00137         }
00138       case 'O':
00139         {
00140           if (n1 != 4) goto badargs;
00141           P.SetLocation(gp_Pnt(a(1).RealValue(), a(2).RealValue(), a(3).RealValue()));
00142           stayfirst = Standard_True;
00143           break;
00144         }
00145       case 'P':
00146         {
00147           if (n1 != 7) goto badargs;
00148           gp_Vec vn(a(1).RealValue(), a(2).RealValue(), a(3).RealValue());
00149           gp_Vec vx(a(4).RealValue(), a(5).RealValue(), a(6).RealValue());
00150           if (vn.Magnitude() <= Precision::Confusion() || vx.Magnitude() <= Precision::Confusion()) {
00151             MESSAGE("profile : null direction");
00152             return;
00153           }
00154           gp_Ax2 ax(P.Location(), vn, vx);
00155           P.SetPosition(ax);
00156           stayfirst = Standard_True;
00157           break;
00158         }
00159       case 'X':
00160         {
00161           if (n1 != 2) goto badargs;
00162           length = a(1).RealValue();
00163           if (a(0) == "XX")
00164             length -= x;
00165           dx = 1; dy = 0;
00166           move = line;
00167           break;
00168         }
00169       case 'Y':
00170         {
00171           if (n1 != 2) goto badargs;
00172           length = a(1).RealValue();
00173           if (a(0) == "YY")
00174             length -= y;
00175           dx = 0; dy = 1;
00176           move = line;
00177           break;
00178         }
00179       case 'L':
00180         {
00181           if (n1 != 2) goto badargs;
00182           length = a(1).RealValue();
00183           if (Abs(length) > Precision::Confusion())
00184             move = line;
00185           else
00186             move = none;
00187           break;
00188         }
00189       case 'T':
00190         {
00191           if (n1 != 3) goto badargs;
00192           Standard_Real vx = a(1).RealValue();
00193           Standard_Real vy = a(2).RealValue();
00194           if (a(0) == "TT") {
00195             vx -= x;
00196             vy -= y;
00197           }
00198           length = Sqrt(vx * vx + vy * vy);
00199           if (length > Precision::Confusion()) {
00200             move = line;
00201             dx = vx / length;
00202             dy = vy / length;
00203           }
00204           else
00205             move = none;
00206           break;
00207         }
00208       case 'R':
00209         {
00210           if (n1 != 2) goto badargs;
00211           angle = a(1).RealValue() * M_PI / 180.;
00212           if (a(0) == "RR") {
00213             dx = Cos(angle);
00214             dy = Sin(angle);
00215           }
00216           else {
00217             Standard_Real c = Cos(angle);
00218             Standard_Real s = Sin(angle);
00219             Standard_Real t = c * dx - s * dy;
00220             dy = s * dx + c * dy;
00221             dx = t;
00222           }
00223           break;
00224         }
00225       case 'D':
00226         {
00227           if (n1 != 3) goto badargs;
00228           Standard_Real vx = a(1).RealValue();
00229           Standard_Real vy = a(2).RealValue();
00230           length = Sqrt(vx * vx + vy * vy);
00231           if (length > Precision::Confusion()) {
00232             dx = vx / length;
00233             dy = vy / length;
00234           }
00235           else
00236             move = none;
00237           break;
00238         }
00239       case 'C':
00240         {
00241           if (n1 != 3) goto badargs;
00242           radius = a(1).RealValue();
00243           if (Abs(radius) > Precision::Confusion()) {
00244             angle = a(2).RealValue() * M_PI / 180.;
00245             move = circle;
00246           }
00247           else
00248             move = none;
00249           break;
00250         }
00251       case 'A':                                // TAngential arc by end point
00252         {
00253           if (n1 != 3) goto badargs;
00254           Standard_Real vx = a(1).RealValue();
00255           Standard_Real vy = a(2).RealValue();
00256           if (a(0) == "AA") {
00257             vx -= x;
00258             vy -= y;
00259           }
00260           Standard_Real det = dx * vy - dy * vx;
00261           if ( Abs(det) > Precision::Confusion()) {
00262             // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
00263             Standard_Real c = (dx * vx + dy * vy) / Sqrt((dx * dx + dy * dy) * (vx * vx + vy * vy));
00264             // radius = distance between start and end point / 2 * sin(alpha)
00265             // radius is > 0 or < 0
00266             radius = (vx * vx + vy * vy)* Sqrt(dx * dx + dy * dy) / (2.0 * det);
00267             if (Abs(radius) > Precision::Confusion()) {
00268               angle = 2.0 * acos(c); // angle in [0,2Pi]
00269               move = circle;
00270             }
00271             else
00272               move = none;
00273             break;
00274           }
00275           else
00276             move = none;
00277           break;
00278         }
00279       case 'U':                                // Arc by end point and radiUs
00280         {
00281           if (n1 != 5) goto badargs;
00282           Standard_Real vx = a(1).RealValue();
00283           Standard_Real vy = a(2).RealValue();
00284           radius  = a(3).RealValue();
00285           reversed = a(4).IntegerValue();
00286           if (a(0) == "UU") {                 // Absolute
00287             vx -= x;
00288             vy -= y;
00289           }
00290           Standard_Real length = Sqrt(vx * vx + vy * vy);
00291           if ( (4.0 - (vx * vx + vy * vy) / (radius * radius) >= 0.0 ) && (length > Precision::Confusion()) ) {
00292             // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
00293             Standard_Real c = 0.5 * Sqrt(4.0 - (vx * vx + vy * vy) / (radius * radius));
00294             angle = 2.0 * acos(c); // angle in [0,Pi]
00295             if ( reversed == 2 )
00296               angle = angle - 2 * M_PI;
00297             dx =    0.5 * (  vy * 1.0/radius
00298                            + vx * Sqrt(4.0  / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
00299             dy = -  0.5 * (  vx * 1.0/radius
00300                            - vy * Sqrt(4.0  / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
00301             move = circle;
00302           }
00303           else{
00304             move = none;
00305           }
00306           break;
00307         }
00308       case 'E':                                // Arc by end point and cEnter
00309         {
00310           if (n1 != 7) goto badargs;
00311           Standard_Real vx = a(1).RealValue();
00312           Standard_Real vy = a(2).RealValue();
00313           Standard_Real vxc  = a(3).RealValue();
00314           Standard_Real vyc  = a(4).RealValue();
00315           reversed = a(5).IntegerValue();
00316           control_Tolerance = a(6).IntegerValue();
00317 
00318           if (a(0) == "EE") {                 // Absolute
00319             vx -= x;
00320             vy -= y;
00321             vxc -= x;
00322             vyc -= y;
00323           }
00324           radius = Sqrt( vxc * vxc + vyc * vyc );
00325           Standard_Real det = vx * vyc - vy * vxc;
00326           Standard_Real length = Sqrt(vx * vx + vy * vy);
00327           Standard_Real length2 = Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc));
00328           Standard_Real length3 = Sqrt(vxc * vxc + vyc * vyc);
00329           Standard_Real error = Abs(length2 - radius);
00330           myError = error;
00331           if ( error > Precision::Confusion() ){
00332             MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
00333           }
00334           if ( error > Precision::Confusion() && control_Tolerance == 1)                      // Don't create the arc if the end point
00335             move = none;                                                                      // is too far from it
00336           else if ( (length > Precision::Confusion()) &&
00337                     (length2 > Precision::Confusion()) &&
00338                     (length3 > Precision::Confusion()) ) {
00339             Standard_Real c = ( radius * radius - (vx * vxc + vy * vyc) )
00340                             / ( radius * Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc)) ) ;  // Cosine of arc angle
00341             angle = acos(c);                                                                  // angle in [0,Pi]
00342             if ( reversed == 2 )
00343               angle = angle - 2 * M_PI;
00344             if (det < 0)
00345               angle = -angle;
00346             dx =  vyc / radius;
00347             dy = -vxc / radius;
00348             move = circle;
00349           }
00350           else {
00351             move = none;
00352           }
00353           break;
00354         }
00355       case 'I':
00356         {
00357           if (n1 != 2) goto badargs;
00358           length = a(1).RealValue();
00359           if (a(0) == "IX") {
00360             if (Abs(dx) < Precision::Confusion()) {
00361               MESSAGE("profile : cannot intersect, arg "<<i-1);
00362               return;
00363             }
00364             length = (length - x) / dx;
00365           }
00366           else if (a(0) == "IY") {
00367             if (Abs(dy) < Precision::Confusion()) {
00368               MESSAGE("profile : cannot intersect, arg "<<i-1);
00369               return;
00370             }
00371             length = (length - y) / dy;
00372           }
00373           if (Abs(length) > Precision::Confusion())
00374             move = line;
00375           else
00376             move = none;
00377           break;
00378         }
00379       case 'W':
00380         {
00381           if (a(0) == "WW")
00382             close = Standard_True;
00383           else if(a(0) == "WF") {
00384             close = Standard_True;
00385             face = Standard_True;
00386           }
00387           i = n - 1;
00388           break;
00389         }
00390       default:
00391         {
00392           MESSAGE("profile : unknown code " << a(i));
00393           return;
00394         }
00395     }
00396 
00397 again :
00398     switch (move)
00399     {
00400     case line :
00401       {
00402         if (length < 0) {
00403           length = -length;
00404           dx = -dx;
00405           dy = -dy;
00406         }
00407         Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
00408         BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(l,P),0,length);
00409         if (!ME.IsDone())
00410           return;
00411         MW.Add(ME);
00412         x += length*dx;
00413         y += length*dy;
00414         break;
00415       }
00416     case circle :
00417       {
00418         Standard_Boolean sense = Standard_True;
00419         if (radius < 0) {
00420           radius = -radius;
00421           sense = !sense;
00422           dx = -dx;
00423           dy = -dy;
00424         }
00425         gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
00426         if (angle < 0) {
00427           angle = -angle;
00428           sense = !sense;
00429         }
00430         Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
00431         BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(c,P),0,angle);
00432         if (!ME.IsDone())
00433           return;
00434         MW.Add(ME);
00435         gp_Pnt2d p;
00436         gp_Vec2d v;
00437         c->D1(angle,p,v);
00438         x = p.X();
00439         y = p.Y();
00440         dx = v.X() / radius;
00441         dy = v.Y() / radius;
00442         break;
00443       }
00444     case point:
00445       {
00446         MP = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, 0.0));
00447         break;
00448       }
00449     case none:
00450       {
00451         i = n - 1;
00452         break;
00453       }
00454     }
00455 
00456     // update first
00457     first = stayfirst;
00458     stayfirst = Standard_False;
00459 
00460     if(!(dx == 0 && dy == 0))
00461       myLastDir.SetCoord(dx, dy, 0.0);
00462     else
00463       return;
00464     myLastPoint.SetX(x);
00465     myLastPoint.SetY(y);
00466 
00467     // next segment....
00468     i++;
00469     if ((i == n) && close) {
00470       // the closing segment
00471       dx = x0 - x;
00472       dy = y0 - y;
00473       length = Sqrt(dx * dx + dy * dy);
00474       move = line;
00475       if (length > Precision::Confusion()) {
00476         dx = dx / length;
00477         dy = dy / length;
00478         goto again;
00479       }
00480     }
00481   }
00482 
00483   // get the result, face or wire
00484   if (move == none) {
00485     return;
00486   } else if (move == point) {
00487     S = MP;
00488   } else if (face) {
00489     if (!MW.IsDone()) {
00490       return;
00491     }
00492     BRepBuilderAPI_MakeFace MF (P, MW.Wire());
00493     if (!MF.IsDone()) {
00494       return;
00495     }
00496     S = MF;
00497   } else {
00498     if (!MW.IsDone()) {
00499       return;
00500     }
00501     S = MW;
00502   }
00503 
00504   if(!TheLocation.IsIdentity())
00505     S.Move(TheLocation);
00506 
00507   myShape = S;
00508   myOK = true;
00509   return;
00510 
00511   badargs :
00512     MESSAGE("profile : bad number of arguments");
00513     return;
00514 }