TheSwamp
Code Red => VB(A) => Topic started by: surveyor_randy on November 11, 2007, 10:28:31 AM
-
Is there any way to get the closest point (start or end) of a line or 2-vertex polyline of a selected line? Right now, I am having the user select the entity, then drawing a marker on one of the endpoints and prompting the user if this is the correct point, if not, it selects the other. What I would like to do, is have the user click on the line closest to the endpoint they want to work with. Is this even possible? Thanks for any input/suggestions.
-
Yes, it is possilbe. The ThisDrawing.Utility.GetEntity function will return the entity selected (the line/pline) and the point that was picked to select the entity.
You could then test the distances from the end points to the 'pick point' and return the closest end point. It would be a bit tougher if you didnt limit it to a 2 vertex pline.
I have some proto-type code if you care to see it
-
I have some proto-type code if you care to see it
Sure! That'd be great! I have an idea if the user selected a polyline with more then 2 vertexes. First, find the vertex closest to where the user selected the pline. Determine what vertex number that is in the pline and then sum the distances of the segments up to that vertex, then get the sum of the remaining segments. Which ever is shorter, select either the first vertex or the last vertex based on that.
I ended up finishing my stationing routine and just set the OSMODE and made them pick the start and end points. I still am interested in them just selecting the line they want to station closest to the point they want to begin stationing at.
-
Here is the rough code. It needs error checking, entity type testing, etc
But I think it gets the idea across (if I interpreted you first post correctly).
Public Sub testGetClosestEndpoint()
Dim oEnt As AcadEntity
Dim vPickedPoint As Variant
Dim vPoint As Variant
Dim vResult As Variant
ThisDrawing.Utility.GetEntity oEnt, vPickedPoint, "Pick (p)Line: "
vResult = GetClosestEndPt(oEnt, vPickedPoint, False)
Debug.Print vResult(0), vResult(1), vResult(2)
End Sub
Public Function GetClosestEndPt(pLineEnt As AcadEntity, pPoint As Variant, p3dIfTrue As Boolean) As Variant
Dim vTemp1 As Variant
Dim oLine As AcadLine
Dim oLwPline As AcadLWPolyline
Dim oPline As AcadPolyline
Dim o3dPline As Acad3DPolyline
Dim maxVert As Integer
Dim dist1 As Double
Dim dist2 As Double
Dim retVal As Variant
If TypeOf pLineEnt Is AcadLine Then
Set oLine = pLineEnt
dist1 = CalcDist(oLine.StartPoint, pPoint, p3dIfTrue)
dist2 = CalcDist(oLine.EndPoint, pPoint, p3dIfTrue)
If dist1 <= dist2 Then
retVal = oLine.StartPoint
Else
retVal = oLine.EndPoint
End If
ElseIf TypeOf pLineEnt Is AcadLWPolyline Then
Set oLwPline = pLineEnt
maxVert = (UBound(oLwPline.Coordinates) - 1) / 2
dist1 = CalcDist(oLwPline.Coordinate(0), pPoint, p3dIfTrue)
dist2 = CalcDist(oLwPline.Coordinate(maxVert), pPoint, p3dIfTrue)
If dist1 <= dist2 Then
retVal = oLwPline.Coordinate(0)
Else
retVal = oLwPline.Coordinate(maxVert)
End If
ElseIf TypeOf pLineEnt Is AcadPolyline Then
Set oPline = pLineEnt
maxVert = (UBound(oPline.Coordinates) - 2) / 3
dist1 = CalcDist(oPline.Coordinate(0), pPoint, p3dIfTrue)
dist2 = CalcDist(oPline.Coordinate(maxVert), pPoint, p3dIfTrue)
If dist1 <= dist2 Then
retVal = oPline.Coordinate(0)
Else
retVal = oPline.Coordinate(maxVert)
End If
ElseIf TypeOf pLineEnt Is Acad3DPolyline Then
Set o3dPline = pLineEnt
maxVert = (UBound(o3dPline.Coordinates) - 2) / 3
dist1 = CalcDist(o3dPline.Coordinate(0), pPoint, p3dIfTrue)
dist2 = CalcDist(o3dPline.Coordinate(maxVert), pPoint, p3dIfTrue)
If dist1 <= dist2 Then
retVal = o3dPline.Coordinate(0)
Else
retVal = o3dPline.Coordinate(maxVert)
End If
End If
GetClosestEndPt = retVal
End Function
Public Function CalcDist(pPt1 As Variant, pPt2 As Variant, p3dIfTrue As Boolean) As Double
Dim temp As Double
If p3dIfTrue Then
temp = Sqr((pPt1(0) - pPt2(0)) ^ 2 + (pPt1(1) - pPt2(1)) ^ 2 + (pPt1(2) - pPt2(2)) ^ 2)
Else
temp = Sqr((pPt1(0) - pPt2(0)) ^ 2 + (pPt1(1) - pPt2(1)) ^ 2)
End If
CalcDist = temp
End Function
The LISP vlax-curve-* functions would probably be helpful to you for determining stationing. They can probably be accessed in VBA using the VL Active X module and/or through Frank O's VLAX class.
-
Thanks for the code snippet! As far as the stationing routines, I will look into the VL active X module. To be honest, I was unaware of such a thing even existing. There are tons of VL routines that I'd love to access! Do you know where I can find documentation on this module.
I already have most of my stationing functions written. The only one left to do is the stationing for a horizontal curve which should be no biggie! Thanks again for the help!