View Issue Details

IDProjectCategoryView StatusLast Update
0001475SketcherFeaturepublic2014-03-29 12:29
Reportermdinger Assigned Towmayer  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Product Versiontrunk 
Fixed in Version0.14 
Summary0001475: Implement a 3 point arc similar to solidworks in sketcher
DescriptionSolidworks gives you 3 different methods to draw arcs in sketches including Centerpoint arc, Tangent arc, and 3 point arc. This bug is to implement a "3 point arc" in FreeCAD.

Tested version:
https://github.com/FreeCAD/FreeCAD_sf_master/commit/3ff9292a36103bf9f954190dc60cf49d73e26860

A 3 point arc takes 3 steps to construct:
1. Place the beginning point of arc
2. Place the end point of arc
3. Place a point on the rim of the arc

This fully defines the arc. Note that centerpoint is not picked and must be calculated.

I have attached a screenshot of the icons that SolidWorks uses for their 3 point arc.
TagsNo tags attached.
FreeCAD Information

Activities

mdinger

2014-03-14 22:29

reporter  

3pointarc.png (60,291 bytes)   
3pointarc.png (60,291 bytes)   

mdinger

2014-03-14 22:45

reporter   ~0004444

This patch implements a 3 point arc tool. It seems to draw the curve quite well but it does have has some issues:

1. I created some functions I needed but I think they are global which should probably change in the future.
2. The icon isn't very good.
3. The cursor shape might not be the best choice.
4. Point snapping is copied from another tool and doesn't work properly yet.
5. Might not build in Linux. Not sure.
6. Stack arc icons in the toolbar like solidworks does.
7. Perhaps stack arc tools in the menus.

mdinger

2014-03-14 22:48

reporter  

wip.patch (38,087 bytes)   
From b4932453d59af9ef03332f3927be351e5b6298d1 Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Wed, 5 Mar 2014 22:04:17 -0500
Subject: [PATCH 1/4] Initial commit to make a 3 point arc.  Includes a new
 icon and cursor.  Just copies create point.

---
 src/Mod/Complete/Gui/Workbench.cpp                 |    2 +
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp          |  128 ++++++++++++++++++++
 src/Mod/Sketcher/Gui/Resources/Makefile.am         |    1 +
 src/Mod/Sketcher/Gui/Resources/Sketcher.qrc        |    1 +
 .../Resources/icons/Sketcher_Create3PointArc.svg   |   99 +++++++++++++++
 src/Mod/Sketcher/Gui/Workbench.cpp                 |    2 +
 6 files changed, 233 insertions(+), 0 deletions(-)
 create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Create3PointArc.svg

diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp
index ebc9b06..a67b47f 100644
--- a/src/Mod/Complete/Gui/Workbench.cpp
+++ b/src/Mod/Complete/Gui/Workbench.cpp
@@ -241,6 +241,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
     geom->setCommand("Sketcher geometries");
     *geom << "Sketcher_CreatePoint"
           << "Sketcher_CreateArc"
+          << "Sketcher_Create3PointArc"
           << "Sketcher_CreateCircle"
           << "Sketcher_CreateLine"
           << "Sketcher_CreatePolyline"
@@ -503,6 +504,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
           << "Separator"
           << "Sketcher_CreatePoint"
           << "Sketcher_CreateArc"
+          << "Sketcher_Create3PointArc"
           << "Sketcher_CreateCircle"
           << "Sketcher_CreateLine"
           << "Sketcher_CreatePolyline"
diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index 88a5349..6560a39 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -1214,6 +1214,133 @@ bool CmdSketcherCreateArc::isActive(void)
     return isCreateGeoActive(getActiveGuiDocument());
 }
 
+
+// ======================================================================================
+
+/* XPM */
+static const char *cursor_create3pointarc[]={
+"32 32 3 1",
+"+ c white",
+"# c red",
+". c None",
+"......+...........###...........",
+"......+...........#.#...........",
+"......+...........###...........",
+"......+..............##.........",
+"......+...............##........",
+".......................#........",
+"+++++...+++++...........#.......",
+"........................##......",
+"......+..................#......",
+"......+..................#......",
+"......+...................#.....",
+"......+...................#.....",
+"......+...................#.....",
+"..........................#.....",
+"..........................#.....",
+"..........................#.....",
+"..........................#.....",
+".........................#......",
+".......................###......",
+".......................#.#......",
+".......................###......",
+"...###.................#........",
+"...#.#................#.........",
+"...###...............#..........",
+"......##...........##...........",
+".......###.......##.............",
+"..........#######...............",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
+
+class DrawSketchHandler3PointArc : public DrawSketchHandler
+{
+public:
+    DrawSketchHandler3PointArc() : selectionDone(false) {}
+    virtual ~DrawSketchHandler3PointArc() {}
+
+    virtual void activated(ViewProviderSketch *sketchgui)
+    {
+        setCursor(QPixmap(cursor_create3pointarc),7,7);
+    }
+
+    virtual void mouseMove(Base::Vector2D onSketchPos)
+    {
+        setPositionText(onSketchPos);
+        if (seekAutoConstraint(sugConstr, onSketchPos, Base::Vector2D(0.f,0.f))) {
+            renderSuggestConstraintsCursor(sugConstr);
+            return;
+        }
+        applyCursor();
+    }
+
+    virtual bool pressButton(Base::Vector2D onSketchPos)
+    {
+        EditPoint = onSketchPos;
+        selectionDone = true;
+        return true;
+    }
+
+    virtual bool releaseButton(Base::Vector2D onSketchPos)
+    {
+        if (selectionDone){
+            unsetCursor();
+            resetPositionText();
+
+            Gui::Command::openCommand("Add sketch point");
+            Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
+                      sketchgui->getObject()->getNameInDocument(),
+                      EditPoint.fX,EditPoint.fY);
+            Gui::Command::commitCommand();
+            Gui::Command::updateActive();
+
+            // add auto constraints for the line segment start
+            if (sugConstr.size() > 0) {
+                createAutoConstraints(sugConstr, getHighestCurveIndex(), Sketcher::start);
+                sugConstr.clear();
+            }
+
+            sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
+        }
+        return true;
+    }
+protected:
+    bool selectionDone;
+    Base::Vector2D EditPoint;
+    std::vector<AutoConstraint> sugConstr;
+};
+
+
+DEF_STD_CMD_A(CmdSketcherCreate3PointArc);
+
+CmdSketcherCreate3PointArc::CmdSketcherCreate3PointArc()
+  : Command("Sketcher_Create3PointArc")
+{
+    sAppModule      = "Sketcher";
+    sGroup          = QT_TR_NOOP("Sketcher");
+    sMenuText       = QT_TR_NOOP("Create a 3 point arc");
+    sToolTipText    = QT_TR_NOOP("Create an arc in the sketch");
+    sWhatsThis      = sToolTipText;
+    sStatusTip      = sToolTipText;
+    sPixmap         = "Sketcher_Create3PointArc";
+    eType           = ForEdit;
+}
+
+void CmdSketcherCreate3PointArc::activated(int iMsg)
+{
+    ActivateHandler(getActiveGuiDocument(),new DrawSketchHandler3PointArc() );
+}
+
+bool CmdSketcherCreate3PointArc::isActive(void)
+{
+    return isCreateGeoActive(getActiveGuiDocument());
+}
+
+
+
 // ======================================================================================
 
 /* XPM */
@@ -2135,6 +2262,7 @@ void CreateSketcherCommandsCreateGeo(void)
 
     rcCmdMgr.addCommand(new CmdSketcherCreatePoint());
     rcCmdMgr.addCommand(new CmdSketcherCreateArc());
