Matlab - crash function for detecting collisions between line and circle segments

Many questions already exist regarding the detection of collisions between a line segment and a circle.

In my code, I use the Matlab function linecirc, then comparing the intersection points that it returns with the ends of my line segments to check that the points are inside the line (linecirc accepts an infinite line, 't have / want).

Copying and adding some calls sprintfto a function linecircshows that it calculates the points by purpose. They seem to be lost by my function.

My code is below:

function cutCount = getCutCountHex(R_g, centre)
clf;
cutCount = 0;

% Generate a hex grid
Dg = R_g*2;
L_b = 62;

range = L_b*8;

dx = Dg*cosd(30);
dy = 3*R_g;
xMax = ceil(range/dx); yMax = ceil(range/dy);
d1 = @(xc, yc) [dx*xc dy*yc];
d2 = @(xc, yc) [dx*(xc+0.5) dy*(yc+0.5)];

centres = zeros((xMax*yMax),2);
count = 1;

for yc = 0:yMax-1
    for xc = 0:xMax-1
        centres(count,:) = d1(xc, yc);
        count = count + 1;
        centres(count, :) = d2(xc, yc);
        count = count + 1;
    end
end

for i=1:size(centres,1)
    centres(i,:) = centres(i,:) - [xMax/2 * dx, yMax/2 * dy];
end

hold on
axis equal

% Get counter for intersected lines
[VertexX, VertexY] = voronoi(centres(:,1), centres(:,2));
numLines = size(VertexX, 2);
for lc = 1:numLines
    segStartPt = [VertexX(1,lc) VertexY(1,lc)];
    segEndPt = [VertexX(2,lc) VertexY(2,lc)];
    slope = (segEndPt(2) - segStartPt(2))/(segEndPt(1) - segStartPt(1));
    intercept = segEndPt(2) - (slope*segEndPt(1));
    testSlope = isinf(slope);
    if (testSlope(1)==1)
        % Pass the x-axis intercept instead
        intercept = segStartPt(1);
    end
    [xInterceptionPoints, yInterceptionPoints] = ...
        linecirc(slope, intercept, centre(1), centre(2), L_b);

    testArr = isnan(xInterceptionPoints);
    if (testArr(1) == 0) % Line intersects. Line segment may not.
        interceptionPoint1 = [xInterceptionPoints(1), yInterceptionPoints(1)];
        interceptionPoint2 = [xInterceptionPoints(2), yInterceptionPoints(2)];

        % Test if first intersection is on the line segment
        p1OnSeg = onSeg(segStartPt, segEndPt, interceptionPoint1);
        p2OnSeg = onSeg(segStartPt, segEndPt, interceptionPoint2);
        if (p1OnSeg == 1)
            cutCount = cutCount + 1;
            scatter(interceptionPoint1(1), interceptionPoint1(2), 60, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k');
        end

        % Test if second intersection point is on the line segment
        if (interceptionPoint1(1) ~= interceptionPoint2(1) || interceptionPoint1(2) ~= interceptionPoint2(2)) % Don't double count touching points
            if (p2OnSeg == 1)
                cutCount = cutCount + 1;
                scatter(interceptionPoint2(1), interceptionPoint2(2), 60, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k');
            end
        end
    end
end

% Plot circle

viscircles(centre, L_b, 'EdgeColor', 'b');
H = voronoi(centres(:,1), centres(:,2));
for i = 1:size(H)
    set(H(i), 'Color', 'g');
end
end

function boolVal = onSeg(segStart, segEnd, testPoint)
bvX = isBetweenOrEq(segStart(1), segEnd(1), testPoint(1));
bvY = isBetweenOrEq(segStart(2), segEnd(2), testPoint(2));
if (bvX == 1 && bvY == 1)
    boolVal = 1;
else
    boolVal = 0;
end
end

function boolVal = isBetweenOrEq(end1, end2, test)
    if ((test <= end1 && test >= end2) || (test >= end1 && test <= end2))
        boolVal = 1;
    else
        boolVal = 0;
    end
end

It creates a hexagonal grid, then calculates the number of intersections between the circle drawn with a fixed radius (in this case 62) and the specified center.

scatter , . sprintf if(p1OnSeg == 1) , ( )

if (interceptionPoint1(1) > -26 && interceptionPoint1(1) < -25)
                sprintf('p1 = [%f, %f]. Vx = [%f, %f], Vy = [%f, %f].\nxint = [%f, %f], yint = [%f, %f]',...
                    interceptionPoint1(1), interceptionPoint1(2), VertexX(1,lc), VertexX(2,lc), VertexY(1,lc), VertexY(2,lc),...
                    xInterceptionPoints(1), xInterceptionPoints(2), yInterceptionPoints(1), yInterceptionPoints(2))
            end

p1 = [-25.980762, 0.000000]. Vx = [-25.980762, -25.980762], Vy = [-15.000000, 15.000000].
xint = [-25.980762, -25.980762], yint = [0.000000, 0.000000]

.

enter image description here

, . ( mylinecirc (-25, 55) (-25, -55) ( ).

, . ?

: , [Vx, Vy] = voronoi(...), (.. , ..), -, . , "" , NaN "" "". , - , .

. Jan de Gier, .

%Rotate slightly
RotAngle = 8;
RotMat = [cosd(RotAngle), -sind(RotAngle); sind(RotAngle), cosd(RotAngle)];

for i=1:size(centres,1)
    centres(i,:) = centres(i,:) - [floor(xMax/2) * dx, floor(yMax/2) * dy]; %Translation
    centres(i,:) = ( RotMat * centres(i,:)' ); %Rotation
end


% Get counter for intersected lines
[VertexX, VertexY] = voronoi(centres(:,1), centres(:,2));

% Filter vertices
numLines = size(VertexX, 2);
newVx = [];
newVy = [];
for lc = 1:numLines
    testVec = [VertexX(:,lc) VertexY(:,lc)];
    if ~any(abs(testVec) > range*1.5)
        newVx = [newVx; VertexX(:,lc)'];
        newVy = [newVy; VertexY(:,lc)'];
    end
end
VertexX = newVx';
VertexY = newVy';
numLines = size(VertexX, 2);

- , , . , : getCutCountHex(30, [0,0]) ...(35, [0,0])

+4
1

, , onSeg() : true, , segStart segEnd.

, true, ( : ), (segStart, segEnd) :

function boolVal = onSeg(segStart, segEnd, testPoint)

    tolerance = .5;

    AB = sqrt((segEnd(1)-segStart(1))*(segEnd(1)-segStart(1))+(segEnd(2)-segStart(2))*(segEnd(2)-segStart(2)));
    AP = sqrt((testPoint(1)-segEnd(1))*(testPoint(1)-segEnd(1))+(testPoint(2)-segEnd(2))*(testPoint(2)-segEnd(2)));
    PB = sqrt((segStart(1)-testPoint(1))*(segStart(1)-testPoint(1))+(segStart(2)-testPoint(2))*(segStart(2)-testPoint(2)));

    boolVal = abs(AB - (AP + PB)) < tolerance;

end

, : , . , .

+1

All Articles