Подтвердить что ты не робот

Функция, которая возвращает пересечение двух TShapes, включая TPaths?

Кто-нибудь знает какую-либо функцию, которая возвращает пересечение TPath для двух TShapes? Особенно тот, который возвращает пересечение TPath двух TPath.

Например:

pthIntersection := PathIntersection(Path1,Path2);

enter image description here

4b9b3361

Ответ 1

Для этого нет встроенной функции.
Но я думаю, что вы пытаетесь это сделать:

Учитывая многоугольник (aka TPath), созданный для разных точек, связанных линиями.
Верните все точки в ShapeA, которые лежат внутри ShapeB.

Пересечение точки
Это можно сделать, используя PointInObjectLocal.
Запустите петлю, посещая все точки в PathA и посмотрите, не лежит ли внутри PathB.

Пересечение линий
Если вы хотите знать все вершины, которые перекрываются, сначала нужно Flatten (копия) обоих TPath, а затем запустить алгоритм пересечения строк для всех строк в обеих фигурах.
Это преобразует все кривые в строки.

Вот рутина для этого:
От: http://www.partow.net/projects/fastgeo/index.html

function Intersect(const x1, y1, x2, y2, x3, y3, x4, y4: TFloat; out ix, iy: TFloat): boolean;
var
  UpperX, UpperY, LowerX, LowerY: TFloat;
  Ax, Bx, Cx, Ay, By, Cy: TFloat;
  D, F, E, Ratio: TFloat;
begin
  Result:= false;

  Ax:= x2 - x1;
  Bx:= x3 - x4;

  if Ax < Zero then begin
    LowerX:= x2;
    UpperX:= x1;
  end else begin
    UpperX:= x2;
    LowerX:= x1;
  end;

  if Bx > Zero then begin
    if (UpperX < x4) or (x3 < LowerX) then Exit;
  end else if (UpperX < x3) or (x4 < LowerX) then Exit;

  Ay:= y2 - y1;
  By:= y3 - y4;

  if Ay < Zero then begin
    LowerY:= y2;
    UpperY:= y1;
  end else begin
    UpperY:= y2;
    LowerY:= y1;
  end;

  if By > Zero then begin
    if (UpperY < y4) or (y3 < LowerY) then Exit;
  end else if (UpperY < y3) or (y4 < LowerY) then Exit;

  Cx:= x1 - x3;
  Cy:= y1 - y3;
  D:= (By * Cx) - (Bx * Cy);
  F:= (Ay * Bx) - (Ax * By);

  if F > Zero then begin
    if (D < Zero) or (D > F) then Exit;
  end else if (D > Zero) or (D < F) then Exit;

  E:= (Ax * Cy) - (Ay * Cx);

  if F > Zero then begin
    if (E < Zero) or (E > F) then Exit;
  end else if (E > Zero) or (E < F) then Exit;

  Result:= true;

  Ratio:= (Ax * -By) - (Ay * -Bx);

  if NotEqual(Ratio, Zero) then begin
    Ratio:= ((Cy * -Bx) - (Cx * -By)) / Ratio;
    ix:= x1 + (Ratio * Ax);
    iy:= y1 + (Ratio * Ay);
  end else begin
    //if Collinear(x1,y1,x2,y2,x3,y3) then
    if IsEqual((Ax * -Cy), ( -Cx * Ay)) then begin
      ix:= x3;
      iy:= y3;
    end else begin
      ix:= x4;
      iy:= y4;
    end;
  end;
end;

function Intersect(const Segment1,Segment2:TSegment2D; out ix, iy : TFloat):Boolean;
begin
  Result := Intersect(Segment1[1].x,Segment1[1].y,Segment1[2].x,Segment1[2].y,Segment2[1].x,Segment2[1].y,Segment2[2].x,Segment2[2].y,ix,iy);
end;

Просто преобразуйте пары TFloat x, y в TPointF, и вы находитесь в бизнесе. Приятная вещь о рутине заключается в том, что она также сообщает вам точную точку, в которой линии пересекаются.

Если вы следуете строкам, пока две линии не перекрываются, а оттуда при запуске отслеживают как перекрывающиеся строки, так и PointInShape, вы можете построить точное изображение перекрытия двух фигур.

Быстрое ускорение
Если сглаживание и соответствующее увеличение числа сегментов линии делают ваш код слишком медленным, вы можете сохранить кривые и посмотреть, пересекает ли линия/кривая другую кривую.
Для этого вы можете преобразовать кривые в bezier curve и использовать алгоритм De_Casteljau

Дополнительная информация
См. Также этот вопрос и ссылка на исходный код Delphi в его первой или второй ответ.