source: trunk/SRC/Interpolation/inquad.pro @ 118

Last change on this file since 118 was 118, checked in by pinsard, 18 years ago

add $ in Calendar, Grid, Interpolation, Obsolete and Postscript *.pro files, add svn:keywords Id to all these files, some improvements in header

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 9.9 KB
Line 
1;+
2; @file_comments to find if an (x,y) point is in a quadrilateral (x1,x2,x3,x4)
3;
4; @categories grid manipulation
5;
6; @examples
7; IDL> res = inquad(x, y, x1, y1, x2, y2, x3, y3, x4, y4)
8;
9; @param x {in}{required}
10; @param y {in}{required}
11;  the coordinates of the point we want to know where it is.
12;  Must be a scalar if /onsphere activated else can be scalar or array.
13;
14; @param x1 {in}{required}
15; @param y1 {in}{required}
16; @param x2 {in}{required}
17; @param y2 {in}{required}
18; @param x3 {in}{required}
19; @param y3 {in}{required}
20; @param x4 {in}{required}
21; @param y4 {in}{required}
22;  the coordinates of the quadrilateral given in the CLOCKWISE order.
23;  Scalar or array.
24;
25; @keyword /DOUBLE use double precision to perform the computation
26;
27; @keyword /ONSPHERE to specify that the quadilateral are on a sphere and
28;    that teir coordinates are longitude-latitude coordinates. In this
29;    case, est-west periodicity, poles singularity and other pbs
30;    related to longitude-latitude coordinates are managed
31;    automatically.
32;
33; @keyword ZOOMRADIUS the zoom (circle centred on the (x,y) with a radius of
34;    zoomradius degree where we look for the the quadrilateral which;    contains the (x,y) point) used for the satellite projection
35;    when /onsphere is activated. Default is 4 and seems to be the
36;    minimum which can be used. Can be increase if the cell size is
37;    larger than 5 degrees.
38;   
39; @keyword /NOPRINT to suppress the print messages.
40;
41; @keyword NEWCOORD
42;
43; @returns
44;    a n element vector. Where n is the number of elements of
45;    x. res[i]=j means that the point number i is located in the
46;    quadrilateral number j with (0 <= j <= n_elements(x0)-1)
47;
48; @restrictions I think degenerated quadrilateral (e.g. flat of
49; twisted) is not work. This has to be tested.
50;
51; @examples
52;
53; IDL> x = 1.*[1, 2, 6, 7, 3]
54; IDL> y = 1.*[1, 3, 3, 4, 7]
55; IDL> x1 = 1.*[0,4,2]
56; IDL> y1 = 1.*[1,4,8]
57; IDL> x2 = 1.*[1,6,4]
58; IDL> y2 = 1.*[5,6,8]
59; IDL> x3 = 1.*[3,8,4]
60; IDL> y3 = 1.*[4,4,6]
61; IDL> x4 = 1.*[2,6,2]
62; IDL> y4 = 1.*[0,2,6]
63; IDL> splot, [0,10], [0,10], xstyle = 1, ystyle = 1,/nodata
64; IDL> for i=0,2 do oplot, [x4[i],x1[i],x2[i],x3[i],x4[i]],[y4[i],y1[i],y2[i],y3[i],y4[i]]
65; IDL> oplot, x, y, color = 20, psym = 1, thick = 2
66; IDL> print, inquad(x, y, x1, y1, x2, y2, x3, y3, x4, y4)
67;
68;      On a sphere see clickincell.pro...
69;
70; @history
71;      Sebastien Masson (smasson\@lodyc.jussieu.fr)
72;      August 2003
73;      Based on Convert_clic_ij.pro written by Gurvan Madec
74;
75; @version $Id$
76;
77;-
78FUNCTION inquad, x, y, x1, y1, x2, y2, x3, y3, x4, y4, ONSPHERE = onsphere,  DOUBLE = double, ZOOMRADIUS = zoomradius, NOPRINT = noprint, NEWCOORD = newcoord
79;
80  compile_opt idl2, strictarrsubs
81;
82  ntofind = n_elements(x)
83  nquad = n_elements(x2)
84;
85  IF keyword_set(onsphere) THEN BEGIN
86; save the inputs parameters
87    xin = x
88    yin = y
89    x1in = x1
90    y1in = y1
91    x2in = x2
92    y2in = y2
93    x3in = x3
94    y3in = y3
95    x4in = x4
96    y4in = y4
97; for map_set
98    x = x MOD 360
99    x1 = x1 MOD 360
100    x2 = x2 MOD 360
101    x3 = x3 MOD 360
102    x4 = x4 MOD 360
103; save !map
104    save = {map:!map, x:!x, y:!y, z:!z, p:!p}
105; do a satellite projection
106    IF NOT keyword_set(zoomradius) THEN zoomradius = 4
107    map_set, y[0], x[0], 0, /satellite, sat_p = [1+zoomradius*20/6371.229, 0, 0], /noerase, /iso, /noborder
108; use normal coordinates to reject cells which are out of the projection.
109    tmp  = convert_coord(x, y, /DATA, /TO_NORMAL, DOUBLE = double)
110    tmp1 = convert_coord(x1, y1, /DATA, /TO_NORMAL, DOUBLE = double)
111    tmp2 = convert_coord(x2, y2, /DATA, /TO_NORMAL, DOUBLE = double)
112    tmp3 = convert_coord(x3, y3, /DATA, /TO_NORMAL, DOUBLE = double)
113    tmp4 = convert_coord(x4, y4, /DATA, /TO_NORMAL, DOUBLE = double)
114; remove cell which have one corner with coordinates equal to NaN
115    test = finite(tmp1[0, *]+tmp1[1, *]+tmp2[0, *]+tmp2[1, *] $
116                  +tmp3[0, *]+tmp3[1, *]+tmp4[0, *]+tmp4[1, *])
117    good = where(temporary(test) EQ 1)
118;
119    IF good[0] EQ -1 THEN BEGIN
120      IF NOT keyword_set(noprint) THEN print, 'The point is out of the cells'
121; restore the input parameters
122      x = temporary(xin)
123      y = temporary(yin)
124      x1 = temporary(x1in)
125      y1 = temporary(y1in)
126      x2 = temporary(x2in)
127      y2 = temporary(y2in)
128      x3 = temporary(x3in)
129      y3 = temporary(y3in)
130      x4 = temporary(x4in)
131      y4 = temporary(y4in)
132; restore old !map...
133      !map = save.map
134      !x = save.x
135      !y = save.y
136      !z = save.z
137      !p = save.p
138      RETURN,  -1
139    ENDIF
140;
141    x  = tmp[0]
142    y  = tmp[1]
143    x1 = tmp1[0, good]
144    y1 = tmp1[1, good]
145    x2 = tmp2[0, good]
146    y2 = tmp2[1, good]
147    x3 = tmp3[0, good]
148    y3 = tmp3[1, good]
149    x4 = tmp4[0, good]
150    y4 = tmp4[1, good]
151;
152    tmp1 = -1 & tmp2 = -1 & tmp3 = -1 & tmp4 = -1
153; remove cells which are obviously bad
154    test = (x1 GT x AND x2 GT x AND x3 GT x AND x4 GT x) $
155      OR (x1 LT x AND x2 LT x AND x3 LT x AND x4 LT x) $
156      OR (y1 GT y AND y2 GT y AND y3 GT y AND y4 GT y) $
157      OR (y1 LT y AND y2 LT y AND y3 LT y AND y4 LT y)
158    good2 = where(temporary(test) EQ 0)
159;
160    IF good2[0] EQ -1 THEN BEGIN
161      IF NOT keyword_set(noprint) THEN print, 'The point is out of the cells'
162; restore the input parameters
163      x = temporary(xin)
164      y = temporary(yin)
165      x1 = temporary(x1in)
166      y1 = temporary(y1in)
167      x2 = temporary(x2in)
168      y2 = temporary(y2in)
169      x3 = temporary(x3in)
170      y3 = temporary(y3in)
171      x4 = temporary(x4in)
172      y4 = temporary(y4in)
173; restore old !map...
174      !map = save.map
175      !x = save.x
176      !y = save.y
177      !z = save.z
178      !p = save.p
179      RETURN,  -1
180    ENDIF
181;
182    nquad = n_elements(good2)
183    x1 = x1[good2]
184    y1 = y1[good2]
185    x2 = x2[good2]
186    y2 = y2[good2]
187    x3 = x3[good2]
188    y3 = y3[good2]
189    x4 = x4[good2]
190    y4 = y4[good2]
191  ENDIF
192;
193;
194; the point is inside the quadilateral if test eq 1
195; with test equal to:
196;     test = ((x-x1)*(y2-y1) GE (x2-x1)*(y-y1)) $
197;       *((x-x2)*(y3-y2) GT (x3-x2)*(y-y2)) $
198;       *((x-x3)*(y4-y3) GT (x4-x3)*(y-y3)) $
199;       *((x-x4)*(y1-y4) GE (x1-x4)*(y-y4))
200;
201; computation of test without any do loop for ntofind points (x,y) and
202; nquad quadilateral((x1,x2,x3,x4),(y1,y2,y3,y4))
203; test dimensions are (ntofind, nquad)
204; column i of test corresponds to the intersection of point i with all
205; quadirlateral.
206; row j of test corresponds to all the points localized in cell j
207  test = $
208; (x-x1)
209  ((x[*]#replicate(1, nquad)-replicate(1, ntofind)#x1[*]) $
210; *(y2-y1)
211  *(replicate(1, ntofind)#(y2-y1)[*]) $
212; GE (x2-x1)
213  GE ((replicate(1, ntofind)#(x2-x1)[*]) $
214; *(y-y1)
215  *(y[*]#replicate(1, nquad)-replicate(1, ntofind)#y1[*])))
216;-------
217  test = temporary(test) $
218; *(x-x2)
219  *((x[*]#replicate(1, nquad)-replicate(1, ntofind)#x2[*]) $
220; *(y3-y2)
221  *(replicate(1, ntofind)#(y3-y2)[*]) $
222; GE (x3-x2)
223  GE ((replicate(1, ntofind)#(x3-x2)[*]) $
224; *(y-y2)
225  *(y[*]#replicate(1, nquad)-replicate(1, ntofind)#y2[*])))
226;-------
227  test = temporary(test) $
228; *(x-x3)
229  *((x[*]#replicate(1, nquad)-replicate(1, ntofind)#x3[*]) $
230; *(y4-y3)
231  *(replicate(1, ntofind)#(y4-y3)[*]) $
232; GE (x4-x3)
233  GE ((replicate(1, ntofind)#(x4-x3)[*]) $
234; *(y-y3)
235  *(y[*]#replicate(1, nquad)-replicate(1, ntofind)#y3[*])))
236;-------
237  test = temporary(test) $
238; *(x-x4)
239  *((x[*]#replicate(1, nquad)-replicate(1, ntofind)#x4[*]) $
240; *(y1-y4)
241  *(replicate(1, ntofind)#(y1-y4)[*]) $
242; GE (x1-x4)
243  GE ((replicate(1, ntofind)#(x1-x4)[*]) $
244; *(y-y4)
245  *(y[*]#replicate(1, nquad)-replicate(1, ntofind)#y4[*])))
246;
247; check test if ntofind gt 1
248; if ntofind gt 1, each point must be localised in one uniq cell.
249  IF ntofind GT 1 THEN BEGIN
250; each column of test must have only 1 position equal to one
251    chtest = total(test, 2)
252; points out of the cells
253    IF (where(chtest EQ 0))[0] NE -1 THEN BEGIN
254      IF NOT keyword_set(noprint) THEN print, 'Points number '+strjoin(strtrim(where(chtest EQ 0), 1), ', ')+' are out of the grid'
255      stop
256    ENDIF
257; points in more than one cell
258    IF (where(chtest GT 1))[0] NE -1 THEN BEGIN
259      IF NOT keyword_set(noprint) THEN print, 'Points number '+strjoin(strtrim(where(chtest GT 1), 1), ', ')+' are in more than one cell'
260      stop
261    ENDIF
262  ENDIF
263; find the points for which test eq 1
264  found = where(temporary(test) EQ 1)
265; if ntofind eq 1, the point may be localised in more than one grid
266; cell ou may also be out of the cells
267  IF ntofind EQ 1 THEN BEGIN
268    CASE 1 OF
269      found[0] EQ -1:BEGIN
270        IF NOT keyword_set(noprint) THEN print, 'The point is out of the cells'
271        IF keyword_set(onsphere) THEN BEGIN
272; restore old !map...
273          !map = save.map
274          !x = save.x
275          !y = save.y
276          !z = save.z
277          !p = save.p
278        ENDIF
279        return,  -1
280      END
281      n_elements(found) GT ntofind:BEGIN
282        IF NOT keyword_set(noprint) THEN print, 'The point is in more than one cell'
283      END
284      ELSE:
285    ENDCASE
286  ENDIF ELSE BEGIN
287; if ntofind GT 1, found must be sorted
288; i position of found. this corresponds to one x,y point
289    forsort = found MOD ntofind
290; j position of found. this corresponds to cell in which is one x,y
291; point
292    found = temporary(found)/ntofind
293; found must be sorted accordind to forsort
294    found = found[sort(forsort)]
295  ENDELSE
296;
297  IF keyword_set(onsphere) THEN BEGIN
298    IF arg_present(newcoord) THEN BEGIN
299      found = found[0]
300      newcoord = [[x1[found], y1[found]] $
301                  , [x2[found], y2[found]] $
302                  , [x3[found], y3[found]] $
303                  , [x4[found], y4[found]] $
304                  , [x, y]]
305    ENDIF
306;
307    found = good[good2[found]]
308; restore the input parameters
309    x = temporary(xin)
310    y = temporary(yin)
311    x1 = temporary(x1in)
312    y1 = temporary(y1in)
313    x2 = temporary(x2in)
314    y2 = temporary(y2in)
315    x3 = temporary(x3in)
316    y3 = temporary(y3in)
317    x4 = temporary(x4in)
318    y4 = temporary(y4in)
319; restore old !map...
320    !map = save.map
321    !x = save.x
322    !y = save.y
323    !z = save.z
324    !p = save.p
325  ENDIF
326;;
327  RETURN, found
328END
Note: See TracBrowser for help on using the repository browser.