From ee43612125d2e470a562648898f14cadda2117d4 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Mon, 3 Aug 2015 16:58:50 +0200 Subject: [PATCH] Sketcher: AddSymmetric End-to-End point tangency bug fix ======================================================== For a while End-to-endpoint tangency is implemented via AngleViaPoint constraint. The code was not recalculating the "value" of the constraint in this case. This also forces to set the geometry first and constraints afterwards, as the AutoLockTangencyAndPerpty function requires a valid GeoId to operate (not a big deal anyway). Correction of the condition to allow the symmetry when a single line is mirrored about a point pertaining to a geometric element. --- src/Mod/Sketcher/App/SketchObject.cpp | 833 +++++++++--------- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 129 +-- 2 files changed, 484 insertions(+), 478 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 9d51c64d3..28579d8c5 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1628,12 +1628,11 @@ int SketchObject::addSymmetric(const std::vector &geoIdList, int refGeoId, std::map isStartEndInverted; // reference is a line - if(refPosId == Sketcher::none) - { - const Part::Geometry *georef = getGeometry(refGeoId); - if(georef->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { - Base::Console().Error("Reference for symmetric is neither a point nor a line.\n"); - return -1; + if(refPosId == Sketcher::none) { + const Part::Geometry *georef = getGeometry(refGeoId); + if(georef->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + Base::Console().Error("Reference for symmetric is neither a point nor a line.\n"); + return -1; } const Part::GeomLineSegment *refGeoLine = static_cast(georef); @@ -1642,100 +1641,100 @@ int SketchObject::addSymmetric(const std::vector &geoIdList, int refGeoId, Base::Vector3d vectline = refGeoLine->getEndPoint()-refstart; for (std::vector::const_iterator it = geoIdList.begin(); it != geoIdList.end(); ++it) { - const Part::Geometry *geo = getGeometry(*it); - Part::Geometry *geosym = geo->clone(); + const Part::Geometry *geo = getGeometry(*it); + Part::Geometry *geosym = geo->clone(); // Handle Geometry if(geosym->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ - Part::GeomLineSegment *geosymline = static_cast(geosym); - Base::Vector3d sp = geosymline->getStartPoint(); - Base::Vector3d ep = geosymline->getEndPoint(); - + Part::GeomLineSegment *geosymline = static_cast(geosym); + Base::Vector3d sp = geosymline->getStartPoint(); + Base::Vector3d ep = geosymline->getEndPoint(); + - geosymline->setPoints(sp+2.0*(sp.Perpendicular(refGeoLine->getStartPoint(),vectline)-sp), - ep+2.0*(ep.Perpendicular(refGeoLine->getStartPoint(),vectline)-ep)); - isStartEndInverted.insert(std::make_pair(*it, false)); + geosymline->setPoints(sp+2.0*(sp.Perpendicular(refGeoLine->getStartPoint(),vectline)-sp), + ep+2.0*(ep.Perpendicular(refGeoLine->getStartPoint(),vectline)-ep)); + isStartEndInverted.insert(std::make_pair(*it, false)); } else if(geosym->getTypeId() == Part::GeomCircle::getClassTypeId()){ - Part::GeomCircle *geosymcircle = static_cast(geosym); - Base::Vector3d cp = geosymcircle->getCenter(); + Part::GeomCircle *geosymcircle = static_cast(geosym); + Base::Vector3d cp = geosymcircle->getCenter(); - geosymcircle->setCenter(cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp)); - isStartEndInverted.insert(std::make_pair(*it, false)); + geosymcircle->setCenter(cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp)); + isStartEndInverted.insert(std::make_pair(*it, false)); } else if(geosym->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ - Part::GeomArcOfCircle *geoaoc = static_cast(geosym); - Base::Vector3d sp = geoaoc->getStartPoint(true); - Base::Vector3d ep = geoaoc->getEndPoint(true); - Base::Vector3d cp = geoaoc->getCenter(); - - Base::Vector3d ssp = sp+2.0*(sp.Perpendicular(refGeoLine->getStartPoint(),vectline)-sp); - Base::Vector3d sep = ep+2.0*(ep.Perpendicular(refGeoLine->getStartPoint(),vectline)-ep); - Base::Vector3d scp = cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp); + Part::GeomArcOfCircle *geoaoc = static_cast(geosym); + Base::Vector3d sp = geoaoc->getStartPoint(true); + Base::Vector3d ep = geoaoc->getEndPoint(true); + Base::Vector3d cp = geoaoc->getCenter(); + + Base::Vector3d ssp = sp+2.0*(sp.Perpendicular(refGeoLine->getStartPoint(),vectline)-sp); + Base::Vector3d sep = ep+2.0*(ep.Perpendicular(refGeoLine->getStartPoint(),vectline)-ep); + Base::Vector3d scp = cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp); - double theta1 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f*M_PI); - double theta2 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f*M_PI); - - geoaoc->setCenter(scp); - geoaoc->setRange(theta1,theta2,true); - isStartEndInverted.insert(std::make_pair(*it, true)); + double theta1 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f*M_PI); + double theta2 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f*M_PI); + + geoaoc->setCenter(scp); + geoaoc->setRange(theta1,theta2,true); + isStartEndInverted.insert(std::make_pair(*it, true)); } else if(geosym->getTypeId() == Part::GeomEllipse::getClassTypeId()){ - Part::GeomEllipse *geosymellipse = static_cast(geosym); - Base::Vector3d cp = geosymellipse->getCenter(); - - Base::Vector3d majdir = geosymellipse->getMajorAxisDir(); - double majord=geosymellipse->getMajorRadius(); - double minord=geosymellipse->getMinorRadius(); - double df= sqrt(majord*majord-minord*minord); - Base::Vector3d f1 = cp + df * majdir; - - Base::Vector3d sf1 = f1+2.0*(f1.Perpendicular(refGeoLine->getStartPoint(),vectline)-f1); - Base::Vector3d scp = cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp); - - geosymellipse->setMajorAxisDir(sf1-scp); + Part::GeomEllipse *geosymellipse = static_cast(geosym); + Base::Vector3d cp = geosymellipse->getCenter(); + + Base::Vector3d majdir = geosymellipse->getMajorAxisDir(); + double majord=geosymellipse->getMajorRadius(); + double minord=geosymellipse->getMinorRadius(); + double df= sqrt(majord*majord-minord*minord); + Base::Vector3d f1 = cp + df * majdir; + + Base::Vector3d sf1 = f1+2.0*(f1.Perpendicular(refGeoLine->getStartPoint(),vectline)-f1); + Base::Vector3d scp = cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp); + + geosymellipse->setMajorAxisDir(sf1-scp); - geosymellipse->setCenter(scp); - isStartEndInverted.insert(std::make_pair(*it, false)); + geosymellipse->setCenter(scp); + isStartEndInverted.insert(std::make_pair(*it, false)); } else if(geosym->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ - Part::GeomArcOfEllipse *geosymaoe = static_cast(geosym); - Base::Vector3d cp = geosymaoe->getCenter(); - Base::Vector3d sp = geosymaoe->getStartPoint(true); - Base::Vector3d ep = geosymaoe->getEndPoint(true); - - Base::Vector3d majdir = geosymaoe->getMajorAxisDir(); - double majord=geosymaoe->getMajorRadius(); - double minord=geosymaoe->getMinorRadius(); - double df= sqrt(majord*majord-minord*minord); - Base::Vector3d f1 = cp + df * majdir; - - Base::Vector3d sf1 = f1+2.0*(f1.Perpendicular(refGeoLine->getStartPoint(),vectline)-f1); - Base::Vector3d scp = cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp); - Base::Vector3d ssp = sp+2.0*(sp.Perpendicular(refGeoLine->getStartPoint(),vectline)-sp); - Base::Vector3d sep = ep+2.0*(ep.Perpendicular(refGeoLine->getStartPoint(),vectline)-ep); - - geosymaoe->setMajorAxisDir(sf1-scp); + Part::GeomArcOfEllipse *geosymaoe = static_cast(geosym); + Base::Vector3d cp = geosymaoe->getCenter(); + Base::Vector3d sp = geosymaoe->getStartPoint(true); + Base::Vector3d ep = geosymaoe->getEndPoint(true); + + Base::Vector3d majdir = geosymaoe->getMajorAxisDir(); + double majord=geosymaoe->getMajorRadius(); + double minord=geosymaoe->getMinorRadius(); + double df= sqrt(majord*majord-minord*minord); + Base::Vector3d f1 = cp + df * majdir; + + Base::Vector3d sf1 = f1+2.0*(f1.Perpendicular(refGeoLine->getStartPoint(),vectline)-f1); + Base::Vector3d scp = cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp); + Base::Vector3d ssp = sp+2.0*(sp.Perpendicular(refGeoLine->getStartPoint(),vectline)-sp); + Base::Vector3d sep = ep+2.0*(ep.Perpendicular(refGeoLine->getStartPoint(),vectline)-ep); + + geosymaoe->setMajorAxisDir(sf1-scp); - geosymaoe->setCenter(scp); + geosymaoe->setCenter(scp); - double theta1,theta2; - geosymaoe->closestParameter(sep,theta1); - geosymaoe->closestParameter(ssp,theta2); - - geosymaoe->setRange(theta1,theta2,true); - isStartEndInverted.insert(std::make_pair(*it, true)); + double theta1,theta2; + geosymaoe->closestParameter(sep,theta1); + geosymaoe->closestParameter(ssp,theta2); + + geosymaoe->setRange(theta1,theta2,true); + isStartEndInverted.insert(std::make_pair(*it, true)); } else if(geosym->getTypeId() == Part::GeomPoint::getClassTypeId()){ - Part::GeomPoint *geosympoint = static_cast(geosym); - Base::Vector3d cp = geosympoint->getPoint(); + Part::GeomPoint *geosympoint = static_cast(geosym); + Base::Vector3d cp = geosympoint->getPoint(); - geosympoint->setPoint(cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp)); - isStartEndInverted.insert(std::make_pair(*it, false)); + geosympoint->setPoint(cp+2.0*(cp.Perpendicular(refGeoLine->getStartPoint(),vectline)-cp)); + isStartEndInverted.insert(std::make_pair(*it, false)); } else { - Base::Console().Error("Unsupported Geometry!! Just copying it.\n"); - isStartEndInverted.insert(std::make_pair(*it, false)); + Base::Console().Error("Unsupported Geometry!! Just copying it.\n"); + isStartEndInverted.insert(std::make_pair(*it, false)); } newgeoVals.push_back(geosym); @@ -1746,260 +1745,268 @@ int SketchObject::addSymmetric(const std::vector &geoIdList, int refGeoId, } else //reference is a point { - Vector3d refpoint; - const Part::Geometry *georef = getGeometry(refGeoId); - - if (georef->getTypeId() == Part::GeomPoint::getClassTypeId()) { - refpoint = static_cast(georef)->getPoint(); - } - else if ( refGeoId == -1 && refPosId == Sketcher::start) { - refpoint = Vector3d(0,0,0); - } - else { - switch(refPosId){ - case Sketcher::start: - if(georef->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ - const Part::GeomLineSegment *geosymline = static_cast(georef); - refpoint = geosymline->getStartPoint(); - } - else if(georef->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ - const Part::GeomArcOfCircle *geoaoc = static_cast(georef); - refpoint = geoaoc->getStartPoint(true); - } - else if(georef->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ - const Part::GeomArcOfEllipse *geosymaoe = static_cast(georef); - refpoint = geosymaoe->getStartPoint(true); - } - break; - case Sketcher::end: - if(georef->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ - const Part::GeomLineSegment *geosymline = static_cast(georef); - refpoint = geosymline->getEndPoint(); - } - else if(georef->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ - const Part::GeomArcOfCircle *geoaoc = static_cast(georef); - refpoint = geoaoc->getEndPoint(true); - } - else if(georef->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ - const Part::GeomArcOfEllipse *geosymaoe = static_cast(georef); - refpoint = geosymaoe->getEndPoint(true); - } - break; - case Sketcher::mid: - if(georef->getTypeId() == Part::GeomCircle::getClassTypeId()){ - const Part::GeomCircle *geosymcircle = static_cast(georef); - refpoint = geosymcircle->getCenter(); - } - else if(georef->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ - const Part::GeomArcOfCircle *geoaoc = static_cast(georef); - refpoint = geoaoc->getCenter(); - } - else if(georef->getTypeId() == Part::GeomEllipse::getClassTypeId()){ - const Part::GeomEllipse *geosymellipse = static_cast(georef); - refpoint = geosymellipse->getCenter(); - } - else if(georef->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ - const Part::GeomArcOfEllipse *geosymaoe = static_cast(georef); - refpoint = geosymaoe->getCenter(); - } - break; - default: - Base::Console().Error("Wrong PointPosId.\n"); - return -1; - } - } - - for (std::vector::const_iterator it = geoIdList.begin(); it != geoIdList.end(); ++it) { - const Part::Geometry *geo = getGeometry(*it); - Part::Geometry *geosym = geo->clone(); - - // Handle Geometry - if(geosym->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ - Part::GeomLineSegment *geosymline = static_cast(geosym); - Base::Vector3d sp = geosymline->getStartPoint(); - Base::Vector3d ep = geosymline->getEndPoint(); - Base::Vector3d ssp = sp + 2.0*(refpoint-sp); - Base::Vector3d sep = ep + 2.0*(refpoint-ep); + Vector3d refpoint; + const Part::Geometry *georef = getGeometry(refGeoId); + + if (georef->getTypeId() == Part::GeomPoint::getClassTypeId()) { + refpoint = static_cast(georef)->getPoint(); + } + else if ( refGeoId == -1 && refPosId == Sketcher::start) { + refpoint = Vector3d(0,0,0); + } + else { + switch(refPosId){ + case Sketcher::start: + if(georef->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ + const Part::GeomLineSegment *geosymline = static_cast(georef); + refpoint = geosymline->getStartPoint(); + } + else if(georef->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ + const Part::GeomArcOfCircle *geoaoc = static_cast(georef); + refpoint = geoaoc->getStartPoint(true); + } + else if(georef->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ + const Part::GeomArcOfEllipse *geosymaoe = static_cast(georef); + refpoint = geosymaoe->getStartPoint(true); + } + break; + case Sketcher::end: + if(georef->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ + const Part::GeomLineSegment *geosymline = static_cast(georef); + refpoint = geosymline->getEndPoint(); + } + else if(georef->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ + const Part::GeomArcOfCircle *geoaoc = static_cast(georef); + refpoint = geoaoc->getEndPoint(true); + } + else if(georef->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ + const Part::GeomArcOfEllipse *geosymaoe = static_cast(georef); + refpoint = geosymaoe->getEndPoint(true); + } + break; + case Sketcher::mid: + if(georef->getTypeId() == Part::GeomCircle::getClassTypeId()){ + const Part::GeomCircle *geosymcircle = static_cast(georef); + refpoint = geosymcircle->getCenter(); + } + else if(georef->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ + const Part::GeomArcOfCircle *geoaoc = static_cast(georef); + refpoint = geoaoc->getCenter(); + } + else if(georef->getTypeId() == Part::GeomEllipse::getClassTypeId()){ + const Part::GeomEllipse *geosymellipse = static_cast(georef); + refpoint = geosymellipse->getCenter(); + } + else if(georef->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ + const Part::GeomArcOfEllipse *geosymaoe = static_cast(georef); + refpoint = geosymaoe->getCenter(); + } + break; + default: + Base::Console().Error("Wrong PointPosId.\n"); + return -1; + } + } + + for (std::vector::const_iterator it = geoIdList.begin(); it != geoIdList.end(); ++it) { + const Part::Geometry *geo = getGeometry(*it); + Part::Geometry *geosym = geo->clone(); + + // Handle Geometry + if(geosym->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ + Part::GeomLineSegment *geosymline = static_cast(geosym); + Base::Vector3d sp = geosymline->getStartPoint(); + Base::Vector3d ep = geosymline->getEndPoint(); + Base::Vector3d ssp = sp + 2.0*(refpoint-sp); + Base::Vector3d sep = ep + 2.0*(refpoint-ep); - geosymline->setPoints(ssp, sep); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - else if(geosym->getTypeId() == Part::GeomCircle::getClassTypeId()){ - Part::GeomCircle *geosymcircle = static_cast(geosym); - Base::Vector3d cp = geosymcircle->getCenter(); + geosymline->setPoints(ssp, sep); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + else if(geosym->getTypeId() == Part::GeomCircle::getClassTypeId()){ + Part::GeomCircle *geosymcircle = static_cast(geosym); + Base::Vector3d cp = geosymcircle->getCenter(); - geosymcircle->setCenter(cp + 2.0*(refpoint-cp)); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - else if(geosym->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ - Part::GeomArcOfCircle *geoaoc = static_cast(geosym); - Base::Vector3d sp = geoaoc->getStartPoint(true); - Base::Vector3d ep = geoaoc->getEndPoint(true); - Base::Vector3d cp = geoaoc->getCenter(); - - Base::Vector3d ssp = sp + 2.0*(refpoint-sp); - Base::Vector3d sep = ep + 2.0*(refpoint-ep); - Base::Vector3d scp = cp + 2.0*(refpoint-cp); + geosymcircle->setCenter(cp + 2.0*(refpoint-cp)); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + else if(geosym->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ + Part::GeomArcOfCircle *geoaoc = static_cast(geosym); + Base::Vector3d sp = geoaoc->getStartPoint(true); + Base::Vector3d ep = geoaoc->getEndPoint(true); + Base::Vector3d cp = geoaoc->getCenter(); + + Base::Vector3d ssp = sp + 2.0*(refpoint-sp); + Base::Vector3d sep = ep + 2.0*(refpoint-ep); + Base::Vector3d scp = cp + 2.0*(refpoint-cp); - double theta1 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f*M_PI); - double theta2 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f*M_PI); - - geoaoc->setCenter(scp); - geoaoc->setRange(theta1,theta2,true); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - else if(geosym->getTypeId() == Part::GeomEllipse::getClassTypeId()){ - Part::GeomEllipse *geosymellipse = static_cast(geosym); - Base::Vector3d cp = geosymellipse->getCenter(); - - Base::Vector3d majdir = geosymellipse->getMajorAxisDir(); - double majord=geosymellipse->getMajorRadius(); - double minord=geosymellipse->getMinorRadius(); - double df= sqrt(majord*majord-minord*minord); - Base::Vector3d f1 = cp + df * majdir; - - Base::Vector3d sf1 = f1 + 2.0*(refpoint-f1); - Base::Vector3d scp = cp + 2.0*(refpoint-cp); - - geosymellipse->setMajorAxisDir(sf1-scp); + double theta1 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f*M_PI); + double theta2 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f*M_PI); + + geoaoc->setCenter(scp); + geoaoc->setRange(theta1,theta2,true); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + else if(geosym->getTypeId() == Part::GeomEllipse::getClassTypeId()){ + Part::GeomEllipse *geosymellipse = static_cast(geosym); + Base::Vector3d cp = geosymellipse->getCenter(); + + Base::Vector3d majdir = geosymellipse->getMajorAxisDir(); + double majord=geosymellipse->getMajorRadius(); + double minord=geosymellipse->getMinorRadius(); + double df= sqrt(majord*majord-minord*minord); + Base::Vector3d f1 = cp + df * majdir; + + Base::Vector3d sf1 = f1 + 2.0*(refpoint-f1); + Base::Vector3d scp = cp + 2.0*(refpoint-cp); + + geosymellipse->setMajorAxisDir(sf1-scp); - geosymellipse->setCenter(scp); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - else if(geosym->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ - Part::GeomArcOfEllipse *geosymaoe = static_cast(geosym); - Base::Vector3d cp = geosymaoe->getCenter(); - Base::Vector3d sp = geosymaoe->getStartPoint(true); - Base::Vector3d ep = geosymaoe->getEndPoint(true); - - Base::Vector3d majdir = geosymaoe->getMajorAxisDir(); - double majord=geosymaoe->getMajorRadius(); - double minord=geosymaoe->getMinorRadius(); - double df= sqrt(majord*majord-minord*minord); - Base::Vector3d f1 = cp + df * majdir; - - Base::Vector3d sf1 = f1 + 2.0*(refpoint-f1); - Base::Vector3d scp = cp + 2.0*(refpoint-cp); - Base::Vector3d ssp = sp + 2.0*(refpoint-sp); - Base::Vector3d sep = ep + 2.0*(refpoint-ep); - - geosymaoe->setMajorAxisDir(sf1-scp); + geosymellipse->setCenter(scp); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + else if(geosym->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ + Part::GeomArcOfEllipse *geosymaoe = static_cast(geosym); + Base::Vector3d cp = geosymaoe->getCenter(); + Base::Vector3d sp = geosymaoe->getStartPoint(true); + Base::Vector3d ep = geosymaoe->getEndPoint(true); + + Base::Vector3d majdir = geosymaoe->getMajorAxisDir(); + double majord=geosymaoe->getMajorRadius(); + double minord=geosymaoe->getMinorRadius(); + double df= sqrt(majord*majord-minord*minord); + Base::Vector3d f1 = cp + df * majdir; + + Base::Vector3d sf1 = f1 + 2.0*(refpoint-f1); + Base::Vector3d scp = cp + 2.0*(refpoint-cp); + Base::Vector3d ssp = sp + 2.0*(refpoint-sp); + Base::Vector3d sep = ep + 2.0*(refpoint-ep); + + geosymaoe->setMajorAxisDir(sf1-scp); - geosymaoe->setCenter(scp); + geosymaoe->setCenter(scp); - double theta1,theta2; - geosymaoe->closestParameter(ssp,theta1); - geosymaoe->closestParameter(sep,theta2); - - geosymaoe->setRange(theta1,theta2,true); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - else if(geosym->getTypeId() == Part::GeomPoint::getClassTypeId()){ - Part::GeomPoint *geosympoint = static_cast(geosym); - Base::Vector3d cp = geosympoint->getPoint(); + double theta1,theta2; + geosymaoe->closestParameter(ssp,theta1); + geosymaoe->closestParameter(sep,theta2); + + geosymaoe->setRange(theta1,theta2,true); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + else if(geosym->getTypeId() == Part::GeomPoint::getClassTypeId()){ + Part::GeomPoint *geosympoint = static_cast(geosym); + Base::Vector3d cp = geosympoint->getPoint(); - geosympoint->setPoint(cp + 2.0*(refpoint-cp)); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - else { - Base::Console().Error("Unsupported Geometry!! Just copying it.\n"); - isStartEndInverted.insert(std::make_pair(*it, false)); - } - - newgeoVals.push_back(geosym); - geoIdMap.insert(std::make_pair(*it, cgeoid)); - cgeoid++; - } + geosympoint->setPoint(cp + 2.0*(refpoint-cp)); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + else { + Base::Console().Error("Unsupported Geometry!! Just copying it.\n"); + isStartEndInverted.insert(std::make_pair(*it, false)); + } + + newgeoVals.push_back(geosym); + geoIdMap.insert(std::make_pair(*it, cgeoid)); + cgeoid++; + } } - for (std::vector::const_iterator it = constrvals.begin(); it != constrvals.end(); ++it) { - - std::vector::const_iterator fit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->First); - - if(fit != geoIdList.end()) { // if First of constraint is in geoIdList - - if( (*it)->Second == Constraint::GeoUndef /*&& (*it)->Third == Constraint::GeoUndef*/) { - if((*it)->Type != Sketcher::DistanceX && - (*it)->Type != Sketcher::DistanceY) { - - Constraint *constNew = (*it)->clone(); - constNew->First = geoIdMap[(*it)->First]; - newconstrVals.push_back(constNew); - } - } - else { // other geoids intervene in this constraint - - std::vector::const_iterator sit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Second); - - if(sit != geoIdList.end()) { // Second is also in the list - - if( (*it)->Third == Constraint::GeoUndef ) { - if((*it)->Type == Sketcher::Coincident || - (*it)->Type == Sketcher::Perpendicular || - (*it)->Type == Sketcher::Parallel || - (*it)->Type == Sketcher::Tangent || - (*it)->Type == Sketcher::Distance || - (*it)->Type == Sketcher::Equal || - (*it)->Type == Sketcher::Radius || - (*it)->Type == Sketcher::PointOnObject ){ - Constraint *constNew = (*it)->clone(); - constNew->First = geoIdMap[(*it)->First]; - constNew->Second = geoIdMap[(*it)->Second]; - if(isStartEndInverted[(*it)->First]){ - if((*it)->FirstPos == Sketcher::start) - constNew->FirstPos = Sketcher::end; - else if((*it)->FirstPos == Sketcher::end) - constNew->FirstPos = Sketcher::start; - } - if(isStartEndInverted[(*it)->Second]){ - if((*it)->SecondPos == Sketcher::start) - constNew->SecondPos = Sketcher::end; - else if((*it)->SecondPos == Sketcher::end) - constNew->SecondPos = Sketcher::start; - } - newconstrVals.push_back(constNew); - } - } - else { - std::vector::const_iterator tit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Third); - - if(tit != geoIdList.end()) { // Third is also in the list - Constraint *constNew = (*it)->clone(); - constNew->First = geoIdMap[(*it)->First]; - constNew->Second = geoIdMap[(*it)->Second]; - constNew->Third = geoIdMap[(*it)->Third]; - if(isStartEndInverted[(*it)->First]){ - if((*it)->FirstPos == Sketcher::start) - constNew->FirstPos = Sketcher::end; - else if((*it)->FirstPos == Sketcher::end) - constNew->FirstPos = Sketcher::start; - } - if(isStartEndInverted[(*it)->Second]){ - if((*it)->SecondPos == Sketcher::start) - constNew->SecondPos = Sketcher::end; - else if((*it)->SecondPos == Sketcher::end) - constNew->SecondPos = Sketcher::start; - } - if(isStartEndInverted[(*it)->Third]){ - if((*it)->ThirdPos == Sketcher::start) - constNew->ThirdPos = Sketcher::end; - else if((*it)->ThirdPos == Sketcher::end) - constNew->ThirdPos = Sketcher::start; - } - newconstrVals.push_back(constNew); - } - } - } - } - } - } + // add the geometry Geometry.setValues(newgeoVals); Constraints.acceptGeometry(getCompleteGeometry()); rebuildVertexIndex(); + + for (std::vector::const_iterator it = constrvals.begin(); it != constrvals.end(); ++it) { + + std::vector::const_iterator fit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->First); + + if(fit != geoIdList.end()) { // if First of constraint is in geoIdList + + if( (*it)->Second == Constraint::GeoUndef /*&& (*it)->Third == Constraint::GeoUndef*/) { + if( (*it)->Type != Sketcher::DistanceX && + (*it)->Type != Sketcher::DistanceY) { + + Constraint *constNew = (*it)->clone(); + + constNew->First = geoIdMap[(*it)->First]; + newconstrVals.push_back(constNew); + } + } + else { // other geoids intervene in this constraint + + std::vector::const_iterator sit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Second); + + if(sit != geoIdList.end()) { // Second is also in the list + + if( (*it)->Third == Constraint::GeoUndef ) { + if((*it)->Type == Sketcher::Coincident || + (*it)->Type == Sketcher::Perpendicular || + (*it)->Type == Sketcher::Parallel || + (*it)->Type == Sketcher::Tangent || + (*it)->Type == Sketcher::Distance || + (*it)->Type == Sketcher::Equal || + (*it)->Type == Sketcher::Radius || + (*it)->Type == Sketcher::PointOnObject ){ + Constraint *constNew = (*it)->clone(); + + constNew->First = geoIdMap[(*it)->First]; + constNew->Second = geoIdMap[(*it)->Second]; + if(isStartEndInverted[(*it)->First]){ + if((*it)->FirstPos == Sketcher::start) + constNew->FirstPos = Sketcher::end; + else if((*it)->FirstPos == Sketcher::end) + constNew->FirstPos = Sketcher::start; + } + if(isStartEndInverted[(*it)->Second]){ + if((*it)->SecondPos == Sketcher::start) + constNew->SecondPos = Sketcher::end; + else if((*it)->SecondPos == Sketcher::end) + constNew->SecondPos = Sketcher::start; + } + + if (constNew->Type == Tangent || constNew->Type == Perpendicular) + AutoLockTangencyAndPerpty(constNew,true); + + newconstrVals.push_back(constNew); + } + } + else { + std::vector::const_iterator tit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Third); + + if(tit != geoIdList.end()) { // Third is also in the list + Constraint *constNew = (*it)->clone(); + constNew->First = geoIdMap[(*it)->First]; + constNew->Second = geoIdMap[(*it)->Second]; + constNew->Third = geoIdMap[(*it)->Third]; + if(isStartEndInverted[(*it)->First]){ + if((*it)->FirstPos == Sketcher::start) + constNew->FirstPos = Sketcher::end; + else if((*it)->FirstPos == Sketcher::end) + constNew->FirstPos = Sketcher::start; + } + if(isStartEndInverted[(*it)->Second]){ + if((*it)->SecondPos == Sketcher::start) + constNew->SecondPos = Sketcher::end; + else if((*it)->SecondPos == Sketcher::end) + constNew->SecondPos = Sketcher::start; + } + if(isStartEndInverted[(*it)->Third]){ + if((*it)->ThirdPos == Sketcher::start) + constNew->ThirdPos = Sketcher::end; + else if((*it)->ThirdPos == Sketcher::end) + constNew->ThirdPos = Sketcher::start; + } + newconstrVals.push_back(constNew); + } + } + } + } + } + } if( newconstrVals.size() > constrvals.size() ) - Constraints.setValues(newconstrVals); + Constraints.setValues(newconstrVals); return Geometry.getSize()-1; } @@ -2021,109 +2028,107 @@ int SketchObject::addCopy(const std::vector &geoIdList, const Base::Vector3 int x,y; for (y=0;y::const_iterator it = geoIdList.begin(); it != geoIdList.end(); ++it) { - const Part::Geometry *geo = getGeometry(*it); - Part::Geometry *geosym = geo->clone(); - - // Handle Geometry - if(geosym->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ - Part::GeomLineSegment *geosymline = static_cast(geosym); - Base::Vector3d sp = geosymline->getStartPoint(); - Base::Vector3d ep = geosymline->getEndPoint(); - - geosymline->setPoints(sp+double(x)*displacement+double(y)*perpendicularDisplacement, - ep+double(x)*displacement+double(y)*perpendicularDisplacement); - } - else if(geosym->getTypeId() == Part::GeomCircle::getClassTypeId()){ - Part::GeomCircle *geosymcircle = static_cast(geosym); - Base::Vector3d cp = geosymcircle->getCenter(); + for (x=0;x::const_iterator it = geoIdList.begin(); it != geoIdList.end(); ++it) { + const Part::Geometry *geo = getGeometry(*it); + Part::Geometry *geosym = geo->clone(); + + // Handle Geometry + if(geosym->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ + Part::GeomLineSegment *geosymline = static_cast(geosym); + Base::Vector3d sp = geosymline->getStartPoint(); + Base::Vector3d ep = geosymline->getEndPoint(); + + geosymline->setPoints( sp+double(x)*displacement+double(y)*perpendicularDisplacement, + ep+double(x)*displacement+double(y)*perpendicularDisplacement); + } + else if(geosym->getTypeId() == Part::GeomCircle::getClassTypeId()){ + Part::GeomCircle *geosymcircle = static_cast(geosym); + Base::Vector3d cp = geosymcircle->getCenter(); - geosymcircle->setCenter(cp+double(x)*displacement+double(y)*perpendicularDisplacement); - } - else if(geosym->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ - Part::GeomArcOfCircle *geoaoc = static_cast(geosym); - Base::Vector3d cp = geoaoc->getCenter(); - Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement; - - geoaoc->setCenter(scp); - } - else if(geosym->getTypeId() == Part::GeomEllipse::getClassTypeId()){ - Part::GeomEllipse *geosymellipse = static_cast(geosym); - Base::Vector3d cp = geosymellipse->getCenter(); - Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement; + geosymcircle->setCenter(cp+double(x)*displacement+double(y)*perpendicularDisplacement); + } + else if(geosym->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ + Part::GeomArcOfCircle *geoaoc = static_cast(geosym); + Base::Vector3d cp = geoaoc->getCenter(); + Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement; + + geoaoc->setCenter(scp); + } + else if(geosym->getTypeId() == Part::GeomEllipse::getClassTypeId()){ + Part::GeomEllipse *geosymellipse = static_cast(geosym); + Base::Vector3d cp = geosymellipse->getCenter(); + Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement; - geosymellipse->setCenter(scp); - } - else if(geosym->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ - Part::GeomArcOfEllipse *geosymaoe = static_cast(geosym); - Base::Vector3d cp = geosymaoe->getCenter(); - Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement; + geosymellipse->setCenter(scp); + } + else if(geosym->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){ + Part::GeomArcOfEllipse *geosymaoe = static_cast(geosym); + Base::Vector3d cp = geosymaoe->getCenter(); + Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement; - geosymaoe->setCenter(scp); - } - else if(geosym->getTypeId() == Part::GeomPoint::getClassTypeId()){ - Part::GeomPoint *geosympoint = static_cast(geosym); - Base::Vector3d cp = geosympoint->getPoint(); + geosymaoe->setCenter(scp); + } + else if(geosym->getTypeId() == Part::GeomPoint::getClassTypeId()){ + Part::GeomPoint *geosympoint = static_cast(geosym); + Base::Vector3d cp = geosympoint->getPoint(); - geosympoint->setPoint(cp+double(x)*displacement+double(y)*perpendicularDisplacement); - } - else { - Base::Console().Error("Unsupported Geometry!! Just copying it.\n"); - } + geosympoint->setPoint(cp+double(x)*displacement+double(y)*perpendicularDisplacement); + } + else { + Base::Console().Error("Unsupported Geometry!! Just copying it.\n"); + } - newgeoVals.push_back(geosym); - geoIdMap.insert(std::make_pair(*it, cgeoid)); - cgeoid++; - } - - // handle constraints - for (std::vector::const_iterator it = constrvals.begin(); it != constrvals.end(); ++it) { - - std::vector::const_iterator fit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->First); - - if(fit != geoIdList.end()) { // if First of constraint is in geoIdList - - if( (*it)->Second == Constraint::GeoUndef /*&& (*it)->Third == Constraint::GeoUndef*/) { - Constraint *constNew = (*it)->clone(); - constNew->First = geoIdMap[(*it)->First]; - newconstrVals.push_back(constNew); - } - else { // other geoids intervene in this constraint - - std::vector::const_iterator sit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Second); - - if(sit != geoIdList.end()) { // Second is also in the list - - if( (*it)->Third == Constraint::GeoUndef ) { - Constraint *constNew = (*it)->clone(); - constNew->First = geoIdMap[(*it)->First]; - constNew->Second = geoIdMap[(*it)->Second]; - newconstrVals.push_back(constNew); - } - else { - std::vector::const_iterator tit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Third); - - if(tit != geoIdList.end()) { // Third is also in the list - Constraint *constNew = (*it)->clone(); - constNew->First = geoIdMap[(*it)->First]; - constNew->Second = geoIdMap[(*it)->Second]; - constNew->Third = geoIdMap[(*it)->Third]; + newgeoVals.push_back(geosym); + geoIdMap.insert(std::make_pair(*it, cgeoid)); + cgeoid++; + } + + // handle constraints + for (std::vector::const_iterator it = constrvals.begin(); it != constrvals.end(); ++it) { + + std::vector::const_iterator fit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->First); + + if(fit != geoIdList.end()) { // if First of constraint is in geoIdList + + if( (*it)->Second == Constraint::GeoUndef /*&& (*it)->Third == Constraint::GeoUndef*/) { + Constraint *constNew = (*it)->clone(); + constNew->First = geoIdMap[(*it)->First]; + newconstrVals.push_back(constNew); + } + else { // other geoids intervene in this constraint + + std::vector::const_iterator sit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Second); + + if(sit != geoIdList.end()) { // Second is also in the list + if( (*it)->Third == Constraint::GeoUndef ) { + Constraint *constNew = (*it)->clone(); + constNew->First = geoIdMap[(*it)->First]; + constNew->Second = geoIdMap[(*it)->Second]; + newconstrVals.push_back(constNew); + } + else { + std::vector::const_iterator tit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Third); + + if(tit != geoIdList.end()) { // Third is also in the list + Constraint *constNew = (*it)->clone(); + constNew->First = geoIdMap[(*it)->First]; + constNew->Second = geoIdMap[(*it)->Second]; + constNew->Third = geoIdMap[(*it)->Third]; - newconstrVals.push_back(constNew); - } - } - } - } - } - } - + newconstrVals.push_back(constNew); + } + } + } + } + } + } - geoIdMap.clear(); // after each creation reset map so that the key-value is univoque - } + geoIdMap.clear(); // after each creation reset map so that the key-value is univoque + } } Geometry.setValues(newgeoVals); @@ -2131,7 +2136,7 @@ int SketchObject::addCopy(const std::vector &geoIdList, const Base::Vector3 rebuildVertexIndex(); if( newconstrVals.size() > constrvals.size() ) - Constraints.setValues(newconstrVals); + Constraints.setValues(newconstrVals); return Geometry.getSize()-1; diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index 04070b449..8521448c6 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -1027,88 +1027,89 @@ void CmdSketcherSymmetry::activated(int iMsg) for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) { // only handle non-external edges if ((it->size() > 4 && it->substr(0,4) == "Edge") || - (it->size() > 12 && it->substr(0,12) == "ExternalEdge")) { + (it->size() > 12 && it->substr(0,12) == "ExternalEdge")) { - if(it->substr(0,4) == "Edge") { - LastGeoId = std::atoi(it->substr(4,4000).c_str()) - 1; - LastPointPos = Sketcher::none; - } - else { - LastGeoId = -std::atoi(it->substr(12,4000).c_str()) - 2; - LastPointPos = Sketcher::none; - } - - // reference can be external or non-external - LastGeo = Obj->getGeometry(LastGeoId); - // Only for supported types - if(LastGeo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) - lastgeotype = line; - else - lastgeotype = invalid; + if(it->substr(0,4) == "Edge") { + LastGeoId = std::atoi(it->substr(4,4000).c_str()) - 1; + LastPointPos = Sketcher::none; + } + else { + LastGeoId = -std::atoi(it->substr(12,4000).c_str()) - 2; + LastPointPos = Sketcher::none; + } + + // reference can be external or non-external + LastGeo = Obj->getGeometry(LastGeoId); + // Only for supported types + if(LastGeo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) + lastgeotype = line; + else + lastgeotype = invalid; - // lines to make symmetric (only non-external) - if(LastGeoId>=0) { - geoids++; - stream << LastGeoId << ","; - } - } - else if(it->size() > 6 && it->substr(0,6) == "Vertex"){ - // only if it is a GeomPoint - int VtId = std::atoi(it->substr(6,4000).c_str()) - 1; - int GeoId; - Sketcher::PointPos PosId; - Obj->getGeoVertexIndex(VtId, GeoId, PosId); - if (Obj->getGeometry(GeoId)->getTypeId() == Part::GeomPoint::getClassTypeId()) { - LastGeoId = GeoId; - LastPointPos = Sketcher::start; - lastgeotype = point; - - // points to make symmetric - if(LastGeoId>=0) { - geoids++; - stream << LastGeoId << ","; - } - } - } + // lines to make symmetric (only non-external) + if(LastGeoId>=0) { + geoids++; + stream << LastGeoId << ","; + } + } + else if(it->size() > 6 && it->substr(0,6) == "Vertex"){ + // only if it is a GeomPoint + int VtId = std::atoi(it->substr(6,4000).c_str()) - 1; + int GeoId; + Sketcher::PointPos PosId; + Obj->getGeoVertexIndex(VtId, GeoId, PosId); + + if (Obj->getGeometry(GeoId)->getTypeId() == Part::GeomPoint::getClassTypeId()) { + LastGeoId = GeoId; + LastPointPos = Sketcher::start; + lastgeotype = point; + + // points to make symmetric + if(LastGeoId>=0) { + geoids++; + stream << LastGeoId << ","; + } + } + } } bool lastvertexoraxis=false; // check if last selected element is a Vertex, not being a GeomPoint if(SubNames.rbegin()->size() > 6 && SubNames.rbegin()->substr(0,6) == "Vertex"){ - int VtId = std::atoi(SubNames.rbegin()->substr(6,4000).c_str()) - 1; - int GeoId; - Sketcher::PointPos PosId; - Obj->getGeoVertexIndex(VtId, GeoId, PosId); - if (Obj->getGeometry(GeoId)->getTypeId() != Part::GeomPoint::getClassTypeId()) { - LastGeoId = GeoId; - LastPointPos = PosId; - lastgeotype = point; - lastvertexoraxis=true; - } + int VtId = std::atoi(SubNames.rbegin()->substr(6,4000).c_str()) - 1; + int GeoId; + Sketcher::PointPos PosId; + Obj->getGeoVertexIndex(VtId, GeoId, PosId); + if (Obj->getGeometry(GeoId)->getTypeId() != Part::GeomPoint::getClassTypeId()) { + LastGeoId = GeoId; + LastPointPos = PosId; + lastgeotype = point; + lastvertexoraxis=true; + } } // check if last selected element is horizontal axis else if(SubNames.rbegin()->size() == 6 && SubNames.rbegin()->substr(0,6) == "H_Axis"){ - LastGeoId = -1; - LastPointPos = Sketcher::none; - lastgeotype = line; - lastvertexoraxis=true; + LastGeoId = -1; + LastPointPos = Sketcher::none; + lastgeotype = line; + lastvertexoraxis=true; } // check if last selected element is vertical axis else if(SubNames.rbegin()->size() == 6 && SubNames.rbegin()->substr(0,6) == "V_Axis"){ - LastGeoId = -2; - LastPointPos = Sketcher::none; - lastgeotype = line; - lastvertexoraxis=true; + LastGeoId = -2; + LastPointPos = Sketcher::none; + lastgeotype = line; + lastvertexoraxis=true; } // check if last selected element is the root point else if(SubNames.rbegin()->size() == 9 && SubNames.rbegin()->substr(0,9) == "RootPoint"){ - LastGeoId = -1; - LastPointPos = Sketcher::start; - lastgeotype = point; - lastvertexoraxis=true; + LastGeoId = -1; + LastPointPos = Sketcher::start; + lastgeotype = point; + lastvertexoraxis=true; } - if ( geoids < 2 || (geoids<1 && LastGeoId<0) || (geoids<1 && lastvertexoraxis) ) { + if ( geoids == 0 || (geoids == 1 && LastGeoId>=0 && !lastvertexoraxis) ) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("A symmetric construction requires at least two geometric elements, the last geometric element being the reference for the symmetry construction.")); return;