aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/ncarutil/conlib/contng.f
blob: 7ebad596f691c223ff4e0f25effa1cf2d59e9cf5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
SUBROUTINE CONTNG (NDP,XD,YD,NT,IPT,NL,IPL,IWL,IWP,WK)
C                                                                               
C +-----------------------------------------------------------------+           
C |                                                                 |           
C |                Copyright (C) 1986 by UCAR                       |           
C |        University Corporation for Atmospheric Research          |           
C |                    All Rights Reserved                          |           
C |                                                                 |           
C |                 NCARGRAPHICS  Version 1.00                      |           
C |                                                                 |           
C +-----------------------------------------------------------------+           
C                                                                               
C                                                                               
C
C THIS SUBROUTINE PERFORMS TRIANGULATION.  IT DIVIDES THE X-Y
C PLANE INTO A NUMBER OF TRIANGLES ACCORDING TO GIVEN DATA
C POINTS IN THE PLANE, DETERMINES LINE SEGMENTS THAT FORM THE
C BORDER OF DATA AREA, AND DETERMINES THE TRIANGLE NUMBERS
C CORRESPONDING TO THE BORDER LINE SEGMENTS.
C AT COMPLETION, POINT NUMBERS OF THE VERTEXES OF EACH TRIANGLE
C ARE LISTED COUNTER-CLOCKWISE.  POINT NUMBERS OF THE END POINTS
C OF EACH BORDER LINE SEGMENT ARE LISTED COUNTER-CLOCKWISE,
C LISTING ORDER OF THE LINE SEGMENTS BEING COUNTER-CLOCKWISE.
C THE INPUT PARAMETERS ARE
C     NDP = NUMBER OF DATA POINTS,
C     XD  = ARRAY OF DIMENSION NDP CONTAINING THE
C           X COORDINATES OF THE DATA POINTS,
C     YD  = ARRAY OF DIMENSION NDP CONTAINING THE
C           Y COORDINATES OF THE DATA POINTS.
C THE OUTPUT PARAMETERS ARE
C     NT  = NUMBER OF TRIANGLES,
C     IPT = ARRAY OF DIMENSION 6*NDP-15, WHERE THE POINT
C           NUMBERS OF THE VERTEXES OF THE (IT)TH TRIANGLE
C           ARE TO BE STORED AS THE (3*IT-2)ND, (3*IT-1)ST,
C           AND (3*IT)TH ELEMENTS, IT=1,2,...,NT,
C     NL  = NUMBER OF BORDER LINE SEGMENTS,
C     IPL = ARRAY OF DIMENSION 6*NDP, WHERE THE POINT
C           NUMBERS OF THE END POINTS OF THE (IL)TH BORDER
C           LINE SEGMENT AND ITS RESPECTIVE TRIANGLE NUMBER
C           ARE TO BE STORED AS THE (3*IL-2)ND, (3*IL-1)ST,
C           AND (3*IL)TH ELEMENTS, IL=1,2,..., NL.
C THE OTHER PARAMETERS ARE
C     IWL = INTEGER ARRAY OF DIMENSION 18*NDP USED
C           INTERNALLY AS A WORK AREA,
C     IWP = INTEGER ARRAY OF DIMENSION NDP USED
C           INTERNALLY AS A WORK AREA,
C     WK  = ARRAY OF DIMENSION NDP USED INTERNALLY AS A
C           WORK AREA.
C DECLARATION STATEMENTS
C
      SAVE
C
      INTEGER         CONXCH
      COMMON /CONRA3/ IREC
      DIMENSION       XD(*)      ,YD(*)      ,IPT(*)     ,IPL(*)     ,
     1                IWL(*)     ,IWP(*)     ,WK(*)
      DIMENSION       ITF(2)
        CHARACTER*4  IP1C, IP2C
        CHARACTER*64  ITEMP
      DATA  RATIO/1.0E-6/, NREP/100/
C
C STATEMENT FUNCTIONS
C
      DSQF(U1,V1,U2,V2) = (U2-U1)**2+(V2-V1)**2
      SIDE(U1,V1,U2,V2,U3,V3) = (V3-V1)*(U2-U1)-(U3-U1)*(V2-V1)
