Find rightmost/leftmost point of SVG path

梦想的初衷 提交于 2020-01-26 04:16:05

问题


How to find leftmost/rightmost point of SVG C (bezier curve) path segment? I know there is getBoundingClientRect() and getBBox() but none of them apply since they return only single coordinate of the point.


Just to avoid XY problem - I want to split single path composed of bezier curves into several paths each monotonously going from left to right (or right to left). It means that on any single path should be no 2 points having equal X coordinate. I understand that required split point may potentially be inside the bounding box of a segment thus not being leftmost/rightmost, but I'm almost sure that way of finding such point should use same techniques as finding horizontally extreme point.


回答1:


You would need to iterate through the path length with .getPointAtLength(i) method, and then find the limits. Seemed like a fun thing to do so I made a quick and dirty implementation, this is the important part:

function findLimits(path) {

  var boundingPoints = {
    minX: {x: dimensions.width, y: dimensions.height},
    minY: {x: dimensions.width, y: dimensions.height},
    maxX: {x: 0, y: 0},
    maxY: {x: 0, y: 0}
  }
  var l = path.getTotalLength();
  for (var p = 0; p < l; p++) {
    var coords = path.getPointAtLength(p);
    if (coords.x < boundingPoints.minX.x) boundingPoints.minX = coords;
    if (coords.y < boundingPoints.minY.y) boundingPoints.minY = coords;
    if (coords.x > boundingPoints.maxX.x) boundingPoints.maxX = coords;
    if (coords.y > boundingPoints.maxY.y) boundingPoints.maxY = coords;
  }
  return boundingPoints
}

You can find the implementation here: https://jsfiddle.net/4gus3hks/1/




回答2:


Paul LeBeau's comment and fancy animation on the wiki inspired me for the solution. It is based mostly on following terms:

  • Values of parameter t from [0, 1] can be matched to the curve points.

  • For any parameter value point on the curve can be constructed step-by-step by linearly combining pairs of adjacent control points into intermediate control points of higher "depth". This operation can be repeated until only single point left - point on the curve itself.

  • Coordinates of the intermediate points can be defined by t-polynoms of degree equal to point "depth". And coefficients of those polynoms ultimately depend only on coordinates of initial control points.

  • Penultimate step of construction gives 2 points that define tangent to the curve at the final point, and coordinates of those points are controlled by quadratic polynom.

  • Having direction of tangent in question as vector allows to construct quadratic equation against t where curve has required tangent.

So, in fact, finding required points can be performed in constant O(1) time:

  tangentPoints: function(tx, ty){
    var ends = this.getPolynoms(2);
    var tangent = [ends[1][0].subtractPoly(ends[0][0]),
                   ends[1][1].subtractPoly(ends[0][1])];
    var eq = tangent[0].multiplyScalar(ty).subtractPoly(tangent[1].multiplyScalar(tx));
    return solveQuadratic(...eq.values).filter(t => t >= 0 && t <= 1);
  }

Full code with assisting Polynom class and visual demo I placed into this repo and fiddle



来源:https://stackoverflow.com/questions/40864528/find-rightmost-leftmost-point-of-svg-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!