449 lines
17 KiB
VB.net
449 lines
17 KiB
VB.net
#Region "Microsoft.VisualBasic::36e514099caeeb4140f6a8ab98e877ea, Microsoft.VisualBasic.Core\Extensions\Image\GDI+\Layouts\Rectangle2D.vb"
|
|
|
|
' Author:
|
|
'
|
|
' asuka (amethyst.asuka@gcmodeller.org)
|
|
' xie (genetics@smrucc.org)
|
|
' xieguigang (xie.guigang@live.com)
|
|
'
|
|
' Copyright (c) 2018 GPL3 Licensed
|
|
'
|
|
'
|
|
' GNU GENERAL PUBLIC LICENSE (GPL3)
|
|
'
|
|
'
|
|
' This program is free software: you can redistribute it and/or modify
|
|
' it under the terms of the GNU General Public License as published by
|
|
' the Free Software Foundation, either version 3 of the License, or
|
|
' (at your option) any later version.
|
|
'
|
|
' This program is distributed in the hope that it will be useful,
|
|
' but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
' GNU General Public License for more details.
|
|
'
|
|
' You should have received a copy of the GNU General Public License
|
|
' along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
' /********************************************************************************/
|
|
|
|
' Summaries:
|
|
|
|
' Class Rectangle2D
|
|
'
|
|
' Properties: Bottom, CenterX, CenterY, Height, Rectangle
|
|
' Right, Width
|
|
'
|
|
' Constructor: (+7 Overloads) Sub New
|
|
'
|
|
' Function: Clone, contains, Equals, inflate, intersection
|
|
' intersectLine, OverlapLambda, OverlapX, OverlapY, ToString
|
|
' union, Union, Vertices
|
|
'
|
|
' Sub: add, grow, setRect
|
|
'
|
|
'
|
|
' /********************************************************************************/
|
|
|
|
#End Region
|
|
|
|
Imports System.Drawing
|
|
Imports System.Runtime.CompilerServices
|
|
Imports Microsoft.VisualBasic.Language
|
|
Imports sys = System.Math
|
|
|
|
' $Id: mxRectangle.java,v 1.1 2012/11/15 13:26:39 gaudenz Exp $
|
|
' Copyright (c) 2007-2010, Gaudenz Alder, David Benson
|
|
|
|
Namespace Imaging.LayoutModel
|
|
|
|
''' <summary>
|
|
''' Implements a 2-dimensional rectangle with double precision coordinates.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' 除了左上角+宽和高这种方式进行矩形区域的定义,还可以用左上角+右下角的方式来定义一个矩形
|
|
''' </remarks>
|
|
Public Class Rectangle2D : Inherits Point2D
|
|
|
|
''' <summary>
|
|
''' Returns the width of the rectangle.
|
|
''' </summary>
|
|
''' <returns> Returns the width. </returns>
|
|
Public Overridable Property Width As Double
|
|
|
|
''' <summary>
|
|
''' Returns the height of the rectangle.
|
|
''' </summary>
|
|
''' <returns> Returns the height. </returns>
|
|
Public Overridable Property Height As Double
|
|
|
|
''' <summary>
|
|
''' Returns the x-coordinate of the center.
|
|
''' </summary>
|
|
''' <returns> Returns the x-coordinate of the center. </returns>
|
|
Public Overridable ReadOnly Property CenterX As Double
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Get
|
|
Return X + Width / 2
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Returns the y-coordinate of the center.
|
|
''' </summary>
|
|
''' <returns> Returns the y-coordinate of the center. </returns>
|
|
Public Overridable ReadOnly Property CenterY As Double
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Get
|
|
Return Y + Height / 2
|
|
End Get
|
|
End Property
|
|
|
|
Public Property Right As Double
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Get
|
|
Return X + Width
|
|
End Get
|
|
Set(value As Double)
|
|
' 保持当前的位置不变,但是宽度变了
|
|
Width = value - X
|
|
End Set
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' 底部的``Y``坐标值
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Property Bottom As Double
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Get
|
|
Return Y + Height
|
|
End Get
|
|
Set(value As Double)
|
|
' 保持当前的位置不变,但是高度变了
|
|
Height = value - Y
|
|
End Set
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Returns the bounds as a new rectangle.
|
|
''' </summary>
|
|
''' <returns> Returns a new rectangle for the bounds. </returns>
|
|
Public Overridable ReadOnly Property Rectangle As RectangleF
|
|
Get
|
|
Dim ix As Integer = CInt(Fix(sys.Round(X)))
|
|
Dim iy As Integer = CInt(Fix(sys.Round(Y)))
|
|
Dim iw As Integer = CInt(Fix(sys.Round(Width - ix + X)))
|
|
Dim ih As Integer = CInt(Fix(sys.Round(Height - iy + Y)))
|
|
|
|
Return New RectangleF(ix, iy, iw, ih)
|
|
End Get
|
|
End Property
|
|
|
|
Default Public Overrides Property Axis(a As String) As Double
|
|
Get
|
|
Select Case Strings.LCase(a)
|
|
Case "cx" : Return CenterX
|
|
Case "cy" : Return CenterY
|
|
Case Else
|
|
Return MyBase.Axis(a)
|
|
End Select
|
|
End Get
|
|
Set(value As Double)
|
|
MyBase.Axis(a) = value
|
|
End Set
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Constructs a new rectangle at (0, 0) with the width and height set to 0.
|
|
''' </summary>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Sub New()
|
|
Me.New(0, 0, 0, 0)
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Constructs a copy of the given rectangle.
|
|
''' </summary>
|
|
''' <param name="rect"> Rectangle to construct a copy of. </param>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Sub New(rect As Rectangle)
|
|
Me.New(rect.X, rect.Y, rect.Width, rect.Height)
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Constructs a copy of the given rectangle.
|
|
''' </summary>
|
|
''' <param name="rect"> Rectangle to construct a copy of. </param>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Sub New(rect As RectangleF)
|
|
Me.New(rect.X, rect.Y, rect.Width, rect.Height)
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Constructs a copy of the given rectangle.
|
|
''' </summary>
|
|
''' <param name="rect"> Rectangle to construct a copy of. </param>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Sub New(rect As Rectangle2D)
|
|
Me.New(rect.X, rect.Y, rect.Width, rect.Height)
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Constructs a rectangle using the given parameters.
|
|
''' </summary>
|
|
''' <param name="x"> X-coordinate of the new rectangle. </param>
|
|
''' <param name="y"> Y-coordinate of the new rectangle. </param>
|
|
''' <param name="width"> Width of the new rectangle. </param>
|
|
''' <param name="height"> Height of the new rectangle. </param>
|
|
Public Sub New(x As Double, y As Double, width As Double, height As Double)
|
|
MyBase.New(x, y)
|
|
|
|
Me.Width = width
|
|
Me.Height = height
|
|
End Sub
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Sub New(layout As (x#, y#, w#, h#))
|
|
Call Me.New(layout.x, layout.y, layout.w, layout.h)
|
|
End Sub
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Sub New(width%, height%)
|
|
Call Me.New(0, 0, width, height)
|
|
End Sub
|
|
|
|
Public Function OverlapLambda(axis As String) As Func(Of Rectangle2D, Double)
|
|
Select Case Strings.LCase(axis)
|
|
Case "x"
|
|
Return AddressOf OverlapX
|
|
Case "y"
|
|
Return AddressOf OverlapY
|
|
Case Else
|
|
Throw New InvalidExpressionException(axis)
|
|
End Select
|
|
End Function
|
|
|
|
Public Function OverlapX(r As Rectangle2D) As Double
|
|
Dim ux = CenterX, vx = r.CenterX
|
|
|
|
If (ux <= vx AndAlso r.X < Right) Then
|
|
Return Right - r.X
|
|
End If
|
|
If (vx <= ux AndAlso X < r.Right) Then
|
|
Return r.Right - X
|
|
End If
|
|
|
|
Return 0
|
|
End Function
|
|
|
|
Public Function OverlapY(r As Rectangle2D) As Double
|
|
Dim uy = CenterY, vy = r.CenterY
|
|
|
|
If (uy <= vy AndAlso r.Y < Bottom) Then
|
|
Return Bottom - r.Y
|
|
End If
|
|
If (vy <= uy AndAlso Y < r.Bottom) Then
|
|
Return r.Bottom - Y
|
|
End If
|
|
|
|
Return 0
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Sets this rectangle to the specified values
|
|
''' </summary>
|
|
''' <param name="x"> the new x-axis position </param>
|
|
''' <param name="y"> the new y-axis position </param>
|
|
''' <param name="w"> the new width of the rectangle </param>
|
|
''' <param name="h"> the new height of the rectangle </param>
|
|
Public Overridable Sub setRect(x As Double, y As Double, w As Double, h As Double)
|
|
Me.X = x
|
|
Me.Y = y
|
|
Me.Width = w
|
|
Me.Height = h
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Adds the given rectangle to this rectangle. Union two rectangle.
|
|
''' (取两个区域的交集部分,并且这个函数会改变当前的这个矩形对象的值)
|
|
''' </summary>
|
|
Public Overridable Sub add(rect As Rectangle2D)
|
|
If rect IsNot Nothing Then
|
|
With union(X, Y, Right, Bottom, rect)
|
|
X = .x
|
|
Y = .y
|
|
Width = .w
|
|
Height = .h
|
|
End With
|
|
End If
|
|
End Sub
|
|
|
|
Private Shared Function union(x#, y#, right#, bottom#, r As Rectangle2D) As (x#, y#, w#, h#)
|
|
Dim minX As Double = sys.Min(x, r.X)
|
|
Dim minY As Double = sys.Min(y, r.Y)
|
|
Dim maxX As Double = sys.Max(right, r.Right)
|
|
Dim maxY As Double = sys.Max(bottom, r.Bottom)
|
|
|
|
x = minX
|
|
y = minY
|
|
|
|
Return (x, y, w:=maxX - minX, h:=maxY - minY)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' 这个函数的功能和<see cref="add"/>函数几乎一致,只不过这个函数返回新的<see cref="Rectangle2D"/>
|
|
''' 而非修改自身的值
|
|
''' </summary>
|
|
''' <param name="rect"></param>
|
|
''' <returns></returns>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Function Union(rect As Rectangle2D) As Rectangle2D
|
|
Return New Rectangle2D(union(X, Y, Right, Bottom, rect))
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Grows the rectangle by the given amount, that is, this method subtracts
|
|
''' the given amount from the x- and y-coordinates and adds twice the amount
|
|
''' to the width and height.
|
|
'''
|
|
''' ``inflate(pad: number): Rectangle``
|
|
''' </summary>
|
|
''' <param name="amount"> Amount by which the rectangle should be grown. </param>
|
|
Public Overridable Sub grow(amount As Double)
|
|
X -= amount
|
|
Y -= amount
|
|
Width += 2 * amount
|
|
Height += 2 * amount
|
|
End Sub
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Function inflate(pad As Double) As Rectangle2D
|
|
Return New Rectangle2D(X - pad, Y - pad, Width + 2 * pad, Height + 2 * pad)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns true if the given point is contained in the rectangle.
|
|
''' </summary>
|
|
''' <param name="x"> X-coordinate of the point. </param>
|
|
''' <param name="y"> Y-coordinate of the point. </param>
|
|
''' <returns> Returns true if the point is contained in the rectangle.</returns>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Overridable Function contains(x As Double, y As Double) As Boolean
|
|
Return (Me.X <= x AndAlso Me.X + Width >= x AndAlso Me.Y <= y AndAlso Me.Y + Height >= y)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns the point at which the specified point intersects the perimeter
|
|
''' of this rectangle or null if there is no intersection.
|
|
''' </summary>
|
|
''' <param name="x0"> the x co-ordinate of the first point of the line </param>
|
|
''' <param name="y0"> the y co-ordinate of the first point of the line </param>
|
|
''' <param name="x1"> the x co-ordinate of the second point of the line </param>
|
|
''' <param name="y1"> the y co-ordinate of the second point of the line </param>
|
|
''' <returns>
|
|
''' The point at which the line intersects this rectangle, or null if there is no intersection
|
|
''' </returns>
|
|
Public Overridable Function intersectLine(x0 As Double, y0 As Double, x1 As Double, y1 As Double) As Point2D
|
|
Dim result As Point2D = intersection(X, Y, X + Width, Y, x0, y0, x1, y1)
|
|
|
|
If result Is Nothing Then result = intersection(X + Width, Y, X + Width, Y + Height, x0, y0, x1, y1)
|
|
If result Is Nothing Then result = intersection(X + Width, Y + Height, X, Y + Height, x0, y0, x1, y1)
|
|
If result Is Nothing Then result = intersection(X, Y, X, Y + Height, x0, y0, x1, y1)
|
|
|
|
Return result
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns the intersection of two lines as an mxPoint.
|
|
''' </summary>
|
|
''' <param name="x0">X-coordinate of the first line's startpoint.</param>
|
|
''' <param name="y0">Y-coordinate of the first line's startpoint.</param>
|
|
''' <param name="x1">X-coordinate of the first line's endpoint.</param>
|
|
''' <param name="y1">Y-coordinate of the first line's endpoint.</param>
|
|
''' <param name="x2">X-coordinate of the second line's startpoint.</param>
|
|
''' <param name="y2">Y-coordinate of the second line's startpoint.</param>
|
|
''' <param name="x3">X-coordinate of the second line's endpoint.</param>
|
|
''' <param name="y3">Y-coordinate of the second line's endpoint.</param>
|
|
''' <returns> Returns the intersection between the two lines.</returns>
|
|
Public Shared Function intersection(x0 As Double, y0 As Double,
|
|
x1 As Double, y1 As Double,
|
|
x2 As Double, y2 As Double,
|
|
x3 As Double, y3 As Double) As Point2D
|
|
|
|
Dim denom As Double = ((y3 - y2) * (x1 - x0)) - ((x3 - x2) * (y1 - y0))
|
|
Dim nume_a As Double = ((x3 - x2) * (y0 - y2)) - ((y3 - y2) * (x0 - x2))
|
|
Dim nume_b As Double = ((x1 - x0) * (y0 - y2)) - ((y1 - y0) * (x0 - x2))
|
|
Dim ua As Double = nume_a / denom
|
|
Dim ub As Double = nume_b / denom
|
|
|
|
If ua >= 0.0 AndAlso ua <= 1.0 AndAlso ub >= 0.0 AndAlso ub <= 1.0 Then
|
|
' Get the intersection point
|
|
Dim iX As Double = x0 + ua * (x1 - x0)
|
|
Dim iY As Double = y0 + ua * (y1 - y0)
|
|
|
|
Return New Point2D(iX, iY)
|
|
Else
|
|
' No intersection
|
|
Return Nothing
|
|
End If
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns true if the given object value equals this rectangle.
|
|
''' </summary>
|
|
Public Overrides Function Equals(obj As Object) As Boolean
|
|
If TypeOf obj Is Rectangle2D Then
|
|
With TryCast(obj, Rectangle2D)
|
|
Return .X = X AndAlso
|
|
.Y = Y AndAlso
|
|
.Width = Width AndAlso
|
|
.Height = Height
|
|
End With
|
|
End If
|
|
|
|
Return False
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a new instance of the same rectangle.
|
|
''' </summary>
|
|
Public Overrides Function Clone() As Object
|
|
With CType(MyBase.Clone(), Rectangle2D)
|
|
.Width = Width
|
|
.Height = Height
|
|
|
|
Return .ByRef
|
|
End With
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns the <code>String</code> representation of this
|
|
''' <code>mxRectangle</code>. </summary>
|
|
''' <returns> a <code>String</code> representing this
|
|
''' <code>mxRectangle</code>. </returns>
|
|
Public Overrides Function ToString() As String
|
|
Return $"{Me.GetType.Name} [x={X}, y={Y}, w={Width}, h={Height}]"
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' 枚举出当前的这个矩形对象之中的4个顶点坐标
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Iterator Function Vertices() As IEnumerable(Of Point2D)
|
|
Yield New Point2D(X, Y)
|
|
Yield New Point2D(Right, Y)
|
|
Yield New Point2D(Right, Bottom)
|
|
Yield New Point2D(X, Bottom)
|
|
End Function
|
|
End Class
|
|
End Namespace
|