C
C PRELIMINARY PROCESSING
C
      NDPM1 = NDP-1
C
C DETERMINES THE CLOSEST PAIR OF DATA POINTS AND THEIR MIDPOINT.
C
      DSQMN = DSQF(XD(1),YD(1),XD(2),YD(2))
      IPMN1 = 1
      IPMN2 = 2
      DO  140 IP1=1,NDPM1
         X1 = XD(IP1)
         Y1 = YD(IP1)
         IP1P1 = IP1+1
         DO  130 IP2=IP1P1,NDP
            DSQI = DSQF(X1,Y1,XD(IP2),YD(IP2))
            IF (DSQI .NE. 0.) GO TO  120
C
C  ERROR, IDENTICAL INPUT DATA POINTS
C
          ITEMP = ' CONTNG-IDENTICAL INPUT DATA POINTS FOUND
     1 AT      AND      '
C 
C + NOAO - FTN internal writes rewritten as calls to encode for IRAF
C
C         WRITE(IP1C,'(I4)')IP1
C         WRITE(IP2C,'(I4)')IP2
          call encode (4, '(I4)', ip1c, ip1)
	  call encode (4, '(I4)', ip2c, ip2)
C - NOAO
C
            CALL SETER (ITEMP,1,1)
            ITEMP(46:49) = IP1C
            ITEMP(55:58) = IP2C
            RETURN
  120       IF (DSQI .GE. DSQMN) GO TO  130
            DSQMN = DSQI
            IPMN1 = IP1
            IPMN2 = IP2
  130    CONTINUE
  140 CONTINUE
      DSQ12 = DSQMN
      XDMP = (XD(IPMN1)+XD(IPMN2))/2.0
      YDMP = (YD(IPMN1)+YD(IPMN2))/2.0
C
C SORTS THE OTHER (NDP-2) DATA POINTS IN ASCENDING ORDER OF
C DISTANCE FROM THE MIDPOINT AND STORES THE SORTED DATA POINT
C NUMBERS IN THE IWP ARRAY.
C
      JP1 = 2
      DO  150 IP1=1,NDP
         IF (IP1.EQ.IPMN1 .OR. IP1.EQ.IPMN2) GO TO  150
         JP1 = JP1+1
         IWP(JP1) = IP1
         WK(JP1) = DSQF(XDMP,YDMP,XD(IP1),YD(IP1))
  150 CONTINUE
      DO  170 JP1=3,NDPM1
         DSQMN = WK(JP1)
         JPMN = JP1
         DO  160 JP2=JP1,NDP
            IF (WK(JP2) .GE. DSQMN) GO TO  160
            DSQMN = WK(JP2)
            JPMN = JP2
  160    CONTINUE
         ITS = IWP(JP1)
         IWP(JP1) = IWP(JPMN)
         IWP(JPMN) = ITS
         WK(JPMN) = WK(JP1)
  170 CONTINUE
C
C IF NECESSARY, MODIFIES THE ORDERING IN SUCH A WAY THAT THE
C FIRST THREE DATA POINTS ARE NOT COLLINEAR.
C
      AR = DSQ12*RATIO
      X1 = XD(IPMN1)
      Y1 = YD(IPMN1)
      DX21 = XD(IPMN2)-X1
      DY21 = YD(IPMN2)-Y1
      DO  180 JP=3,NDP
         IP = IWP(JP)
         IF (ABS((YD(IP)-Y1)*DX21-(XD(IP)-X1)*DY21) .GT. AR) GO TO  190
  180 CONTINUE
      CALL SETER (' CONTNG - ALL COLLINEAR DATA POINTS',1,1)
  190 IF (JP .EQ. 3) GO TO  210
      JPMX = JP
      JP = JPMX+1
      DO  200 JPC=4,JPMX
         JP = JP-1
         IWP(JP) = IWP(JP-1)
  200 CONTINUE
      IWP(3) = IP
