Home > matGeom > geom2d > clipEdge.m

clipEdge

PURPOSE ^

CLIPEDGE Clip an edge with a rectangular box.

SYNOPSIS ^

function edge2 = clipEdge(edge, box)

DESCRIPTION ^

CLIPEDGE Clip an edge with a rectangular box.

   EDGE2 = clipEdge(EDGE, BOX);
   EDGE: [x1 y1 x2 y2],
   BOX : [xmin xmax ymin ymax], or [xmin xmax ; ymin ymax].
   return :
   EDGE2 = [xc1 yc1 xc2 yc2];

   If clipping is null, return [0 0 0 0];

   if EDGE is a N-by-4 array, return an N-by-4 array, corresponding to
   each clipped edge.

   See also
   edges2d, boxes2d, clipLine

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function edge2 = clipEdge(edge, box)
0002 %CLIPEDGE Clip an edge with a rectangular box.
0003 %
0004 %   EDGE2 = clipEdge(EDGE, BOX);
0005 %   EDGE: [x1 y1 x2 y2],
0006 %   BOX : [xmin xmax ymin ymax], or [xmin xmax ; ymin ymax].
0007 %   return :
0008 %   EDGE2 = [xc1 yc1 xc2 yc2];
0009 %
0010 %   If clipping is null, return [0 0 0 0];
0011 %
0012 %   if EDGE is a N-by-4 array, return an N-by-4 array, corresponding to
0013 %   each clipped edge.
0014 %
0015 %   See also
0016 %   edges2d, boxes2d, clipLine
0017 %
0018 
0019 % ---------
0020 % author : David Legland
0021 % e-mail: david.legland@inra.fr
0022 % created: the 14/05/2005.
0023 % Copyright 2010 INRA - Cepia Software Platform.
0024 
0025 %   HISTORY
0026 %   2007-01-08 sort points according to position on edge, not to x coord
0027 %       -> this allows to return edges with same orientation a source, and
0028 %       to keep first or end points at the same position if their are not
0029 %       clipped.
0030 %   01/10/2010 fix bug due to precision, thanks to Reto Zingg.
0031 
0032 % process data input
0033 if size(box, 1) == 2
0034     box = box';
0035 end
0036 
0037 % get limits of window
0038 xmin = box(1);
0039 xmax = box(2);
0040 ymin = box(3);
0041 ymax = box(4);
0042 
0043 
0044 % convert window limits into lines
0045 lineX0 = [xmin ymin xmax-xmin 0];
0046 lineX1 = [xmin ymax xmax-xmin 0];
0047 lineY0 = [xmin ymin 0 ymax-ymin];
0048 lineY1 = [xmax ymin 0 ymax-ymin];
0049 
0050 
0051 % compute outcodes of each vertex
0052 p11 = edge(:,1) < xmin; p21 = edge(:,3) < xmin;
0053 p12 = edge(:,1) > xmax; p22 = edge(:,3) > xmax;
0054 p13 = edge(:,2) < ymin; p23 = edge(:,4) < ymin;
0055 p14 = edge(:,2) > ymax; p24 = edge(:,4) > ymax;
0056 out1 = [p11 p12 p13 p14];
0057 out2 = [p21 p22 p23 p24];
0058 
0059 % detect edges totally inside window -> no clip.
0060 inside = sum(out1 | out2, 2) == 0;
0061 
0062 % detect edges totally outside window
0063 outside = sum(out1 & out2, 2) > 0;
0064 
0065 % select edges not totally outside, and process separately edges totally
0066 % inside window
0067 ind = find(~(inside | outside));
0068 
0069 % allocate memroty for all clipped edges
0070 edge2 = zeros(size(edge));
0071 
0072 % copy result of edges totally inside clipping box
0073 edge2(inside, :) = edge(inside, :);
0074 
0075 % iterate over edges
0076 for i = 1:length(ind)
0077     % current edge
0078     iedge = edge(ind(i), :);
0079         
0080     % compute intersection points with each line of bounding window
0081     px0 = intersectLineEdge(lineX0, iedge);
0082     px1 = intersectLineEdge(lineX1, iedge);
0083     py0 = intersectLineEdge(lineY0, iedge);
0084     py1 = intersectLineEdge(lineY1, iedge);
0085          
0086     % create array of points
0087     points  = [px0; px1; py0; py1; iedge(1:2); iedge(3:4)];
0088     
0089     % remove infinite points (edges parallel to box edges)
0090     points  = points(all(isfinite(points), 2), :);
0091     
0092     % sort points by x then y
0093     points = sortrows(points);
0094     
0095     % get center positions between consecutive points
0096     centers = (points(2:end,:) + points(1:end-1,:))/2;
0097     
0098     % find the centers (if any) inside window
0099     inside = find(  centers(:,1) >= xmin & centers(:,2) >= ymin & ...
0100                     centers(:,1) <= xmax & centers(:,2) <= ymax);
0101 
0102     % if multiple segments are inside box, which can happen due to finite
0103     % resolution, only take the longest segment
0104     if length(inside) > 1
0105         % compute delta vectors of the segments
0106         dv = points(inside+1,:) - points(inside,:); 
0107         % compute lengths of segments
0108         len = hypot(dv(:,1), dv(:,2));
0109         % find index of longest segment
0110         [a, I] = max(len); %#ok<ASGLU>
0111         inside = inside(I);
0112     end
0113     
0114     % if one of the center points is inside box, then the according edge
0115     % segment is indide box
0116     if length(inside) == 1
0117          % restore same direction of edge
0118         if iedge(1) > iedge(3) || (iedge(1) == iedge(3) && iedge(2) > iedge(4))
0119             edge2(ind(i), :) = [points(inside+1,:) points(inside,:)];
0120         else
0121             edge2(ind(i), :) = [points(inside,:) points(inside+1,:)];
0122         end
0123     end
0124     
0125 end % end of loop over edges
0126

Generated on Wed 16-Feb-2022 15:10:47 by m2html © 2003-2019