00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <BRep_Builder.hxx>
00027 # include <TopoDS_Compound.hxx>
00028 #endif
00029
00030 #include <Base/Writer.h>
00031 #include <Base/Reader.h>
00032 #include <Base/Exception.h>
00033 #include <Base/TimeInfo.h>
00034 #include <Base/Console.h>
00035
00036 #include <Base/VectorPy.h>
00037
00038 #include <Mod/Part/App/Geometry.h>
00039 #include <Mod/Part/App/GeometryCurvePy.h>
00040 #include <Mod/Part/App/ArcOfCirclePy.h>
00041 #include <Mod/Part/App/CirclePy.h>
00042 #include <Mod/Part/App/EllipsePy.h>
00043 #include <Mod/Part/App/LinePy.h>
00044
00045 #include <TopoDS.hxx>
00046 #include <TopoDS_Edge.hxx>
00047 #include <BRepBuilderAPI_MakeWire.hxx>
00048
00049 #include "Sketch.h"
00050 #include "Constraint.h"
00051 #include <math.h>
00052
00053 #include <iostream>
00054
00055
00056 using namespace Sketcher;
00057 using namespace Base;
00058 using namespace Part;
00059
00060 TYPESYSTEM_SOURCE(Sketcher::Sketch, Base::Persistence)
00061
00062 Sketch::Sketch()
00063 : GCSsys(), ConstraintsCounter(0), isInitMove(false)
00064 {
00066
00068
00069
00070
00071
00072
00073
00074
00075
00076 }
00077
00078 Sketch::~Sketch()
00079 {
00080 clear();
00081 }
00082
00083 void Sketch::clear(void)
00084 {
00085
00086 Points.clear();
00087 Lines.clear();
00088 Arcs.clear();
00089 Circles.clear();
00090
00091
00092 for (std::vector<double*>::iterator it = Parameters.begin(); it != Parameters.end(); ++it)
00093 if (*it) delete *it;
00094 Parameters.clear();
00095 for (std::vector<double*>::iterator it = FixParameters.begin(); it != FixParameters.end(); ++it)
00096 if (*it) delete *it;
00097 FixParameters.clear();
00098
00099
00100 for (std::vector<GeoDef>::iterator it = Geoms.begin(); it != Geoms.end(); ++it)
00101 if (it->geo) delete it->geo;
00102 Geoms.clear();
00103
00104 GCSsys.clear();
00105 isInitMove = false;
00106 ConstraintsCounter = 0;
00107 Conflicting.clear();
00108 }
00109
00110 int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
00111 bool withDiagnose)
00112 {
00113 clear();
00114
00115 for (std::vector<Part::Geometry *>::const_iterator it = GeoList.begin(); it != GeoList.end(); ++it) {
00116 if ((*it)->getTypeId()== GeomLineSegment::getClassTypeId()) {
00117 const GeomLineSegment *lineSeg = dynamic_cast<const GeomLineSegment*>((*it));
00118
00119 addLineSegment(*lineSeg);
00120 } else if ((*it)->getTypeId()== GeomCircle::getClassTypeId()) {
00121 const GeomCircle *circle = dynamic_cast<const GeomCircle*>((*it));
00122 addCircle(*circle);
00123 } else if ((*it)->getTypeId()== GeomArcOfCircle::getClassTypeId()) {
00124 const GeomArcOfCircle *aoc = dynamic_cast<const GeomArcOfCircle*>((*it));
00125 addArc(*aoc);
00126 } else {
00127 Base::Exception("Sketch::setUpSketch(): Unknown or unsupported type added to a sketch");
00128 }
00129 }
00130
00131
00132 if (!Geoms.empty())
00133 addConstraints(ConstraintList);
00134
00135 GCSsys.clearByTag(-1);
00136 GCSsys.clearByTag(-2);
00137 GCSsys.initSolution(Parameters);
00138
00139 if (withDiagnose)
00140 return diagnose();
00141 else
00142 return 0;
00143 }
00144
00145 const char* nameByType(Sketch::GeoType type)
00146 {
00147 switch (type) {
00148 case Sketch::Point:
00149 return "point";
00150 case Sketch::Line:
00151 return "line";
00152 case Sketch::Arc:
00153 return "arc";
00154 case Sketch::Circle:
00155 return "circle";
00156 case Sketch::Ellipse:
00157 return "ellipse";
00158 case Sketch::None:
00159 default:
00160 return "unknown";
00161 }
00162 }
00163
00164
00165
00166 int Sketch::addGeometry(const Part::Geometry *geo)
00167 {
00168 if (geo->getTypeId()== GeomLineSegment::getClassTypeId()) {
00169 const GeomLineSegment *lineSeg = dynamic_cast<const GeomLineSegment*>(geo);
00170
00171 return addLineSegment(*lineSeg);
00172 } else if (geo->getTypeId()== GeomCircle::getClassTypeId()) {
00173 const GeomCircle *circle = dynamic_cast<const GeomCircle*>(geo);
00174
00175 return addCircle(*circle);
00176 } else if (geo->getTypeId()== GeomArcOfCircle::getClassTypeId()) {
00177 const GeomArcOfCircle *aoc = dynamic_cast<const GeomArcOfCircle*>(geo);
00178
00179 return addArc(*aoc);
00180 } else {
00181 Base::Exception("Sketch::addGeometry(): Unknown or unsupported type added to a sketch");
00182 return 0;
00183 }
00184 }
00185
00186 void Sketch::addGeometry(const std::vector<Part::Geometry *> &geo)
00187 {
00188 for (std::vector<Part::Geometry *>::const_iterator it = geo.begin();it!=geo.end();++it)
00189 addGeometry(*it);
00190 }
00191
00192 int Sketch::addPoint(const Base::Vector3d &newPoint)
00193 {
00194
00195 GeoDef def;
00196 def.geo = 0;
00197 def.type = Point;
00198 def.construction = false;
00199
00200
00201 int paramStartIndex = Parameters.size();
00202 Parameters.push_back(new double(newPoint.x));
00203 Parameters.push_back(new double(newPoint.y));
00204
00205
00206 GCS::Point p1;
00207 p1.x = Parameters[paramStartIndex+0];
00208 p1.y = Parameters[paramStartIndex+1];
00209 def.startPointId = Points.size();
00210 Points.push_back(p1);
00211
00212
00213 Geoms.push_back(def);
00214
00215
00216 return Geoms.size()-1;
00217 }
00218
00219 int Sketch::addLine(const Part::GeomLineSegment &line)
00220 {
00221
00222
00223 return Geoms.size()-1;
00224 }
00225
00226 int Sketch::addLineSegment(const Part::GeomLineSegment &lineSegment)
00227 {
00228
00229 GeomLineSegment *lineSeg = static_cast<GeomLineSegment*>(lineSegment.clone());
00230
00231 GeoDef def;
00232 def.geo = lineSeg;
00233 def.type = Line;
00234 def.construction = lineSeg->Construction;
00235
00236
00237 Base::Vector3d start = lineSeg->getStartPoint();
00238 Base::Vector3d end = lineSeg->getEndPoint();
00239
00240
00241 GCS::Point p1, p2;
00242
00243 Parameters.push_back(new double(start.x));
00244 Parameters.push_back(new double(start.y));
00245 p1.x = Parameters[Parameters.size()-2];
00246 p1.y = Parameters[Parameters.size()-1];
00247
00248 Parameters.push_back(new double(end.x));
00249 Parameters.push_back(new double(end.y));
00250 p2.x = Parameters[Parameters.size()-2];
00251 p2.y = Parameters[Parameters.size()-1];
00252
00253
00254 def.startPointId = Points.size();
00255 def.endPointId = Points.size()+1;
00256 Points.push_back(p1);
00257 Points.push_back(p2);
00258
00259
00260 GCS::Line l;
00261 l.p1 = p1;
00262 l.p2 = p2;
00263 def.index = Lines.size();
00264 Lines.push_back(l);
00265
00266
00267 Geoms.push_back(def);
00268
00269
00270 return Geoms.size()-1;
00271 }
00272
00273 int Sketch::addArc(const Part::GeomArcOfCircle &circleSegment)
00274 {
00275
00276 GeomArcOfCircle *aoc = static_cast<GeomArcOfCircle*>(circleSegment.clone());
00277
00278 GeoDef def;
00279 def.geo = aoc;
00280 def.type = Arc;
00281 def.construction = aoc->Construction;
00282
00283 Base::Vector3d center = aoc->getCenter();
00284 Base::Vector3d startPnt = aoc->getStartPoint();
00285 Base::Vector3d endPnt = aoc->getEndPoint();
00286 double radius = aoc->getRadius();
00287 double startAngle, endAngle;
00288 aoc->getRange(startAngle, endAngle);
00289
00290 GCS::Point p1, p2, p3;
00291
00292 Parameters.push_back(new double(startPnt.x));
00293 Parameters.push_back(new double(startPnt.y));
00294 p1.x = Parameters[Parameters.size()-2];
00295 p1.y = Parameters[Parameters.size()-1];
00296
00297 Parameters.push_back(new double(endPnt.x));
00298 Parameters.push_back(new double(endPnt.y));
00299 p2.x = Parameters[Parameters.size()-2];
00300 p2.y = Parameters[Parameters.size()-1];
00301
00302 Parameters.push_back(new double(center.x));
00303 Parameters.push_back(new double(center.y));
00304 p3.x = Parameters[Parameters.size()-2];
00305 p3.y = Parameters[Parameters.size()-1];
00306
00307 def.startPointId = Points.size();
00308 Points.push_back(p1);
00309 def.endPointId = Points.size();
00310 Points.push_back(p2);
00311 def.midPointId = Points.size();
00312 Points.push_back(p3);
00313
00314 Parameters.push_back(new double(radius));
00315 double *r = Parameters[Parameters.size()-1];
00316 Parameters.push_back(new double(startAngle));
00317 double *a1 = Parameters[Parameters.size()-1];
00318 Parameters.push_back(new double(endAngle));
00319 double *a2 = Parameters[Parameters.size()-1];
00320
00321
00322 GCS::Arc a;
00323 a.start = p1;
00324 a.end = p2;
00325 a.center = p3;
00326 a.rad = r;
00327 a.startAngle = a1;
00328 a.endAngle = a2;
00329 def.index = Arcs.size();
00330 Arcs.push_back(a);
00331
00332
00333 Geoms.push_back(def);
00334
00335
00336 GCSsys.addConstraintArcRules(a);
00337
00338
00339 return Geoms.size()-1;
00340 }
00341
00342 int Sketch::addCircle(const Part::GeomCircle &cir)
00343 {
00344
00345 GeomCircle *circ = static_cast<GeomCircle*>(cir.clone());
00346
00347 GeoDef def;
00348 def.geo = circ;
00349 def.type = Circle;
00350 def.construction = circ->Construction;
00351
00352 Base::Vector3d center = circ->getCenter();
00353 double radius = circ->getRadius();
00354
00355 GCS::Point p1;
00356
00357 Parameters.push_back(new double(center.x));
00358 Parameters.push_back(new double(center.y));
00359 p1.x = Parameters[Parameters.size()-2];
00360 p1.y = Parameters[Parameters.size()-1];
00361
00362 Parameters.push_back(new double(radius));
00363
00364 def.midPointId = Points.size();
00365 Points.push_back(p1);
00366
00367
00368 double *r = Parameters[Parameters.size()-1];
00369
00370
00371 GCS::Circle c;
00372 c.center = p1;
00373 c.rad = r;
00374 def.index = Circles.size();
00375 Circles.push_back(c);
00376
00377
00378 Geoms.push_back(def);
00379
00380
00381 return Geoms.size()-1;
00382 }
00383
00384 int Sketch::addEllipse(const Part::GeomEllipse &ellipse)
00385 {
00386
00387 return Geoms.size()-1;
00388 }
00389
00390 std::vector<Part::Geometry *> Sketch::getGeometry(bool withConstrucionElements) const
00391 {
00392 std::vector<Part::Geometry *> temp(Geoms.size());
00393 int i=0;
00394 std::vector<GeoDef>::const_iterator it=Geoms.begin();
00395
00396 for (;it!=Geoms.end();++it,i++)
00397 if (!it->construction || withConstrucionElements)
00398 temp[i] = it->geo->clone();
00399
00400 return temp;
00401 }
00402
00403 Py::Tuple Sketch::getPyGeometry(void) const
00404 {
00405 Py::Tuple tuple(Geoms.size());
00406 int i=0;
00407 std::vector<GeoDef>::const_iterator it=Geoms.begin();
00408
00409 for (;it!=Geoms.end();++it,i++) {
00410 if (it->type == Line) {
00411 GeomLineSegment *lineSeg = dynamic_cast<GeomLineSegment*>(it->geo->clone());
00412 tuple[i] = Py::asObject(new LinePy(lineSeg));
00413 } else if (it->type == Arc) {
00414 GeomArcOfCircle *aoc = dynamic_cast<GeomArcOfCircle*>(it->geo->clone());
00415 tuple[i] = Py::asObject(new ArcOfCirclePy(aoc));
00416 } else if (it->type == Circle) {
00417 GeomCircle *circle = dynamic_cast<GeomCircle*>(it->geo->clone());
00418 tuple[i] = Py::asObject(new CirclePy(circle));
00419 } else if (it->type == Point) {
00420 Base::Vector3d temp(*(Points[Geoms[i].startPointId].x),*(Points[Geoms[i].startPointId].y),0);
00421 tuple[i] = Py::asObject(new VectorPy(temp));
00422 } else if (it->type == Ellipse) {
00423 GeomEllipse *ellipse = dynamic_cast<GeomEllipse*>(it->geo->clone());
00424 tuple[i] = Py::asObject(new EllipsePy(ellipse));
00425 } else {
00426
00427 }
00428 }
00429 return tuple;
00430 }
00431
00432 void Sketch::setConstruction(int geoId, bool isConstruction)
00433 {
00434 assert(geoId < int(Geoms.size()));
00435
00436 Geoms[geoId].construction = isConstruction;
00437 }
00438
00439 bool Sketch::getConstruction(int geoId) const
00440 {
00441 assert(geoId < int(Geoms.size()));
00442
00443 return Geoms[geoId].construction;
00444 }
00445
00446
00447
00448 int Sketch::addConstraint(const Constraint *constraint)
00449 {
00450
00451 assert(int(Geoms.size()) > 0);
00452 int rtn = -1;
00453 switch (constraint->Type) {
00454 case DistanceX:
00455 if (constraint->FirstPos == none)
00456 rtn = addDistanceXConstraint(constraint->First,constraint->Value);
00457 else if (constraint->Second == Constraint::GeoUndef)
00458 rtn = addCoordinateXConstraint(constraint->First,constraint->FirstPos,constraint->Value);
00459 else if (constraint->SecondPos != none)
00460 rtn = addDistanceXConstraint(constraint->First,constraint->FirstPos,
00461 constraint->Second,constraint->SecondPos,constraint->Value);
00462 break;
00463 case DistanceY:
00464 if (constraint->FirstPos == none)
00465 rtn = addDistanceYConstraint(constraint->First,constraint->Value);
00466 else if (constraint->Second == Constraint::GeoUndef)
00467 rtn = addCoordinateYConstraint(constraint->First,constraint->FirstPos,constraint->Value);
00468 else if (constraint->SecondPos != none)
00469 rtn = addDistanceYConstraint(constraint->First,constraint->FirstPos,
00470 constraint->Second,constraint->SecondPos,constraint->Value);
00471 break;
00472 case Horizontal:
00473 if (constraint->Second == Constraint::GeoUndef)
00474 rtn = addHorizontalConstraint(constraint->First);
00475 else
00476 rtn = addHorizontalConstraint(constraint->First,constraint->FirstPos,
00477 constraint->Second,constraint->SecondPos);
00478 break;
00479 case Vertical:
00480 if (constraint->Second == Constraint::GeoUndef)
00481 rtn = addVerticalConstraint(constraint->First);
00482 else
00483 rtn = addVerticalConstraint(constraint->First,constraint->FirstPos,
00484 constraint->Second,constraint->SecondPos);
00485 break;
00486 case Coincident:
00487 rtn = addPointCoincidentConstraint(constraint->First,constraint->FirstPos,constraint->Second,constraint->SecondPos);
00488 break;
00489 case PointOnObject:
00490 rtn = addPointOnObjectConstraint(constraint->First,constraint->FirstPos, constraint->Second);
00491 break;
00492 case Parallel:
00493 rtn = addParallelConstraint(constraint->First,constraint->Second);
00494 break;
00495 case Perpendicular:
00496 rtn = addPerpendicularConstraint(constraint->First,constraint->Second);
00497 break;
00498 case Tangent:
00499 if (constraint->SecondPos != none)
00500 rtn = addTangentConstraint(constraint->First,constraint->FirstPos,
00501 constraint->Second,constraint->SecondPos);
00502 else if (constraint->Second != Constraint::GeoUndef) {
00503 if (constraint->FirstPos != none)
00504 rtn = addTangentConstraint(constraint->First,constraint->FirstPos,
00505 constraint->Second);
00506 else
00507 rtn = addTangentConstraint(constraint->First,constraint->Second);
00508 }
00509 break;
00510 case Distance:
00511 if (constraint->SecondPos != none)
00512 rtn = addDistanceConstraint(constraint->First,constraint->FirstPos,
00513 constraint->Second,constraint->SecondPos,
00514 constraint->Value);
00515 else if (constraint->Second != Constraint::GeoUndef) {
00516 if (constraint->FirstPos != none)
00517 rtn = addDistanceConstraint(constraint->First,constraint->FirstPos,
00518 constraint->Second,constraint->Value);
00519 else
00520 rtn = addDistanceConstraint(constraint->First,constraint->Second,constraint->Value);
00521 }
00522 else
00523 rtn = addDistanceConstraint(constraint->First,constraint->Value);
00524 break;
00525 case Angle:
00526 if (constraint->SecondPos != none)
00527 rtn = addAngleConstraint(constraint->First,constraint->FirstPos,
00528 constraint->Second,constraint->SecondPos,constraint->Value);
00529 else if (constraint->Second != Constraint::GeoUndef)
00530 rtn = addAngleConstraint(constraint->First,constraint->Second,constraint->Value);
00531 else if (constraint->First != Constraint::GeoUndef)
00532 rtn = addAngleConstraint(constraint->First,constraint->Value);
00533 break;
00534 case Radius:
00535 rtn = addRadiusConstraint(constraint->First, constraint->Value);
00536 break;
00537 case Equal:
00538 rtn = addEqualConstraint(constraint->First,constraint->Second);
00539 break;
00540 case Symmetric:
00541 rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
00542 constraint->Second,constraint->SecondPos,constraint->Third);
00543 break;
00544 case None:
00545 break;
00546 }
00547 return rtn;
00548 }
00549
00550 int Sketch::addConstraints(const std::vector<Constraint *> &ConstraintList)
00551 {
00552
00553 assert(!Geoms.empty() || ConstraintList.empty());
00554
00555 int rtn = -1;
00556 for (std::vector<Constraint *>::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it)
00557 rtn = addConstraint (*it);
00558
00559 return rtn;
00560 }
00561
00562 int Sketch::addCoordinateXConstraint(int geoId, PointPos pos, double value)
00563 {
00564 int pointId = getPointId(geoId, pos);
00565
00566 if (pointId >= 0 && pointId < int(Points.size())) {
00567 double *val = new double(value);
00568 FixParameters.push_back(val);
00569 GCS::Point &p = Points[pointId];
00570 int tag = ++ConstraintsCounter;
00571 GCSsys.addConstraintCoordinateX(p, val, tag);
00572 return ConstraintsCounter;
00573 }
00574 return -1;
00575 }
00576
00577 int Sketch::addCoordinateYConstraint(int geoId, PointPos pos, double value)
00578 {
00579 int pointId = getPointId(geoId, pos);
00580
00581 if (pointId >= 0 && pointId < int(Points.size())) {
00582 double *val = new double(value);
00583 FixParameters.push_back(val);
00584 GCS::Point &p = Points[pointId];
00585 int tag = ++ConstraintsCounter;
00586 GCSsys.addConstraintCoordinateY(p, val, tag);
00587 return ConstraintsCounter;
00588 }
00589 return -1;
00590 }
00591
00592 int Sketch::addDistanceXConstraint(int geoId, double value)
00593 {
00594 assert(geoId < int(Geoms.size()));
00595 if (Geoms[geoId].type != Line)
00596 return -1;
00597
00598 GCS::Line &l = Lines[Geoms[geoId].index];
00599
00600 FixParameters.push_back(new double(value));
00601 double *diff = FixParameters[FixParameters.size()-1];
00602
00603 int tag = ++ConstraintsCounter;
00604 GCSsys.addConstraintDifference(l.p1.x, l.p2.x, diff, tag);
00605 return ConstraintsCounter;
00606 }
00607
00608 int Sketch::addDistanceYConstraint(int geoId, double value)
00609 {
00610 assert(geoId < int(Geoms.size()));
00611 if (Geoms[geoId].type != Line)
00612 return -1;
00613
00614 GCS::Line &l = Lines[Geoms[geoId].index];
00615
00616 FixParameters.push_back(new double(value));
00617 double *diff = FixParameters[FixParameters.size()-1];
00618
00619 int tag = ++ConstraintsCounter;
00620 GCSsys.addConstraintDifference(l.p1.y, l.p2.y, diff, tag);
00621 return ConstraintsCounter;
00622 }
00623
00624 int Sketch::addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
00625 {
00626 int pointId1 = getPointId(geoId1, pos1);
00627 int pointId2 = getPointId(geoId2, pos2);
00628
00629 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
00630 pointId2 >= 0 && pointId2 < int(Points.size())) {
00631 GCS::Point &p1 = Points[pointId1];
00632 GCS::Point &p2 = Points[pointId2];
00633
00634 FixParameters.push_back(new double(value));
00635 double *difference = FixParameters[FixParameters.size()-1];
00636
00637 int tag = ++ConstraintsCounter;
00638 GCSsys.addConstraintDifference(p1.x, p2.x, difference, tag);
00639 return ConstraintsCounter;
00640 }
00641 return -1;
00642 }
00643
00644 int Sketch::addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
00645 {
00646 int pointId1 = getPointId(geoId1, pos1);
00647 int pointId2 = getPointId(geoId2, pos2);
00648
00649 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
00650 pointId2 >= 0 && pointId2 < int(Points.size())) {
00651 GCS::Point &p1 = Points[pointId1];
00652 GCS::Point &p2 = Points[pointId2];
00653
00654 FixParameters.push_back(new double(value));
00655 double *difference = FixParameters[FixParameters.size()-1];
00656
00657 int tag = ++ConstraintsCounter;
00658 GCSsys.addConstraintDifference(p1.y, p2.y, difference, tag);
00659 return ConstraintsCounter;
00660 }
00661 return -1;
00662 }
00663
00664
00665 int Sketch::addHorizontalConstraint(int geoId)
00666 {
00667 assert(geoId < int(Geoms.size()));
00668 if (Geoms[geoId].type != Line)
00669 return -1;
00670
00671 GCS::Line &l = Lines[Geoms[geoId].index];
00672 int tag = ++ConstraintsCounter;
00673 GCSsys.addConstraintHorizontal(l, tag);
00674 return ConstraintsCounter;
00675 }
00676
00677
00678 int Sketch::addHorizontalConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
00679 {
00680 int pointId1 = getPointId(geoId1, pos1);
00681 int pointId2 = getPointId(geoId2, pos2);
00682
00683 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
00684 pointId2 >= 0 && pointId2 < int(Points.size())) {
00685 GCS::Point &p1 = Points[pointId1];
00686 GCS::Point &p2 = Points[pointId2];
00687 int tag = ++ConstraintsCounter;
00688 GCSsys.addConstraintHorizontal(p1, p2, tag);
00689 return ConstraintsCounter;
00690 }
00691 return -1;
00692 }
00693
00694
00695 int Sketch::addVerticalConstraint(int geoId)
00696 {
00697 assert(geoId < int(Geoms.size()));
00698 if (Geoms[geoId].type != Line)
00699 return -1;
00700
00701 GCS::Line &l = Lines[Geoms[geoId].index];
00702 int tag = ++ConstraintsCounter;
00703 GCSsys.addConstraintVertical(l, tag);
00704 return ConstraintsCounter;
00705 }
00706
00707
00708 int Sketch::addVerticalConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
00709 {
00710 int pointId1 = getPointId(geoId1, pos1);
00711 int pointId2 = getPointId(geoId2, pos2);
00712
00713 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
00714 pointId2 >= 0 && pointId2 < int(Points.size())) {
00715 GCS::Point &p1 = Points[pointId1];
00716 GCS::Point &p2 = Points[pointId2];
00717 int tag = ++ConstraintsCounter;
00718 GCSsys.addConstraintVertical(p1, p2, tag);
00719 return ConstraintsCounter;
00720 }
00721 return -1;
00722 }
00723
00724 int Sketch::addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
00725 {
00726 int pointId1 = getPointId(geoId1, pos1);
00727 int pointId2 = getPointId(geoId2, pos2);
00728
00729 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
00730 pointId2 >= 0 && pointId2 < int(Points.size())) {
00731 GCS::Point &p1 = Points[pointId1];
00732 GCS::Point &p2 = Points[pointId2];
00733 int tag = ++ConstraintsCounter;
00734
00735
00736
00737 GCSsys.addConstraintP2PCoincident(p1, p2);
00738 return ConstraintsCounter;
00739 }
00740 return -1;
00741 }
00742
00743 int Sketch::addParallelConstraint(int geoId1, int geoId2)
00744 {
00745 assert(geoId1 < int(Geoms.size()));
00746 assert(geoId2 < int(Geoms.size()));
00747 if (Geoms[geoId1].type != Line ||
00748 Geoms[geoId2].type != Line)
00749 return -1;
00750
00751 GCS::Line &l1 = Lines[Geoms[geoId1].index];
00752 GCS::Line &l2 = Lines[Geoms[geoId2].index];
00753 int tag = ++ConstraintsCounter;
00754 GCSsys.addConstraintParallel(l1, l2, tag);
00755 return ConstraintsCounter;
00756 }
00757
00758 int Sketch::addPerpendicularConstraint(int geoId1, int geoId2)
00759 {
00760 assert(geoId1 < int(Geoms.size()));
00761 assert(geoId2 < int(Geoms.size()));
00762
00763 if (Geoms[geoId2].type == Line) {
00764 if (Geoms[geoId1].type == Line) {
00765 GCS::Line &l1 = Lines[Geoms[geoId1].index];
00766 GCS::Line &l2 = Lines[Geoms[geoId2].index];
00767 int tag = ++ConstraintsCounter;
00768 GCSsys.addConstraintPerpendicular(l1, l2, tag);
00769 return ConstraintsCounter;
00770 }
00771 else
00772 std::swap(geoId1, geoId2);
00773 }
00774
00775 if (Geoms[geoId1].type == Line) {
00776 GCS::Line &l = Lines[Geoms[geoId1].index];
00777 if (Geoms[geoId2].type == Arc) {
00778 GCS::Arc &a = Arcs[Geoms[geoId2].index];
00779
00780 Base::Console().Warning("Perpendicular constraints between lines and arcs are not implemented yet.\n");
00781 return -1;
00782 } else if (Geoms[geoId2].type == Circle) {
00783 GCS::Circle &c = Circles[Geoms[geoId2].index];
00784
00785 Base::Console().Warning("Perpendicular constraints between lines and circles are not implemented yet.\n");
00786 return -1;
00787 }
00788 }
00789
00790 Base::Console().Warning("Perpendicular constraints between %s and %s are not supported.\n",
00791 nameByType(Geoms[geoId1].type), nameByType(Geoms[geoId2].type));
00792 return -1;
00793 }
00794
00795
00796 int Sketch::addTangentConstraint(int geoId1, int geoId2)
00797 {
00798
00799
00800
00801
00802
00803
00804 assert(geoId1 < int(Geoms.size()));
00805 assert(geoId2 < int(Geoms.size()));
00806
00807 if (Geoms[geoId2].type == Line) {
00808 if (Geoms[geoId1].type == Line) {
00809 GCS::Line &l1 = Lines[Geoms[geoId1].index];
00810 GCS::Point &l2p1 = Points[Geoms[geoId2].startPointId];
00811 GCS::Point &l2p2 = Points[Geoms[geoId2].endPointId];
00812 int tag = ++ConstraintsCounter;
00813 GCSsys.addConstraintPointOnLine(l2p1, l1, tag);
00814 GCSsys.addConstraintPointOnLine(l2p2, l1, tag);
00815 return ConstraintsCounter;
00816 }
00817 else
00818 std::swap(geoId1, geoId2);
00819 }
00820
00821 if (Geoms[geoId1].type == Line) {
00822 GCS::Line &l = Lines[Geoms[geoId1].index];
00823 if (Geoms[geoId2].type == Arc) {
00824 GCS::Arc &a = Arcs[Geoms[geoId2].index];
00825 int tag = ++ConstraintsCounter;
00826 GCSsys.addConstraintTangent(l, a, tag);
00827 return ConstraintsCounter;
00828 } else if (Geoms[geoId2].type == Circle) {
00829 GCS::Circle &c = Circles[Geoms[geoId2].index];
00830 int tag = ++ConstraintsCounter;
00831 GCSsys.addConstraintTangent(l, c, tag);
00832 return ConstraintsCounter;
00833 }
00834 } else
00835 Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n");
00836
00837 return -1;
00838 }
00839
00840
00841 int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
00842 {
00843
00844
00845
00846
00847
00848
00849
00850
00851 int pointId1 = getPointId(geoId1, pos1);
00852 assert(geoId2 < int(Geoms.size()));
00853
00854 if (pointId1 < 0 || pointId1 >= int(Points.size()))
00855 return addTangentConstraint(geoId1, geoId2);
00856
00857 GCS::Point &p1 = Points[pointId1];
00858 if (Geoms[geoId1].type == Line) {
00859 GCS::Line &l1 = Lines[Geoms[geoId1].index];
00860 if (Geoms[geoId2].type == Line) {
00861 GCS::Line &l2 = Lines[Geoms[geoId2].index];
00862 int tag = ++ConstraintsCounter;
00863 GCSsys.addConstraintPointOnLine(p1, l2, tag);
00864 GCSsys.addConstraintParallel(l1, l2, tag);
00865 return ConstraintsCounter;
00866 }
00867 else if (Geoms[geoId2].type == Arc) {
00868 GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
00869 int tag = ++ConstraintsCounter;
00870 GCSsys.addConstraintPointOnArc(p1, a2, tag);
00871 GCSsys.addConstraintTangent(l1, a2, tag);
00872 return ConstraintsCounter;
00873 }
00874 else if (Geoms[geoId2].type == Circle) {
00875 GCS::Circle &c2 = Circles[Geoms[geoId2].index];
00876 int tag = ++ConstraintsCounter;
00877 GCSsys.addConstraintPointOnCircle(p1, c2, tag);
00878 GCSsys.addConstraintTangent(l1, c2, tag);
00879 return ConstraintsCounter;
00880 }
00881 }
00882 else if (Geoms[geoId1].type == Arc) {
00883 GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
00884 if (Geoms[geoId2].type == Line) {
00885 GCS::Line &l2 = Lines[Geoms[geoId2].index];
00886 int tag = ++ConstraintsCounter;
00887 GCSsys.addConstraintPointOnLine(p1, l2, tag);
00888 GCSsys.addConstraintTangent(l2, a1, tag);
00889 return ConstraintsCounter;
00890 }
00891 else if (Geoms[geoId2].type == Arc) {
00892
00893
00894
00895 Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n");
00896 }
00897 else if (Geoms[geoId2].type == Circle) {
00898
00899
00900
00901 Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n");
00902 }
00903 }
00904 return -1;
00905 }
00906
00907
00908 int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
00909 {
00910
00911
00912
00913
00914
00915
00916 int pointId1 = getPointId(geoId1, pos1);
00917 int pointId2 = getPointId(geoId2, pos2);
00918
00919 if (pointId1 < 0 || pointId1 >= int(Points.size()) ||
00920 pointId2 < 0 || pointId2 >= int(Points.size()))
00921 return -1;
00922
00923 GCS::Point &p1 = Points[pointId1];
00924 GCS::Point &p2 = Points[pointId2];
00925 if (Geoms[geoId2].type == Line) {
00926 if (Geoms[geoId1].type == Line) {
00927 GCS::Line &l1 = Lines[Geoms[geoId1].index];
00928 GCS::Line &l2 = Lines[Geoms[geoId2].index];
00929 int tag = ++ConstraintsCounter;
00930 GCSsys.addConstraintP2PCoincident(p1, p2, tag);
00931 GCSsys.addConstraintParallel(l1, l2, tag);
00932 return ConstraintsCounter;
00933 }
00934 else {
00935 std::swap(geoId1, geoId2);
00936 std::swap(pos1, pos2);
00937 std::swap(pointId1, pointId2);
00938 p1 = Points[pointId1];
00939 p2 = Points[pointId2];
00940 }
00941 }
00942
00943 if (Geoms[geoId1].type == Line) {
00944 GCS::Line &l1 = Lines[Geoms[geoId1].index];
00945 if (Geoms[geoId2].type == Line) {
00946 GCS::Line &l2 = Lines[Geoms[geoId2].index];
00947 int tag = ++ConstraintsCounter;
00948 GCSsys.addConstraintP2PCoincident(p1, p2, tag);
00949 GCSsys.addConstraintParallel(l1, l2, tag);
00950 return ConstraintsCounter;
00951 }
00952 else if (Geoms[geoId2].type == Arc) {
00953 GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
00954 if (pos2 == start) {
00955 if (pos1 == start) {
00956 int tag = ++ConstraintsCounter;
00957 GCSsys.addConstraintTangentLine2Arc(l1.p2, l1.p1, a2, tag);
00958 return ConstraintsCounter;
00959 }
00960 else if (pos1 == end) {
00961 int tag = ++ConstraintsCounter;
00962 GCSsys.addConstraintTangentLine2Arc(l1.p1, l1.p2, a2, tag);
00963 return ConstraintsCounter;
00964 }
00965 else if (pos1 == mid) {
00966 int tag = ++ConstraintsCounter;
00967 GCSsys.addConstraintP2PCoincident(p1, p2, tag);
00968 GCSsys.addConstraintTangent(l1, a2, tag);
00969 return ConstraintsCounter;
00970 }
00971 }
00972 else if (pos2 == end) {
00973 if (pos1 == start) {
00974 int tag = ++ConstraintsCounter;
00975 GCSsys.addConstraintTangentArc2Line(a2, l1.p1, l1.p2, tag);
00976 return ConstraintsCounter;
00977 }
00978 else if (pos1 == end) {
00979 int tag = ++ConstraintsCounter;
00980 GCSsys.addConstraintTangentArc2Line(a2, l1.p2, l1.p1, tag);
00981 return ConstraintsCounter;
00982 }
00983 else if (pos1 == mid) {
00984 int tag = ++ConstraintsCounter;
00985 GCSsys.addConstraintP2PCoincident(p1, p2, tag);
00986 GCSsys.addConstraintTangent(l1, a2, tag);
00987 return ConstraintsCounter;
00988 }
00989 }
00990 else
00991 return -1;
00992 }
00993 }
00994 else if (Geoms[geoId1].type == Arc) {
00995
00996 if (Geoms[geoId2].type == Arc) {
00997
00998
00999
01000 Base::Console().Warning("Tangency constraints between arcs are not implemented yet.\n");
01001 }
01002 }
01003 return -1;
01004 }
01005
01006
01007 int Sketch::addDistanceConstraint(int geoId, double value)
01008 {
01009 assert(geoId < int(Geoms.size()));
01010 if (Geoms[geoId].type != Line)
01011 return -1;
01012
01013 GCS::Line &l = Lines[Geoms[geoId].index];
01014
01015
01016 FixParameters.push_back(new double(value));
01017 double *distance = FixParameters[FixParameters.size()-1];
01018
01019 int tag = ++ConstraintsCounter;
01020 GCSsys.addConstraintP2PDistance(l.p1, l.p2, distance, tag);
01021 return ConstraintsCounter;
01022 }
01023
01024
01025 int Sketch::addDistanceConstraint(int geoId1, int geoId2, double value)
01026 {
01027 assert(geoId1 < int(Geoms.size()));
01028 assert(geoId2 < int(Geoms.size()));
01029
01030
01031
01032
01033 Base::Console().Warning("Line to line distance constraints are not implemented yet.\n");
01034
01035 return -1;
01036 }
01037
01038
01039 int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double value)
01040 {
01041 int pointId1 = getPointId(geoId1, pos1);
01042 assert(geoId2 < int(Geoms.size()));
01043 if (Geoms[geoId2].type != Line)
01044 return -1;
01045
01046 if (pointId1 >= 0 && pointId1 < int(Points.size())) {
01047 GCS::Point &p1 = Points[pointId1];
01048 GCS::Line &l2 = Lines[Geoms[geoId2].index];
01049
01050
01051 FixParameters.push_back(new double(value));
01052 double *distance = FixParameters[FixParameters.size()-1];
01053
01054 int tag = ++ConstraintsCounter;
01055 GCSsys.addConstraintP2LDistance(p1, l2, distance, tag);
01056 return ConstraintsCounter;
01057 }
01058 return -1;
01059 }
01060
01061
01062 int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
01063 {
01064 int pointId1 = getPointId(geoId1, pos1);
01065 int pointId2 = getPointId(geoId2, pos2);
01066
01067 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
01068 pointId2 >= 0 && pointId2 < int(Points.size())) {
01069 GCS::Point &p1 = Points[pointId1];
01070 GCS::Point &p2 = Points[pointId2];
01071
01072
01073 FixParameters.push_back(new double(value));
01074 double *distance = FixParameters[FixParameters.size()-1];
01075
01076 int tag = ++ConstraintsCounter;
01077 GCSsys.addConstraintP2PDistance(p1, p2, distance, tag);
01078 return ConstraintsCounter;
01079 }
01080 return -1;
01081 }
01082
01083 int Sketch::addRadiusConstraint(int geoId, double value)
01084 {
01085 assert(geoId < int(Geoms.size()));
01086
01087 if (Geoms[geoId].type == Circle) {
01088 GCS::Circle &c = Circles[Geoms[geoId].index];
01089
01090 FixParameters.push_back(new double(value));
01091 double *radius = FixParameters[FixParameters.size()-1];
01092 int tag = ++ConstraintsCounter;
01093 GCSsys.addConstraintCircleRadius(c, radius, tag);
01094 return ConstraintsCounter;
01095 }
01096 else if (Geoms[geoId].type == Arc) {
01097 GCS::Arc &a = Arcs[Geoms[geoId].index];
01098
01099 FixParameters.push_back(new double(value));
01100 double *radius = FixParameters[FixParameters.size()-1];
01101 int tag = ++ConstraintsCounter;
01102 GCSsys.addConstraintArcRadius(a, radius, tag);
01103 return ConstraintsCounter;
01104 }
01105 return -1;
01106 }
01107
01108
01109 int Sketch::addAngleConstraint(int geoId, double value)
01110 {
01111 assert(geoId < int(Geoms.size()));
01112 if (Geoms[geoId].type != Line)
01113 return -1;
01114
01115 GCS::Line &l = Lines[Geoms[geoId].index];
01116
01117
01118 FixParameters.push_back(new double(value));
01119 double *angle = FixParameters[FixParameters.size()-1];
01120
01121 int tag = ++ConstraintsCounter;
01122 GCSsys.addConstraintP2PAngle(l.p1, l.p2, angle, tag);
01123 return ConstraintsCounter;
01124 }
01125
01126
01127 int Sketch::addAngleConstraint(int geoId1, int geoId2, double value)
01128 {
01129 assert(geoId1 < int(Geoms.size()));
01130 assert(geoId2 < int(Geoms.size()));
01131
01132 if (Geoms[geoId1].type != Line ||
01133 Geoms[geoId2].type != Line)
01134 return -1;
01135
01136 GCS::Line &l1 = Lines[Geoms[geoId1].index];
01137 GCS::Line &l2 = Lines[Geoms[geoId2].index];
01138
01139
01140 FixParameters.push_back(new double(value));
01141 double *angle = FixParameters[FixParameters.size()-1];
01142
01143 int tag = ++ConstraintsCounter;
01144 GCSsys.addConstraintL2LAngle(l1, l2, angle, tag);
01145 return ConstraintsCounter;
01146 }
01147
01148
01149 int Sketch::addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
01150 {
01151 assert(geoId1 < int(Geoms.size()));
01152 assert(geoId2 < int(Geoms.size()));
01153
01154 if (Geoms[geoId1].type != Line ||
01155 Geoms[geoId2].type != Line)
01156 return -1;
01157
01158 GCS::Point *l1p1=0, *l1p2=0;
01159 if (pos1 == start) {
01160 l1p1 = &Points[Geoms[geoId1].startPointId];
01161 l1p2 = &Points[Geoms[geoId1].endPointId];
01162 } else if (pos1 == end) {
01163 l1p1 = &Points[Geoms[geoId1].endPointId];
01164 l1p2 = &Points[Geoms[geoId1].startPointId];
01165 }
01166
01167 GCS::Point *l2p1=0, *l2p2=0;
01168 if (pos2 == start) {
01169 l2p1 = &Points[Geoms[geoId2].startPointId];
01170 l2p2 = &Points[Geoms[geoId2].endPointId];
01171 } else if (pos2 == end) {
01172 l2p1 = &Points[Geoms[geoId2].endPointId];
01173 l2p2 = &Points[Geoms[geoId2].startPointId];
01174 }
01175
01176 if (l1p1 == 0 || l2p1 == 0)
01177 return -1;
01178
01179
01180 FixParameters.push_back(new double(value));
01181 double *angle = FixParameters[FixParameters.size()-1];
01182
01183 int tag = ++ConstraintsCounter;
01184 GCSsys.addConstraintL2LAngle(*l1p1, *l1p2, *l2p1, *l2p2, angle, tag);
01185 return ConstraintsCounter;
01186 }
01187
01188 int Sketch::addEqualConstraint(int geoId1, int geoId2)
01189 {
01190 assert(geoId1 < int(Geoms.size()));
01191 assert(geoId2 < int(Geoms.size()));
01192
01193 if (Geoms[geoId1].type == Line &&
01194 Geoms[geoId2].type == Line) {
01195 GCS::Line &l1 = Lines[Geoms[geoId1].index];
01196 GCS::Line &l2 = Lines[Geoms[geoId2].index];
01197 double dx1 = (*l1.p2.x - *l1.p1.x);
01198 double dy1 = (*l1.p2.y - *l1.p1.y);
01199 double dx2 = (*l2.p2.x - *l2.p1.x);
01200 double dy2 = (*l2.p2.y - *l2.p1.y);
01201 double value = (sqrt(dx1*dx1+dy1*dy1)+sqrt(dx2*dx2+dy2*dy2))/2;
01202
01203 Parameters.push_back(new double(value));
01204 double *length = Parameters[Parameters.size()-1];
01205 int tag = ++ConstraintsCounter;
01206 GCSsys.addConstraintEqualLength(l1, l2, length, tag);
01207 return ConstraintsCounter;
01208 }
01209
01210 if (Geoms[geoId2].type == Circle) {
01211 if (Geoms[geoId1].type == Circle) {
01212 GCS::Circle &c1 = Circles[Geoms[geoId1].index];
01213 GCS::Circle &c2 = Circles[Geoms[geoId2].index];
01214 int tag = ++ConstraintsCounter;
01215 GCSsys.addConstraintEqualRadius(c1, c2, tag);
01216 return ConstraintsCounter;
01217 }
01218 else
01219 std::swap(geoId1, geoId2);
01220 }
01221
01222 if (Geoms[geoId1].type == Circle) {
01223 GCS::Circle &c1 = Circles[Geoms[geoId1].index];
01224 if (Geoms[geoId2].type == Arc) {
01225 GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
01226 int tag = ++ConstraintsCounter;
01227 GCSsys.addConstraintEqualRadius(c1, a2, tag);
01228 return ConstraintsCounter;
01229 }
01230 }
01231
01232 if (Geoms[geoId1].type == Arc &&
01233 Geoms[geoId2].type == Arc) {
01234 GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
01235 GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
01236 int tag = ++ConstraintsCounter;
01237 GCSsys.addConstraintEqualRadius(a1, a2, tag);
01238 return ConstraintsCounter;
01239 }
01240
01241 Base::Console().Warning("Equality constraints between %s and %s are not supported.\n",
01242 nameByType(Geoms[geoId1].type), nameByType(Geoms[geoId2].type));
01243 return -1;
01244 }
01245
01246
01247 int Sketch::addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2)
01248 {
01249 int pointId1 = getPointId(geoId1, pos1);
01250 assert(geoId2 < int(Geoms.size()));
01251
01252 if (pointId1 >= 0 && pointId1 < int(Points.size())) {
01253 GCS::Point &p1 = Points[pointId1];
01254
01255 if (Geoms[geoId2].type == Line) {
01256 GCS::Line &l2 = Lines[Geoms[geoId2].index];
01257 int tag = ++ConstraintsCounter;
01258 GCSsys.addConstraintPointOnLine(p1, l2, tag);
01259 return ConstraintsCounter;
01260 }
01261 else if (Geoms[geoId2].type == Arc) {
01262 GCS::Arc &a = Arcs[Geoms[geoId2].index];
01263 int tag = ++ConstraintsCounter;
01264 GCSsys.addConstraintPointOnArc(p1, a, tag);
01265 return ConstraintsCounter;
01266 }
01267 else if (Geoms[geoId2].type == Circle) {
01268 GCS::Circle &c = Circles[Geoms[geoId2].index];
01269 int tag = ++ConstraintsCounter;
01270 GCSsys.addConstraintPointOnCircle(p1, c, tag);
01271 return ConstraintsCounter;
01272 }
01273 }
01274 return -1;
01275 }
01276
01277
01278 int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3)
01279 {
01280 assert(geoId1 < int(Geoms.size()));
01281 assert(geoId2 < int(Geoms.size()));
01282 assert(geoId3 < int(Geoms.size()));
01283
01284 if (Geoms[geoId3].type != Line)
01285 return -1;
01286
01287 int pointId1 = getPointId(geoId1, pos1);
01288 int pointId2 = getPointId(geoId2, pos2);
01289
01290 if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
01291 pointId2 >= 0 && pointId2 < int(Points.size())) {
01292 GCS::Point &p1 = Points[pointId1];
01293 GCS::Point &p2 = Points[pointId2];
01294 GCS::Line &l = Lines[Geoms[geoId3].index];
01295 int tag = ++ConstraintsCounter;
01296 GCSsys.addConstraintP2PSymmetric(p1, p2, l, tag);
01297 return ConstraintsCounter;
01298 }
01299 return -1;
01300 }
01301
01302 bool Sketch::updateGeometry()
01303 {
01304 int i=0;
01305 for (std::vector<GeoDef>::const_iterator it=Geoms.begin();it!=Geoms.end();++it,i++) {
01306 try {
01307 if (it->type == Line) {
01308 GeomLineSegment *lineSeg = dynamic_cast<GeomLineSegment*>(it->geo);
01309 lineSeg->setPoints(Vector3d(*Lines[it->index].p1.x,
01310 *Lines[it->index].p1.y,
01311 0.0),
01312 Vector3d(*Lines[it->index].p2.x,
01313 *Lines[it->index].p2.y,
01314 0.0)
01315 );
01316 } else if (it->type == Arc) {
01317 GCS::Arc &myArc = Arcs[it->index];
01318
01319
01320
01321
01322
01323 GeomArcOfCircle *aoc = dynamic_cast<GeomArcOfCircle*>(it->geo);
01324 aoc->setCenter(Vector3d(*Points[it->midPointId].x,
01325 *Points[it->midPointId].y,
01326 0.0)
01327 );
01328 aoc->setRadius(*myArc.rad);
01329 aoc->setRange(*myArc.startAngle, *myArc.endAngle);
01330 } else if (it->type == Circle) {
01331 GeomCircle *circ = dynamic_cast<GeomCircle*>(it->geo);
01332 circ->setCenter(Vector3d(*Points[it->midPointId].x,
01333 *Points[it->midPointId].y,
01334 0.0)
01335 );
01336 circ->setRadius(*Circles[it->index].rad);
01337 }
01338 } catch (Base::Exception e) {
01339 Base::Console().Error("Updating geometry: Error build geometry(%d): %s\n",
01340 i,e.what());
01341 return false;
01342 }
01343 }
01344 return true;
01345 }
01346
01347
01348
01349 int Sketch::solve()
01350 {
01351
01352 Base::TimeInfo start_time;
01353 if (!isInitMove) {
01354 GCSsys.clearByTag(-1);
01355 GCSsys.clearByTag(-2);
01356 }
01357
01358 int ret;
01359 bool valid_solution;
01360 for (int soltype=0; soltype < (isInitMove ? 1 : 4); soltype++) {
01361 std::string solvername;
01362 switch (soltype) {
01363 case 0:
01364
01365 solvername = isInitMove ? "SQP" : "DogLeg";
01366 ret = GCSsys.solve(true, GCS::DogLeg);
01367 break;
01368 case 1:
01369 solvername = "LevenbergMarquardt";
01370 ret = GCSsys.solve(true, GCS::LevenbergMarquardt);
01371 break;
01372 case 2:
01373 solvername = "BFGS";
01374 ret = GCSsys.solve(true, GCS::BFGS);
01375 break;
01376 case 3:
01377 solvername = "SQP(augmented system)";
01378 GCSsys.clearByTag(-1);
01379 GCSsys.clearByTag(-2);
01380 InitParameters.resize(Parameters.size());
01381 int i=0;
01382 for (std::vector<double*>::iterator it = Parameters.begin(); it != Parameters.end(); ++it, i++) {
01383 InitParameters[i] = **it;
01384 GCSsys.addConstraintEqual(*it, &InitParameters[i], -2);
01385 }
01386 GCSsys.initSolution(Parameters);
01387 ret = GCSsys.solve(true);
01388 break;
01389 }
01390
01391
01392 if (ret == GCS::Success) {
01393 GCSsys.applySolution();
01394 valid_solution = updateGeometry();
01395 if (!valid_solution)
01396 Base::Console().Warning("Invalid solution from %s solver.\n", solvername.c_str());
01397 } else {
01398 valid_solution = false;
01399
01400 }
01401
01402 if (soltype == 3)
01403 GCSsys.clearByTag(-2);
01404
01405 if (valid_solution) {
01406 if (soltype == 1)
01407 Base::Console().Log("Important: the LevenbergMarquardt solver succeeded where the DogLeg solver had failed.\n");
01408 else if (soltype == 2)
01409 Base::Console().Log("Important: the BFGS solver succeeded where the DogLeg and LevenbergMarquardt solvers have failed.\n");
01410 else if (soltype == 3)
01411 Base::Console().Log("Important: the SQP solver succeeded where all single subsystem solvers have failed.\n");
01412
01413 if (soltype > 0) {
01414 Base::Console().Log("If you see this message please report a way of reproducing this result at\n");
01415 Base::Console().Log("https://sourceforge.net/apps/mantisbt/free-cad/main_page.php\n");
01416 }
01417
01418 break;
01419 }
01420 }
01421
01422 if (!valid_solution) {
01423 GCSsys.undoSolution();
01424 updateGeometry();
01425 }
01426
01427 Base::TimeInfo end_time;
01428
01429 SolveTime = Base::TimeInfo::diffTimeF(start_time,end_time);
01430 return ret;
01431 }
01432
01433 int Sketch::initMove(int geoId, PointPos pos)
01434 {
01435 assert(geoId >= 0 && geoId < int(Geoms.size()));
01436
01437 GCSsys.clearByTag(-1);
01438 GCSsys.clearByTag(-2);
01439
01440
01441 if (hasConflicts()) {
01442 isInitMove = false;
01443 return -1;
01444 }
01445
01446 if (Geoms[geoId].type == Line) {
01447 if (pos == start || pos == end) {
01448 MoveParameters.resize(2);
01449 GCS::Point p0;
01450 p0.x = &MoveParameters[0];
01451 p0.y = &MoveParameters[1];
01452 if (pos == start) {
01453 GCS::Point &p = Points[Geoms[geoId].startPointId];
01454 *p0.x = *p.x;
01455 *p0.y = *p.y;
01456 GCSsys.addConstraintP2PCoincident(p0,p,-1);
01457 } else if (pos == end) {
01458 GCS::Point &p = Points[Geoms[geoId].endPointId];
01459 *p0.x = *p.x;
01460 *p0.y = *p.y;
01461 GCSsys.addConstraintP2PCoincident(p0,p,-1);
01462 }
01463 } else if (pos == none || pos == mid) {
01464 MoveParameters.resize(4);
01465 GCS::Point p1, p2;
01466 p1.x = &MoveParameters[0];
01467 p1.y = &MoveParameters[1];
01468 p2.x = &MoveParameters[2];
01469 p2.y = &MoveParameters[3];
01470 GCS::Line &l = Lines[Geoms[geoId].index];
01471 *p1.x = *l.p1.x;
01472 *p1.y = *l.p1.y;
01473 *p2.x = *l.p2.x;
01474 *p2.y = *l.p2.y;
01475 GCSsys.addConstraintP2PCoincident(p1,l.p1,-1);
01476 GCSsys.addConstraintP2PCoincident(p2,l.p2,-1);
01477 }
01478 } else if (Geoms[geoId].type == Circle) {
01479 GCS::Point ¢er = Points[Geoms[geoId].midPointId];
01480 GCS::Point p0,p1;
01481 if (pos == mid) {
01482 MoveParameters.resize(2);
01483 p0.x = &MoveParameters[0];
01484 p0.y = &MoveParameters[1];
01485 *p0.x = *center.x;
01486 *p0.y = *center.y;
01487 GCSsys.addConstraintP2PCoincident(p0,center,-1);
01488 } else if (pos == none) {
01489 MoveParameters.resize(4);
01490 GCS::Circle &c = Circles[Geoms[geoId].index];
01491 p0.x = &MoveParameters[0];
01492 p0.y = &MoveParameters[1];
01493 *p0.x = *center.x;
01494 *p0.y = *center.y + *c.rad;
01495 GCSsys.addConstraintPointOnCircle(p0,c,-1);
01496 p1.x = &MoveParameters[2];
01497 p1.y = &MoveParameters[3];
01498 *p1.x = *center.x;
01499 *p1.y = *center.y;
01500 int i=GCSsys.addConstraintP2PCoincident(p1,center,-1);
01501 GCSsys.rescaleConstraint(i-1, 0.01);
01502 GCSsys.rescaleConstraint(i, 0.01);
01503 }
01504 } else if (Geoms[geoId].type == Arc) {
01505 GCS::Point ¢er = Points[Geoms[geoId].midPointId];
01506 GCS::Point p0,p1;
01507 if (pos == mid) {
01508 MoveParameters.resize(2);
01509 p0.x = &MoveParameters[0];
01510 p0.y = &MoveParameters[1];
01511 *p0.x = *center.x;
01512 *p0.y = *center.y;
01513 GCSsys.addConstraintP2PCoincident(p0,center,-1);
01514 } else if (pos == start || pos == end || pos == none) {
01515 MoveParameters.resize(4);
01516 if (pos == start || pos == end) {
01517 GCS::Point &p = (pos == start) ? Points[Geoms[geoId].startPointId]
01518 : Points[Geoms[geoId].endPointId];;
01519 p0.x = &MoveParameters[0];
01520 p0.y = &MoveParameters[1];
01521 *p0.x = *p.x;
01522 *p0.y = *p.y;
01523 GCSsys.addConstraintP2PCoincident(p0,p,-1);
01524 } else if (pos == none) {
01525 GCS::Arc &a = Arcs[Geoms[geoId].index];
01526 p0.x = &MoveParameters[0];
01527 p0.y = &MoveParameters[1];
01528 *p0.x = *center.x;
01529 *p0.y = *center.y + *a.rad;
01530 GCSsys.addConstraintPointOnArc(p0,a,-1);
01531 }
01532 p1.x = &MoveParameters[2];
01533 p1.y = &MoveParameters[3];
01534 *p1.x = *center.x;
01535 *p1.y = *center.y;
01536 int i=GCSsys.addConstraintP2PCoincident(p1,center,-1);
01537 GCSsys.rescaleConstraint(i-1, 0.01);
01538 GCSsys.rescaleConstraint(i, 0.01);
01539 }
01540 }
01541 InitParameters = MoveParameters;
01542
01543 GCSsys.initSolution(Parameters);
01544 isInitMove = true;
01545 return 0;
01546 }
01547
01548 int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative)
01549 {
01550
01551 assert(geoId < int(Geoms.size()));
01552
01553
01554 if (hasConflicts())
01555 return -1;
01556
01557 if (!isInitMove)
01558 initMove(geoId, pos);
01559
01560 if (relative) {
01561 for (int i=0; i < MoveParameters.size()-1; i+=2) {
01562 MoveParameters[i] = InitParameters[i] + toPoint.x;
01563 MoveParameters[i+1] = InitParameters[i+1] + toPoint.y;
01564 }
01565 } else if (Geoms[geoId].type == Line) {
01566 if (pos == start || pos == end) {
01567 MoveParameters[0] = toPoint.x;
01568 MoveParameters[1] = toPoint.y;
01569 } else if (pos == none || pos == mid) {
01570 double dx = (InitParameters[2]-InitParameters[0])/2;
01571 double dy = (InitParameters[3]-InitParameters[1])/2;
01572 MoveParameters[0] = toPoint.x - dx;
01573 MoveParameters[1] = toPoint.y - dy;
01574 MoveParameters[2] = toPoint.x + dx;
01575 MoveParameters[3] = toPoint.y + dy;
01576 }
01577 } else if (Geoms[geoId].type == Circle) {
01578 if (pos == mid || pos == none) {
01579 MoveParameters[0] = toPoint.x;
01580 MoveParameters[1] = toPoint.y;
01581 }
01582 } else if (Geoms[geoId].type == Arc) {
01583 if (pos == start || pos == end || pos == mid || pos == none) {
01584 MoveParameters[0] = toPoint.x;
01585 MoveParameters[1] = toPoint.y;
01586 }
01587 }
01588
01589 return solve();
01590 }
01591
01592 int Sketch::setDatum(int constrId, double value)
01593 {
01594 return -1;
01595 }
01596
01597 int Sketch::getPointId(int geoId, PointPos pos) const
01598 {
01599 assert(geoId < int(Geoms.size()));
01600 switch (pos) {
01601 case start:
01602 return Geoms[geoId].startPointId;
01603 case end:
01604 return Geoms[geoId].endPointId;
01605 case mid:
01606 return Geoms[geoId].midPointId;
01607 case none:
01608 break;
01609 }
01610 return -1;
01611 }
01612
01613 Base::Vector3d Sketch::getPoint(int geoId, PointPos pos)
01614 {
01615 int pointId = getPointId(geoId, pos);
01616 if (pointId != -1)
01617 return Base::Vector3d(*Points[pointId].x, *Points[pointId].y, 0);
01618
01619 return Base::Vector3d();
01620 }
01621
01622 int Sketch::diagnose(void)
01623 {
01624 Conflicting.clear();
01625 if (GCSsys.isInit()) {
01626 int dofs = GCSsys.diagnose(Parameters, Conflicting);
01627 return dofs;
01628 }
01629 else {
01630 return -1;
01631 }
01632 }
01633
01634
01635
01636 TopoShape Sketch::toShape(void) const
01637 {
01638 TopoShape result;
01639 std::vector<GeoDef>::const_iterator it=Geoms.begin();
01640
01641 #if 0
01642
01643 bool first = true;
01644 for (;it!=Geoms.end();++it) {
01645 if (!it->construction) {
01646 TopoDS_Shape sh = it->geo->toShape();
01647 if (first) {
01648 first = false;
01649 result._Shape = sh;
01650 } else {
01651 result._Shape = result.fuse(sh);
01652 }
01653 }
01654 }
01655 return result;
01656 #else
01657 std::list<TopoDS_Edge> edge_list;
01658 std::list<TopoDS_Wire> wires;
01659
01660
01661 for (;it!=Geoms.end();++it) {
01662 if (!it->construction) {
01663 edge_list.push_back(TopoDS::Edge(it->geo->toShape()));
01664 }
01665 }
01666
01667
01668 while (edge_list.size() > 0) {
01669 BRepBuilderAPI_MakeWire mkWire;
01670
01671 mkWire.Add(edge_list.front());
01672 edge_list.pop_front();
01673
01674 TopoDS_Wire new_wire = mkWire.Wire();
01675
01676
01677 bool found = false;
01678 do {
01679 found = false;
01680 for (std::list<TopoDS_Edge>::iterator pE = edge_list.begin(); pE != edge_list.end(); ++pE) {
01681 mkWire.Add(*pE);
01682 if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) {
01683
01684 found = true;
01685 edge_list.erase(pE);
01686 new_wire = mkWire.Wire();
01687 break;
01688 }
01689 }
01690 }
01691 while (found);
01692 wires.push_back(new_wire);
01693 }
01694 if (wires.size() == 1)
01695 result = *wires.begin();
01696 else if (wires.size() > 1) {
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706 BRep_Builder builder;
01707 TopoDS_Compound comp;
01708 builder.MakeCompound(comp);
01709 for (std::list<TopoDS_Wire>::iterator wt = wires.begin(); wt != wires.end(); ++wt)
01710 builder.Add(comp, *wt);
01711 result._Shape = comp;
01712 }
01713
01714
01715
01716 if (edge_list.size() > 0)
01717 Base::Console().Warning("Left over edges in Sketch. Only closed structures will be propagated at the moment!\n");
01718
01719 #endif
01720
01721 return result;
01722 }
01723
01724
01725
01726 unsigned int Sketch::getMemSize(void) const
01727 {
01728 return 0;
01729 }
01730
01731 void Sketch::Save(Writer &writer) const
01732 {
01733
01734 }
01735
01736 void Sketch::Restore(XMLReader &reader)
01737 {
01738
01739 }
01740