+    rcCmdMgr.addCommand(new CmdSketcherCreate3PointArc());
     rcCmdMgr.addCommand(new CmdSketcherCreateCircle());
     rcCmdMgr.addCommand(new CmdSketcherCreateLine());
     rcCmdMgr.addCommand(new CmdSketcherCreatePolyline());
diff --git a/src/Mod/Sketcher/Gui/Resources/Makefile.am b/src/Mod/Sketcher/Gui/Resources/Makefile.am
index abb54c9..2bb55a3 100644
--- a/src/Mod/Sketcher/Gui/Resources/Makefile.am
+++ b/src/Mod/Sketcher/Gui/Resources/Makefile.am
@@ -61,6 +61,7 @@ icons/Constraint_PointOnObject.svg \
 		icons/Sketcher_ConstrainLock.svg \
 		icons/Sketcher_ConstrainVertical.svg \
 		icons/Sketcher_CreateArc.svg \
+        icons/Sketcher_Create3PointArc.svg \
 		icons/Sketcher_CreateCircle.svg \
 		icons/Sketcher_CreateLine.svg \
 		icons/Sketcher_CreatePoint.svg \
diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
index 6a2191e..391f5d0 100644
--- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
+++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
@@ -51,6 +51,7 @@
         <file>icons/Sketcher_ConstrainParallel.svg</file>
         <file>icons/Sketcher_ConstrainVertical.svg</file>
         <file>icons/Sketcher_CreateArc.svg</file>
+        <file>icons/Sketcher_Create3PointArc.svg</file>
         <file>icons/Sketcher_CreateCircle.svg</file>
         <file>icons/Sketcher_CreateLine.svg</file>
         <file>icons/Sketcher_CreatePoint.svg</file>
diff --git a/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Create3PointArc.svg b/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Create3PointArc.svg
new file mode 100644
index 0000000..d2fc840
--- /dev/null
+++ b/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Create3PointArc.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="64"
+   height="64"
+   id="svg3003"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="New document 2">
+  <defs
+     id="defs3005" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="4"
+     inkscape:cx="22.518427"
+     inkscape:cy="31.132034"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="862"
+     inkscape:window-height="829"
+     inkscape:window-x="40"
+     inkscape:window-y="173"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata3008">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-988.36218)">
+    <path
+       sodipodi:type="arc"
+       style="fill:none;stroke:#ff0000;stroke-width:8;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="path3789"
+       sodipodi:cx="9.75"
+       sodipodi:cy="36"
+       sodipodi:rx="28.5"
+       sodipodi:ry="29.75"
+       d="M -18.75,35.999999 A 28.5,29.75 0 0 1 38.25,36"
+       transform="matrix(0.88374305,0,0,0.83607912,23.758505,998.07501)"
+       sodipodi:start="3.1415927"
+       sodipodi:end="6.2831853"
+       sodipodi:open="true" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="path3795"
+       sodipodi:cx="32.875"
+       sodipodi:cy="13.75"
+       sodipodi:rx="1.375"
+       sodipodi:ry="1.25"
+       d="m 34.25,13.75 a 1.375,1.25 0 1 1 -2.75,0 1.375,1.25 0 1 1 2.75,0 z"
+       transform="translate(-1.25,989.86218)" />
+    <path
+       transform="translate(-25.875,1014.6122)"
+       sodipodi:type="arc"
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="path3795-1"
+       sodipodi:cx="32.875"
+       sodipodi:cy="13.75"
+       sodipodi:rx="1.375"
+       sodipodi:ry="1.25"
+       d="m 34.25,13.75 a 1.375,1.25 0 1 1 -2.75,0 1.375,1.25 0 1 1 2.75,0 z" />
+    <path
+       transform="translate(24.375,1014.6122)"
+       sodipodi:type="arc"
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="path3795-7"
+       sodipodi:cx="32.875"
+       sodipodi:cy="13.75"
+       sodipodi:rx="1.375"
+       sodipodi:ry="1.25"
+       d="m 34.25,13.75 a 1.375,1.25 0 1 1 -2.75,0 1.375,1.25 0 1 1 2.75,0 z" />
+  </g>
+</svg>
diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp
index 3d6b36d..828de47 100644
--- a/src/Mod/Sketcher/Gui/Workbench.cpp
+++ b/src/Mod/Sketcher/Gui/Workbench.cpp
@@ -62,6 +62,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
     geom->setCommand("Sketcher geometries");
     *geom << "Sketcher_CreatePoint"
           << "Sketcher_CreateArc"
+          << "Sketcher_Create3PointArc"
           << "Sketcher_CreateCircle"
           << "Sketcher_CreateLine"
           << "Sketcher_CreatePolyline"
@@ -122,6 +123,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
     geom->setCommand("Sketcher geometries");
     *geom << "Sketcher_CreatePoint"
           << "Sketcher_CreateArc"
+          << "Sketcher_Create3PointArc"
           << "Sketcher_CreateCircle"
           << "Sketcher_CreateLine"
           << "Sketcher_CreatePolyline"
-- 
1.7.9


From a854847c237a72f249e2437876a0f182dcdeb07e Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Thu, 13 Mar 2014 02:30:01 -0400
Subject: [PATCH 2/4] Draws correctly after first click.

---
 src/Base/Tools2D.h                        |    6 +
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp |  210 ++++++++++++++++++++++++++---
 2 files changed, 196 insertions(+), 20 deletions(-)

diff --git a/src/Base/Tools2D.h b/src/Base/Tools2D.h
index 1b1b07f..0e2b9b7 100644
--- a/src/Base/Tools2D.h
+++ b/src/Base/Tools2D.h
@@ -61,6 +61,7 @@ public:
   inline bool      operator== (const Vector2D &rclVct) const;
   inline Vector2D  operator+ (const Vector2D &rclVct) const;
   inline Vector2D  operator- (const Vector2D &rclVct) const;
+  inline Vector2D  operator/ (const double x) const;
 
   inline void Set (double fPX, double fPY);
   inline void Scale (double fS);
@@ -221,6 +222,11 @@ inline double Vector2D::operator* (const Vector2D &rclVct) const
   return (fX * rclVct.fX) + (fY * rclVct.fY);
 }
 
