From b3938ad04582053ea9c727129e12f247cbd9cca4 Mon Sep 17 00:00:00 2001 From: logari81 Date: Wed, 18 Jul 2012 16:26:24 +0200 Subject: [PATCH 1/5] Sketcher: simplify positioning of constraint icons --- src/Mod/Sketcher/Gui/CommandConstraints.cpp | 10 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 148 +++++++------------- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 5 +- 3 files changed, 56 insertions(+), 107 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index fd795eb93..1eaa0cd99 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -1636,15 +1636,7 @@ void CmdSketcherConstrainAngle::activated(int iMsg) const std::vector &ConStr = dynamic_cast(selection[0].getObject())->Constraints.getValues(); Sketcher::Constraint *constr = ConStr[ConStr.size() -1]; - float sf = 1.f; - Gui::Document *doc = getActiveGuiDocument(); - if (doc && doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) { - SketcherGui::ViewProviderSketch *vp = dynamic_cast(doc->getInEdit()); - sf = vp->getScaleFactor(); - - constr->LabelDistance = 2. * sf; - vp->draw(); // Redraw - } + updateDatumDistance(getActiveGuiDocument(), constr); //updateActive(); getSelection().clearSelection(); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 9605f3997..981fee2c9 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -1005,55 +1005,55 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo draw(true); } -bool ViewProviderSketch::isConstraintAtPosition(const Base::Vector3d &constrPos, const SoNode *constraint) +Base::Vector3d ViewProviderSketch::seekConstraintPosition(const Base::Vector3d &origPos, + const Base::Vector3d &norm, + const Base::Vector3d &dir, float step, + const SoNode *constraint) { assert(edit); Gui::MDIView *mdi = Gui::Application::Instance->activeDocument()->getActiveView(); Gui::View3DInventorViewer *viewer = static_cast(mdi)->getViewer(); - SoRayPickAction rp(viewer->getViewportRegion()); - rp.setRadius(0.1f); - rp.setPickAll(true); - rp.setRay(SbVec3f(constrPos.x, constrPos.y, -1.f), SbVec3f(0, 0, 1) ); - //problem - rp.apply(edit->constrGroup); // We could narrow it down to just the SoGroup containing the constraints - // returns a copy of the point - SoPickedPoint *pp = rp.getPickedPoint(); - const SoPickedPointList ppl = rp.getPickedPointList(); + float scaled_step = step * getScaleFactor(); - if(ppl.getLength() > 1) - return true; - if (pp) { - SoPath *path = pp->getPath(); - int length = path->getLength(); - SoNode *tailFather1 = path->getNode(length-2); - SoNode *tailFather2 = path->getNode(length-3); - - // checking if a constraint is the same as the one selected - if (tailFather1 == constraint || tailFather2 == constraint) { - return false; - } else { - return true; - } - } else { - return false; - } -} - -Base::Vector3d ViewProviderSketch::seekConstraintPosition(const Base::Vector3d &suggestedPos, - const Base::Vector3d &dir, float step, - const SoNode *constraint) -{ int multiplier = 0; - Base::Vector3d freePos; - do { + Base::Vector3d relPos, freePos; + bool isConstraintAtPosition = true; + while (isConstraintAtPosition && multiplier < 10) { // Calculate new position of constraint - freePos = suggestedPos + (dir * (multiplier * step)); - multiplier++; // Increment the multiplier + relPos = norm * 0.5f + dir * multiplier; + freePos = origPos + relPos * scaled_step; + + rp.setRadius(0.1f); + rp.setPickAll(true); + rp.setRay(SbVec3f(freePos.x, freePos.y, -1.f), SbVec3f(0, 0, 1) ); + //problem + rp.apply(edit->constrGroup); // We could narrow it down to just the SoGroup containing the constraints + + // returns a copy of the point + SoPickedPoint *pp = rp.getPickedPoint(); + const SoPickedPointList ppl = rp.getPickedPointList(); + + if (ppl.getLength() <= 1 && pp) { + SoPath *path = pp->getPath(); + int length = path->getLength(); + SoNode *tailFather1 = path->getNode(length-2); + SoNode *tailFather2 = path->getNode(length-3); + + // checking if a constraint is the same as the one selected + if (tailFather1 == constraint || tailFather2 == constraint) + isConstraintAtPosition = false; + } else + isConstraintAtPosition = false; + + multiplier *= -1; // search in both sides + if (multiplier >= 0) + multiplier++; // Increment the multiplier } - while (isConstraintAtPosition(freePos, constraint)); - return freePos; + if (multiplier == 10) + relPos = norm * 0.5f; // no free position found + return relPos * step; } bool ViewProviderSketch::isSelectable(void) const @@ -1842,19 +1842,12 @@ Restart: Base::Vector3d dir = (lineSeg->getEndPoint()-lineSeg->getStartPoint()).Normalize(); Base::Vector3d norm(-dir.y,dir.x,0); - float scale = dynamic_cast(sep->getChild(1))->getScaleFactor(); - Base::Vector3d constrPos = midpos + (norm * 2.5 * scale); - - constrPos = seekConstraintPosition(constrPos, dir, 2.5 * scale, edit->constrGroup->getChild(i)); - - // Translate the Icon based on calculated position - Base::Vector3d relPos = constrPos - midpos; // Relative Position of Icons to Midpoint - relPos = relPos / scale; // Must Divide by Scale Factor + Base::Vector3d relpos = seekConstraintPosition(midpos, norm, dir, 2.5, edit->constrGroup->getChild(i)); dynamic_cast(sep->getChild(1))->abPos = SbVec3f(midpos.x, midpos.y, zConstr); //Absolute Reference //Reference Position that is scaled according to zoom - dynamic_cast(sep->getChild(1))->translation = SbVec3f(relPos.x, relPos.y, 0); + dynamic_cast(sep->getChild(1))->translation = SbVec3f(relpos.x, relpos.y, 0); } break; @@ -1921,25 +1914,16 @@ Restart: dir1 = Base::Vector3d(1,0,0); } - // Get Current Scale Factor - float scale = dynamic_cast(sep->getChild(1))->getScaleFactor(); - - Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale); - constrPos1 = seekConstraintPosition(constrPos1, dir1, scale * 2.5, edit->constrGroup->getChild(i)); - - // Translate the Icon based on calculated position - Base::Vector3d relPos1 = (constrPos1 - midpos1) / scale ; // Relative Position of Icons to Midpoint1 + Base::Vector3d relpos1 = seekConstraintPosition(midpos1, norm1, dir1, 2.5, edit->constrGroup->getChild(i)); dynamic_cast(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr); - dynamic_cast(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0); + dynamic_cast(sep->getChild(1))->translation = SbVec3f(relpos1.x, relpos1.y, 0); if (Constr->FirstPos == Sketcher::none) { - Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale); - constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i)); + Base::Vector3d relpos2 = seekConstraintPosition(midpos2, norm2, dir2, 2.5, edit->constrGroup->getChild(i)); - Base::Vector3d relPos2 = (constrPos2 - midpos2) / scale ; // Relative Position of Icons to Midpoint2 Base::Vector3d secondPos = midpos2 - midpos1; dynamic_cast(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr); - dynamic_cast(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0); + dynamic_cast(sep->getChild(3))->translation = SbVec3f(relpos2.x -relpos1.x, relpos2.y -relpos1.y, 0); } } @@ -2012,32 +1996,19 @@ Restart: norm2 = Base::Vector3d(-dir2.y,dir2.x,0.); } - // Get Current Scale Factor - float scale = dynamic_cast(sep->getChild(1))->getScaleFactor(); - - Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale); - constrPos1 = seekConstraintPosition(constrPos1, dir1, scale * 2.5, edit->constrGroup->getChild(i)); - - Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale); - constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i)); - - // Translate the Icon based on calculated position - Base::Vector3d relPos1 = constrPos1 - midpos1 ; // Relative Position of Icons to Midpoint1 - Base::Vector3d relPos2 = constrPos2 - midpos2 ; // Relative Position of Icons to Midpoint2 - - relPos1 = relPos1 / scale; - relPos2 = relPos2 / scale; + Base::Vector3d relpos1 = seekConstraintPosition(midpos1, norm1, dir1, 2.5, edit->constrGroup->getChild(i)); + Base::Vector3d relpos2 = seekConstraintPosition(midpos2, norm2, dir2, 2.5, edit->constrGroup->getChild(i)); dynamic_cast(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr); //Absolute Reference //Reference Position that is scaled according to zoom - dynamic_cast(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0); + dynamic_cast(sep->getChild(1))->translation = SbVec3f(relpos1.x, relpos1.y, 0); Base::Vector3d secondPos = midpos2 - midpos1; dynamic_cast(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr); //Absolute Reference //Reference Position that is scaled according to zoom - dynamic_cast(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0); + dynamic_cast(sep->getChild(3))->translation = SbVec3f(relpos2.x - relpos1.x, relpos2.y -relpos1.y, 0); } break; @@ -2148,32 +2119,19 @@ Restart: Base::Vector3d norm1 = Base::Vector3d(-dir1.y,dir1.x,0.f); Base::Vector3d norm2 = Base::Vector3d(-dir2.y,dir2.x,0.f); - // Get Current Scale Factor - float scale = dynamic_cast(sep->getChild(1))->getScaleFactor(); - - Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale); - constrPos1 = seekConstraintPosition(constrPos1, dir1, 2.5 * scale, edit->constrGroup->getChild(i)); - - Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale); - constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i)); - - // Translate the Icon based on calculated position - Base::Vector3d relPos1 = constrPos1 - midpos1 ; // Relative Position of Icons to Midpoint1 - Base::Vector3d relPos2 = constrPos2 - midpos2 ; // Relative Position of Icons to Midpoint2 - - relPos1 = relPos1 / scale; - relPos2 = relPos2 / scale; + Base::Vector3d relpos1 = seekConstraintPosition(midpos1, norm1, dir1, 2.5, edit->constrGroup->getChild(i)); + Base::Vector3d relpos2 = seekConstraintPosition(midpos2, norm2, dir2, 2.5, edit->constrGroup->getChild(i)); dynamic_cast(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr); //Absolute Reference //Reference Position that is scaled according to zoom - dynamic_cast(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0); + dynamic_cast(sep->getChild(1))->translation = SbVec3f(relpos1.x, relpos1.y, 0); Base::Vector3d secondPos = midpos2 - midpos1; dynamic_cast(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr); //Absolute Reference //Reference Position that is scaled according to zoom - dynamic_cast(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0); + dynamic_cast(sep->getChild(3))->translation = SbVec3f(relpos2.x -relpos1.x, relpos2.y -relpos1.y, 0); break; } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index b29f2c377..9b05d69cc 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -137,10 +137,9 @@ public: /// moves a selected constraint void moveConstraint(int constNum, const Base::Vector2D &toPos); - /// checks if there is a constraint object at position vector - bool isConstraintAtPosition(const Base::Vector3d &constrPos, const SoNode *constraint); /// finds a free position for placing a constraint icon - Base::Vector3d seekConstraintPosition(const Base::Vector3d &suggestedPos, + Base::Vector3d seekConstraintPosition(const Base::Vector3d &origPos, + const Base::Vector3d &norm, const Base::Vector3d &dir, float step, const SoNode *constraint); From 6b0f50d98cdce5159aafda2b69abf2396b174419 Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 6 Aug 2012 13:34:29 +0200 Subject: [PATCH 2/5] Sketcher: add perpendicular mode to polyline tool and use M-key for mode-switching --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 214 ++++++++++++++-------- 1 file changed, 142 insertions(+), 72 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index eb0aa74fe..cbacc1392 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -488,50 +488,103 @@ class DrawSketchHandlerLineSet: public DrawSketchHandler { public: DrawSketchHandlerLineSet() - : Mode(STATUS_SEEK_First),LineMode(LINE_MODE_Line),EditCurve(2), - firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(-1), - isTangent(false) {} + : Mode(STATUS_SEEK_First),SegmentMode(SEGMENT_MODE_Line), + TransitionMode(TRANSITION_MODE_Free),suppressTransition(false),EditCurve(2), + firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(-1) {} virtual ~DrawSketchHandlerLineSet() {} /// mode table - enum SelectMode { + enum SELECT_MODE { STATUS_SEEK_First, /**< enum value ----. */ STATUS_SEEK_Second, /**< enum value ----. */ STATUS_Do, STATUS_Close }; - enum SelectLineMode + enum SEGMENT_MODE { - LINE_MODE_Arc, - LINE_MODE_Line + SEGMENT_MODE_Arc, + SEGMENT_MODE_Line + }; + + enum TRANSITION_MODE + { + TRANSITION_MODE_Free, + TRANSITION_MODE_Tangent, + TRANSITION_MODE_Perpendicular_L, + TRANSITION_MODE_Perpendicular_R }; virtual void registerPressedKey(bool pressed, int key) { - if (key == SoKeyboardEvent::A && pressed && previousCurve != -1) { - if (LineMode != LINE_MODE_Arc) { - Base::Vector2D onSketchPos = EditCurve[isTangent ? 2 : 1]; - LineMode = LINE_MODE_Arc; - if (previousCurve != -1) - isTangent = true; - else - isTangent = false; - EditCurve.resize(32); - mouseMove(onSketchPos); // trigger an update of EditCurve + if (key == SoKeyboardEvent::M && pressed && previousCurve != -1) { + // loop through the following modes: + // SEGMENT_MODE_Line, TRANSITION_MODE_Free / TRANSITION_MODE_Tangent + // SEGMENT_MODE_Line, TRANSITION_MODE_Perpendicular_L + // SEGMENT_MODE_Line, TRANSITION_MODE_Tangent / TRANSITION_MODE_Free + // SEGMENT_MODE_Arc, TRANSITION_MODE_Tangent + // SEGMENT_MODE_Arc, TRANSITION_MODE_Perpendicular_L + // SEGMENT_MODE_Arc, TRANSITION_MODE_Perpendicular_R + + Base::Vector2D onSketchPos; + if (SegmentMode == SEGMENT_MODE_Line) + onSketchPos = EditCurve[EditCurve.size()-1]; + else + onSketchPos = EditCurve[29]; + + const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(previousCurve); + + if (SegmentMode == SEGMENT_MODE_Line) { + switch (TransitionMode) { + case TRANSITION_MODE_Free: + if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { // 3rd mode + SegmentMode = SEGMENT_MODE_Arc; + TransitionMode = TRANSITION_MODE_Tangent; + } + else // 1st mode + TransitionMode = TRANSITION_MODE_Perpendicular_L; + break; + case TRANSITION_MODE_Perpendicular_L: // 2nd mode + if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) + TransitionMode = TRANSITION_MODE_Free; + else + TransitionMode = TRANSITION_MODE_Tangent; + break; + case TRANSITION_MODE_Tangent: + if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) // 1st mode + TransitionMode = TRANSITION_MODE_Perpendicular_L; + else { // 3rd mode + SegmentMode = SEGMENT_MODE_Arc; + TransitionMode = TRANSITION_MODE_Tangent; + } + break; + default: // unexpected mode + TransitionMode = TRANSITION_MODE_Free; + break; + } } else { - Base::Vector2D onSketchPos = EditCurve[29]; - LineMode = LINE_MODE_Line; - if (previousCurve != -1) { - const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(previousCurve); - if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) - isTangent = true; - else - isTangent = false; + switch (TransitionMode) { + case TRANSITION_MODE_Tangent: // 4th mode + TransitionMode = TRANSITION_MODE_Perpendicular_L; + break; + case TRANSITION_MODE_Perpendicular_L: // 5th mode + TransitionMode = TRANSITION_MODE_Perpendicular_R; + break; + default: // 6th mode (Perpendicular_R) + unexpexted mode + SegmentMode = SEGMENT_MODE_Line; + if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) + TransitionMode = TRANSITION_MODE_Tangent; + else + TransitionMode = TRANSITION_MODE_Free; + break; } - EditCurve.resize(isTangent ? 3 : 2); - mouseMove(onSketchPos); // trigger an update of EditCurve } + + if (SegmentMode == SEGMENT_MODE_Line) + EditCurve.resize(TransitionMode == TRANSITION_MODE_Free ? 2 : 3); + else + EditCurve.resize(32); + mouseMove(onSketchPos); // trigger an update of EditCurve } } @@ -542,6 +595,7 @@ public: virtual void mouseMove(Base::Vector2D onSketchPos) { + suppressTransition = false; setPositionText(onSketchPos); if (Mode==STATUS_SEEK_First) { if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { @@ -550,23 +604,41 @@ public: } } else if (Mode==STATUS_SEEK_Second){ - if (LineMode == LINE_MODE_Line) { - EditCurve[isTangent ? 2 : 1] = onSketchPos; - if (isTangent) { + if (SegmentMode == SEGMENT_MODE_Line) { + EditCurve[EditCurve.size()-1] = onSketchPos; + if (TransitionMode == TRANSITION_MODE_Tangent) { Base::Vector2D Tangent(dirVec.x,dirVec.y); EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Tangent); + if (EditCurve[1] * Tangent < 0) { + EditCurve[1] = EditCurve[2]; + suppressTransition = true; + } + else + EditCurve[1] = EditCurve[0] + EditCurve[1]; + } + else if (TransitionMode == TRANSITION_MODE_Perpendicular_L || + TransitionMode == TRANSITION_MODE_Perpendicular_R) { + Base::Vector2D Perpendicular(-dirVec.y,dirVec.x); + EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Perpendicular); EditCurve[1] = EditCurve[0] + EditCurve[1]; } sketchgui->drawEdit(EditCurve); - if (!isTangent) { + if (TransitionMode == TRANSITION_MODE_Free) { if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) { renderSuggestConstraintsCursor(sugConstr2); return; } } } - else if (LineMode == LINE_MODE_Arc) { - Base::Vector2D Tangent(dirVec.x,dirVec.y); + else if (SegmentMode == SEGMENT_MODE_Arc) { + Base::Vector2D Tangent; + if (TransitionMode == TRANSITION_MODE_Tangent) + Tangent = Base::Vector2D(dirVec.x,dirVec.y); + else if (TransitionMode == TRANSITION_MODE_Perpendicular_L) + Tangent = Base::Vector2D(-dirVec.y,dirVec.x); + else if (TransitionMode == TRANSITION_MODE_Perpendicular_R) + Tangent = Base::Vector2D(dirVec.y,-dirVec.x); + float theta = Tangent.GetAngle(onSketchPos - EditCurve[0]); arcRadius = (onSketchPos - EditCurve[0]).Length()/(2.0*sin(theta)); // At this point we need a unit normal vector pointing torwards @@ -581,10 +653,7 @@ public: if ((x2*y3-x3*y2)-(x1*y3-x3*y1)+(x1*y2-x2*y1) > 0) arcRadius *= -1; - Base::Vector3d centerVec = dirVec % Base::Vector3d(0.f,0.f,1.0); - centerVec.Normalize(); // this step should actually be redundant - - CenterPoint = EditCurve[0] + Base::Vector2D(arcRadius * centerVec.x, arcRadius * centerVec.y); + CenterPoint = EditCurve[0] + Base::Vector2D(arcRadius * Tangent.fY, -arcRadius * Tangent.fX); float rx = EditCurve[0].fX - CenterPoint.fX; float ry = EditCurve[0].fY - CenterPoint.fY; @@ -622,35 +691,23 @@ public: virtual bool pressButton(Base::Vector2D onSketchPos) { - if (Mode==STATUS_SEEK_First) { + if (Mode == STATUS_SEEK_First) { // remember our first point firstVertex = getHighestVertexIndex() + 1; firstCurve = getHighestCurveIndex() + 1; // TODO: here we should check if there is a preselected point // and set up a transition from the neighbouring segment. - // (peviousCurve, previousPosId, dirVec, isTangent) + // (peviousCurve, previousPosId, dirVec, TransitionMode) // in that case we should set firstCurve and firstVertex to -1 // in order to disable closing the wire - if (LineMode == LINE_MODE_Line) - EditCurve.resize(isTangent ? 3 : 2); - else if (LineMode == LINE_MODE_Arc) + if (SegmentMode == SEGMENT_MODE_Line) + EditCurve.resize(TransitionMode == TRANSITION_MODE_Free ? 2 : 3); + else if (SegmentMode == SEGMENT_MODE_Arc) EditCurve.resize(32); EditCurve[0] = onSketchPos; Mode = STATUS_SEEK_Second; } - else if (Mode==STATUS_SEEK_Second) { - if (LineMode == LINE_MODE_Line) { - EditCurve[isTangent ? 2 : 1] = onSketchPos; - if (isTangent) { - Base::Vector2D Tangent(dirVec.x,dirVec.y); - EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Tangent); - EditCurve[1] = EditCurve[0] + EditCurve[1]; - } - } - else if (LineMode == LINE_MODE_Arc) - EditCurve[29] = onSketchPos; // not so important - sketchgui->drawEdit(EditCurve); - applyCursor(); + else if (Mode == STATUS_SEEK_Second) { // exit on clicking exactly at the same position (e.g. double click) if (onSketchPos == EditCurve[0]) { unsetCursor(); @@ -671,7 +728,7 @@ public: { if (Mode == STATUS_Do || Mode == STATUS_Close) { - if (LineMode == LINE_MODE_Line) { + if (SegmentMode == SEGMENT_MODE_Line) { // open the transaction Gui::Command::openCommand("Add line to sketch wire"); // issue the geometry @@ -680,7 +737,7 @@ public: sketchgui->getObject()->getNameInDocument(), EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY); } - else if (LineMode == LINE_MODE_Arc) { // We're dealing with an Arc + else if (SegmentMode == SEGMENT_MODE_Arc) { // We're dealing with an Arc Gui::Command::openCommand("Add arc to sketch wire"); Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addGeometry(Part.ArcOfCircle" @@ -692,13 +749,20 @@ public: // issue the constraint if (previousCurve != -1) { int lastCurve = previousCurve+1; - int lastStartPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 2 : 1; - int lastEndPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2; - // in case of a tangency constraint, the coincident constraint is redundant + int lastStartPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? 2 : 1; + int lastEndPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? 1 : 2; + // in case of a tangency constraint, the coincident constraint is redundant + std::string constrType = "Coincident"; + if (!suppressTransition) { + if (TransitionMode == TRANSITION_MODE_Tangent) + constrType = "Tangent"; + else if (TransitionMode == TRANSITION_MODE_Perpendicular_L || + TransitionMode == TRANSITION_MODE_Perpendicular_R) + constrType = "Perpendicular"; + } Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('%s',%i,%i,%i,%i)) ", - sketchgui->getObject()->getNameInDocument(), - isTangent ? "Tangent" : "Coincident", + sketchgui->getObject()->getNameInDocument(), constrType.c_str(), previousCurve, previousPosId /* == 2 */, lastCurve, lastStartPosId); if (Mode == STATUS_Close) { int firstGeoId; @@ -750,7 +814,7 @@ public: // remember the vertex for the next rounds constraint.. previousCurve = getHighestCurveIndex(); - previousPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2; + previousPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? 1 : 2; // setup for the next line segment // Use updated endPoint as autoconstraints can modify the position @@ -764,7 +828,7 @@ public: 0.f); } else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - assert(LineMode == LINE_MODE_Arc); + assert(SegmentMode == SEGMENT_MODE_Arc); const Part::GeomArcOfCircle *arcSeg = dynamic_cast(geom); if (startAngle > endAngle) { EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y); @@ -779,20 +843,27 @@ public: applyCursor(); Mode = STATUS_SEEK_Second; - isTangent = (LineMode == LINE_MODE_Arc); - LineMode = LINE_MODE_Line; - EditCurve.resize(isTangent ? 3 : 2); - EditCurve[1] = EditCurve[0]; - if (isTangent) + if (SegmentMode == SEGMENT_MODE_Arc) { + TransitionMode = TRANSITION_MODE_Tangent; + EditCurve.resize(3); EditCurve[2] = EditCurve[0]; + } + else { + TransitionMode = TRANSITION_MODE_Free; + EditCurve.resize(2); + } + SegmentMode = SEGMENT_MODE_Line; + EditCurve[1] = EditCurve[0]; sketchgui->drawEdit(EditCurve); } } return true; } protected: - SelectMode Mode; - SelectLineMode LineMode; + SELECT_MODE Mode; + SEGMENT_MODE SegmentMode; + TRANSITION_MODE TransitionMode; + bool suppressTransition; std::vector EditCurve; int firstVertex; @@ -803,7 +874,6 @@ protected: Base::Vector2D CenterPoint; Base::Vector3d dirVec; - bool isTangent; float startAngle, endAngle, arcRadius; }; From 3f3b7cd68f94aa235ad85cf5993d722d851387bd Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 6 Aug 2012 16:13:09 +0200 Subject: [PATCH 3/5] Sketcher: allow starting a new polyline connected at some already available geometry --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 109 ++++++++++++++-------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index cbacc1392..f45f9d54d 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -490,7 +490,7 @@ public: DrawSketchHandlerLineSet() : Mode(STATUS_SEEK_First),SegmentMode(SEGMENT_MODE_Line), TransitionMode(TRANSITION_MODE_Free),suppressTransition(false),EditCurve(2), - firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(-1) {} + firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(Sketcher::none) {} virtual ~DrawSketchHandlerLineSet() {} /// mode table enum SELECT_MODE { @@ -692,19 +692,41 @@ public: virtual bool pressButton(Base::Vector2D onSketchPos) { if (Mode == STATUS_SEEK_First) { - // remember our first point - firstVertex = getHighestVertexIndex() + 1; - firstCurve = getHighestCurveIndex() + 1; - // TODO: here we should check if there is a preselected point - // and set up a transition from the neighbouring segment. + + EditCurve[0] = onSketchPos; // this may be overwritten if previousCurve is found + + // here we check if there is a preselected point and + // we set up a transition from the neighbouring segment. // (peviousCurve, previousPosId, dirVec, TransitionMode) - // in that case we should set firstCurve and firstVertex to -1 - // in order to disable closing the wire + for (int i=0; i < sugConstr1.size(); i++) + if (sugConstr1[i].Type == Sketcher::Coincident) { + const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(sugConstr1[i].GeoId); + if ((geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() || + geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) && + (sugConstr1[i].PosId == Sketcher::start || + sugConstr1[i].PosId == Sketcher::end)) { + previousCurve = sugConstr1[i].GeoId; + previousPosId = sugConstr1[i].PosId; + updateTransitionData(previousCurve,previousPosId); // -> dirVec, EditMode[0] + if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) + TransitionMode = TRANSITION_MODE_Tangent; + sugConstr1.erase(sugConstr1.begin()+i); // actually we should clear the vector completely + break; + } + } + + // in case a transition is set up, firstCurve and firstVertex should + // remain set to -1 in order to disable closing the wire + if (previousCurve == -1) { + // remember our first point + firstVertex = getHighestVertexIndex() + 1; + firstCurve = getHighestCurveIndex() + 1; + } + if (SegmentMode == SEGMENT_MODE_Line) EditCurve.resize(TransitionMode == TRANSITION_MODE_Free ? 2 : 3); else if (SegmentMode == SEGMENT_MODE_Arc) EditCurve.resize(32); - EditCurve[0] = onSketchPos; Mode = STATUS_SEEK_Second; } else if (Mode == STATUS_SEEK_Second) { @@ -716,7 +738,7 @@ public: sketchgui->drawEdit(EditCurve); sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider } - if (sketchgui->getPreselectPoint() == firstVertex) + if (sketchgui->getPreselectPoint() == firstVertex && firstVertex != -1) Mode = STATUS_Close; else Mode = STATUS_Do; @@ -748,9 +770,11 @@ public: } // issue the constraint if (previousCurve != -1) { - int lastCurve = previousCurve+1; - int lastStartPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? 2 : 1; - int lastEndPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? 1 : 2; + int lastCurve = getHighestCurveIndex(); + Sketcher::PointPos lastStartPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? + Sketcher::end : Sketcher::start; + Sketcher::PointPos lastEndPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? + Sketcher::start : Sketcher::end; // in case of a tangency constraint, the coincident constraint is redundant std::string constrType = "Coincident"; if (!suppressTransition) { @@ -763,7 +787,7 @@ public: Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('%s',%i,%i,%i,%i)) ", sketchgui->getObject()->getNameInDocument(), constrType.c_str(), - previousCurve, previousPosId /* == 2 */, lastCurve, lastStartPosId); + previousCurve, previousPosId, lastCurve, lastStartPosId); if (Mode == STATUS_Close) { int firstGeoId; Sketcher::PointPos firstPosId; @@ -814,32 +838,12 @@ public: // remember the vertex for the next rounds constraint.. previousCurve = getHighestCurveIndex(); - previousPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? 1 : 2; + previousPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ? + Sketcher::start : Sketcher::end; // cw arcs are rendered in reverse // setup for the next line segment - // Use updated endPoint as autoconstraints can modify the position - // Need to determine if the previous element was a line or an arc or ??? - const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(getHighestCurveIndex()); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment *lineSeg = dynamic_cast(geom); - EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y); - dirVec.Set(lineSeg->getEndPoint().x - lineSeg->getStartPoint().x, - lineSeg->getEndPoint().y - lineSeg->getStartPoint().y, - 0.f); - } - else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - assert(SegmentMode == SEGMENT_MODE_Arc); - const Part::GeomArcOfCircle *arcSeg = dynamic_cast(geom); - if (startAngle > endAngle) { - EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y); - dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint()-arcSeg->getCenter()); - } - else { // cw arcs are rendered in reverse - EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint().x,arcSeg->getEndPoint().y); - dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint()-arcSeg->getCenter()); - } - } - dirVec.Normalize(); + // calculate dirVec and EditCurve[0] + updateTransitionData(previousCurve,previousPosId); applyCursor(); Mode = STATUS_SEEK_Second; @@ -868,13 +872,40 @@ protected: std::vector EditCurve; int firstVertex; int firstCurve; - int previousPosId; int previousCurve; + Sketcher::PointPos previousPosId; std::vector sugConstr1, sugConstr2; Base::Vector2D CenterPoint; Base::Vector3d dirVec; float startAngle, endAngle, arcRadius; + + void updateTransitionData(int GeoId, Sketcher::PointPos PosId) { + + // Use updated startPoint/endPoint as autoconstraints can modify the position + const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId); + if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + const Part::GeomLineSegment *lineSeg = dynamic_cast(geom); + EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y); + dirVec.Set(lineSeg->getEndPoint().x - lineSeg->getStartPoint().x, + lineSeg->getEndPoint().y - lineSeg->getStartPoint().y, + 0.f); + if (PosId == Sketcher::start) + dirVec *= -1; + } + else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + const Part::GeomArcOfCircle *arcSeg = dynamic_cast(geom); + if (PosId == Sketcher::start) { + EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y); + dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint()-arcSeg->getCenter()); + } + else { + EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint().x,arcSeg->getEndPoint().y); + dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint()-arcSeg->getCenter()); + } + } + dirVec.Normalize(); + } }; From db2ccb31b40685daf31b36a6b397643954c357ac Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 6 Aug 2012 23:05:31 +0200 Subject: [PATCH 4/5] Sketcher: improve position text during geometry creation --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 47 +++++++++++++++++---- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 2 +- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index f45f9d54d..f008aa82b 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -142,15 +142,21 @@ public: virtual void mouseMove(Base::Vector2D onSketchPos) { - setPositionText(onSketchPos); - if (Mode==STATUS_SEEK_First) { + setPositionText(onSketchPos); if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { renderSuggestConstraintsCursor(sugConstr1); return; } } else if (Mode==STATUS_SEEK_Second){ + float length = (onSketchPos - EditCurve[0]).Length(); + float angle = (onSketchPos - EditCurve[0]).GetAngle(Base::Vector2D(1.f,0.f)); + char buf[40]; + sprintf(buf, " (%.1f,%.1f°)", length, angle * 180 / M_PI); + std::string text = buf; + setPositionText(onSketchPos, text); + EditCurve[1] = onSketchPos; sketchgui->drawEdit(EditCurve); if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) { @@ -301,15 +307,22 @@ public: virtual void mouseMove(Base::Vector2D onSketchPos) { - setPositionText(onSketchPos); if (Mode==STATUS_SEEK_First) { + setPositionText(onSketchPos); if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { renderSuggestConstraintsCursor(sugConstr1); return; } } else if (Mode==STATUS_SEEK_Second) { + float dx = onSketchPos.fX - EditCurve[0].fX; + float dy = onSketchPos.fY - EditCurve[0].fY; + char buf[40]; + sprintf(buf, " (%.1f x %.1f)", dx, dy); + std::string text = buf; + setPositionText(onSketchPos, text); + EditCurve[2] = onSketchPos; EditCurve[1] = Base::Vector2D(onSketchPos.fX ,EditCurve[0].fY); EditCurve[3] = Base::Vector2D(EditCurve[0].fX,onSketchPos.fY); @@ -596,8 +609,8 @@ public: virtual void mouseMove(Base::Vector2D onSketchPos) { suppressTransition = false; - setPositionText(onSketchPos); if (Mode==STATUS_SEEK_First) { + setPositionText(onSketchPos); if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { renderSuggestConstraintsCursor(sugConstr1); return; @@ -622,7 +635,17 @@ public: EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Perpendicular); EditCurve[1] = EditCurve[0] + EditCurve[1]; } + sketchgui->drawEdit(EditCurve); + + float length = (EditCurve[1] - EditCurve[0]).Length(); + float angle = (EditCurve[1] - EditCurve[0]).GetAngle(Base::Vector2D(1.f,0.f)); + + char buf[40]; + sprintf(buf, " (%.1f,%.1f°)", length, angle * 180 / M_PI); + std::string text = buf; + setPositionText(EditCurve[1], text); + if (TransitionMode == TRANSITION_MODE_Free) { if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) { renderSuggestConstraintsCursor(sugConstr2); @@ -680,6 +703,12 @@ public: EditCurve[31] = EditCurve[0]; sketchgui->drawEdit(EditCurve); + + char buf[40]; + sprintf(buf, " (%.1fR,%.1f°)", std::abs(arcRadius), arcAngle * 180 / M_PI); + std::string text = buf; + setPositionText(onSketchPos, text); + if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) { renderSuggestConstraintsCursor(sugConstr2); return; @@ -1017,10 +1046,10 @@ public: // Display radius and start angle float radius = (onSketchPos - EditCurve[0]).Length(); - float angle = atan2f(dy_ , dx_) * 180 / M_PI; + float angle = atan2f(dy_ , dx_); char buf[40]; - sprintf( buf, " (R%.1f,%.1f)", radius, angle); + sprintf(buf, " (%.1fR,%.1f°)", radius, angle * 180 / M_PI); std::string text = buf; setPositionText(onSketchPos, text); @@ -1042,11 +1071,11 @@ public: EditCurve[i] = Base::Vector2D(CenterPoint.fX + dx, CenterPoint.fY + dy); } - // Display radius and end angle + // Display radius and arc angle float radius = (onSketchPos - EditCurve[0]).Length(); char buf[40]; - sprintf( buf, " (R%.1f,%.1f)", radius, arcAngle * 180 / M_PI); + sprintf(buf, " (%.1fR,%.1f°)", radius, arcAngle * 180 / M_PI); std::string text = buf; setPositionText(onSketchPos, text); @@ -1256,7 +1285,7 @@ public: float radius = (onSketchPos - EditCurve[0]).Length(); char buf[40]; - sprintf( buf, "R%.1f", radius); + sprintf(buf, " (%.1fR)", radius); std::string text = buf; setPositionText(onSketchPos, text); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 981fee2c9..40b2a5ae4 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -2834,7 +2834,7 @@ void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos, const std::s void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos) { char buf[40]; - sprintf( buf, " (%.1f,%.1f)", Pos.fX,Pos.fY ); + sprintf(buf, " (%.1f,%.1f)", Pos.fX, Pos.fY); edit->textX->string = buf; edit->textPos->translation = SbVec3f(Pos.fX,Pos.fY,zText); } From fef08056a14a458e380ecde489805b8d1b871942 Mon Sep 17 00:00:00 2001 From: logari81 Date: Tue, 7 Aug 2012 01:21:45 +0200 Subject: [PATCH 5/5] Sketcher, Issue 0000808: fix one more issue with restoring of external geometry --- src/Mod/Sketcher/App/SketchObject.cpp | 4 ++-- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 82813a607..1c2bd9a33 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1350,6 +1350,8 @@ void SketchObject::rebuildExternalGeometry(void) break; } } + + rebuildVertexIndex(); } std::vector SketchObject::getCompleteGeometry(void) const @@ -1491,8 +1493,6 @@ void SketchObject::Restore(XMLReader &reader) { // read the father classes Part::Part2DObject::Restore(reader); - Constraints.acceptGeometry(getCompleteGeometry()); - rebuildVertexIndex(); } void SketchObject::onChanged(const App::Property* prop) diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 40b2a5ae4..7c0072a16 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -1716,7 +1716,7 @@ void ViewProviderSketch::draw(bool temp) Points.push_back(start); Points.push_back(end); } - else if ((*it)->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { // add a circle + else if ((*it)->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { // add a bspline const Part::GeomBSplineCurve *spline = dynamic_cast(*it); Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast(spline->handle());