]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Improved line gaps 28/4928/1
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 15 Dec 2022 11:36:08 +0000 (13:36 +0200)
committerMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 15 Dec 2022 11:36:08 +0000 (13:36 +0200)
gitlab #888

Change-Id: I72fe0768500bc9830109e9a8e0501a967beff003

bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java
bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java

index 3ccb492b6ae56bcfa4e7b28b3820b85dd3c05fb9..2367805caed2dcbc9c44a5fb72e9c897d759cd7e 100644 (file)
@@ -29,10 +29,14 @@ public class ConnectionCrossings implements PathModifier {
 
     private List<Segment> segments = new ArrayList<>();
     private double width;
+    private double widthd2;
     private Type type;
+    private boolean keepLines = false;
+    
 
     public void setWidth(double gapWidth) {
         this.width = gapWidth;
+        this.widthd2 = width * 0.5;
     }
 
     public double getWidth() {
@@ -46,6 +50,18 @@ public class ConnectionCrossings implements PathModifier {
     public Type getType() {
         return type;
     }
+    
+    /**
+     * When keep lines is enabled, we keep short lines in the start and end of a line segment, instead of removing them completely with gaps.
+     * @return
+     */
+    public boolean isKeepLines() {
+        return keepLines;
+    }
+    
+    public void setKeepLines(boolean keepLines) {
+        this.keepLines = keepLines;
+    }
 
     static class Segment {
         public double x1, y1, x2, y2;
@@ -80,83 +96,177 @@ public class ConnectionCrossings implements PathModifier {
     public Path2D modify(Path2D path) {
         Path2D.Double path2 = new Path2D.Double();
         PathIterator iter = path.getPathIterator(null);
+        if (!isKeepLines()) {
+            while (!iter.isDone()) {
+    
+                double c[] = new double[6];
+                int i = iter.currentSegment(c);
+                switch (i) {
+                case PathIterator.SEG_MOVETO:
+                    path2.moveTo(c[0], c[1]);
+                    break;
+                case PathIterator.SEG_LINETO:
+                    Segment l = new Segment(path2.getCurrentPoint().getX(), path2.getCurrentPoint().getY(), c[0], c[1]);
 
-        while (!iter.isDone()) {
-
-            double c[] = new double[6];
-            int i = iter.currentSegment(c);
-            switch (i) {
-            case PathIterator.SEG_MOVETO:
-                path2.moveTo(c[0], c[1]);
-                break;
-            case PathIterator.SEG_LINETO:
-                Segment l = new Segment(path2.getCurrentPoint().getX(), path2.getCurrentPoint().getY(), c[0], c[1]);
-                
-                List<Double> gaps = new ArrayList<>();
-                for (Segment old : segments) {
-                    Double t = lineLineIntersection(old, l);
-                    if (t != null) {
-                        gaps.add(t);
+                    List<Double> gaps = new ArrayList<>();
+                    for (Segment old : segments) {
+                        Double t = lineLineIntersection(old, l);
+                        if (t != null) {
+                            gaps.add(t);
+                        }
                     }
-                }
 
-                if (gaps.isEmpty()) {
-                    path2.lineTo(c[0], c[1]);
-                } else {
-                    Collections.sort(gaps);
-                    double dx = l.x2 - l.x1;
-                    double dy = l.y2 - l.y1;
-
-                    double pos = 0.0;
-                    double len = Math.sqrt(dx*dx + dy*dy);
-
-                    boolean finish = true;
-                    Point2D prevGapEnd = null;
-                    for (Double gapCenter : gaps) {
-                        double pos2 = gapCenter - width / 2 / len;
-                        double pos3 = gapCenter + width / 2 / len;
-                        if (pos2 > pos) {
-                            handleGap(path2, prevGapEnd);
-                            prevGapEnd = null;
-                            path2.lineTo(l.x1 + pos2 * dx, l.y1 + pos2 * dy);
+                    if (gaps.isEmpty()) {
+                        path2.lineTo(c[0], c[1]);
+                    } else {
+                        Collections.sort(gaps);
+                        double dx = l.x2 - l.x1;
+                        double dy = l.y2 - l.y1;
+
+                        double pos = 0.0;
+                        double len = Math.sqrt(dx * dx + dy * dy);
+                        double len1 = 1.0 / len;
+
+                        boolean finish = true;
+                        Point2D prevGapEnd = null;
+                        for (Double gapCenter : gaps) {
+                            double pos2 = gapCenter - widthd2 * len1;
+                            double pos3 = gapCenter + widthd2 * len1;
+                            if (pos2 > pos) {
+                                handleGap(path2, prevGapEnd);
+                                prevGapEnd = null;
+                                path2.lineTo(l.x1 + pos2 * dx, l.y1 + pos2 * dy);
+                            }
+                            if (pos3 < 1.0) {
+                                double x = l.x1 + pos3 * dx;
+                                double y = l.y1 + pos3 * dy;
+                                prevGapEnd = new Point2D.Double(x, y);
+                            } else {
+                                finish = false;
+                            }
+                            pos = pos3;
                         }
-                        if (pos3 < 1.0) {
-                            double x = l.x1 + pos3 * dx;
-                            double y = l.y1 + pos3 * dy;
-                            prevGapEnd = new Point2D.Double(x, y);
+
+                        if (finish) {
+                            handleGap(path2, prevGapEnd);
+                            path2.lineTo(l.x2, l.y2);
                         } else {
-                            finish = false;
+                            prevGapEnd = new Point2D.Double(l.x2, l.y2);
+                            handleGap(path2, prevGapEnd);
                         }
-                        pos = pos3;
                     }
-                    
-                    if (finish) {
-                        handleGap(path2, prevGapEnd);
-                        path2.lineTo(l.x2, l.y2);
+                    segments.add(l);
+
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    // TODO: implement gaps
+                    path2.quadTo(c[0], c[1], c[2], c[3]);
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    // TODO: implement gaps
+                    path2.curveTo(c[0], c[1], c[2], c[3], c[4], c[5]);
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    // TODO: implement gaps
+                    path2.closePath();
+                    break;
+                default:
+                    throw new RuntimeException("Unexpected segment type " + i);
+                }
+                iter.next();
+            }
+        } else {
+            while (!iter.isDone()) {
+
+                double c[] = new double[6];
+                int i = iter.currentSegment(c);
+                switch (i) {
+                case PathIterator.SEG_MOVETO:
+                    path2.moveTo(c[0], c[1]);
+                    break;
+                case PathIterator.SEG_LINETO:
+                    Segment l = new Segment(path2.getCurrentPoint().getX(), path2.getCurrentPoint().getY(), c[0], c[1]);
+
+                    List<Double> gaps = new ArrayList<>();
+                    for (Segment old : segments) {
+                        Double t = lineLineIntersection(old, l);
+                        if (t != null) {
+                            gaps.add(t);
+                        }
+                    }
+
+                    if (gaps.isEmpty()) {
+                        path2.lineTo(c[0], c[1]);
                     } else {
-                        prevGapEnd = new Point2D.Double(l.x2, l.y2);
-                        handleGap(path2, prevGapEnd);
+                        Collections.sort(gaps);
+                        double dx = l.x2 - l.x1;
+                        double dy = l.y2 - l.y1;
+
+                        double pos = 0.0;
+                        double len = Math.sqrt(dx * dx + dy * dy);
+                        double len1 = 1.0 / len;
+
+                        boolean finish = true;
+                        Point2D prevGapEnd = null;
+                        for (int j = 0; j < gaps.size(); j++) {
+                            Double gapCenter = gaps.get(j);
+                            double gc = gapCenter * len;
+                            double pos2 = gc - widthd2;
+                            double pos3 = gc + widthd2;
+                            if (j == 0) {
+                                if (pos2 < widthd2)
+                                    pos2 += (widthd2 - pos2) * 0.5;
+                            }
+                            if (j == gaps.size() - 1) {
+                                double d = len - pos3;
+                                if (d < widthd2)
+                                    pos3 -= (widthd2 - d) * 0.5;
+                            }
+                            if (pos2 > pos) {
+                                handleGap(path2, prevGapEnd);
+                                prevGapEnd = null;
+                                pos2 *= len1;
+                                path2.lineTo(l.x1 + pos2 * dx, l.y1 + pos2 * dy);
+                            }
+                            if (pos3 < len) {
+                                pos3 *= len1;
+                                double x = l.x1 + pos3 * dx;
+                                double y = l.y1 + pos3 * dy;
+                                prevGapEnd = new Point2D.Double(x, y);
+                            } else {
+                                finish = false;
+                            }
+                            pos = pos3;
+                        }
+
+                        if (finish) {
+                            handleGap(path2, prevGapEnd);
+                            path2.lineTo(l.x2, l.y2);
+                        } else {
+                            prevGapEnd = new Point2D.Double(l.x2, l.y2);
+                            handleGap(path2, prevGapEnd);
+                        }
                     }
-                }
-                segments.add(l);
+                    segments.add(l);
 
-                break;
-            case PathIterator.SEG_QUADTO:
-                // TODO: implement gaps
-                path2.quadTo(c[0], c[1], c[2], c[3]);
-                break;
-            case PathIterator.SEG_CUBICTO:
-                // TODO: implement gaps
-                path2.curveTo(c[0], c[1], c[2], c[3], c[4], c[5]);
-                break;
-            case PathIterator.SEG_CLOSE:
-                // TODO: implement gaps
-                path2.closePath();
-                break;
-            default:
-                throw new RuntimeException("Unexpected segment type " + i);
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    // TODO: implement gaps
+                    path2.quadTo(c[0], c[1], c[2], c[3]);
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    // TODO: implement gaps
+                    path2.curveTo(c[0], c[1], c[2], c[3], c[4], c[5]);
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    // TODO: implement gaps
+                    path2.closePath();
+                    break;
+                default:
+                    throw new RuntimeException("Unexpected segment type " + i);
+                }
+                iter.next();
             }
-            iter.next();
         }
         return path2;
     }
index 5e97febdaf77a11a2ab28bcba7505c027cd71af4..4dd5144757dc7c3843256bef976b0b5ad6c883aa 100644 (file)
@@ -44,6 +44,12 @@ public class ConnectionCrossingsParticipant extends AbstractDiagramParticipant {
         crossings.setWidth(width);
         crossings.setType(type);
     }
+    
+    public ConnectionCrossingsParticipant(double width, ConnectionCrossings.Type type, boolean keepLines) {
+        crossings.setWidth(width);
+        crossings.setType(type);
+        crossings.setKeepLines(keepLines);
+    }
 
     @SGInit(designation = SGDesignation.CONTROL)
     public void initSG(G2DParentNode parent) {