+inline Vector2D Vector2D::operator/ (const double x) const
+{
+  return Vector2D(fX / x, fY / x);
+}
+
 inline void Vector2D::Scale (double fS)
 {
   fX *= fS;
diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index 6560a39..c62fc80 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -49,6 +49,40 @@ using namespace SketcherGui;
 
 /* helper functions ======================================================*/
 
+// Return counter-clockwise angle from horizontal out of p1 to p2 in radians.
+double GetPointAngle (const Base::Vector2D &p1, const Base::Vector2D &p2)
+{
+  double dX = p2.fX - p1.fX;
+  double dY = p2.fY - p1.fY;
+  return dY >= 0 ? atan2(dY, dX) : atan2(dY, dX) + 2*M_PI;
+}
+
+/*
+Find the centerpoint of a circle drawn through any 3 points:
+
+Given points p1-3, draw 2 lines: S12 and S23 which each connect two points.  From the
+midpoint of each line, draw a perpendicular line (S12p/S23p) across the circle.  These
+lines will cross at the centerpoint.
+
+Mathematically, line S12 will have a slope of m12 which can be determined.  Therefore,
+the slope m12p is -1/m12. Line S12p will have an equation of y = m12p*x + b12p.  b12p can
+be solved for using the midpoint of the line.  This can be done for both lines.  Since
+both S12p and S23p cross at the centerpoint, solving the two equations together will give
+the location of the centerpoint.
+*/
+Base::Vector2D GetCircleCenter (const Base::Vector2D &p1, const Base::Vector2D &p2, const Base::Vector2D &p3)
+{
+  double m12p = (p1.fX - p2.fX) / (p2.fY - p1.fY);
+  double m23p = (p2.fX - p3.fX) / (p3.fY - p2.fY);
+  double x = 1/( 2*(m12p - m23p) ) * ( (pow(p3.fX, 2) - pow(p2.fX, 2)) / (p3.fY - p2.fY) -
+                                       (pow(p2.fX, 2) - pow(p1.fX, 2)) / (p2.fY - p1.fY) +
+                                        p3.fY - p1.fY );
+  double y = m12p * ( x - (p1.fX + p2.fX)/2 ) + (p1.fY + p2.fY)/2;
+
+  return Base::Vector2D(x, y);
+}
+
+
 void ActivateHandler(Gui::Document *doc,DrawSketchHandler *handler)
 {
     if (doc) {
@@ -1259,8 +1293,16 @@ static const char *cursor_create3pointarc[]={
 class DrawSketchHandler3PointArc : public DrawSketchHandler
 {
 public:
-    DrawSketchHandler3PointArc() : selectionDone(false) {}
-    virtual ~DrawSketchHandler3PointArc() {}
+    DrawSketchHandler3PointArc()
+      : Mode(STATUS_SEEK_First),EditCurve(2){}
+    virtual ~DrawSketchHandler3PointArc(){}
+    /// mode table
+    enum SelectMode {
+        STATUS_SEEK_First,      /**< enum value ----. */
+        STATUS_SEEK_Second,     /**< enum value ----. */
+        STATUS_SEEK_Third,      /**< enum value ----. */
+        STATUS_End
+    };
 
     virtual void activated(ViewProviderSketch *sketchgui)
     {
@@ -1269,48 +1311,176 @@ public:
 
     virtual void mouseMove(Base::Vector2D onSketchPos)
     {
-        setPositionText(onSketchPos);
-        if (seekAutoConstraint(sugConstr, onSketchPos, Base::Vector2D(0.f,0.f))) {
-            renderSuggestConstraintsCursor(sugConstr);
-            return;
+        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) {
+            EditCurve[0] = (onSketchPos - FirstPoint)/2 + FirstPoint; // Centerpoint
+            EditCurve[1] = EditCurve[33] = onSketchPos;
+            double radius = (onSketchPos - EditCurve[0]).Length();
+            double lineAngle = GetPointAngle(EditCurve[0], onSketchPos);
+
+            // Build a 32 point circle ignoring already constructed points
+            for (int i=1; i <= 32; i++) {
+                // Start at current angle
+                double angle = (i-1)*2*M_PI/32.0 + lineAngle; // N point closed circle has N segments
+                if (i != 1 && i != 17 ) {
+                    EditCurve[i] = Base::Vector2D(EditCurve[0].fX + radius*cos(angle),
+                                                  EditCurve[0].fY + radius*sin(angle));
+                }
+            }
+
+            // Display radius and start angle
+            // This lineAngle will report counter-clockwise from +X, not relatively
+            SbString text;
+            text.sprintf(" (%.1fR,%.1fdeg)", (float) radius, (float) lineAngle * 180 / M_PI);
+            setPositionText(onSketchPos, text);
+
+            sketchgui->drawEdit(EditCurve);
+            if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) {
+                renderSuggestConstraintsCursor(sugConstr2);
+                return;
+            }
+        }
+        else if (Mode==STATUS_SEEK_Third) {
+            EditCurve[30] = GetCircleCenter(FirstPoint, SecondPoint, onSketchPos);
+            double radius = (SecondPoint - EditCurve[30]).Length();
+
+            double angle1 = GetPointAngle(EditCurve[30], FirstPoint);
+            double angle2 = GetPointAngle(EditCurve[30], SecondPoint);
+            double angle3 = GetPointAngle(EditCurve[30], onSketchPos);
+
+            startAngle = min(angle1, angle2); // Angle actually greater than 2*Pi
+            endAngle =   max(angle1, angle2);
+            // angle3 == angle1 or angle2 shouldn't be allowed but not sure...catch/try?
+            // Point 3 is between Point 1 and 2
+            if ( angle3 > startAngle && angle3 < endAngle ) {
+                arcAngle = endAngle - startAngle;
+                // Build a 30 point circle ignoring already constructed points
+                for (int i=1; i <= 28; i++) {
+                    double angle = i*arcAngle/29.0 + startAngle; // N point arc has N-1 segments
+                    EditCurve[i] = Base::Vector2D(EditCurve[30].fX + radius*cos(angle),
+                                                  EditCurve[30].fY + radius*sin(angle));
+                }
+            }
+            // Point 3 is not between Point 1 and 2
+            else {
+                arcAngle = 2*M_PI - (endAngle - startAngle);
+                // Build a 30 point circle ignoring already constructed points
+                for (int i=28; i >= 1; i--) {
+                    double angle = startAngle - i*arcAngle/29.0 ; // N point arc has N-1 segments
+                    EditCurve[i] = Base::Vector2D(EditCurve[30].fX + radius*cos(angle),
+                                                  EditCurve[30].fY + radius*sin(angle));
+                }
+            }
+
+            // This arcAngle will report counter-clockwise from +X, not relatively
+            SbString text;
+            text.sprintf(" (%.1fR,%.1fdeg)", (float) radius, (float) arcAngle * 180 / M_PI);
+            setPositionText(onSketchPos, text);
+
+            sketchgui->drawEdit(EditCurve);
+            if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.0,0.0))) {
+                renderSuggestConstraintsCursor(sugConstr3);
+                return;
+            }
         }
         applyCursor();
+
     }
 
     virtual bool pressButton(Base::Vector2D onSketchPos)
     {
-        EditPoint = onSketchPos;
-        selectionDone = true;
+        if (Mode==STATUS_SEEK_First){
+            // 32 point curve + center + endpoint
+            EditCurve.resize(34);
+            // 17 is circle halfway point (1+32/2)
+            FirstPoint = EditCurve[17] = onSketchPos;
+
+            Mode = STATUS_SEEK_Second;
+        }
+        else if (Mode==STATUS_SEEK_Second){
+            // 30 point arc and center point
+            EditCurve.resize(31);
+            EditCurve[0] = FirstPoint;
+            SecondPoint = EditCurve[29] = onSketchPos;
+
+            Mode = STATUS_SEEK_Third;
+        }
+        else {
+            EditCurve.resize(30);
+            double angle1 = atan2(onSketchPos.fY - CenterPoint.fY,
+                                 onSketchPos.fX - CenterPoint.fX) - startAngle;
+            double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
+            arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
+            if (arcAngle > 0)
+                endAngle = startAngle + arcAngle;
+            else {
+                endAngle = startAngle;
+                startAngle += arcAngle;
+            }
+
+            sketchgui->drawEdit(EditCurve);
+            applyCursor();
+            Mode = STATUS_End;
+        }
+
         return true;
     }
 
     virtual bool releaseButton(Base::Vector2D onSketchPos)
     {
-        if (selectionDone){
+        // Need to look at.  rx might need fixing.
+        if (Mode==STATUS_End) {
             unsetCursor();
             resetPositionText();
-
-            Gui::Command::openCommand("Add sketch point");
-            Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
+            Gui::Command::openCommand("Add sketch arc");
+            Gui::Command::doCommand(Gui::Command::Doc,
+                "App.ActiveDocument.%s.addGeometry(Part.ArcOfCircle"
+                "(Part.Circle(App.Vector(%f,%f,0),App.Vector(0,0,1),%f),"
+                "%f,%f))",
                       sketchgui->getObject()->getNameInDocument(),
-                      EditPoint.fX,EditPoint.fY);
+                      CenterPoint.fX, CenterPoint.fY, sqrt(rx*rx + ry*ry),
+                      startAngle, endAngle); //arcAngle > 0 ? 0 : 1);
+
             Gui::Command::commitCommand();
             Gui::Command::updateActive();
 
-            // add auto constraints for the line segment start
-            if (sugConstr.size() > 0) {
-                createAutoConstraints(sugConstr, getHighestCurveIndex(), Sketcher::start);
-                sugConstr.clear();
+            // Auto Constraint center point
+            if (sugConstr1.size() > 0) {
+                createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
+                sugConstr1.clear();
+            }
+
+            // Auto Constraint first picked point
+            if (sugConstr2.size() > 0) {
+                createAutoConstraints(sugConstr2, getHighestCurveIndex(), (arcAngle > 0) ? Sketcher::start : Sketcher::end );
+                sugConstr2.clear();
             }
 
+            // Auto Constraint second picked point
+            if (sugConstr3.size() > 0) {
+                createAutoConstraints(sugConstr3, getHighestCurveIndex(), (arcAngle > 0) ? Sketcher::end : Sketcher::start);
+                sugConstr3.clear();
+            }
+
+            EditCurve.clear();
+            sketchgui->drawEdit(EditCurve);
             sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
         }
         return true;
     }
 protected:
-    bool selectionDone;
-    Base::Vector2D EditPoint;
-    std::vector<AutoConstraint> sugConstr;
+    SelectMode Mode;
+    std::vector<Base::Vector2D> EditCurve;
+    Base::Vector2D CenterPoint;
+    Base::Vector2D FirstPoint, SecondPoint, ThirdPoint;
+    double rx, ry, startAngle, endAngle, arcAngle;
+    std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3;
 };
 
 
-- 
1.7.9


From c389e85eb143bb16d2efa2e1687fb5c0fde965cb Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Thu, 13 Mar 2014 03:06:20 -0400
Subject: [PATCH 3/4] Moving mouse to choose 3rd point appears to work
 correctly

---
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp |   57 +++++++++++++++++------------
 1 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index c62fc80..c3fce92 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -1347,35 +1347,48 @@ public:
             }
         }
         else if (Mode==STATUS_SEEK_Third) {
-            EditCurve[30] = GetCircleCenter(FirstPoint, SecondPoint, onSketchPos);
-            double radius = (SecondPoint - EditCurve[30]).Length();
-
-            double angle1 = GetPointAngle(EditCurve[30], FirstPoint);
-            double angle2 = GetPointAngle(EditCurve[30], SecondPoint);
-            double angle3 = GetPointAngle(EditCurve[30], onSketchPos);
+            /*
+            Centerline inverts when the centerpoint goes from below to above the right point
+            or vice versa.  Easily taken care of by replacing centerline with a point.  It
+            happens because the direction the curve is being drawn reverses.  This happens because
+            it is much easier to draw the line in a consistent direction than otherwise.
+            */
+            CenterPoint = EditCurve[30] = GetCircleCenter(FirstPoint, SecondPoint, onSketchPos);
+            double radius = (SecondPoint - CenterPoint).Length();
+            bool buildForward = true; // Construct curve clockwise
+
+            double angle1 = GetPointAngle(CenterPoint, FirstPoint);
+            double angle2 = GetPointAngle(CenterPoint, SecondPoint);
+            double angle3 = GetPointAngle(CenterPoint, onSketchPos);
+            // Specify what direction curve is drawn
+            if (angle2 > angle1) {
+                EditCurve[0] =  FirstPoint;
+                EditCurve[29] = SecondPoint;
+            }
+            else {
+                EditCurve[0] =  SecondPoint;
+                EditCurve[29] = FirstPoint;
+            }
 
-            startAngle = min(angle1, angle2); // Angle actually greater than 2*Pi
+            startAngle = min(angle1, angle2);
             endAngle =   max(angle1, angle2);
             // angle3 == angle1 or angle2 shouldn't be allowed but not sure...catch/try?
             // Point 3 is between Point 1 and 2
             if ( angle3 > startAngle && angle3 < endAngle ) {
                 arcAngle = endAngle - startAngle;
-                // Build a 30 point circle ignoring already constructed points
-                for (int i=1; i <= 28; i++) {
-                    double angle = i*arcAngle/29.0 + startAngle; // N point arc has N-1 segments
-                    EditCurve[i] = Base::Vector2D(EditCurve[30].fX + radius*cos(angle),
-                                                  EditCurve[30].fY + radius*sin(angle));
-                }
             }
             // Point 3 is not between Point 1 and 2
             else {
                 arcAngle = 2*M_PI - (endAngle - startAngle);
-                // Build a 30 point circle ignoring already constructed points
-                for (int i=28; i >= 1; i--) {
-                    double angle = startAngle - i*arcAngle/29.0 ; // N point arc has N-1 segments
-                    EditCurve[i] = Base::Vector2D(EditCurve[30].fX + radius*cos(angle),
-                                                  EditCurve[30].fY + radius*sin(angle));
-                }
+                buildForward = false;
+            }
+
+            // Build a 30 point circle ignoring already constructed points
+            for (int i=1; i <= 28; i++) {
+                double angle = buildForward ? startAngle + i*arcAngle/29.0 :
+                                              startAngle - i*arcAngle/29.0; // N point arc has N-1 segments
+                EditCurve[i] = Base::Vector2D(EditCurve[30].fX + radius*cos(angle),
+                                              EditCurve[30].fY + radius*sin(angle));
             }
 
             // This arcAngle will report counter-clockwise from +X, not relatively
@@ -1406,8 +1419,7 @@ public:
         else if (Mode==STATUS_SEEK_Second){
             // 30 point arc and center point
             EditCurve.resize(31);
-            EditCurve[0] = FirstPoint;
-            SecondPoint = EditCurve[29] = onSketchPos;
+            SecondPoint = onSketchPos;
 
             Mode = STATUS_SEEK_Third;
         }
@@ -1477,8 +1489,7 @@ public:
 protected:
     SelectMode Mode;
     std::vector<Base::Vector2D> EditCurve;
-    Base::Vector2D CenterPoint;
-    Base::Vector2D FirstPoint, SecondPoint, ThirdPoint;
+    Base::Vector2D CenterPoint, FirstPoint, SecondPoint, ThirdPoint;
     double rx, ry, startAngle, endAngle, arcAngle;
     std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3;
 };
