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

Last change on this file since 163 was 163, checked in by navarro, 18 years ago

header improvements : type of parameters and keywords, default values, spell checking + idldoc assistant (IDL online_help)

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