thelonious / kld-intersections

A library of intersection algorithms covering all SVG shape types
BSD 3-Clause "New" or "Revised" License
343 stars 55 forks source link

SvgShapes. SVG transformations are ignored. #49

Open ievgennaida opened 4 years ago

ievgennaida commented 4 years ago

Transformations and 'viewBox' are completely ignored by the SvgShapes.

A workaround fix: (svg rotated + viewBox + group rotated + elements rotated):

<svg transform="rotate(12 12 12)" viewBox="0,0, 800,800" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="go(evt)">
  <script type="text/javascript" xlink:href="../dist/index-umd.js"/>
  <script type="text/javascript" xlink:href="./show_intersections.js"/>
  <defs>
    <g id="intersection">
      <circle r="3" fill="none" stroke="red" stroke-width="1"/>
      <circle r="1" fill="black"/>
    </g>
  </defs>
  <g id="shapes" transform="rotate(12 12 12)">
    <polygon x="44" transform="matrix(1, 1, 4, 1.3, 2, 2)" points="48,20 100,17 125,98 64,130 18,98" fill="blue" opacity="0.5"/>
    <polygon y="12" transform="matrix(1, 3, 4,0.5, -5, 4)" points="20,48 17,100 98,125 130,64 98,18 43,16" fill="orange" opacity="0.5"/>
  </g>
  <g id="result"/>
</svg>

A simple fix might help when setting the points for SvgShapes:

let ctm = _polygon.getCTM();
        for (var i = 0; i < _polygon.points.numberOfItems; i++) {
          var point = _polygon.points.getItem(i);
          point = point.matrixTransform(ctm);
          //points.push(point);
          points.push(new Point2D(point.x, point.y));
 }

And the fix to show the output point in a proper place:


function go() {
    const shapes = getShapes();
    const container = document.getElementById("shapes");
    if (shapes !== null) {
        const [shape1, shape2] = shapes;
        const result = Intersection.intersect(shape1, shape2);
        // chrome, firefox
        let ctm = container.ownerSVGElement.getCTM() || container.ownerSVGElement.getScreenCTM();       
        if(ctm) ctm = ctm.inverse();
        const xml = result.points.map(point => {
            point = ctm ? point.transform(ctm): point;
            return `<use href="#intersection" x="${point.x}" y="${point.y}"/>`;
        }).join("\n");

        document.getElementById("result").innerHTML = xml;
    }
}

Suggestion: add a transformation matrix to the ShapeInfo element. So shapes might be transformed independently