1## Copyright (C) 2021 David Legland 2## All rights reserved. 3## 4## Redistribution and use in source and binary forms, with or without 5## modification, are permitted provided that the following conditions are met: 6## 7## 1 Redistributions of source code must retain the above copyright notice, 8## this list of conditions and the following disclaimer. 9## 2 Redistributions in binary form must reproduce the above copyright 10## notice, this list of conditions and the following disclaimer in the 11## documentation and/or other materials provided with the distribution. 12## 13## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' 14## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 17## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23## 24## The views and conclusions contained in the software and documentation are 25## those of the authors and should not be interpreted as representing official 26## policies, either expressed or implied, of the copyright holders. 27 28function edge = clipLine(line, box, varargin) 29%CLIPLINE Clip a line with a box. 30% 31% EDGE = clipLine(LINE, BOX); 32% LINE is a straight line given as a 4 element row vector: [x0 y0 dx dy], 33% with (x0 y0) being a point of the line and (dx dy) a direction vector, 34% BOX is the clipping box, given by its extreme coordinates: 35% [xmin xmax ymin ymax]. 36% The result is given as an edge, defined by the coordinates of its 2 37% extreme points: [x1 y1 x2 y2]. 38% If line does not intersect the box, [NaN NaN NaN NaN] is returned. 39% 40% Function works also if LINE is a N-by-4 array, if BOX is a Nx4 array, 41% or if both LINE and BOX are N-by-4 arrays. In these cases, EDGE is a 42% N-by-4 array. 43% 44% 45% Example 46% line = [30 40 10 0]; 47% box = [0 100 0 100]; 48% res = clipLine(line, box) 49% res = 50% 0 40 100 40 51% 52% See also: 53% lines2d, boxes2d, edges2d 54% clipEdge, clipRay, clipLine3d 55% 56 57% ------ 58% Author: David Legland 59% e-mail: david.legland@inra.fr 60% Created: 2007-08-27, using Matlab 7.4.0.287 (R2007a) 61% Copyright 2010 INRA - Cepia Software Platform. 62 63% HISTORY 64% 2010-05-16 rewrite using intersectLines, add precision management 65% 2010-08-03 fix bugs (thanks to Reto Zingg) 66% 2010-08-06 remove management of EPS by checking edge midpoint (thanks 67% again to Reto Zingg) 68 69% adjust size of two input arguments 70nLines = size(line, 1); 71nBoxes = size(box, 1); 72if nLines == 1 && nBoxes > 1 73 line = repmat(line, nBoxes, 1); 74elseif nBoxes == 1 && nLines > 1 75 box = repmat(box, nLines, 1); 76elseif nLines ~= nBoxes 77 error('bad sizes for input'); 78end 79 80% allocate memory 81nLines = size(line, 1); 82edge = zeros(nLines, 4); 83 84% main loop on lines 85for i = 1:nLines 86 % extract limits of the box 87 xmin = box(i, 1); 88 xmax = box(i, 2); 89 ymin = box(i, 3); 90 ymax = box(i, 4); 91 92 % use direction vector for box edges similar to direction vector of the 93 % line in order to reduce computation errors 94 delta = hypot(line(i,3), line(i,4)); 95 96 % compute intersection with each edge of the box 97 px1 = intersectLines(line(i,:), [xmin ymin delta 0]); % lower edge 98 px2 = intersectLines(line(i,:), [xmax ymin 0 delta]); % right edge 99 py1 = intersectLines(line(i,:), [xmax ymax -delta 0]); % upper edge 100 py2 = intersectLines(line(i,:), [xmin ymax 0 -delta]); % left edge 101 102 % remove undefined intersections (case of lines parallel to box edges) 103 points = [px1 ; px2 ; py1 ; py2]; 104 points = points(isfinite(points(:,1)), :); 105 106 % sort points according to their position on the line 107 pos = linePosition(points, line(i,:)); 108 [pos, inds] = sort(pos); %#ok<ASGLU> 109 points = points(inds, :); 110 111 % create clipped edge by using the two points in the middle 112 ind = size(points, 1)/2; 113 inter1 = points(ind,:); 114 inter2 = points(ind+1,:); 115 edge(i, 1:4) = [inter1 inter2]; 116 117 % check that middle point of the edge is contained in the box 118 midX = mean(edge(i, [1 3])); 119 xOk = xmin <= midX && midX <= xmax; 120 midY = mean(edge(i, [2 4])); 121 yOk = ymin <= midY && midY <= ymax; 122 123 % if one of the bounding condition is not met, set edge to NaN 124 if ~(xOk && yOk) 125 edge (i,:) = NaN; 126 end 127end 128