-- 
1.7.9


From 4288012951a8a63c0f0411bc25d7d40e1190eb24 Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Fri, 14 Mar 2014 14:31:15 -0400
Subject: [PATCH 4/4] Arc draws correctly.  Autosnap doesn't work at all.

---
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp |   75 +++++++++++------------------
 1 files changed, 28 insertions(+), 47 deletions(-)

diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index c3fce92..0521e9b 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -1319,18 +1319,18 @@ public:
             }
         }
         else if (Mode==STATUS_SEEK_Second) {
-            EditCurve[0] = (onSketchPos - FirstPoint)/2 + FirstPoint; // Centerpoint
+            CenterPoint  = EditCurve[0] = (onSketchPos - FirstPoint)/2 + FirstPoint;
             EditCurve[1] = EditCurve[33] = onSketchPos;
-            double radius = (onSketchPos - EditCurve[0]).Length();
-            double lineAngle = GetPointAngle(EditCurve[0], onSketchPos);
+            radius = (onSketchPos - CenterPoint).Length();
+            double lineAngle = GetPointAngle(CenterPoint, onSketchPos);
 
             // Build a 32 point circle ignoring already constructed points
             for (int i=1; i <= 32; i++) {
                 // Start at current angle
                 double angle = (i-1)*2*M_PI/32.0 + lineAngle; // N point closed circle has N segments
                 if (i != 1 && i != 17 ) {
-                    EditCurve[i] = Base::Vector2D(EditCurve[0].fX + radius*cos(angle),
-                                                  EditCurve[0].fY + radius*sin(angle));
+                    EditCurve[i] = Base::Vector2D(CenterPoint.fX + radius*cos(angle),
+                                                  CenterPoint.fY + radius*sin(angle));
                 }
             }
 
@@ -1348,50 +1348,42 @@ public:
         }
         else if (Mode==STATUS_SEEK_Third) {
             /*
-            Centerline inverts when the centerpoint goes from below to above the right point
-            or vice versa.  Easily taken care of by replacing centerline with a point.  It
-            happens because the direction the curve is being drawn reverses.  This happens because
-            it is much easier to draw the line in a consistent direction than otherwise.
+            Centerline inverts when the arc flips sides.  Easily taken care of by replacing
+            centerline with a point.  It happens because the direction the curve is being drawn
+            reverses.
             */
             CenterPoint = EditCurve[30] = GetCircleCenter(FirstPoint, SecondPoint, onSketchPos);
-            double radius = (SecondPoint - CenterPoint).Length();
-            bool buildForward = true; // Construct curve clockwise
+            radius = (SecondPoint - CenterPoint).Length();
 
             double angle1 = GetPointAngle(CenterPoint, FirstPoint);
             double angle2 = GetPointAngle(CenterPoint, SecondPoint);
             double angle3 = GetPointAngle(CenterPoint, onSketchPos);
-            // Specify what direction curve is drawn
-            if (angle2 > angle1) {
-                EditCurve[0] =  FirstPoint;
-                EditCurve[29] = SecondPoint;
-            }
-            else {
-                EditCurve[0] =  SecondPoint;
-                EditCurve[29] = FirstPoint;
-            }
-
-            startAngle = min(angle1, angle2);
-            endAngle =   max(angle1, angle2);
-            // angle3 == angle1 or angle2 shouldn't be allowed but not sure...catch/try?
+            
+			// angle3 == angle1 or angle2 shouldn't be allowed but not sure...catch/try?
             // Point 3 is between Point 1 and 2
-            if ( angle3 > startAngle && angle3 < endAngle ) {
+            if ( angle3 > min(angle1, angle2) && angle3 < max(angle1, angle2) ) {
+                EditCurve[0] =  angle2 > angle1 ? FirstPoint  : SecondPoint;
+                EditCurve[29] = angle2 > angle1 ? SecondPoint : FirstPoint;
+				startAngle = min(angle1, angle2);
+				endAngle   = max(angle1, angle2);
                 arcAngle = endAngle - startAngle;
             }
             // Point 3 is not between Point 1 and 2
             else {
-                arcAngle = 2*M_PI - (endAngle - startAngle);
-                buildForward = false;
+                EditCurve[0] =  angle2 > angle1 ? SecondPoint : FirstPoint;
+                EditCurve[29] = angle2 > angle1 ? FirstPoint  : SecondPoint;
+				startAngle = max(angle1, angle2);
+				endAngle   = min(angle1, angle2);
+                arcAngle = 2*M_PI - (startAngle - endAngle);
             }
 
             // Build a 30 point circle ignoring already constructed points
             for (int i=1; i <= 28; i++) {
-                double angle = buildForward ? startAngle + i*arcAngle/29.0 :
-                                              startAngle - i*arcAngle/29.0; // N point arc has N-1 segments
-                EditCurve[i] = Base::Vector2D(EditCurve[30].fX + radius*cos(angle),
-                                              EditCurve[30].fY + radius*sin(angle));
+                double angle = startAngle + i*arcAngle/29.0; // N point arc has N-1 segments
+                EditCurve[i] = Base::Vector2D(CenterPoint.fX + radius*cos(angle),
+                                              CenterPoint.fY + radius*sin(angle));
             }
 
-            // This arcAngle will report counter-clockwise from +X, not relatively
             SbString text;
             text.sprintf(" (%.1fR,%.1fdeg)", (float) radius, (float) arcAngle * 180 / M_PI);
             setPositionText(onSketchPos, text);
@@ -1403,7 +1395,6 @@ public:
             }
         }
         applyCursor();
