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
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