diff --git a/.cspell/libraries.txt b/.cspell/libraries.txt index 185d284f7..10be49ad4 100644 --- a/.cspell/libraries.txt +++ b/.cspell/libraries.txt @@ -47,6 +47,7 @@ mdbook Mermerd mkdocs Nextra +NODECOUNT nodenext npmjs pageview @@ -58,6 +59,7 @@ presetAttributify pyplot redmine rehype +RIGHTDOWN roughjs rscratch shiki @@ -67,6 +69,7 @@ sphinxcontrib ssim stylis Swimm +topdown tsbuildinfo tseslint Tuleap diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index bc624ad0c..da92fde25 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -93,14 +93,14 @@ config: look: classic theme: forest - layout: elk + layout: dagre --- flowchart LR A["A"] --> C B("B B B B B") --> C[/"C C C C C"/] C@{ shape: circle } %%C@{ shape: question } - %%C@{ shape: stadium } + C@{ shape: stadium }
 ---
@@ -114,6 +114,7 @@ flowchart LR
     C -- One --> D["Option 1"]
     C -- Two --> E["Option 2"]
     C -- Three --> F["fa:fa-car Option 3"]
+    C@{ shape: db }
     
 ---
diff --git a/packages/mermaid-layout-elk/src/render.ts b/packages/mermaid-layout-elk/src/render.ts
index cc373f700..82b271fa8 100644
--- a/packages/mermaid-layout-elk/src/render.ts
+++ b/packages/mermaid-layout-elk/src/render.ts
@@ -484,317 +484,6 @@ export const render = async (
     }
   }
 
