Browse Source

Adds EdgeSplitting

TomTroppmann 2 years ago
parent
commit
c8cf4c79c2

+ 28 - 6
src/holeg/ui/view/canvas/Canvas.java

@@ -5,10 +5,10 @@ import holeg.ui.controller.Control;
 import holeg.ui.model.GuiSettings;
 import holeg.ui.view.dialog.CreateTemplatePopUp;
 import holeg.utility.math.vector.Geometry;
+import holeg.utility.math.vector.Vec2f;
 import holeg.utility.math.vector.Vec2i;
 
 import javax.swing.*;
-import javax.swing.text.html.Option;
 import java.awt.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
@@ -16,7 +16,6 @@ import java.awt.event.MouseMotionListener;
 import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
-import java.util.logging.Filter;
 import java.util.logging.Logger;
 
 public class Canvas extends JPanel {
@@ -231,7 +230,7 @@ public class Canvas extends JPanel {
                 }
                 case ObjectDragging -> {
                     Vec2i delta = actualPos.subtract(lastPosition);
-                    GuiSettings.getSelectedObjects().forEach(obj -> obj.setPosition(BoundsToCanvas(obj.getPosition().add(delta))));
+                    GuiSettings.getSelectedObjects().forEach(obj -> obj.setPosition(boundsToCanvas(obj.getPosition().add(delta))));
                     canBeReplaced = checkForReplacement(actualPos).isPresent();
                     repaint();
                 }
@@ -278,10 +277,25 @@ public class Canvas extends JPanel {
                         control.addEdgeOnCanvasOrRemoveExisting(new Edge(selectedOnPressed, obj, GuiSettings.maxCapacityForNewCreatedEdges));
                     }
                 }, () -> {
+
                     Node node = new Node("Node");
                     groupNode.add(node);
-                    node.setPosition(new Vec2i(BoundsToCanvas(lastPosition)));
-
+                    Geometry.Circle detectionCircle = new Geometry.Circle(new Vec2f(lastPosition), 15f);
+                    node.setPosition(new Vec2i(boundsToCanvas(lastPosition)));
+                    for(Edge edge : control.getModel().getEdgesOnCanvas()) {
+                        if(edge.getA().getGroupNode().isEmpty() || edge.getB().getGroupNode().isEmpty() ||
+                                edge.getA().getGroupNode().get() != groupNode || edge.getB().getGroupNode().get() != groupNode){
+                            continue;
+                        }
+                        Optional<Vec2f> pos = Geometry.getProjectionOnSegmentIfInRange(new Geometry.Line(new Vec2f(edge.getA().getPosition())
+                                , new Vec2f(edge.getB().getPosition())), detectionCircle);
+                        if(pos.isPresent()){
+                            Vec2f position = pos.get();
+                            node.setPosition(new Vec2i((int)position.getX(), (int)position.getY()));
+                            splitEdge(edge, node);
+                            break;
+                        }
+                    }
                     control.addEdgeOnCanvas(new Edge(selectedOnPressed, node, GuiSettings.maxCapacityForNewCreatedEdges));
                     control.calculateStateForCurrentIteration();
                 });
@@ -339,7 +353,7 @@ public class Canvas extends JPanel {
                 });
             }
         }
