Return the material value for point, based on the position in relation to the polygon.
The point containment is decided with the help of the Gauss-Bonnet theorem, which is highly robust, but requires the polygon vertices to follow an ordering along the polygon lines.
The returned value will be polygon%inval, if the point is inside and polygon%outside otherwise.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(tem_polygon_vertex_type), | intent(in) | :: | me |
Polygon to describe the material shape. |
||
integer, | intent(in) | :: | nComponents | |||
real(kind=rk), | intent(in) | :: | inVal(nComponents) | |||
real(kind=rk), | intent(in) | :: | outVal(nComponents) | |||
real(kind=rk), | intent(in) | :: | point(:) |
Point to check against the polygon. |
Material value at point, as defined by the polygon.
function tem_polygon_material_value(me, nComponents, inVal, outVal, point) & & result(res) ! ---------------------------------------------------------------------- !> Polygon to describe the material shape. type(tem_polygon_vertex_type), intent(in) :: me integer, intent(in) :: nComponents real(kind=rk), intent(in) :: inVal(nComponents) real(kind=rk), intent(in) :: outVal(nComponents) !> Point to check against the polygon. real(kind=rk), intent(in) :: point(:) ! ---------------------------------------------------------------------- !> Material value at point, as defined by the polygon. real(kind=rk) :: res(nComponents) real(kind=rk) :: diffa(me%nVertices,2) real(kind=rk) :: diffb(me%nVertices,2) real(kind=rk) :: anglesum integer :: iDir ! ---------------------------------------------------------------------- ! Compute difference between all vertices of the polygon and the given ! point. diffa(:,1) = me%vertex(:,1) - point(1) diffa(:,2) = me%vertex(:,2) - point(2) ! Copy the differences to a shifted array, to allow the simultaneous ! computation of all the angles for polygon segments. ! After the last point, we jump back to the first index to close the ! polygon again. do iDir=1,2 diffb(:me%nVertices-1,iDir) = diffa(2:,iDir) diffb(me%nVertices,iDir) = diffa(1,iDir) end do ! With the Gauss-Bonnet theorem, we can decide the containment of the ! point within the polygon, based on the sum of all angles under which ! the polygon segments are seen from the point. anglesum = sum( angle_between(va_x = diffa(:,1), va_y = diffa(:,2), & & vb_x = diffb(:,1), vb_y = diffb(:,2)) ) if (abs(anglesum) > 3.0_rk) then ! The point is inside, if the sum of angles is 2 Pi actually, but to ! allow for numerical inaccuracies and points on the polygon segments ! we just check for greater 3 here. res = inval else ! Points with a smaller value are deemed to be outside the polygon. ! They might actually be located on a vertex, but the angle at the ! vertex would be greater for the outside part than the inside, so it ! should definitely be ok to assume this point as outside. res = outval end if end function tem_polygon_material_value