Changeset 2262 in lmdz_wrf


Ignore:
Timestamp:
Dec 19, 2018, 8:13:23 PM (6 years ago)
Author:
lfita
Message:

Adding polygon-vertex functionalities

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/module_scientific.f90

    r2235 r2262  
    1414!   to a map of integer polygons filtrered by a minimal area
    1515! clean_polygons: Subroutine to clean polygons from non-used paths, polygons only left as path since they are inner path of a hole
     16! distanceRK: Function to provide the distance between two points
    1617! FindMinimumR_K*: Function returns the location of the minimum in the section between Start and End.
    1718! fill3DI_2Dvec: Subroutine to fill a 3D integer matrix from a series of indices from a 2D matrix
     
    1920! gridpoints_InsidePolygon: Subroutine to determine if a series of grid points are inside a polygon
    2021!   following ray casting algorithm
     22! Heron_area_triangle: Subroutine to compute area of a triangle using Heron's formula
     23! intersectfaces: Subroutine to provide if two faces of two polygons intersect
     24! intersection_2Dlines: Subroutine to provide the intersection point between two lines on the plane using Cramer's method
     25! join_polygon: Subroutine to join two polygons
    2126! look_clockwise_borders: Subroutine to look clock-wise for a next point within a collection of borders
    2227!   (limits of a region)
     
    2530! path_properties: Subroutine to determine the properties of a path
    2631! percentiles_R_K*D: Subroutine to compute the percentiles of a *D R_K array along given set of axis
     32! point_inside: Function to determine if a given point is inside a polygon providing its sorted vertices
     33! poly_has_point: Function to determine if a polygon has already a given point as one of its vertex
    2734! polygon_properties: Subroutine to determine the properties of a polygon (as .TRUE. matrix)
    2835! polygons: Subroutine to search the polygons of a border field. FORTRAN based. 1st = 1!
    2936! polygons_t: Subroutine to search the polygons of a temporal series of boolean fields. FORTRAN based. 1st = 1!
    3037! poly_overlap_tracks: Subroutine to determine tracks of a series of consecutive 2D field with polygons using
    31 !   maximum overlaping/coincidence! PrintQuantilesR_K: Subroutine to print the quantiles of values REAL(r_k)
     38!   maximum overlaping/coincidence
     39! PrintQuantilesR_K: Subroutine to print the quantiles of values REAL(r_k)
    3240! poly_overlap_tracks_area: Subroutine to determine tracks of a series of consecutive 2D field with polygons using
    3341!   maximum overlaping/coincidence filtrered by a minimal area
     
    4351!   and y coordinates
    4452! runmean_F1D: Subroutine fo computing the running mean of a given set of float 1D values
     53! shoelace_area_polygon: Computing the area of a polygon using sholace formula
     54! sort_polygon: Subroutine to sort a polygon using its center as average of the coordinates
    4555! SortR_K*: Subroutine receives an array x() r_K and sorts it into ascending order.
    4656! StatsR_K: Subroutine to provide the minmum, maximum, mean, the quadratic mean, and the standard deviation of a
     
    34743484! Subroutine swaps the values of its two formal arguments.
    34753485
    3476       IMPLICIT  NONE
     3486      IMPLICIT NONE
    34773487
    34783488      REAL(r_k), INTENT(INOUT)                           :: a, b
     
    40444054  END SUBROUTINE percentiles_R_K4D
    40454055
     4056  REAL(r_k) FUNCTION distanceRK(pointA, pointB)
     4057  ! Function to provide the distance between two points
     4058
     4059    IMPLICIT NONE
     4060
     4061    REAL(r_k), DIMENSION(2), INTENT(in)                  :: pointA, pointB
     4062
     4063!!!!!!! Variables
     4064! pointA, B: couple of points to compute the distance between them
     4065
     4066    fname = 'distanceRK'
     4067
     4068    distanceRK = SQRT( (pointB(1)-pointA(1))**2 + (pointB(2)-pointA(2))**2 )
     4069
     4070  END FUNCTION distanceRK
     4071
     4072  REAL(r_k) FUNCTION shoelace_area_polygon(Nvertex, poly)
     4073  ! Computing the area of a polygon using sholace formula
     4074  ! FROM: https://en.wikipedia.org/wiki/Shoelace_formula
     4075
     4076    IMPLICIT NONE
     4077
     4078      INTEGER, INTENT(in)                                :: Nvertex
     4079      REAL(r_k), DIMENSION(Nvertex,2), INTENT(in)        :: poly
     4080
     4081! Local
     4082      INTEGER                                            :: i
     4083      REAL(r_k)                                          :: areapos, areaneg
     4084
     4085!!!!!!! Variables
     4086! Nvertex: number of vertices of the polygon
     4087! poly: coordinates of the vertex of the polygon (sorted)
     4088
     4089    fname = 'shoelace_area_polygon'
     4090
     4091    areapos = 0.
     4092    areaneg = 0.
     4093
     4094    DO i=1, Nvertex-1
     4095      areapos = areapos + poly(i,1)*poly(i+1,2)
     4096      areaneg = areaneg + poly(i+1,1)*poly(i,2)
     4097    END DO
     4098
     4099    areapos = areapos + poly(Nvertex,1)*poly(1,2)
     4100    areaneg = areaneg + poly(1,1)*poly(Nvertex,2)
     4101
     4102    shoelace_area_polygon = 0.5*(areapos - areaneg)
     4103
     4104  END FUNCTION shoelace_area_polygon
     4105
     4106  SUBROUTINE intersection_2Dlines(lineA, lineB, intersect, ptintersect)
     4107  ! Subroutine to provide the intersection point between two lines on the plane using Cramer's method
     4108
     4109    IMPLICIT NONE
     4110
     4111    REAL(r_k), DIMENSION(2,2), INTENT(in)                  :: lineA, lineB
     4112    LOGICAL, INTENT(out)                                   :: intersect
     4113    REAL(r_k), DIMENSION(2), INTENT(out)                   :: ptintersect
     4114
     4115! Local
     4116    REAL(r_k), DIMENSION(2)                                :: segmentA, segmentB
     4117    REAL(r_k)                                              :: a11, a12, a21, a22, z1, z2
     4118    REAL(r_k)                                              :: det, detX, detY
     4119    LOGICAL                                                :: axisAx, axisBx, axisAy, axisBy
     4120
     4121!!!!!!! Variables
     4122! lineA: couple of coordinates for the line A
     4123! lineB: couple of coordinates for the line B
     4124! intersect: whether two lines intersect
     4125! ptintersect: point of intersection [(0,0) if they do not intersect]
     4126
     4127    fname = 'intersection_2Dlines'
     4128
     4129    axisAx = .FALSE.
     4130    axisAy = .FALSE.
     4131    axisBx = .FALSE.
     4132    axisBy = .FALSE.
     4133    ! Setting segment parameters y = A + B*x
     4134    IF (lineA(2,1) /= lineA(1,1)) THEN
     4135      segmentA(2) = (lineA(2,2)-lineA(1,2))/(lineA(2,1)-lineA(1,1))
     4136      IF ( (lineA(1,1)*segmentA(2) - lineA(1,2)) /= (lineA(2,1)*segmentA(2) - lineA(2,2)) ) THEN
     4137        PRINT *,'A = y1 - x2*B = ', lineA(1,2) - lineA(1,1)*segmentA(2)
     4138        PRINT *,'A = y2 - x2*B = ', lineA(2,2) - lineA(2,1)*segmentA(2)
     4139        msg = 'Wrong calculation of parameter A, for lineA'
     4140        CALL ErrMSg(msg, fname, -1)
     4141      END IF
     4142      segmentA(1) = lineA(1,2) - lineA(1,1)*segmentA(2)
     4143      a11 = segmentA(2)
     4144      a12 = -oneRK
     4145      z1 = -segmentA(1)
     4146      IF (lineA(2,2) == lineA(1,2)) axisAx = .TRUE.
     4147    ELSE
     4148      ! lineA || y-axis
     4149      axisAy = .TRUE.
     4150    END IF
     4151
     4152    IF (lineB(2,1) /= lineB(1,1)) THEN
     4153      segmentB(2) = (lineB(2,2)-lineB(1,2))/(lineB(2,1)-lineB(1,1))
     4154      IF ( (lineB(1,1)*segmentB(2) - lineB(1,2)) /= (lineB(2,1)*segmentB(2) - lineB(2,2)) ) THEN
     4155        PRINT *,'A = x1*B -y1 = ', lineB(1,1)*segmentB(2) - lineB(1,2)
     4156        PRINT *,'A = x2*B -y2 = ', lineB(2,1)*segmentB(2) - lineB(2,2)
     4157        msg = 'Wrong calculation of parameter A, for lineB'
     4158        CALL ErrMSg(msg, fname, -1)
     4159      END IF
     4160      segmentB(1) = lineB(1,2) - lineB(1,1)*segmentB(2)
     4161      a21 = segmentB(2)
     4162      a22 = -oneRK
     4163      z2 = -segmentB(1)
     4164      IF (lineB(2,2) == lineB(1,2)) axisBx = .TRUE.
     4165    ELSE
     4166      ! lineB || y-axis
     4167      axisBy = .TRUE.
     4168    END IF
     4169    ! Cramer's method
     4170    ! a11 = B1; a12 = -1
     4171    ! a21 = B2; a22 = -1
     4172    ! z1 = -A1
     4173    ! z2 = -A2
     4174    ! (a11 a12)(x) (z1)
     4175    ! (a21 a22)(y) (z2)
     4176    ! -------- ------ ----- ---- --- -- -
     4177    ! det = (a11*a22-a12*a21)
     4178    ! detX = (z1*a22-z2*a21)
     4179    ! detY = (a11*z1-a12*z2)
     4180    ! ptintercept = (detX/det, detY/det)
     4181
     4182    ! Cases when some of the lines are parallel to any given axis
     4183!    PRINT *,'          axisAx', axisAx, 'axisAy', axisAy, 'axisBx', axisBx, 'axisBy', axisBy
     4184    IF (axisAx .OR. axisAy .OR. axisBx .OR. axisBy) THEN
     4185      IF (axisAx) THEN
     4186        IF (axisBy) THEN
     4187          intersect = .TRUE.
     4188          ptintersect(1) = lineB(1,1)
     4189          ptintersect(2) = lineA(1,2)
     4190        ELSE
     4191          intersect = .TRUE.
     4192          ptintersect(1) = (lineA(1,2)-segmentB(1))/segmentB(2)
     4193          ptintersect(2) = lineA(1,2)
     4194        END IF
     4195      END IF
     4196      IF (axisAy) THEN
     4197        IF (axisBy) THEN
     4198          intersect = .TRUE.
     4199          ptintersect(1) = lineA(1,1)
     4200          ptintersect(2) = lineB(1,2)
     4201        ELSE
     4202          intersect = .TRUE.
     4203          ptintersect(1) = lineA(1,1)
     4204          ptintersect(2) = segmentB(1) + lineA(1,1)*segmentB(2)
     4205        END IF
     4206      END IF
     4207      IF (axisBx) THEN
     4208        IF (axisAy) THEN
     4209          intersect = .TRUE.
     4210          ptintersect(1) = lineA(1,1)
     4211          ptintersect(2) = lineB(1,2)
     4212        ELSE
     4213          intersect = .TRUE.
     4214          ptintersect(1) = (lineB(1,2)-segmentA(1))/segmentA(2)
     4215          ptintersect(2) = lineB(1,2)
     4216        END IF
     4217      END IF
     4218      IF (axisBy) THEN
     4219        IF (axisAx) THEN
     4220          intersect = .TRUE.
     4221          ptintersect(1) = lineB(1,1)
     4222          ptintersect(2) = lineA(1,2)
     4223        ELSE
     4224          intersect = .TRUE.
     4225          ptintersect(1) = lineB(1,1)
     4226          ptintersect(2) = segmentA(1) + lineB(1,1)*segmentA(2)
     4227        END IF
     4228      END IF
     4229    ELSE
     4230      det = (a11*a22-a12*a21)
     4231      ! Parallel lines !
     4232      IF (det == zeroRK) THEN
     4233        intersect = .FALSE.
     4234        ptintersect = zeroRK
     4235      ELSE
     4236        intersect = .TRUE.
     4237        detX = (z1*a22-z2*a12)
     4238        detY = (a11*z2-a21*z1)
     4239
     4240        ptintersect(1) = detX/det
     4241        ptintersect(2) = detY/det
     4242      END IF
     4243    END IF
     4244
     4245  END SUBROUTINE intersection_2Dlines
     4246
     4247!refs:
     4248!https://www.mathopenref.com/heronsformula.html
     4249!https://math.stackexchange.com/questions/1406340/intersect-area-of-two-polygons-in-cartesian-plan
     4250!http://www.cap-lore.com/MathPhys/IP/
     4251!http://www.cap-lore.com/MathPhys/IP/IL.html
     4252!https://www.element84.com/blog/determining-the-winding-of-a-polygon-given-as-a-set-of-ordered-points
     4253!https://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order
     4254!https://en.wikipedia.org/wiki/Shoelace_formula
     4255!https://en.wikipedia.org/wiki/Winding_number
     4256!https://en.wikipedia.org/wiki/Simple_polygon
     4257!https://en.wikipedia.org/wiki/Polygon#Properties
     4258!https://en.wikipedia.org/wiki/Convex_polygon
     4259!https://en.wikipedia.org/wiki/Jordan_curve_theorem
     4260!https://www.sangakoo.com/ca/temes/metode-de-cramer
     4261!https://www.geogebra.org/m/pw4QHFYT
     4262
     4263  SUBROUTINE intersectfaces(faceA, faceB, intersect, intersectpt)
     4264  ! Subroutine to provide if two faces of two polygons intersect
     4265  ! AFTER: http://www.cap-lore.com/MathPhys/IP/IL.html
     4266  !   A: faceA(1,:)
     4267  !   B: faceA(2,:)
     4268  !   C: faceB(1,:)
     4269  !   D: faceB(2,:)
     4270
     4271    IMPLICIT NONE
     4272
     4273    REAL(r_k), DIMENSION(2,2), INTENT(in)                :: faceA, faceB
     4274    INTEGER, INTENT(out)                                 :: intersect
     4275    REAL(r_k), DIMENSION(2), INTENT(out)                 :: intersectpt
     4276
     4277! Local
     4278    REAL(r_k)                                            :: Axmin, Aymin, Axmax, Aymax
     4279    REAL(r_k)                                            :: Bxmin, Bymin, Bxmax, Bymax
     4280    REAL(r_k)                                            :: areaABD, areaACD, areaBDC, areaDAB
     4281    REAL(r_k), DIMENSION(3,2)                            :: triangle
     4282    LOGICAL                                              :: Lintersect
     4283
     4284!!!!!!! Variables
     4285! faceA/B: coordinates of faces A and B to determine if they intersect
     4286! intersect: integer to say if they intersect (0, no-intersect, +/-1 intersect)
     4287! intersectpt: point where faces intersect [(0,0) otherwise]
     4288
     4289    fname = 'intersectfaces'
     4290
     4291!    PRINT *,'     ' // TRIM(fname) // ' ________'
     4292!    PRINT *,'            faceA:', faceA(1,:), ';',faceA(2,:)
     4293!    PRINT *,'            faceB:', faceB(1,:), ';',faceB(2,:)
     4294
     4295    Axmin = MINVAL(faceA(:,1))
     4296    Axmax = MAXVAL(faceA(:,1))
     4297    Aymin = MINVAL(faceA(:,2))
     4298    Aymax = MAXVAL(faceA(:,2))
     4299    Bxmin = MINVAL(faceB(:,1))
     4300    Bxmax = MAXVAL(faceB(:,1))
     4301    Bymin = MINVAL(faceB(:,2))
     4302    Bymax = MAXVAL(faceB(:,2))
     4303
     4304    ! No intersection
     4305    IF ( (Axmax <= Bxmin) .OR. (Axmin >= Bxmax) .OR. (Aymax <= Bymin) .OR. (Aymin >= Bymax) ) THEN
     4306      intersect = 0
     4307      intersectpt = zeroRK
     4308    ELSE
     4309      ! Triangle ABD
     4310      triangle(1,:) = faceA(1,:)
     4311      triangle(2,:) = faceA(2,:)
     4312      triangle(3,:) = faceB(2,:)
     4313      areaABD = shoelace_area_polygon(3, triangle)
     4314 
     4315      ! Triangle ACD
     4316      triangle(1,:) = faceA(1,:)
     4317      triangle(2,:) = faceB(1,:)
     4318      triangle(3,:) = faceB(2,:)
     4319      areaACD = shoelace_area_polygon(3, triangle)
     4320
     4321      ! Triangle BDC
     4322      triangle(1,:) = faceA(2,:)
     4323      triangle(2,:) = faceB(2,:)
     4324      triangle(3,:) = faceB(1,:)
     4325      areaBDC = shoelace_area_polygon(3, triangle)
     4326
     4327      ! Triangle DAB
     4328      triangle(1,:) = faceB(2,:)
     4329      triangle(2,:) = faceA(1,:)
     4330      triangle(3,:) = faceA(2,:)
     4331      areaDAB = shoelace_area_polygon(3, triangle)
     4332
     4333      IF (areaABD>zeroRK .AND. areaACD>zeroRK .AND. areaBDC>zeroRK .AND. areaDAB>zeroRK) THEN
     4334        intersect = INT(ABS(areaABD)/areaABD)
     4335        CALL intersection_2Dlines(faceA, faceB, Lintersect, intersectpt)
     4336      ELSE IF (areaABD<zeroRK .AND. areaACD<zeroRK .AND. areaBDC<zeroRK .AND. areaDAB<zeroRK) THEN
     4337        intersect = INT(ABS(areaABD)/areaABD)
     4338        CALL intersection_2Dlines(faceA, faceB, Lintersect, intersectpt)
     4339      ELSE
     4340        intersect = 0
     4341        intersectpt = zeroRK
     4342      END IF
     4343!      PRINT *,'     intersect faces: areaABD',areaABD, 'areaACD', areaACD, 'areaBDC',areaBDC, 'areaDAB',areaDAB, 'prod', &
     4344!        areaABD*areaACD*areaBDC*areaDAB, 'L:', areaABD*areaACD*areaBDC*areaDAB > zeroRK, 'I', intersect
     4345
     4346    END IF
     4347
     4348  END SUBROUTINE intersectfaces
     4349
     4350  LOGICAL FUNCTION poly_has_point(Nvertex, polygon, point)
     4351  ! Function to determine if a polygon has already a given point as one of its vertex
     4352
     4353    IMPLICIT NONE
     4354
     4355    INTEGER, INTENT(in)                                  :: Nvertex
     4356    REAL(r_k), DIMENSION(Nvertex,2), INTENT(in)          :: polygon
     4357    REAL(r_k), DIMENSION(2), INTENT(in)                  :: point
     4358
     4359! Local
     4360    INTEGER                                              :: iv
     4361    REAL(r_k), DIMENSION(2)                              :: diff
     4362
     4363!!!!!!! Vertrex
     4364! Nvertex: number of vertexs of the polygon
     4365! polygon: vertexs of the polygon
     4366! point: point to look for its ownership into the polygon
     4367
     4368    fname = 'poly_has_point'
     4369
     4370    poly_has_point = .FALSE.
     4371    DO iv=1, Nvertex
     4372      diff = polygon(iv,:)-point
     4373      IF ( (diff(1) == zeroRK) .AND. (diff(2) == zeroRK)) THEN
     4374        poly_has_point = .TRUE.
     4375        EXIT
     4376      END IF
     4377    END DO
     4378
     4379  END FUNCTION poly_has_point
     4380
     4381  SUBROUTINE join_polygon(NvertexA, NvertexB, NvertexAB, polyA, polyB, Ncoinvertex, coinpoly)
     4382  ! Subroutine to join two polygons
     4383  ! AFTER: http://www.cap-lore.com/MathPhys/IP/ and http://www.cap-lore.com/MathPhys/IP/IL.html
     4384
     4385    IMPLICIT NONE
     4386
     4387    INTEGER, INTENT(in)                                  :: NvertexA, NvertexB, NvertexAB
     4388    REAL(r_k), DIMENSION(NvertexA,2), INTENT(in)         :: polyA
     4389    REAL(r_k), DIMENSION(NvertexB,2), INTENT(in)         :: polyB
     4390    INTEGER, INTENT(out)                                 :: Ncoinvertex
     4391    REAL(r_k), DIMENSION(NvertexAB,2), INTENT(out)        :: coinpoly
     4392
     4393! Local
     4394    INTEGER                                              :: iA, iB, icoin, ii
     4395    REAL(r_k), DIMENSION(2,2)                            :: face1, face2
     4396    INTEGER                                              :: intersct
     4397    REAL(r_k), DIMENSION(2)                              :: ptintersct
     4398
     4399
     4400!!!!!!! variables
     4401! NvertexA: number of vertexs polygon A
     4402! NvertexB: number of vertexs polygon B
     4403! polyA: pairs of coordinates for the polygon A (clockwise)
     4404! polyB: pairs of coordinates for the polygon B (clockwise)
     4405! Ncoinvertex: number of vertexes for the coincident polygon
     4406! coinpoly: pairs of coordinates for the coincident polygon (clockwise)
     4407
     4408    fname = 'join_polygon'
     4409
     4410    icoin = 0
     4411    coinpoly = 0.
     4412
     4413    ! First, include that vertex which do not lay within any polygon
     4414    DO iA=1, NvertexA
     4415      PRINT *, '  iA:', iA, ':', polyA(iA,:), point_inside(polyA(iA,:), NvertexB, polyB)
     4416      IF (.NOT. point_inside(polyA(iA,:), NvertexB, polyB)) THEN
     4417        icoin = icoin + 1
     4418        coinpoly(icoin,:) = polyA(iA,:)
     4419      END IF
     4420    END DO
     4421
     4422    DO iB=1, NvertexB
     4423      PRINT *, '  iB:', iB, ':', polyB(iB,:), point_inside(polyB(iB,:), NvertexA, polyA)
     4424      IF (.NOT. point_inside(polyB(iB,:), NvertexA, polyA)) THEN
     4425        icoin = icoin + 1
     4426        coinpoly(icoin,:) = polyB(iB,:)
     4427      END IF
     4428    END DO
     4429
     4430    DO iA=1, NvertexA
     4431      ! Getting couple of vertexs from polyA and polyB
     4432      IF (iA /= NvertexA) THEN
     4433        face1(1,:) = polyA(iA,:)
     4434        face1(2,:) = polyA(iA+1,:)
     4435      ELSE
     4436        face1(1,:) = polyA(iA,:)
     4437        face1(2,:) = polyA(1,:)
     4438      END IF
     4439      DO iB=1, NvertexB
     4440        IF (iB /= NvertexB) THEN
     4441          face2(1,:) = polyB(iB,:)
     4442          face2(2,:) = polyB(iB+1,:)
     4443        ELSE
     4444          face2(1,:) = polyB(iB,:)
     4445          face2(2,:) = polyB(1,:)
     4446        END IF
     4447       
     4448        ! Compute areas of the four possible triangles. Introduce the coincident vertexs not included
     4449        CALL intersectfaces(face1, face2, intersct, ptintersct)
     4450        PRINT *,iA,':',face1(1,:),';',face1(2,:), '=', iB, face2(1,:),';',face2(2,:), '<>', intersct,':', ptintersct
     4451        IF (intersct == 1) THEN
     4452          IF (.NOT.poly_has_point(icoin,coinpoly(1:icoin,:),ptintersct) ) THEN
     4453            icoin = icoin + 1
     4454            coinpoly(icoin,:) = ptintersct
     4455          END IF
     4456        ELSE IF (intersct == -1) THEN
     4457          IF (.NOT.poly_has_point(icoin,coinpoly(1:icoin,:),ptintersct) ) THEN
     4458            icoin = icoin + 1
     4459            coinpoly(icoin,:) = ptintersct
     4460          END IF
     4461        END IF
     4462
     4463      END DO
     4464    END DO
     4465    Ncoinvertex = icoin
     4466
     4467  END SUBROUTINE join_polygon
     4468
     4469  SUBROUTINE sort_polygon(Nvertex, polygon, sortpoly)
     4470  ! Subroutine to sort a polygon using its center as average of the coordinates
     4471  !    Should be used the centroid instead, but by now let do it simple
     4472  !    https://en.wikipedia.org/wiki/Centroid
     4473
     4474
     4475    IMPLICIT NONE
     4476
     4477    INTEGER, INTENT(in)                                  :: Nvertex
     4478    REAL(r_k), DIMENSION(Nvertex,2), INTENT(in)          :: polygon
     4479    REAL(r_k), DIMENSION(Nvertex,2), INTENT(out)         :: sortpoly
     4480
     4481! Local
     4482    INTEGER                                              :: iv, j
     4483    REAL(r_k)                                            :: vang
     4484    REAL(r_k), DIMENSION(2)                              :: center
     4485    REAL(r_k), DIMENSION(Nvertex)                        :: angles
     4486
     4487!!!!!!! Variables
     4488! Nvertex: number of vetexs
     4489! polygon: coordinates of the vertices of the polygon
     4490! sortpoly: sorted polygon (clockwise)
     4491
     4492    fname = 'sort_polygon'
     4493
     4494    ! To be substituted by centroid calculation (which requires already sorted vetexs...)
     4495    center(1) = SUM(polygon(:,1))/Nvertex
     4496    center(2) = SUM(polygon(:,2))/Nvertex
     4497
     4498    DO iv=1, Nvertex
     4499      angles(iv) = ATAN2(polygon(iv,2)-center(2),polygon(iv,1)-center(1))
     4500    END DO
     4501    CALL sortR_K(angles, Nvertex)
     4502
     4503    sortpoly = zeroRK
     4504    DO iv=1, Nvertex
     4505      DO j=1, Nvertex
     4506        vang = ATAN2(polygon(j,2)-center(2), polygon(j,1)-center(1))
     4507        IF (angles(iv) == vang) THEN
     4508          sortpoly(iv,:) = polygon(j,:)
     4509          EXIT
     4510        END IF
     4511      END DO
     4512    END DO
     4513
     4514  END SUBROUTINE sort_polygon
     4515
     4516  LOGICAL FUNCTION point_inside(point, Nvertex, polygon)
     4517  ! Function to determine if a given point is inside a polygon providing its sorted vertices
     4518  ! FROM: https://en.wikipedia.org/wiki/Point_in_polygon
     4519
     4520    IMPLICIT NONE
     4521
     4522    REAL(r_k), DIMENSION(2), INTENT(in)                  :: point
     4523    INTEGER, INTENT(in)                                  :: Nvertex
     4524    REAL(r_k), DIMENSION(Nvertex,2), INTENT(in)          :: polygon
     4525
     4526    ! Local
     4527    INTEGER                                              :: iv, Nintersect
     4528    INTEGER                                              :: cross
     4529    REAL(r_k)                                            :: xmin
     4530    REAL(r_k), DIMENSION(2)                              :: crosspoint
     4531    REAL(r_k), DIMENSION(2,2)                            :: face1, face2
     4532    REAL(r_k), DIMENSION(Nvertex)                        :: abovebelow
     4533
     4534!!!!!!! Variables
     4535! point: point to look for
     4536! Nvertrex: number of vertices of a polygon
     4537! polygon: vertices of a polygon
     4538
     4539    fname = 'point_inside'
     4540
     4541    xmin = MINVAL(polygon(:,1))
     4542
     4543    ! Looking for the intersection with the ray
     4544    Nintersect = 0
     4545    face1(1,:) = (/ xmin-0.5, point(2) /)
     4546    face1(2,:) = (/ point(1), point(2) /)
     4547
     4548    DO iv = 1, Nvertex
     4549      IF (iv /= Nvertex) THEN
     4550        face2(1,:) = polygon(iv,:)
     4551        face2(2,:) = polygon(iv+1,:)
     4552      ELSE
     4553        face2(1,:) = polygon(iv,:)
     4554        face2(2,:) = polygon(1,:)
     4555      END IF
     4556      CALL intersectfaces(face1, face2, cross, crosspoint)
     4557      IF (cross /= 0) THEN
     4558        Nintersect = Nintersect + 1
     4559        abovebelow(Nintersect) = iv
     4560      END IF
     4561    END DO
     4562
     4563    IF (MOD(Nintersect,2) == 0) THEN
     4564      point_inside = .FALSE.
     4565    ELSE
     4566      point_inside = .TRUE.
     4567    END IF
     4568
     4569  END FUNCTION point_inside
     4570
    40464571END MODULE module_scientific
Note: See TracChangeset for help on using the changeset viewer.