-        private Vec2i BoundsToCanvas(Vec2i pos){
+        private Vec2i boundsToCanvas(Vec2i pos){
             Vec2i position = new Vec2i(pos);
             position.clampX(GuiSettings.getPictureScaleDiv2(), GuiSettings.canvasSize.getX() - GuiSettings.getPictureScaleDiv2());
             position.clampY(GuiSettings.getPictureScaleDiv2(), GuiSettings.canvasSize.getY() - GuiSettings.getPictureScaleDiv2());
@@ -350,6 +364,14 @@ public class Canvas extends JPanel {
             return Geometry.createRectangleFromCorners(lastPosition, pressedPosition);
         }
 
+
+        public void splitEdge(Edge edge, Node node){
+            AbstractCanvasObject end = edge.getB();
+            edge.setB(node);
+            Edge additional = new Edge(node, end, edge.maxCapacity);
+            control.getModel().addEdgeOnCanvas(additional);
+        }
+
         @Override
         public void mouseEntered(MouseEvent e) {
         }

+ 8 - 1
src/holeg/utility/math/Maths.java

@@ -1,7 +1,7 @@
 package holeg.utility.math;
 
 public class Maths {
-	private final static double EPSILON = 1E-6;
+	public final static double EPSILON = 1E-6;
 	
 	/**
 	 * Linear Interpolation from first to second via alpha amount.
@@ -24,4 +24,11 @@ public class Maths {
 		if (Math.abs(max - min) < EPSILON) return max;
 		else return (value - min) / (max - min);
 	}
+
+//	public static double Clamp(double value, double min, double max){
+//		return Math.max(min, Math.min(max, value));
+//	}
+	public static float Clamp(float value, float min, float max){
+		return Math.max(min, Math.min(max, value));
+	}
 }

+ 45 - 0
src/holeg/utility/math/vector/Geometry.java

@@ -1,6 +1,11 @@
 package holeg.utility.math.vector;
 
+import holeg.utility.math.Maths;
+
 import java.awt.*;
+import java.util.Optional;
+
+import static holeg.utility.math.Maths.EPSILON;
 
 public class Geometry {
     public static Rectangle createRectangleFromCorners(Vec2i corner, Vec2i otherCorner){
@@ -11,4 +16,44 @@ public class Geometry {
         int height = bottomRight.getY() - topLeft.getY();
         return new Rectangle(topLeft.getX(),topLeft.getY(), width, height);
     }
+
+    public static Optional<Vec2f> getProjectionOnSegmentIfInRange(Line line , Circle circle){
+        float lineLengthSqr = line.distanceSqr();
+        if(lineLengthSqr < EPSILON) {
+            if(line.p1.getSquaredDistance(circle.position) < circle.radius * circle.radius){
+                return Optional.of(new Vec2f(line.p1));
+            }else{
+                return Optional.empty();
+            }
+        }
+        Vec2f p2p1 = line.p2.subtract(line.p1);
+        float t = Maths.Clamp(Vec2f.dot(circle.position.subtract(line.p1), p2p1) / lineLengthSqr, 0.0f, 1.0f);
+        Vec2f projection = line.p1.add(p2p1.multiply(t));
+        if(projection.getSquaredDistance(circle.position) < circle.radius * circle.radius){
+            return Optional.of(projection);
+        }else{
+            return Optional.empty();
+        }
+    }
+
+    public static class Circle{
+        public Vec2f position;
+        public float radius;
+        public Circle(Vec2f position, float radius){
+            this.position = position;
+            this.radius = radius;
+        }
+    }
+
+    public static class Line{
+        Vec2f p1;
+        Vec2f p2;
+        public Line(Vec2f p1, Vec2f p2){
+            this.p1 = p1;
+            this.p2 = p2;
+        }
+        float distanceSqr(){
+            return p1.getSquaredDistance(p2);
+        }
+    }
 }

+ 12 - 0
src/holeg/utility/math/vector/Vec2f.java

@@ -19,6 +19,11 @@ public class Vec2f {
 		x = other.x;
 		y = other.y;
 	}
+	public Vec2f(Vec2i other)
+	{
+		x = other.getX();
+		y = other.getY();
+	}
 
 	public void setX(float x) {
 		this.x = x;
@@ -50,6 +55,13 @@ public class Vec2f {
 		return result;
 	}
 
+	public static float dot(Vec2f p1, Vec2f p2)
+	{
+		return p1.dot(p2);
+	}
+
+
+
 	public float getLength()
 	{
 		return (float)Math.sqrt(x * x + y * y);