-  function intersectLine(
-    p1: { y: number; x: number },
-    p2: { y: number; x: number },
-    q1: { x: any; y: any },
-    q2: { x: any; y: any }
-  ) {
-    log.debug('UIO intersectLine', p1, p2, q1, q2);
-    // Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
-    // p7 and p473.
-
-    // let a1, a2, b1, b2, c1, c2;
-    // let r1, r2, r3, r4;
-    // let denom, offset, num;
-    // let x, y;
-
-    // Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
-    // b1 y + c1 = 0.
-    const a1 = p2.y - p1.y;
-    const b1 = p1.x - p2.x;
-    const c1 = p2.x * p1.y - p1.x * p2.y;
-
-    // Compute r3 and r4.
-    const r3 = a1 * q1.x + b1 * q1.y + c1;
-    const r4 = a1 * q2.x + b1 * q2.y + c1;
-
-    const epsilon = 1e-6;
-
-    // Check signs of r3 and r4. If both point 3 and point 4 lie on
-    // same side of line 1, the line segments do not intersect.
-    if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) {
-      return /*DON'T_INTERSECT*/;
-    }
-
-    // Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
-    const a2 = q2.y - q1.y;
-    const b2 = q1.x - q2.x;
-    const c2 = q2.x * q1.y - q1.x * q2.y;
-
-    // Compute r1 and r2
-    const r1 = a2 * p1.x + b2 * p1.y + c2;
-    const r2 = a2 * p2.x + b2 * p2.y + c2;
-
-    // Check signs of r1 and r2. If both point 1 and point 2 lie
-    // on same side of second line segment, the line segments do
-    // not intersect.
-    if (Math.abs(r1) < epsilon && Math.abs(r2) < epsilon && sameSign(r1, r2)) {
-      return /*DON'T_INTERSECT*/;
-    }
-
-    // Line segments intersect: compute intersection point.
-    const denom = a1 * b2 - a2 * b1;
-    if (denom === 0) {
-      return /*COLLINEAR*/;
-    }
-
-    const offset = Math.abs(denom / 2);
-
-    // The denom/2 is to get rounding instead of truncating. It
-    // is added or subtracted to the numerator, depending upon the
-    // sign of the numerator.
-    let num = b1 * c2 - b2 * c1;
-    const x = num < 0 ? (num - offset) / denom : (num + offset) / denom;
-
-    num = a2 * c1 - a1 * c2;
-    const y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
-
-    return { x: x, y: y };
-  }
-
-  function sameSign(r1: number, r2: number) {
-    return r1 * r2 > 0;
-  }
-  const diamondIntersection = (
-    bounds: { x: any; y: any; width: any; height: any },
-    outsidePoint: { x: number; y: number },
-    insidePoint: any
-  ) => {
-    const x1 = bounds.x;
-    const y1 = bounds.y;
-
-    const w = bounds.width - 0.1; //+ bounds.padding;
-    const h = bounds.height - 0.1; // + bounds.padding;
-
-    const polyPoints = [
-      { x: x1, y: y1 - h / 2 },
-      { x: x1 + w / 2, y: y1 },
-      { x: x1, y: y1 + h / 2 },
-      { x: x1 - w / 2, y: y1 },
-    ];
-    log.debug(
-      `APA16 diamondIntersection calc abc89:
-  outsidePoint: ${JSON.stringify(outsidePoint)}
-  insidePoint : ${JSON.stringify(insidePoint)}
-  node-bounds       : x:${bounds.x} y:${bounds.y} w:${bounds.width} h:${bounds.height}`,
-      JSON.stringify(polyPoints)
-    );
-
-    const intersections = [];
-
-    let minX = Number.POSITIVE_INFINITY;
-    let minY = Number.POSITIVE_INFINITY;
-
-    polyPoints.forEach(function (entry) {
-      minX = Math.min(minX, entry.x);
-      minY = Math.min(minY, entry.y);
-    });
-
-    const left = x1 - w / 2 - minX;
-    const top = y1 - h / 2 - minY;
-
-    for (let i = 0; i < polyPoints.length; i++) {
-      const p1 = polyPoints[i];
-      const p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
-      const intersect = intersectLine(
-        bounds,
-        outsidePoint,
-        { x: left + p1.x, y: top + p1.y },
-        { x: left + p2.x, y: top + p2.y }
-      );
-
-      if (intersect) {
-        intersections.push(intersect);
-      }
-    }
-
-    if (!intersections.length) {
-      return bounds;
-    }
-
-    log.debug('UIO intersections', intersections);
-
-    if (intersections.length > 1) {
-      // More intersections, find the one nearest to edge end point
-      intersections.sort(function (p, q) {
-        const pdx = p.x - outsidePoint.x;
-        const pdy = p.y - outsidePoint.y;
-        const distp = Math.sqrt(pdx * pdx + pdy * pdy);
-
-        const qdx = q.x - outsidePoint.x;
-        const qdy = q.y - outsidePoint.y;
-        const distq = Math.sqrt(qdx * qdx + qdy * qdy);
-
-        return distp < distq ? -1 : distp === distq ? 0 : 1;
-      });
-    }
-
-    return intersections[0];
-  };
-
-  const intersection = (
-    node: { x: any; y: any; width: number; height: number },
-    outsidePoint: { x: number; y: number },
-    insidePoint: { x: number; y: number }
-  ) => {
-    log.debug(`intersection calc abc89:
-  outsidePoint: ${JSON.stringify(outsidePoint)}
-  insidePoint : ${JSON.stringify(insidePoint)}
-  node        : x:${node.x} y:${node.y} w:${node.width} h:${node.height}`);
-    const x = node.x;
-    const y = node.y;
-
-    const dx = Math.abs(x - insidePoint.x);
-    // const dy = Math.abs(y - insidePoint.y);
-    const w = node.width / 2;
-    let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
-    const h = node.height / 2;
-
-    const Q = Math.abs(outsidePoint.y - insidePoint.y);
-    const R = Math.abs(outsidePoint.x - insidePoint.x);
-
-    if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) {
-      // Intersection is top or bottom of rect.
-      const q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
-      r = (R * q) / Q;
-      const res = {
-        x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r,
-        y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q,
-      };
-
-      if (r === 0) {
-        res.x = outsidePoint.x;
-        res.y = outsidePoint.y;
-      }
-      if (R === 0) {
-        res.x = outsidePoint.x;
-      }
-      if (Q === 0) {
-        res.y = outsidePoint.y;
-      }
-
-      log.debug(`abc89 topp/bott calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res); // cspell: disable-line
-
-      return res;
-    } else {
-      // Intersection onn sides of rect
-      if (insidePoint.x < outsidePoint.x) {
-        r = outsidePoint.x - w - x;
-      } else {
-        // r = outsidePoint.x - w - x;
-        r = x - w - outsidePoint.x;
-      }
-      const q = (Q * r) / R;
-      //  OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w;
-      // OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r;
-      let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r;
-      // let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r;
-      let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q;
-      log.debug(`sides calc abc89, Q ${Q}, q ${q}, R ${R}, r ${r}`, { _x, _y });
-      if (r === 0) {
-        _x = outsidePoint.x;
-        _y = outsidePoint.y;
-      }
-      if (R === 0) {
-        _x = outsidePoint.x;
-      }
-      if (Q === 0) {
-        _y = outsidePoint.y;
-      }
-
-      return { x: _x, y: _y };
-    }
-  };
-  const outsideNode = (
-    node: { x: any; y: any; width: number; height: number },
-    point: { x: number; y: number }
-  ) => {
-    const x = node.x;
-    const y = node.y;
-    const dx = Math.abs(point.x - x);
-    const dy = Math.abs(point.y - y);
-    const w = node.width / 2;
-    const h = node.height / 2;
-    if (dx >= w || dy >= h) {
-      return true;
-    }
-    return false;
-  };
-  /**
-   * This function will take a path and node where the last point(s) in the path is inside the node
-   * and return an update path ending by the border of the node.
-   */
-  // const cutPathAtIntersect2 = (node: any, _points: any[], offset: any, bounds: any) => {
-  //   // Iterate over the points in the path and check if the point is inside the node
-  //   const points: any[] = [];
-  //   let lastPointOutside = _points[0];
-  //   let isInside = false;
-  //   _points.forEach((point: any) => {
-  //     const int = node.intersect(point);
-  //     // console.log('UIO cutPathAtIntersect2 Points:', point, 'int', int);
-  //   });
-  //   return points;
-  // };
-  /**
-   * This function will take a path and node where the last point(s) in the path is inside the node
-   * and return an update path ending by the border of the node.
-   */
-  const cutPathAtIntersect = (
-    _points: any[],
-    bounds: { x: any; y: any; width: any; height: any; padding: any },
-    isDiamond: boolean
-  ) => {
-    log.debug('APA18 cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond);
-    const points: any[] = [];
-    let lastPointOutside = _points[0];
-    let isInside = false;
-    _points.forEach((point: any) => {
-      // check if point is inside the boundary rect
-      if (!outsideNode(bounds, point) && !isInside) {
-        // First point inside the rect found
-        // Calc the intersection coord between the point anf the last point outside the rect
-        let inter;
-
-        if (isDiamond) {
-          const inter2 = diamondIntersection(bounds, lastPointOutside, point);
-          const distance = Math.sqrt(
-            (lastPointOutside.x - inter2.x) ** 2 + (lastPointOutside.y - inter2.y) ** 2
-          );
-          if (distance > 1) {
-            inter = inter2;
-          }
-        }
-        if (!inter) {
-          inter = intersection(bounds, lastPointOutside, point);
-        }
-
-        // Check case where the intersection is the same as the last point
-        let pointPresent = false;
-        points.forEach((p) => {
-          pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y);
-        });
-        // if (!pointPresent) {
-        if (!points.some((e) => e.x === inter.x && e.y === inter.y)) {
-          points.push(inter);
-        } else {
-          log.debug('abc88 no intersect', inter, points);
-        }
-        // points.push(inter);
-        isInside = true;
-      } else {
-        // Outside
-        log.debug('abc88 outside', point, lastPointOutside, points);
-        lastPointOutside = point;
-        // points.push(point);
-        if (!isInside) {
-          points.push(point);
-        }
-      }
-    });
-    return points;
-  };
-
   // @ts-ignore - ELK is not typed
   const elk = new ELK();
   const element = svg.select('g');
@@ -1026,82 +715,40 @@ export const render = async (
         }
         if (startNode.intersect) {
           // Remove the first point of the edge points
-          edge.points.shift();
+          // edge.points.shift();
+          const firstPoint = edge.points[0];
+          // Transpose points to adjust for elk standard
+          const adjustedFirstPoint = {
+            x: firstPoint.x - startNode.width / 2,
+            y: firstPoint.y - startNode.height / 2,
+          };
+          const intersectionRaw = startNode.intersect(adjustedFirstPoint);
+          const intersection = {
+            x: intersectionRaw.x + startNode.width / 2,
+            y: intersectionRaw.y + startNode.height / 2,
+          };
 
-          // console.log(
-          //   'APA13 calculating start intersection start node',
-          //   startNode.id,
-          //   startNode.x,
-          //   startNode.y,
-          //   'w:',
-          //   startNode.width,
-          //   'h:',
-          //   startNode.height,
-          //   '\nPos',
-          //   edge.points[0]
-          // );
-          const intersection2 = startNode.calcIntersect(
-            {
-              x: startNode.offset.posX + startNode.width / 2,
-              y: startNode.offset.posY + startNode.height / 2,
-              width: startNode.width,
-              height: startNode.height,
-            },
-            edge.points[0]
-          );
-          const intersection = startNode.intersect(edge.points[0]);
-
-          if (distance(intersection2, edge.points[0]) > epsilon) {
-            // intersection.x = -startNode.offset.posX + intersection.x + startNode.width / 2;
-            // intersection.y = intersection.y + startNode.height / 2 + 5;
-            edge.points.unshift(intersection2);
+          if (distance(intersection, firstPoint) > epsilon) {
+            edge.points.unshift(intersection);
           }
         }
         if (endNode.intersect) {
           // Remove the last point of the edge points
           // edge.points.pop();
-          const intersection2 = endNode.calcIntersect(
-            {
-              x: endNode.offset.posX + endNode.width / 2,
-              y: endNode.offset.posY + endNode.height / 2,
-              width: endNode.width,
-              height: endNode.height,
-            },
-            edge.points[edge.points.length - 1]
-          );
-          console.log('APA13 intersection2', endNode);
-          const intersection = endNode.intersect(edge.points[edge.points.length - 1]);
-          // if (edge.id === 'L_n4_C_10_0') {
-          // console.log('APA14 lineData', edge.points, 'intersection:', intersection);
-          // console.log(
-          //   'APA14! calculating end intersection\ndistance:',
-          //   distance(intersection, edge.points[edge.points.length - 1])
-          // );
-          // }
-          console.log('APA13 intersection2.2', intersection, intersection2);
 
-          if (distance(intersection2, edge.points[edge.points.length - 1]) > epsilon) {
-            console.log(
-              'APA13! distance ok\nintersection:',
-              intersection,
-              '\nstartNode:',
-              startNode.id,
-              '\nendNode:',
-              endNode.id,
-              '\n distance',
-              distance(intersection2, edge.points[edge.points.length - 1])
-            );
-            edge.points.push(intersection2);
-            // console.log('APA13! distance ok\npoints:', edge.points);
-          } else {
-            console.log(
-              'APA13! distance not ok\nintersection:',
-              intersection,
-              '\nstartNode:',
-              startNode.id,
-              '\nendNode:',
-              endNode.id
-            );
+          const lastPoint = edge.points[edge.points.length - 1];
+          // Transpose points to adjust for elk standard
+          const adjustedLastPoint = {
+            x: lastPoint.x - endNode.width / 2,
+            y: lastPoint.y - endNode.height / 2,
+          };
+          const intersectionRaw = endNode.intersect(adjustedLastPoint);
+          const intersection = {
+            x: intersectionRaw.x + endNode.width / 2,
+            y: intersectionRaw.y + endNode.height / 2,
+          };
+          if (distance(intersection, lastPoint) > epsilon) {
+            edge.points.push(intersection);
           }
         }
 
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js
index 2bbf68e0f..d6bacc0cf 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js
+++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js
@@ -672,11 +672,6 @@ function generateRoundedPath(points, radius) {
         // Draw the quadratic Bezier curve
         path += `Q${currPoint.x},${currPoint.y} ${endX},${endY}`;
       } else {
-        // // Draw the line to the start of the curve
-        // path += `L${startX},${startY}`;
-        // path += `Q${currPoint.x},${currPoint.y} ${currPoint.x},${currPoint.y}`;
-        // Draw the line to the start of the curve
-        // path += `L${startX},${startY}`;
         path += `L${lastPoint.x},${lastPoint.y}`;
       }
     }