C
C FORMS THE FIRST TRIANGLE.  STORES POINT NUMBERS OF THE VER-
C TEXES OF THE TRIANGLE IN THE IPT ARRAY, AND STORES POINT NUM-
C BERS OF THE BORDER LINE SEGMENTS AND THE TRIANGLE NUMBER IN
C THE IPL ARRAY.
C
  210 IP1 = IPMN1
      IP2 = IPMN2
      IP3 = IWP(3)
      IF (SIDE(XD(IP1),YD(IP1),XD(IP2),YD(IP2),XD(IP3),YD(IP3)) .GE.
     1    0.0) GO TO  220
      IP1 = IPMN2
      IP2 = IPMN1
  220 NT0 = 1
      NTT3 = 3
      IPT(1) = IP1
      IPT(2) = IP2
      IPT(3) = IP3
      NL0 = 3
      NLT3 = 9
      IPL(1) = IP1
      IPL(2) = IP2
      IPL(3) = 1
      IPL(4) = IP2
      IPL(5) = IP3
      IPL(6) = 1
      IPL(7) = IP3
      IPL(8) = IP1
      IPL(9) = 1
C
C ADDS THE REMAINING (NDP-3) DATA POINTS, ONE BY ONE.
C
      DO  400 JP1=4,NDP
         IP1 = IWP(JP1)
         X1 = XD(IP1)
         Y1 = YD(IP1)
C
C - DETERMINES THE VISIBLE BORDER LINE SEGMENTS.
C
         IP2 = IPL(1)
         JPMN = 1
         DXMN = XD(IP2)-X1
         DYMN = YD(IP2)-Y1
         DSQMN = DXMN**2+DYMN**2
         ARMN = DSQMN*RATIO
         JPMX = 1
         DXMX = DXMN
         DYMX = DYMN
         DSQMX = DSQMN
         ARMX = ARMN
         DO  240 JP2=2,NL0
            IP2 = IPL(3*JP2-2)
            DX = XD(IP2)-X1
            DY = YD(IP2)-Y1
            AR = DY*DXMN-DX*DYMN
            IF (AR .GT. ARMN) GO TO  230
            DSQI = DX**2+DY**2
            IF (AR.GE.(-ARMN) .AND. DSQI.GE.DSQMN) GO TO  230
            JPMN = JP2
            DXMN = DX
            DYMN = DY
            DSQMN = DSQI
            ARMN = DSQMN*RATIO
  230       AR = DY*DXMX-DX*DYMX
            IF (AR .LT. (-ARMX)) GO TO  240
            DSQI = DX**2+DY**2
            IF (AR.LE.ARMX .AND. DSQI.GE.DSQMX) GO TO  240
            JPMX = JP2
            DXMX = DX
            DYMX = DY
            DSQMX = DSQI
            ARMX = DSQMX*RATIO
  240    CONTINUE
         IF (JPMX .LT. JPMN) JPMX = JPMX+NL0
         NSH = JPMN-1
         IF (NSH .LE. 0) GO TO  270
C
C - SHIFTS (ROTATES) THE IPL ARRAY TO HAVE THE INVISIBLE BORDER
C - LINE SEGMENTS CONTAINED IN THE FIRST PART OF THE IPL ARRAY.
C
         NSHT3 = NSH*3
         DO  250 JP2T3=3,NSHT3,3
            JP3T3 = JP2T3+NLT3
            IPL(JP3T3-2) = IPL(JP2T3-2)
            IPL(JP3T3-1) = IPL(JP2T3-1)
            IPL(JP3T3) = IPL(JP2T3)
  250    CONTINUE
         DO  260 JP2T3=3,NLT3,3
            JP3T3 = JP2T3+NSHT3
            IPL(JP2T3-2) = IPL(JP3T3-2)
            IPL(JP2T3-1) = IPL(JP3T3-1)
            IPL(JP2T3) = IPL(JP3T3)
  260    CONTINUE
         JPMX = JPMX-NSH