-
     }
 
     virtual bool pressButton(Base::Vector2D onSketchPos)
@@ -1425,16 +1416,6 @@ public:
         }
         else {
             EditCurve.resize(30);
-            double angle1 = atan2(onSketchPos.fY - CenterPoint.fY,
-                                 onSketchPos.fX - CenterPoint.fX) - startAngle;
-            double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
-            arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
-            if (arcAngle > 0)
-                endAngle = startAngle + arcAngle;
-            else {
-                endAngle = startAngle;
-                startAngle += arcAngle;
-            }
 
             sketchgui->drawEdit(EditCurve);
             applyCursor();
@@ -1456,8 +1437,8 @@ public:
                 "(Part.Circle(App.Vector(%f,%f,0),App.Vector(0,0,1),%f),"
                 "%f,%f))",
                       sketchgui->getObject()->getNameInDocument(),
-                      CenterPoint.fX, CenterPoint.fY, sqrt(rx*rx + ry*ry),
-                      startAngle, endAngle); //arcAngle > 0 ? 0 : 1);
+                      CenterPoint.fX, CenterPoint.fY, radius,
+                      startAngle, endAngle);
 
             Gui::Command::commitCommand();
             Gui::Command::updateActive();
@@ -1489,8 +1470,8 @@ public:
 protected:
     SelectMode Mode;
     std::vector<Base::Vector2D> EditCurve;
-    Base::Vector2D CenterPoint, FirstPoint, SecondPoint, ThirdPoint;
-    double rx, ry, startAngle, endAngle, arcAngle;
+    Base::Vector2D CenterPoint, FirstPoint, SecondPoint;
+    double radius, startAngle, endAngle, arcAngle;
     std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3;
 };
 
-- 
1.7.9

wip.patch (38,087 bytes)   

mdinger

2014-03-14 23:54

reporter  

Sketcher_Create3PointArc.svg (3,556 bytes)   
Sketcher_Create3PointArc.svg (3,556 bytes)   

mdinger

2014-03-14 23:56

reporter   ~0004445

Since the svg file is essentially a text file, it is bundled directly into the patch. Here I attached it separately for anyone who just wants to look at it.

wmayer

2014-03-15 11:47

administrator   ~0004447

Forum post http://forum.freecadweb.org/viewtopic.php?f=10&t=6070

wmayer

2014-03-15 11:56

administrator   ~0004448

1. OK
2. Jim provided another icon which fits better to the others
3. I think it's OK
4. Oh yes, this has a weird behaviour
5. With MinGW it works, so it should also build under Linux.
6. Makes sense IMO
7. I think we can leave it this way

So, 4. and 6. should be worked on.

mdinger

2014-03-15 20:36

reporter   ~0004452

8. Update menu and tooltip text (see link)
http://forum.freecadweb.org/viewtopic.php?f=10&t=6070#p48485
9. Possibly add button to right click menu (big right click menus can get in the way)

wmayer

