Basically what I have is a solid box that the user has drawn to represent a counter top. I also have a block they pull in for the sink.
All I want to do is automate the placement of the sink by letting them pick the front face of the counter top and placing the center of the sink 11" from the edge of the counter.
But I don't know how I can let them select the edge of the solid.
Can anyone help me with this?
I didn't find a solution to actually picking the face of my solid. Instead I made a jig and used some geometry to find a point on the edge of the solid.
Basically it explodes the solid , then in the jig it determins if your cursor is in front of one of the edges, then projects a point onto the edge. This may not help you, but it was good enough for me.
Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.Geometry Namespace TimberTools Namespace AcadJigs Class SinkToCounterJig Inherits EntityJig Private _ActualPoint As Point3d Private _Counter As Solid3d Private _Sink As BlockReference Private _x As TreeNode Private _BasePoint As Point3d Private _Offset As Double Private _BasePointOffest As Vector3d Private _Vector As Vector3d Public ReadOnly Property SelectedPoint() As Point3d Get Return _ActualPoint End Get End Property Public ReadOnly Property Vector() As Vector3d Get Return _Vector End Get End Property Public Sub New(ByVal BlockRef As BlockReference, ByVal Counter As Solid3d, ByVal BasePoint As Point3d, ByVal Offset As Double) MyBase.New(BlockRef) _Sink = BlockRef _Counter = Counter _BasePoint = BasePoint _Offset = Offset _BasePointOffest = _BasePoint.GetVectorTo(_Sink.Position) '#collect tree of expoded object. Was having trouble ' with acad crashes when this was all in the update routine _x = New TreeNode Dim ents As New DBObjectCollection '#explode wall _Counter.Explode(ents) For Each obj As DBObject In ents Dim ent As New TreeNode ent._Item = obj If obj.GetType() Is GetType(Region) Then '#Explode Region Dim Lines As New DBObjectCollection CType(obj, Region).Explode(Lines) For Each line As DBObject In Lines Dim Ln As New TreeNode Ln._Item = line ent._Children.Add(Ln) Next Lines.Clear() Lines.Dispose() End If _x._Children.Add(ent) Next ents.Clear() ents.Dispose() End Sub Public Sub CleanUp() CleanUp(_x) End Sub Private Sub CleanUp(ByVal node As TreeNode) If node._Item IsNot Nothing Then If GetType(DBObject).IsAssignableFrom(node._Item.GetType()) Then CType(node._Item, DBObject).Dispose() End If End If For Each nd As TreeNode In node._Children CleanUp(nd) Next End Sub Protected Overloads Overrides Function Sampler(ByVal prompts As JigPrompts) As SamplerStatus Dim jigOpts As New JigPromptPointOptions() jigOpts.UserInputControls = (UserInputControls.Accept3dCoordinates Or UserInputControls.NoZeroResponseAccepted Or UserInputControls.NoNegativeResponseAccepted) jigOpts.Message = vbLf & "Pick front side of counter top: " jigOpts.BasePoint = _BasePoint jigOpts.UseBasePoint = True Dim dres As PromptPointResult = prompts.AcquirePoint(jigOpts) If _ActualPoint = dres.Value Then Return SamplerStatus.NoChange Else _ActualPoint = dres.Value End If Return SamplerStatus.OK End Function Protected Overloads Overrides Function Update() As Boolean Try Dim NewLocation As Point3d = _Sink.Position Dim Closest As Point3d = _Sink.Position For Each RegNode As TreeNode In _x._Children '#only look at regions (shouldn't be anything else) Dim Reg As Region = RegNode._Item 'Exclude top and bottom regions of counter If Reg.Normal.Z = 0 Then '# find coordinates by examining lines Dim P1 As Point3d Dim P2 As Point3d '# get lines of region For Each lineNode As TreeNode In RegNode._Children Dim line As Line = lineNode._Item 'Get horizontal lines If line.StartPoint.Z = line.EndPoint.Z Then P1 = line.StartPoint P2 = line.EndPoint End If Next Dim v1 As Vector3d = P1.GetVectorTo(_ActualPoint) Dim v2 As Vector3d = P2.GetVectorTo(_ActualPoint) Dim a1 As Double = Reg.Normal.GetAngleTo(v1) Dim a2 As Double = Reg.Normal.GetAngleTo(v2) Dim a3 As Double = v1.GetAngleTo(v2) '< 45 If (a1 < 0.25 * Math.PI Or a2 < 0.25 * Math.PI) Or _ a3 > 0.5 * Math.PI And a1 < 0.5 * Math.PI And a2 < 0.5 * Math.PI Then 'Pointer in view of this region Dim Loc As Point3d = _BasePoint.OrthoProject(New Plane(P1, Reg.Normal)) Dim Vec As Vector3d = _BasePoint.GetVectorTo(Loc).GetNormal _Vector = Vec Dim FinalPos As Point3d = Loc.Subtract(Vec.MultiplyBy(_Offset)) NewLocation = FinalPos.Add(_BasePointOffest) If _ActualPoint.DistanceTo(NewLocation) < _ActualPoint.DistanceTo(Closest) Then Closest = NewLocation End If End If End If Next If Closest <> _Sink.Position Then _Sink.Position = Closest End If Return True Catch generatedExceptionName As System.Exception Return False End Try Return True End Function Public Function GetEntity() As Entity Return Entity End Function Private Class TreeNode Public _Children As List(Of TreeNode) Public _Item As Object Sub New() _Children = New List(Of TreeNode) End Sub End Class End Class End Namespace End Namespace