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

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

modification of headers : mainly blanks around = sign for keywords in declaration of function and pro

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