|
15 | 15 | % PolygonPath methods: |
16 | 16 | % PolygonPath - Constructor. |
17 | 17 | % discreteFrechetDist - Discrete Frechet distance. |
| 18 | +% findSelfIntersections - Find intersecting path segments. |
18 | 19 | % fitCircle - Fit circle to path. |
19 | 20 | % fitStraight - Fit straight line to path. |
20 | 21 | % interp - Interpolate path. |
|
293 | 294 |
|
294 | 295 | end%fcn |
295 | 296 |
|
| 297 | + function [idxs,taus] = findSelfIntersections(obj, doPlot) |
| 298 | + %FINDSELFINTERSECTIONS Find intersecting path segments - Experimental! |
| 299 | + % IDXS = FINDSELFINTERSECTIONS(OBJ) returns an array of size |
| 300 | + % N-by-2 of indexes IDXS, where each row reports an intersection |
| 301 | + % between two segments. |
| 302 | + % |
| 303 | + % Note: If a segment I has intersections with segments J1 < J2 < |
| 304 | + % J3 < ..., only the first intersection [I J1] is returned! |
| 305 | + |
| 306 | + N = obj.numel(); |
| 307 | + idxs = zeros(0,2); |
| 308 | + taus = zeros(0,2); |
| 309 | + for i = 1:N-1 |
| 310 | + P0 = [obj.x(i) obj.y(i)]; |
| 311 | + P1 = [obj.x(i+1) obj.y(i+1)]; |
| 312 | + |
| 313 | + for j = i+1:N |
| 314 | + Q0 = [obj.x(j) obj.y(j)]; |
| 315 | + Q1 = [obj.x(j+1) obj.y(j+1)]; |
| 316 | + [~,tauIJ] = lineLineIntersection(P0, P1, Q0, Q1); |
| 317 | + if all(tauIJ > 0 & tauIJ < 1) |
| 318 | + % Segment i has an intersection with segment j |
| 319 | + idxs = [idxs; [i j]]; %#ok<AGROW> |
| 320 | + taus = [taus; tauIJ(1) + i - 1, tauIJ(2) + j - 1]; %#ok<AGROW> |
| 321 | + break |
| 322 | + end |
| 323 | + end |
| 324 | + end |
| 325 | + |
| 326 | + if (nargin > 1) && doPlot |
| 327 | + [~,ax] = obj.plot(); |
| 328 | + npState = get(ax, 'NextPlot'); |
| 329 | + set(ax, 'NextPlot','add') |
| 330 | + [xI,yI] = obj.eval(taus(:,1)); |
| 331 | + plot(ax, xI, yI, 'o', 'DisplayName','Intersections') |
| 332 | + set(ax, 'NextPlot',npState) |
| 333 | + end |
| 334 | + |
| 335 | + end%fcn |
| 336 | + |
296 | 337 | function [objc,e,xc,yc,R] = fitCircle(obj, N, doPlot) |
297 | 338 | %FITCIRCLE Fit a circle to PolygonPath. |
298 | 339 | % [OBJC,E,XC,YC,R] = FITCIRCLE(OBJ,N) fits a circle with |
|
319 | 360 |
|
320 | 361 | % Plot if requested |
321 | 362 | if (nargin > 2) && doPlot |
322 | | - plot(obj, 'b-', 'MarkerSize',10, 'DisplayName','PolygonPath'); |
323 | | - hold on |
324 | | - plot(objc, 'Color','k', 'DisplayName','Circle'); |
325 | | - hold off |
| 363 | + [~,ax] = plot(obj, 'b-', 'MarkerSize',10); |
| 364 | + npState = get(ax, 'NextPlot'); |
| 365 | + set(ax, 'NextPlot','add') |
| 366 | + plot(ax, objc, 'Color','k', 'DisplayName','Circle'); |
| 367 | + set(ax, 'NextPlot',npState) |
326 | 368 | legend('-DynamicLegend') |
327 | 369 | end%if |
328 | 370 |
|
|
366 | 408 | end |
367 | 409 |
|
368 | 410 | if (nargin > 1) && doPlot % Plot if requested |
369 | | - plot(obj, 'r', 'Marker','.', 'DisplayName','PolygonPath'); |
370 | | - hold on |
371 | | - plot(objs, 'b', 'Marker','o', 'DisplayName','Straight'); |
372 | | - hold off |
| 411 | + [~,ax] = plot(obj, 'r', 'Marker','.'); |
| 412 | + npState = get(ax, 'NextPlot'); |
| 413 | + set(ax, 'NextPlot','add'); |
| 414 | + plot(ax, objs, 'b', 'Marker','o', 'DisplayName','Straight'); |
| 415 | + set(ax, 'NextPlot',npState); |
373 | 416 | legend('-DynamicLegend') |
374 | 417 | end%if |
375 | 418 |
|
|
398 | 441 | xy = Q + bsxfun(@times, sd(:,2), [-u(:,2), u(:,1)]); |
399 | 442 |
|
400 | 443 | if (nargin > 2) && doPlot |
401 | | - plot(obj, 'Marker','.', 'MarkerSize',15, 'DisplayName','PolygonPath'); |
402 | | - hold on |
403 | | - plot(xy(:,1), xy(:,2), 'o', 'DisplayName','xy'); |
404 | | - plot(Q(:,1), Q(:,2), 'kx', 'DisplayName','Q'); |
405 | | - hold off |
| 444 | + [~,ax] = plot(obj, 'Marker','.', 'MarkerSize',15); |
| 445 | + npState = get(ax, 'NextPlot'); |
| 446 | + set(ax, 'NextPlot','add'); |
| 447 | + plot(ax, xy(:,1), xy(:,2), 'o', 'DisplayName','xy'); |
| 448 | + plot(ax, Q(:,1), Q(:,2), 'kx', 'DisplayName','Q'); |
| 449 | + set(ax, 'NextPlot',npState); |
406 | 450 | legend('-DynamicLegend') |
407 | 451 | end%if |
408 | 452 |
|
409 | 453 | end%fcn |
410 | | - |
| 454 | + |
411 | 455 | function flag = isempty(obj) |
412 | 456 | % ISEMPTY Check if path is empty. |
413 | 457 | % FLAG = ISEMPTY(OBJ) returns true if the path contains no |
|
503 | 547 |
|
504 | 548 | if (nargin > 3) && doPlot |
505 | 549 | [~,ax] = plot(obj, 'Marker','.'); |
506 | | - hold on |
| 550 | + npState = get(ax, 'NextPlot'); |
| 551 | + set(ax, 'NextPlot','add'); |
507 | 552 | phi = 0:pi/100:2*pi; |
508 | 553 | plot(ax, r*cos(phi) + C(1), r*sin(phi) + C(2), 'DisplayName','Circle'); |
509 | 554 | plot(ax, xy(:,1), xy(:,2), 'kx', 'DisplayName','Intersections') |
510 | | - hold off |
| 555 | + set(ax, 'NextPlot',npState); |
511 | 556 | end%if |
512 | 557 |
|
513 | 558 | end%fcn |
|
688 | 733 | dphi = zeros(numel(idx), 1); |
689 | 734 |
|
690 | 735 | if (nargin > 3) && doPlot |
691 | | - plot(obj, 'Marker','.', 'MarkerSize',8, 'DisplayName','RefPath'); |
692 | | - hold on |
693 | | - plot(obj.x(1), obj.y(1), 'g.', 'MarkerSize',18, 'DisplayName','Initial point'); |
694 | | - plot(poi(1), poi(2), 'ro', 'DisplayName','PoI') |
695 | | - plot(Q(:,1), Q(:,2), 'kx', 'DisplayName','Q') |
| 736 | + [~,ax] = plot(obj, 'Marker','.', 'MarkerSize',8, 'DisplayName','RefPath'); |
| 737 | + npState = get(ax, 'NextPlot'); |
| 738 | + set(ax, 'NextPlot','add'); |
| 739 | + plot(ax, obj.x(1), obj.y(1), 'g.', 'MarkerSize',18, 'DisplayName','Initial point'); |
| 740 | + plot(ax, poi(1), poi(2), 'ro', 'DisplayName','PoI') |
| 741 | + plot(ax, Q(:,1), Q(:,2), 'kx', 'DisplayName','Q') |
696 | 742 | legend('-DynamicLegend'); |
697 | | - plot(... |
| 743 | + plot(ax, ... |
698 | 744 | [Q(:,1)'; repmat([poi(1) NaN], size(Q,1),1)'],... |
699 | 745 | [Q(:,2)'; repmat([poi(2) NaN], size(Q,1),1)'], 'k:'); |
700 | | - hold off |
| 746 | + set(ax, 'NextPlot',npState); |
701 | 747 | end%if |
702 | 748 |
|
703 | 749 | end%fcn |
|
932 | 978 | P1 = [obj.x(end); obj.y(end)]; |
933 | 979 | end |
934 | 980 | end%fcn |
935 | | - |
| 981 | + |
936 | 982 | function write2file(obj, fn) |
937 | 983 | %WRITE2FILE Write path to file. |
938 | 984 | % WRITE2FILE(OBJ,FN) writes waypoints OBJ to file with filename |
@@ -1014,9 +1060,9 @@ function write2file(obj, fn) |
1014 | 1060 |
|
1015 | 1061 | function obj = clothoid(L, curv01, N, MODE) |
1016 | 1062 | %CLOTHOID Create clothoid path. |
1017 | | - % OBJ = POLYGONPATH.CLOTHOID(L, PHI01, N) creates a clothoid path |
| 1063 | + % OBJ = POLYGONPATH.CLOTHOID(L,CURV01,N) creates a clothoid path |
1018 | 1064 | % of length L, initial curvature CURV01(1) and end curvature |
1019 | | - % CURV01(2) at N equidistant sample points. |
| 1065 | + % CURV01(2), at N equidistant sample points. |
1020 | 1066 | % |
1021 | 1067 | % OBJ = POLYGONPATH.CLOTHOID(___,MODE) allows to select different |
1022 | 1068 | % calculation methods. Possible values are 'Heald', 'Quad'. |
|
0 commit comments