Changeset 2262 in lmdz_wrf
- Timestamp:
- Dec 19, 2018, 8:13:23 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/module_scientific.f90
r2235 r2262 14 14 ! to a map of integer polygons filtrered by a minimal area 15 15 ! 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 16 17 ! FindMinimumR_K*: Function returns the location of the minimum in the section between Start and End. 17 18 ! fill3DI_2Dvec: Subroutine to fill a 3D integer matrix from a series of indices from a 2D matrix … … 19 20 ! gridpoints_InsidePolygon: Subroutine to determine if a series of grid points are inside a polygon 20 21 ! 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 21 26 ! look_clockwise_borders: Subroutine to look clock-wise for a next point within a collection of borders 22 27 ! (limits of a region) … … 25 30 ! path_properties: Subroutine to determine the properties of a path 26 31 ! 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 27 34 ! polygon_properties: Subroutine to determine the properties of a polygon (as .TRUE. matrix) 28 35 ! polygons: Subroutine to search the polygons of a border field. FORTRAN based. 1st = 1! 29 36 ! polygons_t: Subroutine to search the polygons of a temporal series of boolean fields. FORTRAN based. 1st = 1! 30 37 ! 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) 32 40 ! poly_overlap_tracks_area: Subroutine to determine tracks of a series of consecutive 2D field with polygons using 33 41 ! maximum overlaping/coincidence filtrered by a minimal area … … 43 51 ! and y coordinates 44 52 ! 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 45 55 ! SortR_K*: Subroutine receives an array x() r_K and sorts it into ascending order. 46 56 ! StatsR_K: Subroutine to provide the minmum, maximum, mean, the quadratic mean, and the standard deviation of a … … 3474 3484 ! Subroutine swaps the values of its two formal arguments. 3475 3485 3476 IMPLICIT 3486 IMPLICIT NONE 3477 3487 3478 3488 REAL(r_k), INTENT(INOUT) :: a, b … … 4044 4054 END SUBROUTINE percentiles_R_K4D 4045 4055 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 4046 4571 END MODULE module_scientific
Note: See TracChangeset
for help on using the changeset viewer.