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

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

some improvements and corrections in some .pro file according to
aspell and idldoc log file

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