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

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

upgrade of Interpolation according to cerbere.lodyc.jussieu.fr: /usr/home/smasson/SAXO_RD/

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