C
C - ADDS TRIANGLES TO THE IPT ARRAY, UPDATES BORDER LINE
C - SEGMENTS IN THE IPL ARRAY, AND SETS FLAGS FOR THE BORDER
C - LINE SEGMENTS TO BE REEXAMINED IN THE IWL ARRAY.
C
  270    JWL = 0
         DO  310 JP2=JPMX,NL0
            JP2T3 = JP2*3
            IPL1 = IPL(JP2T3-2)
            IPL2 = IPL(JP2T3-1)
            IT = IPL(JP2T3)
C
C - - ADDS A TRIANGLE TO THE IPT ARRAY.
C
            NT0 = NT0+1
            NTT3 = NTT3+3
            IPT(NTT3-2) = IPL2
            IPT(NTT3-1) = IPL1
            IPT(NTT3) = IP1
C
C - - UPDATES BORDER LINE SEGMENTS IN THE IPL ARRAY.
C
            IF (JP2 .NE. JPMX) GO TO  280
            IPL(JP2T3-1) = IP1
            IPL(JP2T3) = NT0
  280       IF (JP2 .NE. NL0) GO TO  290
            NLN = JPMX+1
            NLNT3 = NLN*3
            IPL(NLNT3-2) = IP1
            IPL(NLNT3-1) = IPL(1)
            IPL(NLNT3) = NT0
C
C - - DETERMINES THE VERTEX THAT DOES NOT LIE ON THE BORDER
C - - LINE SEGMENTS.
C
  290       ITT3 = IT*3
            IPTI = IPT(ITT3-2)
            IF (IPTI.NE.IPL1 .AND. IPTI.NE.IPL2) GO TO  300
            IPTI = IPT(ITT3-1)
            IF (IPTI.NE.IPL1 .AND. IPTI.NE.IPL2) GO TO  300
            IPTI = IPT(ITT3)
C
C - - CHECKS IF THE EXCHANGE IS NECESSARY.
C
  300       IF (CONXCH(XD,YD,IP1,IPTI,IPL1,IPL2) .EQ. 0) GO TO  310
C
C - - MODIFIES THE IPT ARRAY WHEN NECESSARY.
C
            IPT(ITT3-2) = IPTI
            IPT(ITT3-1) = IPL1
            IPT(ITT3) = IP1
            IPT(NTT3-1) = IPTI
            IF (JP2 .EQ. JPMX) IPL(JP2T3) = IT
            IF (JP2.EQ.NL0 .AND. IPL(3).EQ.IT) IPL(3) = NT0
C
C - - SETS FLAGS IN THE IWL ARRAY.
C
            JWL = JWL+4
            IWL(JWL-3) = IPL1
            IWL(JWL-2) = IPTI
            IWL(JWL-1) = IPTI
            IWL(JWL) = IPL2
  310    CONTINUE
         NL0 = NLN
         NLT3 = NLNT3
         NLF = JWL/2
         IF (NLF .EQ. 0) GO TO  400
C
C - IMPROVES TRIANGULATION.
C
         NTT3P3 = NTT3+3
         DO  390 IREP=1,NREP
            DO  370 ILF=1,NLF
               ILFT2 = ILF*2
               IPL1 = IWL(ILFT2-1)
               IPL2 = IWL(ILFT2)
C
C - - LOCATES IN THE IPT ARRAY TWO TRIANGLES ON BOTH SIDES OF
C - - THE FLAGGED LINE SEGMENT.
C
               NTF = 0
               DO  320 ITT3R=3,NTT3,3
                  ITT3 = NTT3P3-ITT3R
                  IPT1 = IPT(ITT3-2)
                  IPT2 = IPT(ITT3-1)
                  IPT3 = IPT(ITT3)
                  IF (IPL1.NE.IPT1 .AND. IPL1.NE.IPT2 .AND.
     1                IPL1.NE.IPT3) GO TO  320
                  IF (IPL2.NE.IPT1 .AND. IPL2.NE.IPT2 .AND.
     1                IPL2.NE.IPT3) GO TO  320
                  NTF = NTF+1
                  ITF(NTF) = ITT3/3
                  IF (NTF .EQ. 2) GO TO  330
  320          CONTINUE
               IF (NTF .LT. 2) GO TO  370