2014-03-16 12:30

administrator   ~0004454

git show 35b10d6 fixes 8. and 9.

wmayer

2014-03-16 15:05

administrator   ~0004456

git show d1341f3 fixes 6.) So only open point is 2.)

mdinger

2014-03-16 17:40

reporter   ~0004458

Correction:
Only 4 remains. The icon appears to have already been replaced.

I am looking at 4 but I'm still learning how it works.

mdinger

2014-03-17 01:23

reporter  

fix_3point_snap.diff (13,557 bytes)   
From 3e57f251ea919e14b285a04d9cf42ec952be31bd Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Sun, 16 Mar 2014 21:00:16 -0400
Subject: [PATCH 1/3] Auto-snapping now works for 3 point curve.  Factored
 GetCircleCenter function.

---
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp |   52 +++++++++++++++++++++--------
 1 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index a7d3fde..5c48446 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -78,9 +78,9 @@ Base::Vector2D GetCircleCenter (const Base::Vector2D &p1, const Base::Vector2D &
 {
   double m12p = (p1.fX - p2.fX) / (p2.fY - p1.fY);
   double m23p = (p2.fX - p3.fX) / (p3.fY - p2.fY);
-  double x = 1/( 2*(m12p - m23p) ) * ( (pow(p3.fX, 2) - pow(p2.fX, 2)) / (p3.fY - p2.fY) -
-                                       (pow(p2.fX, 2) - pow(p1.fX, 2)) / (p2.fY - p1.fY) +
-                                        p3.fY - p1.fY );
+  double x = 1/( 2*(m12p - m23p) ) * ( m12p*(p1.fX + p2.fX) -
+                                       m23p*(p2.fX + p3.fX) +
+                                       p3.fY - p1.fY );
   double y = m12p * ( x - (p1.fX + p2.fX)/2 ) + (p1.fY + p2.fY)/2;
 
   return Base::Vector2D(x, y);
@@ -1363,19 +1363,39 @@ public:
             double angle2 = GetPointAngle(CenterPoint, SecondPoint);
             double angle3 = GetPointAngle(CenterPoint, onSketchPos);
 
-            // angle3 == angle1 or angle2 shouldn't be allowed but not sure...catch/try?
+            // Always build arc counter-clockwise
             // Point 3 is between Point 1 and 2
             if ( angle3 > min(angle1, angle2) && angle3 < max(angle1, angle2) ) {
-                EditCurve[0] =  angle2 > angle1 ? FirstPoint  : SecondPoint;
-                EditCurve[29] = angle2 > angle1 ? SecondPoint : FirstPoint;
+                if (angle2 > angle1) {
+                    EditCurve[0] =  FirstPoint;
+                    EditCurve[29] = SecondPoint;
+                    arcPos1 = Sketcher::start;
+                    arcPos2 = Sketcher::end;
+                }
+                else {
+                    EditCurve[0] =  SecondPoint;
+                    EditCurve[29] = FirstPoint;
+                    arcPos1 = Sketcher::end;
+                    arcPos2 = Sketcher::start;
+                }
                 startAngle = min(angle1, angle2);
                 endAngle   = max(angle1, angle2);
                 arcAngle = endAngle - startAngle;
             }
             // Point 3 is not between Point 1 and 2
             else {
-                EditCurve[0] =  angle2 > angle1 ? SecondPoint : FirstPoint;
-                EditCurve[29] = angle2 > angle1 ? FirstPoint  : SecondPoint;
+                if (angle2 > angle1) {
+                    EditCurve[0] =  SecondPoint;
+                    EditCurve[29] = FirstPoint;
+                    arcPos1 = Sketcher::end;
+                    arcPos2 = Sketcher::start;
+                }
+                else {
+                    EditCurve[0] =  FirstPoint;
+                    EditCurve[29] = SecondPoint;
+                    arcPos1 = Sketcher::start;
+                    arcPos2 = Sketcher::end;
+                }
                 startAngle = max(angle1, angle2);
                 endAngle   = min(angle1, angle2);
                 arcAngle = 2*M_PI - (startAngle - endAngle);
@@ -1394,6 +1414,9 @@ public:
 
             sketchgui->drawEdit(EditCurve);
             if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.0,0.0))) {
+                // seekAutoConstraint doesn't handle this correctly because Coincident
+                // cannot snap to an arc yet it picks coincident because I click a point.
+                sugConstr3.back().Type = Sketcher::PointOnObject;
                 renderSuggestConstraintsCursor(sugConstr3);
                 return;
             }
@@ -1447,21 +1470,21 @@ public:
             Gui::Command::commitCommand();
             Gui::Command::updateActive();
 
-            // Auto Constraint center point
+            // Auto Constraint first picked point
             if (sugConstr1.size() > 0) {
-                createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
+                createAutoConstraints(sugConstr1, getHighestCurveIndex(), arcPos1);
                 sugConstr1.clear();
             }
 
-            // Auto Constraint first picked point
+            // Auto Constraint second picked point
             if (sugConstr2.size() > 0) {
-                createAutoConstraints(sugConstr2, getHighestCurveIndex(), (arcAngle > 0) ? Sketcher::start : Sketcher::end );
+                createAutoConstraints(sugConstr2, getHighestCurveIndex(), arcPos2);
                 sugConstr2.clear();
             }
 
-            // Auto Constraint second picked point
+            // Auto Constraint third picked point
             if (sugConstr3.size() > 0) {
-                createAutoConstraints(sugConstr3, getHighestCurveIndex(), (arcAngle > 0) ? Sketcher::end : Sketcher::start);
+                createAutoConstraints(sugConstr3, getHighestCurveIndex(), Sketcher::none);
                 sugConstr3.clear();
             }
 
@@ -1477,6 +1500,7 @@ protected:
     Base::Vector2D CenterPoint, FirstPoint, SecondPoint;
     double radius, startAngle, endAngle, arcAngle;
     std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3;
+    Sketcher::PointPos arcPos1, arcPos2;
 };
 
 
-- 
1.7.9


From 87a2dd59b31a0c3f1c8353c2f78b2f05c3153bc4 Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Sun, 16 Mar 2014 21:01:36 -0400
Subject: [PATCH 2/3] Added and fixed comments.

---
 src/Mod/Sketcher/App/SketchObject.h         |    2 +-
 src/Mod/Sketcher/Gui/ViewProviderSketch.cpp |    2 +-
 src/Mod/Sketcher/Gui/ViewProviderSketch.h   |    4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h
index 5d19361..edb6282 100644
--- a/src/Mod/Sketcher/App/SketchObject.h
+++ b/src/Mod/Sketcher/App/SketchObject.h
@@ -130,7 +130,7 @@ public:
 
     /// retrieves for a Vertex number the corresponding GeoId and PosId
     void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId) const;
-    int getHighestVertexIndex(void) const { return VertexId2GeoId.size() - 1; }
+    int getHighestVertexIndex(void) const { return VertexId2GeoId.size() - 1; } // Most recently created
     int getHighestCurveIndex(void) const { return Geometry.getSize() - 1; }
     void rebuildVertexIndex(void);
 
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
index 69fb6cf..4b976bd 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
@@ -127,7 +127,7 @@ SbVec2s ViewProviderSketch::newCursorPos;
 //**************************************************************************
 // Edit data structure
 
