Revision: 5484
          http://sourceforge.net/p/jump-pilot/code/5484
Author:   michaudm
Date:     2017-08-05 14:05:48 +0000 (Sat, 05 Aug 2017)
Log Message:
-----------
Improvement from ioan to honour IncrementalAngle constraint even on the first 
segment

Modified Paths:
--------------
    core/trunk/ChangeLog
    
core/trunk/src/org/openjump/core/ui/plugin/edittoolbox/tab/ConstraintManager.java

Modified: core/trunk/ChangeLog
===================================================================
--- core/trunk/ChangeLog        2017-07-31 10:48:49 UTC (rev 5483)
+++ core/trunk/ChangeLog        2017-08-05 14:05:48 UTC (rev 5484)
@@ -3,6 +3,10 @@
 # 2. make sure that lines break at 80 chars for constricted display situations
 #<-------------------------------- 80 chars 
---------------------------------->#
 
+2017-08-05
+  * Improvement from ioan to honour IncrementalAngle constraint even on the 
first
+    segment
+
 2017-07-29 mmichaud <m.michael.mich...@orange.fr>
   * BlendLineStringsPlugIn : improve quality, performance and make it undoable
   * Deactivate ReplaceValuePlugIn (use AutoAssignAttributePlugIn instead)

Modified: 
core/trunk/src/org/openjump/core/ui/plugin/edittoolbox/tab/ConstraintManager.java
===================================================================
--- 
core/trunk/src/org/openjump/core/ui/plugin/edittoolbox/tab/ConstraintManager.java
   2017-07-31 10:48:49 UTC (rev 5483)
+++ 
core/trunk/src/org/openjump/core/ui/plugin/edittoolbox/tab/ConstraintManager.java
   2017-08-05 14:05:48 UTC (rev 5484)
@@ -34,193 +34,228 @@
 package org.openjump.core.ui.plugin.edittoolbox.tab;
 
 import java.awt.event.MouseEvent;
-import java.awt.geom.NoninvertibleTransformException;
 import java.util.List;
 
 import org.openjump.core.geomutils.GeoUtils;
 
 import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.math.Vector2D;
 import com.vividsolutions.jump.workbench.WorkbenchContext;
 import com.vividsolutions.jump.workbench.ui.LayerViewPanel;
 import com.vividsolutions.jump.workbench.ui.plugin.PersistentBlackboardPlugIn;
 