C
C - - DETERMINES THE VERTEXES OF THE TRIANGLES THAT DO NOT LIE
C - - ON THE LINE SEGMENT.
C
  330          IT1T3 = ITF(1)*3
               IPTI1 = IPT(IT1T3-2)
               IF (IPTI1.NE.IPL1 .AND. IPTI1.NE.IPL2) GO TO  340
               IPTI1 = IPT(IT1T3-1)
               IF (IPTI1.NE.IPL1 .AND. IPTI1.NE.IPL2) GO TO  340
               IPTI1 = IPT(IT1T3)
  340          IT2T3 = ITF(2)*3
               IPTI2 = IPT(IT2T3-2)
               IF (IPTI2.NE.IPL1 .AND. IPTI2.NE.IPL2) GO TO  350
               IPTI2 = IPT(IT2T3-1)
               IF (IPTI2.NE.IPL1 .AND. IPTI2.NE.IPL2) GO TO  350
               IPTI2 = IPT(IT2T3)
C
C - - CHECKS IF THE EXCHANGE IS NECESSARY.
C
  350          IF (CONXCH(XD,YD,IPTI1,IPTI2,IPL1,IPL2) .EQ. 0)
     1             GO TO  370
C
C - - MODIFIES THE IPT ARRAY WHEN NECESSARY.
C
               IPT(IT1T3-2) = IPTI1
               IPT(IT1T3-1) = IPTI2
               IPT(IT1T3) = IPL1
               IPT(IT2T3-2) = IPTI2
               IPT(IT2T3-1) = IPTI1
               IPT(IT2T3) = IPL2
C
C - - SETS NEW FLAGS.
C
               JWL = JWL+8
               IWL(JWL-7) = IPL1
               IWL(JWL-6) = IPTI1
               IWL(JWL-5) = IPTI1
               IWL(JWL-4) = IPL2
               IWL(JWL-3) = IPL2
               IWL(JWL-2) = IPTI2
               IWL(JWL-1) = IPTI2
               IWL(JWL) = IPL1
               DO  360 JLT3=3,NLT3,3
                  IPLJ1 = IPL(JLT3-2)
                  IPLJ2 = IPL(JLT3-1)
                  IF ((IPLJ1.EQ.IPL1 .AND. IPLJ2.EQ.IPTI2) .OR.
     1                (IPLJ2.EQ.IPL1 .AND. IPLJ1.EQ.IPTI2))
     2                IPL(JLT3) = ITF(1)
                  IF ((IPLJ1.EQ.IPL2 .AND. IPLJ2.EQ.IPTI1) .OR.
     1                (IPLJ2.EQ.IPL2 .AND. IPLJ1.EQ.IPTI1))
     2                IPL(JLT3) = ITF(2)
  360          CONTINUE
  370       CONTINUE
            NLFC = NLF
            NLF = JWL/2
            IF (NLF .EQ. NLFC) GO TO  400
C
C - - RESETS THE IWL ARRAY FOR THE NEXT ROUND.
C
            JWL = 0
            JWL1MN = (NLFC+1)*2
            NLFT2 = NLF*2
            DO  380 JWL1=JWL1MN,NLFT2,2
               JWL = JWL+2
               IWL(JWL-1) = IWL(JWL1-1)
               IWL(JWL) = IWL(JWL1)
  380       CONTINUE
            NLF = JWL/2
  390    CONTINUE
  400 CONTINUE
C
C REARRANGE THE IPT ARRAY SO THAT THE VERTEXES OF EACH TRIANGLE
C ARE LISTED COUNTER-CLOCKWISE.
C
      DO  410 ITT3=3,NTT3,3
         IP1 = IPT(ITT3-2)
         IP2 = IPT(ITT3-1)
         IP3 = IPT(ITT3)
         IF (SIDE(XD(IP1),YD(IP1),XD(IP2),YD(IP2),XD(IP3),YD(IP3)) .GE.
     1       0.0) GO TO  410
         IPT(ITT3-2) = IP2
         IPT(ITT3-1) = IP1
  410 CONTINUE
      NT = NT0
      NL = NL0
      RETURN
      END