-/// Data structure while edit the sketch
+/// Data structure while editing the sketch
 struct EditData {
     EditData():
     sketchHandler(0),
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h
index 0b7780b..f8e7143 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h
@@ -67,7 +67,7 @@ class DrawSketchHandler;
 /** The Sketch ViewProvider
   * This class handles mainly the drawing and editing of the sketch.
   * It draws the geometry and the constraints applied to the sketch.
-  * It uses the class DrawSketchHandler to facilitade the creation
+  * It uses the class DrawSketchHandler to facilitate the creation
   * of new geometry while editing.
   */
 class SketcherGuiExport ViewProviderSketch : public PartGui::ViewProvider2DObject, public Gui::SelectionObserver
@@ -116,7 +116,7 @@ public:
     enum SketchMode{
         STATUS_NONE,              /**< enum value View provider is in neutral. */
         STATUS_SELECT_Point,      /**< enum value a point was selected. */
-        STATUS_SELECT_Edge,       /**< enum value a edge was selected. */
+        STATUS_SELECT_Edge,       /**< enum value an edge was selected. */
         STATUS_SELECT_Constraint, /**< enum value a constraint was selected. */
         STATUS_SELECT_Cross,      /**< enum value the base coordinate system was selected. */
         STATUS_SKETCH_DragPoint,  /**< enum value while dragging a point. */
-- 
1.7.9


From 415c62cb765b8314864732398c551fd4e677ff7e Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Sun, 16 Mar 2014 21:20:04 -0400
Subject: [PATCH 3/3] Added/removed blank lines so separate tools always have
 2 lines between them.  Then it is more clear when one
 ends.

---
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp |   23 ++++++++++++++---------
 1 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index 5c48446..c40399a 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -51,6 +51,7 @@
 using namespace std;
 using namespace SketcherGui;
 
+
 /* helper functions ======================================================*/
 
 // Return counter-clockwise angle from horizontal out of p1 to p2 in radians.
@@ -86,7 +87,6 @@ Base::Vector2D GetCircleCenter (const Base::Vector2D &p1, const Base::Vector2D &
   return Base::Vector2D(x, y);
 }
 
-
 void ActivateHandler(Gui::Document *doc,DrawSketchHandler *handler)
 {
     if (doc) {
@@ -121,6 +121,7 @@ SketcherGui::ViewProviderSketch* getSketchViewprovider(Gui::Document *doc)
     return 0;
 }
 
+
 /* Sketch commands =======================================================*/
 
 /* XPM */
@@ -256,8 +257,6 @@ protected:
     std::vector<AutoConstraint> sugConstr1, sugConstr2;
 };
 
-
-
 DEF_STD_CMD_A(CmdSketcherCreateLine);
 
 CmdSketcherCreateLine::CmdSketcherCreateLine()
@@ -464,8 +463,6 @@ protected:
     std::vector<AutoConstraint> sugConstr1, sugConstr2;
 };
 
-
-
 DEF_STD_CMD_A(CmdSketcherCreateRectangle);
 
 CmdSketcherCreateRectangle::CmdSketcherCreateRectangle()
@@ -989,7 +986,6 @@ protected:
     }
 };
 
-
 DEF_STD_CMD_A(CmdSketcherCreatePolyline);
 
 CmdSketcherCreatePolyline::CmdSketcherCreatePolyline()
@@ -1015,6 +1011,7 @@ bool CmdSketcherCreatePolyline::isActive(void)
     return isCreateGeoActive(getActiveGuiDocument());
 }
 
+
 // ======================================================================================
 
 /* XPM */
@@ -1503,7 +1500,6 @@ protected:
     Sketcher::PointPos arcPos1, arcPos2;
 };
 
-
 DEF_STD_CMD_A(CmdSketcherCreate3PointArc);
 
 CmdSketcherCreate3PointArc::CmdSketcherCreate3PointArc()
@@ -1529,6 +1525,7 @@ bool CmdSketcherCreate3PointArc::isActive(void)
     return isCreateGeoActive(getActiveGuiDocument());
 }
 
+
 DEF_STD_CMD_ACL(CmdSketcherCompCreateArc);
 
 CmdSketcherCompCreateArc::CmdSketcherCompCreateArc()
@@ -1607,7 +1604,6 @@ bool CmdSketcherCompCreateArc::isActive(void)
 }
 
 
-
 // ======================================================================================
 
 /* XPM */
@@ -1784,6 +1780,7 @@ bool CmdSketcherCreateCircle::isActive(void)
     return isCreateGeoActive(getActiveGuiDocument());
 }
 
+
 // ======================================================================================
 
 /* XPM */
@@ -1882,7 +1879,6 @@ protected:
     std::vector<AutoConstraint> sugConstr;
 };
 
-
 DEF_STD_CMD_A(CmdSketcherCreatePoint);
 
 CmdSketcherCreatePoint::CmdSketcherCreatePoint()
@@ -1908,6 +1904,7 @@ bool CmdSketcherCreatePoint::isActive(void)
     return isCreateGeoActive(getActiveGuiDocument());
 }
 
+
 // ======================================================================================
 
 DEF_STD_CMD_A(CmdSketcherCreateText);
@@ -1934,6 +1931,7 @@ bool CmdSketcherCreateText::isActive(void)
     return false;
 }
 
+
 // ======================================================================================
 
 DEF_STD_CMD_A(CmdSketcherCreateDraftLine);
@@ -1960,6 +1958,7 @@ bool CmdSketcherCreateDraftLine::isActive(void)
     return false;
 }
 
+
 // ======================================================================================
 
 namespace SketcherGui {
@@ -2004,6 +2003,7 @@ namespace SketcherGui {
     };
 };
 
+
 /* XPM */
 static const char *cursor_createfillet[]={
 "32 32 3 1",
@@ -2207,6 +2207,8 @@ bool CmdSketcherCreateFillet::isActive(void)
 {
     return isCreateGeoActive(getActiveGuiDocument());
 }
+
+
 // ======================================================================================
 
 namespace SketcherGui {
@@ -2239,6 +2241,7 @@ namespace SketcherGui {
     };
 };
 
+
 /* XPM */
 static const char *cursor_trimming[]={
 "32 32 3 1",
@@ -2359,6 +2362,7 @@ bool CmdSketcherTrimming::isActive(void)
     return isCreateGeoActive(getActiveGuiDocument());
 }
 
+
 // ======================================================================================
 
 namespace SketcherGui {
@@ -2390,6 +2394,7 @@ namespace SketcherGui {
     };
 };
 
+
 /* XPM */
 static const char *cursor_external[]={
 "32 32 3 1",
-- 
1.7.9

fix_3point_snap.diff (13,557 bytes)   

mdinger

2014-03-17 01:37

reporter   ~0004459

The attached patch fixes the auto-snapping. It also includes miscellaneous code formatting, commenting, and typo fixes.

Of those 9 issues, I believe all are fixed.

Also, I don't know that it's related but the stacked icon arrow button is clipping. See attached picture.

mdinger

2014-03-17 01:37

reporter  

clipping.png (63,131 bytes)   
clipping.png (63,131 bytes)   

mdinger

2014-03-17 05:55

reporter  

fix_typo.diff (1,346 bytes)   
From 18f1d77dc8502af5293b9e3d7d245ca8138df3b2 Mon Sep 17 00:00:00 2001
From: mdinger <mdinger.bugzilla@gmail.com>
Date: Mon, 17 Mar 2014 01:48:04 -0400
Subject: [PATCH] Typo

---
 src/Mod/Sketcher/Gui/CommandCreateGeo.cpp |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index c40399a..e349b1a 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -1593,7 +1593,7 @@ void CmdSketcherCompCreateArc::languageChange()
     arc1->setToolTip(QApplication::translate("Sketcher_CreateArc","Create an arc by its center and by its end points"));
     arc1->setStatusTip(QApplication::translate("Sketcher_CreateArc","Create an arc by its center and by its end points"));
     QAction* arc2 = a[1];
-    arc2->setText(QApplication::translate("CmdSketcherCompCreateArc","End point and rim point"));
+    arc2->setText(QApplication::translate("CmdSketcherCompCreateArc","End points and rim point"));
     arc2->setToolTip(QApplication::translate("Sketcher_Create3PointArc","Create an arc by its end points and a point along the arc"));
     arc2->setStatusTip(QApplication::translate("Sketcher_Create3PointArc","Create an arc by its end points and a point along the arc"));
 }
-- 
1.7.9

fix_typo.diff (1,346 bytes)   

mdinger

2014-03-17 05:57

reporter   ~0004460

Minor typo spotted by jmaustpc. See fix_typo.diff.

wmayer

2014-03-17 08:22

administrator   ~0004461

> Also, I don't know that it's related but the stacked icon arrow button is clipping. See attached picture.
For me the arrows look fine -- no clipping. What is your Qt version? Mine is 4.8.5

mdinger

2014-03-27 03:22

reporter   ~0004492

Last edited: 2014-03-27 03:31

Fix tangency auto-snapping on 3rd point in this pull request.

https://github.com/FreeCAD/FreeCAD_sf_master/pull/19

Is it preferable to put pull requests here or in the Pull Requests forum? I thought here because it is easier to track.

wmayer

2014-03-27 09:55

administrator   ~0004495

Posting here is fine.

wmayer

2014-03-29 09:17

administrator   ~0004508

Sorry, but how can I get the changes you made?

wmayer

2014-03-29 11:19

administrator   ~0004509

FYI, here is a description how to merge pull requests https://help.github.com/articles/merging-a-pull-request

Way 1.) doesn't work for me because
> git pull https://github.com/octocat/repo.git branchname
doesn't use a certain pull request id!?

