简体   繁体   中英

vb.NET - How to Get boundary of GraphicsPath without including Bezier handle locations

I'm trying to do a boundary around a GraphicsPath for easy group sizing. This works fine but when I convert one of the points to a bezier it includes the location of the Bezier handles within the boundary making the selection rectangle much larger than it is supposed to be.

Here is how it looks when the path is first created, by default the points are lines only without beziers. Selection rectangle works as expected.

lines not beziers are right

When I double click on a point it automatically converts the points to a bezier (or if bezier, toggles back to Line) and then the selection rectangle reflects the handle points as well in the path.

when using beziers path is bigger

As you can see, it should stop the rectangle just under the curve made by the bezier but it also seems to expand to the handles.

Here is the code for doing the rectangle perimeter.


Public Overrides Sub DrawSelectionRectangle(ByVal g As Graphics) SelectionRectangle = New RectangleF(0, 0, 0, 0)

Dim GP As GraphicsPath = _lastGp 'DAVE

If GP IsNot Nothing Then If _lastGp.PointCount > 1 Then Try Dim BH As New Single: Dim TH As New Single: Dim LW As New Single: Dim RW As New Single

  TH = GP.PathPoints(0).Y
  LW = GP.PathPoints(0).X

  For i = 0 To GP.PathPoints.Length - 1
   With GP.PathPoints(i)
    If .Y < TH Then TH = .Y
    If .X < LW Then LW = .X
    If .Y > BH Then BH = .Y
    If .X > RW Then RW = .X
   End With

  Next i

  'DAVE - This code won't work as it doesn't factor in for space made by the actual bezier curves, GP path must be followed. BUT! this is a tidier solution.
  'SelectionRectangle = New RectangleF(0, 0, 0, 0)
  'If _pointArray IsNot Nothing Then
  ' If _pointArray.Count > 1 Then
  '  Try
  '   Dim BH As New Single : Dim TH As New Single : Dim LW As New Single : Dim RW As New Single

  '   LW = _pointArray(0).P.X
  '   TH = _pointArray(0).P.Y

  '   For i = 0 To _pointArray.Count - 1
  '    With _pointArray(i).P
  '     If .Y < TH Then TH = .Y
  '     If .X < LW Then LW = .X
  '     If .Y > BH Then BH = .Y
  '     If .X > RW Then RW = .X
  '    End With

  '   Next i
  '=================================

  SelectionRectangle = New RectangleF(New PointF(LW, TH), New SizeF(RW - LW, BH - TH))

  Dim r As RectangleF = DrawRectangle.GetNormalizedRectangle(SelectionRectangle)
  Dim gpen As Pen = New Pen(Color.Gray, MyBase.StrokeWidth)
  gpen.DashStyle = DashStyle.Dash
  g.DrawRectangle(gpen, r.X, r.Y, r.Width, r.Height)

  gpen.Dispose()
 Catch ex As Exception
  ErrH.Log("DrawSelectionRectangle", "Draw", ex.ToString(), ErrH._LogPriority.Info)
 End Try

End If

End If

End Sub


Any help on a simple solution would be much appreciated. :)

I have tried using the actual point array as a reference but this does not factor in for the curves thrown by the Bezier. See example if the above commented code is run.

trying to follow path array instead of graphics path

WOW...

That took a while but I found the answer!

Literally 1 line!

GP.Flatten

The fixed line

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM