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@inrae.fr
0022 % Created: 2005-05-14
0023 % Copyright 2005-2024 INRA - Cepia Software Platform
0024 
0025 % process data input
0026 if size(box, 1) == 2
0027     box = box';
0028 end
0029 
0030 % get limits of window
0031 xmin = box(1);
0032 xmax = box(2);
0033 ymin = box(3);
0034 ymax = box(4);
0035 
0036 
0037 % convert window limits into lines
0038 lineX0 = [xmin ymin xmax-xmin 0];
0039 lineX1 = [xmin ymax xmax-xmin 0];
0040 lineY0 = [xmin ymin 0 ymax-ymin];
0041 lineY1 = [xmax ymin 0 ymax-ymin];
0042 
0043 
0044 % compute outcodes of each vertex
0045 p11 = edge(:,1) < xmin; p21 = edge(:,3) < xmin;
0046 p12 = edge(:,1) > xmax; p22 = edge(:,3) > xmax;
0047 p13 = edge(:,2) < ymin; p23 = edge(:,4) < ymin;
0048 p14 = edge(:,2) > ymax; p24 = edge(:,4) > ymax;
0049 out1 = [p11 p12 p13 p14];
0050 out2 = [p21 p22 p23 p24];
0051 
0052 % detect edges totally inside window -> no clip.
0053 inside = sum(out1 | out2, 2) == 0;
0054 
0055 % detect edges totally outside window
0056 outside = sum(out1 & out2, 2) > 0;
0057 
0058 % select edges not totally outside, and process separately edges totally
0059 % inside window
0060 ind = find(~(inside | outside));
0061 
0062 % allocate memroty for all clipped edges
0063 edge2 = zeros(size(edge));
0064 
0065 % copy result of edges totally inside clipping box
0066 edge2(inside, :) = edge(inside, :);
0067 
0068 % iterate over edges
0069 for i = 1:length(ind)
0070     % current edge
0071     iedge = edge(ind(i), :);
0072         
0073     % compute intersection points with each line of bounding window
0074     px0 = intersectLineEdge(lineX0, iedge);
0075     px1 = intersectLineEdge(lineX1, iedge);
0076     py0 = intersectLineEdge(lineY0, iedge);
0077     py1 = intersectLineEdge(lineY1, iedge);
0078          
0079     % create array of points
0080     points  = [px0; px1; py0; py1; iedge(1:2); iedge(3:4)];
0081     
0082     % remove infinite points (edges parallel to box edges)
0083     points  = points(all(isfinite(points), 2), :);
0084     
0085     % sort points by x then y
0086     points = sortrows(points);
0087     
0088     % get center positions between consecutive points
0089     centers = (points(2:end,:) + points(1:end-1,:))/2;
0090     
0091     % find the centers (if any) inside window
0092     inside = find(  centers(:,1) >= xmin & centers(:,2) >= ymin & ...
0093                     centers(:,1) <= xmax & centers(:,2) <= ymax);
0094 
0095     % if multiple segments are inside box, which can happen due to finite
0096     % resolution, only take the longest segment
0097     if length(inside) > 1
0098         % compute delta vectors of the segments
0099         dv = points(inside+1,:) - points(inside,:); 
0100         % compute lengths of segments
0101         len = hypot(dv(:,1), dv(:,2));
0102         % find index of longest segment
0103         [a, I] = max(len); %#ok<ASGLU>
0104         inside = inside(I);
0105     end
0106     
0107     % if one of the center points is inside box, then the according edge
0108     % segment is indide box
0109     if isscalar(inside)
0110          % restore same direction of edge
0111         if iedge(1) > iedge(3) || (iedge(1) == iedge(3) && iedge(2) > iedge(4))
0112             edge2(ind(i), :) = [points(inside+1,:) points(inside,:)];
0113         else
0114             edge2(ind(i), :) = [points(inside,:) points(inside+1,:)];
0115         end
0116     end
0117     
0118 end % end of loop over edges
0119

Generated on Thu 21-Nov-2024 11:30:22 by m2html © 2003-2022