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

Last change on this file since 295 was 242, checked in by pinsard, 17 years ago

improvements/corrections of some *.pro headers + replace some message by some report

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