Way 2.) as is doesn't work for me either because of line endings issue I guess. But using the patch command directly works, so:

curl https://github.com/FreeCAD/FreeCAD_sf_master/pull/19.patch > pull19.patch
patch -p1 < pull19.patch

Related Changesets

FreeCAD: master ea4abcb5

2014-03-15 12:50:24

wmayer

Details Diff
+ issue 0001475: Implement a 3 point arc similar to solidworks in sketcher Affected Issues
0001475
mod - src/Base/Tools2D.h Diff File
mod - src/Mod/Complete/Gui/Workbench.cpp Diff File
mod - src/Mod/PartDesign/Gui/Workbench.cpp Diff File
mod - src/Mod/Sketcher/Gui/CommandCreateGeo.cpp Diff File
mod - src/Mod/Sketcher/Gui/Resources/Makefile.am Diff File
mod - src/Mod/Sketcher/Gui/Resources/Sketcher.qrc Diff File
add - src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Create3PointArc.svg Diff File
mod - src/Mod/Sketcher/Gui/Workbench.cpp Diff File

FreeCAD: master 35b10d68

2014-03-16 13:29:44

wmayer

Details Diff
+ issue 0001475: Implement a 3 point arc similar to solidworks in sketcher Affected Issues
0001475
mod - src/Mod/Sketcher/Gui/CommandCreateGeo.cpp Diff File
mod - src/Mod/Sketcher/Gui/ViewProviderSketch.cpp Diff File

FreeCAD: master d1341f36

2014-03-16 16:03:32

wmayer

Details Diff
+ issue 0001475: Implement a 3 point arc similar to solidworks in sketcher Affected Issues
0001475
mod - src/Mod/Complete/Gui/Workbench.cpp Diff File
mod - src/Mod/PartDesign/Gui/Workbench.cpp Diff File
mod - src/Mod/Sketcher/Gui/CommandCreateGeo.cpp Diff File
mod - src/Mod/Sketcher/Gui/Workbench.cpp Diff File

FreeCAD: master a7aca65e

2014-03-17 09:37:56

wmayer

Details Diff
+ issue 0001475: Implement a 3 point arc similar to solidworks in sketcher Affected Issues
0001475
mod - src/Mod/Sketcher/App/SketchObject.h Diff File
mod - src/Mod/Sketcher/Gui/CommandCreateGeo.cpp Diff File
mod - src/Mod/Sketcher/Gui/ViewProviderSketch.cpp Diff File
mod - src/Mod/Sketcher/Gui/ViewProviderSketch.h Diff File

FreeCAD: master 13cdc1cd

2014-03-17 09:41:51

wmayer

Details Diff
+ issue 0001475: Implement a 3 point arc similar to solidworks in sketcher Affected Issues
0001475
mod - src/Mod/Sketcher/Gui/CommandCreateGeo.cpp Diff File

FreeCAD: master f255948f

2014-03-29 12:20:32

wmayer

Details Diff
+ fixes: 0001475: Implement a 3 point arc similar to solidworks in sketcher (mdinger) Affected Issues
0001475
mod - src/Mod/Sketcher/Gui/CommandCreateGeo.cpp Diff File

Issue History

Date Modified Username Field Change
2014-03-14 22:29 mdinger New Issue
2014-03-14 22:29 mdinger File Added: 3pointarc.png
2014-03-14 22:45 mdinger Note Added: 0004444
2014-03-14 22:48 mdinger File Added: wip.patch
2014-03-14 23:54 mdinger File Added: Sketcher_Create3PointArc.svg
2014-03-14 23:56 mdinger Note Added: 0004445
2014-03-15 11:47 wmayer Note Added: 0004447
2014-03-15 11:56 wmayer Note Added: 0004448
2014-03-15 12:19 wmayer Changeset attached => FreeCAD Master master ea4abcb5
2014-03-15 20:36 mdinger Note Added: 0004452
2014-03-16 12:30 wmayer Note Added: 0004454
2014-03-16 12:59 wmayer Changeset attached => FreeCAD Master master 35b10d68
2014-03-16 15:05 wmayer Note Added: 0004456
2014-03-16 15:29 wmayer Changeset attached => FreeCAD Master master d1341f36
2014-03-16 17:40 mdinger Note Added: 0004458
2014-03-17 01:23 mdinger File Added: fix_3point_snap.diff
2014-03-17 01:37 mdinger Note Added: 0004459
2014-03-17 01:37 mdinger File Added: clipping.png
2014-03-17 05:55 mdinger File Added: fix_typo.diff
2014-03-17 05:57 mdinger Note Added: 0004460
2014-03-17 08:22 wmayer Note Added: 0004461
2014-03-17 08:42 wmayer Status new => closed
2014-03-17 08:42 wmayer Assigned To => wmayer
2014-03-17 08:42 wmayer Resolution open => fixed
2014-03-17 08:42 wmayer Fixed in Version => 0.14
2014-03-17 08:59 wmayer Changeset attached => FreeCAD Master master a7aca65e
2014-03-17 09:09 wmayer Changeset attached => FreeCAD Master master 13cdc1cd
2014-03-27 03:22 mdinger Note Added: 0004492
2014-03-27 03:22 mdinger Status closed => feedback
2014-03-27 03:22 mdinger Resolution fixed => reopened
2014-03-27 03:31 mdinger Note Edited: 0004492
2014-03-27 09:55 wmayer Note Added: 0004495
2014-03-29 09:17 wmayer Note Added: 0004508
2014-03-29 11:19 wmayer Note Added: 0004509
2014-03-29 12:28 wmayer Changeset attached => FreeCAD Master master f255948f
2014-03-29 12:29 wmayer Status feedback => closed
2014-03-29 12:29 wmayer Resolution reopened => fixed