+/**
+ * Constraint Manager
+ * Improved by ioan on 2017-08-05 to honour IncrementalAngle constraint even 
on the first segment
+ */
 public class ConstraintManager {
-    public static final String CONSTRAIN_LENGTH_ENABLED_KEY = 
"CONSTRAIN_LENGTH - ENABLED";
-    public static final String CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY = 
"CONSTRAIN_INCREMENTAL_ANGLE - ENABLED";
-    public static final String CONSTRAIN_ANGLE_ENABLED_KEY = "CONSTRAIN_ANGLE 
- ENABLED";
-    public static final String LENGTH_CONSTRAINT_KEY = "LENGTH_CONSTRAINT";
-    public static final String INCREMENTAL_ANGLE_SIZE_KEY = 
"INCREMENTAL_ANGLE_CONSTRAINT";
-    public static final String ANGLE_SIZE_KEY = "ANGLE_CONSTRAINT";
-    public static final String RELATIVE_ANGLE_KEY = 
"RELATIVE_ANGLE_CONSTRAINT";
-    public static final String ABSOLUTE_ANGLE_KEY = 
"ABSOLUTE_ANGLE_CONSTRAINT";
-    public static final String CONSTRAIN_RECTANGLE_RATIO_ENABLED_KEY = 
"CONSTRAIN_RECTANGLE_RATIO - ENABLED";
-    public static final String RATIO_WIDTH_KEY = "RATIO_WIDTH_CONSTRAINT";
-    public static final String RATIO_HEIGHT_KEY = "RATIO_HEIGHT_CONSTRAINT";
-    protected LayerViewPanel panel;
-    WorkbenchContext workbenchContext;
+  public static final String CONSTRAIN_LENGTH_ENABLED_KEY = "CONSTRAIN_LENGTH 
- ENABLED";
+  public static final String CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY = 
"CONSTRAIN_INCREMENTAL_ANGLE - ENABLED";
+  public static final String CONSTRAIN_ANGLE_ENABLED_KEY = "CONSTRAIN_ANGLE - 
ENABLED";
+  public static final String LENGTH_CONSTRAINT_KEY = "LENGTH_CONSTRAINT";
+  public static final String INCREMENTAL_ANGLE_SIZE_KEY = 
"INCREMENTAL_ANGLE_CONSTRAINT";
+  public static final String ANGLE_SIZE_KEY = "ANGLE_CONSTRAINT";
+  public static final String RELATIVE_ANGLE_KEY = "RELATIVE_ANGLE_CONSTRAINT";
+  public static final String ABSOLUTE_ANGLE_KEY = "ABSOLUTE_ANGLE_CONSTRAINT";
+  public static final String CONSTRAIN_RECTANGLE_RATIO_ENABLED_KEY = 
"CONSTRAIN_RECTANGLE_RATIO - ENABLED";
+  public static final String RATIO_WIDTH_KEY = "RATIO_WIDTH_CONSTRAINT";
+  public static final String RATIO_HEIGHT_KEY = "RATIO_HEIGHT_CONSTRAINT";
+  protected LayerViewPanel panel;
+  WorkbenchContext workbenchContext;
 
-    public ConstraintManager(WorkbenchContext workbenchContext) 
-    {
-        this.workbenchContext = workbenchContext;
+  public ConstraintManager(WorkbenchContext workbenchContext) {
+    this.workbenchContext = workbenchContext;
+  }
+
+  public Coordinate constrain(LayerViewPanel panel, List coordinates,
+      Coordinate targetPt, MouseEvent e) {
+    if (coordinates == null)
+      return targetPt;
+    this.panel = panel;
+    int numPts = coordinates.size();
+    boolean shiftConstrain = (e.isShiftDown() && (numPts > 0)); // was 1
+    boolean ctrlConstrain = (e.isControlDown() && (numPts > 1));
+    Coordinate retPt = (Coordinate) targetPt.clone();
+
+    if ((PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(CONSTRAIN_LENGTH_ENABLED_KEY, false)) && (numPts >= 1)) {
+      double lengthConstraint = 
PersistentBlackboardPlugIn.get(workbenchContext)
+          .getDouble(LENGTH_CONSTRAINT_KEY);
+      if (lengthConstraint > 0) {
+        Coordinate anchorPt = (Coordinate) coordinates.get(numPts - 1);
+        double run = targetPt.x - anchorPt.x;
+        double rise = targetPt.y - anchorPt.y;
+        double prevLength = anchorPt.distance(targetPt);
+        double t1 = Math.round(prevLength / lengthConstraint);
+        double newLength = t1 * lengthConstraint;
+        double ratio = 1;
+        if (prevLength != 0) // this happens when mouse clicked on first point
+                             // without mouse move
+          ratio = newLength / prevLength;
+        retPt.x = anchorPt.x + (ratio * run);
+        retPt.y = anchorPt.y + (ratio * rise);
+      }
     }
 
-    public Coordinate constrain(LayerViewPanel panel, List coordinates, 
Coordinate targetPt, MouseEvent e)
-    {
-        if (coordinates == null) return targetPt;
-        this.panel = panel;
-        int numPts = coordinates.size();    
-        boolean shiftConstrain = (e.isShiftDown() && (numPts > 1));
-        boolean ctrlConstrain = (e.isControlDown() && (numPts > 1));
-        Coordinate retPt = (Coordinate)targetPt.clone();        
+    if (PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY, false)) {
+      if (shiftConstrain) {
+        int incrementalAngleConstraint = PersistentBlackboardPlugIn
+            .get(workbenchContext).getInt(INCREMENTAL_ANGLE_SIZE_KEY);
+        // If only one point, set startPt to next to last point
+        Coordinate startPt = new Coordinate();
+        if (numPts == 1)
+          startPt = (Coordinate) coordinates.get(numPts - 1);
+        else
+          startPt = (Coordinate) coordinates.get(numPts - 2);
+        Coordinate endPt = (Coordinate) coordinates.get(numPts - 1);
+        retPt = constrainIncrementalAngle(startPt, endPt, retPt,
+            incrementalAngleConstraint);
+      }
+    }
 
-        if 
((PersistentBlackboardPlugIn.get(workbenchContext).get(CONSTRAIN_LENGTH_ENABLED_KEY,
 false)) && (numPts >= 1))
-        {
-            double lengthConstraint = 
PersistentBlackboardPlugIn.get(workbenchContext).getDouble(LENGTH_CONSTRAINT_KEY);
-            if (lengthConstraint > 0)
-            {
-                Coordinate anchorPt = (Coordinate)coordinates.get(numPts - 1);
-                double run = targetPt.x - anchorPt.x;
-                double rise = targetPt.y - anchorPt.y;
-                double prevLength = anchorPt.distance(targetPt);
-                double t1 = Math.round(prevLength / lengthConstraint);
-                double newLength = t1 * lengthConstraint;
-                double ratio = 1;
-                if (prevLength != 0) //this happens when mouse clicked on 
first point without mouse move
-                    ratio = newLength / prevLength;
-                retPt.x = anchorPt.x + (ratio * run);
-                retPt.y = anchorPt.y + (ratio * rise);
-            }
+    if (PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(CONSTRAIN_ANGLE_ENABLED_KEY, false) && (numPts > 1)) {
+      double theta = -PersistentBlackboardPlugIn.get(workbenchContext)
+          .getDouble(ANGLE_SIZE_KEY);
+
+      if (PersistentBlackboardPlugIn.get(workbenchContext)
+          .getBoolean(RELATIVE_ANGLE_KEY)) {
+        if (shiftConstrain) {
+          Coordinate startPt = (Coordinate) coordinates.get(numPts - 2);
+          Coordinate endPt = (Coordinate) coordinates.get(numPts - 1);
+          double length = endPt.distance(retPt);
+          Coordinate newPt = constructVector(startPt, endPt, length);
+          retPt = GeoUtils.rotPt(newPt, endPt, theta);
         }
-                
-        if 
(PersistentBlackboardPlugIn.get(workbenchContext).get(CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY,
 false))
-        {
-            if(shiftConstrain)
-            {
-                int incrementalAngleConstraint = 
PersistentBlackboardPlugIn.get(workbenchContext).getInt(INCREMENTAL_ANGLE_SIZE_KEY);
-                Coordinate startPt = (Coordinate)coordinates.get(numPts - 2);
-                Coordinate endPt = (Coordinate)coordinates.get(numPts - 1);
-                retPt = constrainIncrementalAngle(startPt, endPt, retPt, 
incrementalAngleConstraint);
-            }
+      }
+
+      else // ABSOLUTE_ANGLE_KEY
+      {
+        if (e.isShiftDown() && (numPts >= 1)) {
+          Coordinate startPt = (Coordinate) coordinates.get(numPts - 1);
+          Coordinate endPt = (Coordinate) startPt.clone();
+          endPt.x += startPt.distance(retPt);
+          retPt = GeoUtils.rotPt(endPt, startPt, theta);
         }
-        
-        if 
(PersistentBlackboardPlugIn.get(workbenchContext).get(CONSTRAIN_ANGLE_ENABLED_KEY,
 false))
-        {
-            double theta = 
-PersistentBlackboardPlugIn.get(workbenchContext).getDouble(ANGLE_SIZE_KEY);
-            
-            if 
(PersistentBlackboardPlugIn.get(workbenchContext).getBoolean(RELATIVE_ANGLE_KEY))
-            {
-                if(shiftConstrain)
-                {
-                    Coordinate startPt = (Coordinate)coordinates.get(numPts - 
2);
-                    Coordinate endPt = (Coordinate)coordinates.get(numPts - 1);
-                    double length = endPt.distance(retPt);
-                    Coordinate newPt = constructVector(startPt, endPt, length);
-                    retPt = GeoUtils.rotPt(newPt, endPt, theta);
-                }
-            }
-            
-            else //ABSOLUTE_ANGLE_KEY
-            {
-                if (e.isShiftDown() && (numPts >= 1))
-                {
-                    Coordinate startPt = (Coordinate)coordinates.get(numPts - 
1);
-                    Coordinate endPt = (Coordinate)startPt.clone();
-                    endPt.x += startPt.distance(retPt);
-                    retPt = GeoUtils.rotPt(endPt, startPt, theta);
-                }
-            }
-        }
-      
-        if 
(PersistentBlackboardPlugIn.get(workbenchContext).get(CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY,
 false))
-        {
-            if(ctrlConstrain)
-            {
-                int incrementalAngleConstraint = 
PersistentBlackboardPlugIn.get(workbenchContext).getInt(INCREMENTAL_ANGLE_SIZE_KEY);
-                Coordinate startPt = (Coordinate)coordinates.get(1);
-                Coordinate endPt = (Coordinate)coordinates.get(0);
-                Coordinate p1 = (Coordinate)coordinates.get(numPts - 1);
-                Coordinate p2 = (Coordinate) retPt.clone();
-                Coordinate p3 = (Coordinate)coordinates.get(0);
-                Coordinate p4 = constrainIncrementalAngle(startPt, endPt, 
retPt, incrementalAngleConstraint);
-                Coordinate intxPt = GeoUtils.getIntersection(p1, p2, p3, p4);
-                if (intxPt.z == 0) //z <> 0 means that the lines are parallel
-                    retPt = new Coordinate(intxPt.x, intxPt.y);
-            }
-        }        
-        return retPt;
+      }
     }
- 
-     protected Coordinate constrainIncrementalAngle(Coordinate startPt, 
Coordinate endPt, Coordinate targetPt, int angleConstraint)
-    {
-        double targetLength = endPt.distance(targetPt);
-        Coordinate newPt = constructVector(startPt, endPt, targetLength);
-        Coordinate retPt = (Coordinate)newPt.clone();
-        double currDist = targetPt.distance(newPt);
-        double theta =  360 / angleConstraint;
-        for (int i = 0; i < angleConstraint - 1; i++)
-        {
-            newPt = GeoUtils.rotPt(newPt, endPt, theta);
-            double newDist = targetPt.distance(newPt);
-            if (newDist < currDist)
-            {
-                currDist = newDist;
-                retPt = (Coordinate)newPt.clone();
-            }
-        }
-        return retPt;
+
+    if (PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(CONSTRAIN_INCREMENTAL_ANGLE_ENABLED_KEY, false)) {
+      if (ctrlConstrain) {
+        int incrementalAngleConstraint = PersistentBlackboardPlugIn
+            .get(workbenchContext).getInt(INCREMENTAL_ANGLE_SIZE_KEY);
+        Coordinate startPt = (Coordinate) coordinates.get(1);
+        Coordinate endPt = (Coordinate) coordinates.get(0);
+        Coordinate p1 = (Coordinate) coordinates.get(numPts - 1);
+        Coordinate p2 = (Coordinate) retPt.clone();
+        Coordinate p3 = (Coordinate) coordinates.get(0);
+        Coordinate p4 = constrainIncrementalAngle(startPt, endPt, retPt,
+            incrementalAngleConstraint);
+        Coordinate intxPt = GeoUtils.getIntersection(p1, p2, p3, p4);
+        if (intxPt.z == 0) // z <> 0 means that the lines are parallel
+          retPt = new Coordinate(intxPt.x, intxPt.y);
+      }
     }
-    
-     public Coordinate constrainRectangleToRatio(LayerViewPanel panel, List 
coordinates, Coordinate targetPt, MouseEvent e) throws 
NoninvertibleTransformException
-        {
-        if (coordinates == null) return targetPt;
-        this.panel = panel;
-        boolean shiftConstrain = 
((PersistentBlackboardPlugIn.get(workbenchContext).get(CONSTRAIN_RECTANGLE_RATIO_ENABLED_KEY,
 false)) && (e.isShiftDown()));
+    return retPt;
+  }
 
-        double ratioWidth = 
PersistentBlackboardPlugIn.get(workbenchContext).get(RATIO_WIDTH_KEY, 1.0);
-       double ratioHeight = 
PersistentBlackboardPlugIn.get(workbenchContext).get(RATIO_HEIGHT_KEY, 1.0);
-       double ratio = ratioWidth/ratioHeight;
-       
-        if ((coordinates.size() >= 1) && (shiftConstrain))
-       {
-               Coordinate firstCoordinate = (Coordinate) coordinates.get(0);
-               double yLength = Math.abs((firstCoordinate.x - targetPt.x)) / 
ratio;
-               if (targetPt.y > firstCoordinate.y)             
-                       return new Coordinate(targetPt.x, firstCoordinate.y + 
yLength);
-               else
-                       return new Coordinate(targetPt.x, firstCoordinate.y - 
yLength);
-       }
-       return targetPt;
-        }
-     
-    private Coordinate constructVector(Coordinate startPt, Coordinate endPt, 
double dist)
-    //this routine will use startPt & endPt to determine the slope of the new 
vector
-    //it will calculate a new vector from endPt with the slope and dist
-    {
-        double run = endPt.x - startPt.x;
-        double rise = endPt.y - startPt.y;
-        double sideLength = startPt.distance(endPt);
-        double ratio = dist / sideLength;
-        return new Coordinate(endPt.x + (ratio * run), endPt.y + (ratio * 
rise));
+  protected Coordinate constrainIncrementalAngle(Coordinate startPt,
+      Coordinate endPt, Coordinate targetPt, int angleConstraint) {
+
+    // this version uses the JTS Vector class to make a unit vector along
+    // the direction from the start to end point,
+    // if there's only one point then start along the x angle
+    Vector2D endVector = new Vector2D(endPt);
+    // unit direction vector along vector defined by start->end
+    Vector2D dirVect;
+    if (!startPt.equals2D(endPt))
+      dirVect = new Vector2D(startPt, endPt).normalize();
+    else
+      dirVect = new Vector2D(1, 0); // x axis
+
+    Vector2D targetVect = new Vector2D(endPt, targetPt);
+    double theta = 360 / angleConstraint;
+
+    double currDist = Double.POSITIVE_INFINITY;
+    Coordinate retPt = new Coordinate();
+    Vector2D outVector;
+
+    for (int i = 0; i < angleConstraint - 1; i++) {
+      dirVect = dirVect.rotate(theta * Math.PI / 180);
+      // use dot product to get component of target vector along the unit
+      // direction vector
+      double dotProduct = dirVect.dot(targetVect);
+      // Take the dot product times the unit direction vector and
+      // add it to the endpoint vector
+      outVector = endVector.add(dirVect.multiply(dotProduct));
+      double newDist = targetPt.distance(outVector.toCoordinate());
+      if (newDist < currDist) {
+        currDist = newDist;
+        retPt = outVector.toCoordinate();
+      }
     }
-    
-    public double getBearing(Coordinate startPt, Coordinate endPt)
-    //return Bearing in degrees (-180 to +180) from startPt to endPt
-    {
-        Coordinate r = new Coordinate(endPt.x - startPt.x, endPt.y - 
startPt.y);
-        double rMag = Math.sqrt(r.x * r.x + r.y * r.y );
-        if (rMag == 0.0)
-        {
-            return 0.0;
-        }
-        else
-        {
-            double rCos = r.x / rMag;
-            double rAng = Math.acos(rCos);
-            
-            if (r.y < 0.0)
-                rAng = -rAng;
-            return rAng * 360.0 / (2 * Math.PI);
-        }
+    return retPt;
+  }
+
+  /*
+  public Coordinate constrainRectangleToRatio(LayerViewPanel panel,
+      List coordinates, Coordinate targetPt, MouseEvent e)
+      throws NoninvertibleTransformException {
+    if (coordinates == null)
+      return targetPt;
+    this.panel = panel;
+    boolean shiftConstrain = ((PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(CONSTRAIN_RECTANGLE_RATIO_ENABLED_KEY, false))
+        && (e.isShiftDown()));
+
+    double ratioWidth = PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(RATIO_WIDTH_KEY, 1.0);
+    double ratioHeight = PersistentBlackboardPlugIn.get(workbenchContext)
+        .get(RATIO_HEIGHT_KEY, 1.0);
+    double ratio = ratioWidth / ratioHeight;
+
+    if ((coordinates.size() >= 1) && (shiftConstrain)) {
+      Coordinate firstCoordinate = (Coordinate) coordinates.get(0);
+      double yLength = Math.abs((firstCoordinate.x - targetPt.x)) / ratio;
+      if (targetPt.y > firstCoordinate.y)
+        return new Coordinate(targetPt.x, firstCoordinate.y + yLength);
+      else
+        return new Coordinate(targetPt.x, firstCoordinate.y - yLength);
     }
+    return targetPt;
+  }
+  */
 
+  private Coordinate constructVector(Coordinate startPt, Coordinate endPt,
+      double dist)
+  // this routine will use startPt & endPt to determine the slope of the new
+  // vector
+  // it will calculate a new vector from endPt with the slope and dist
+  {
+    double run = endPt.x - startPt.x;
+    double rise = endPt.y - startPt.y;
+    double sideLength = startPt.distance(endPt);
+    double ratio = dist / sideLength;
+    return new Coordinate(endPt.x + (ratio * run), endPt.y + (ratio * rise));
+  }
+
+  public double getBearing(Coordinate startPt, Coordinate endPt)
+  // return Bearing in degrees (-180 to +180) from startPt to endPt
+  {
+    Coordinate r = new Coordinate(endPt.x - startPt.x, endPt.y - startPt.y);
+    double rMag = Math.sqrt(r.x * r.x + r.y * r.y);
+    if (rMag == 0.0) {
+      return 0.0;
+    } else {
+      double rCos = r.x / rMag;
+      double rAng = Math.acos(rCos);
+
+      if (r.y < 0.0)
+        rAng = -rAng;
+      return rAng * 360.0 / (2 * Math.PI);
+    }
+  }
+
 }


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to