Help drawing perpendicular lines from existing lines

Help drawing perpendicular lines from existing lines

jmmiller.southlandind
Enthusiast Enthusiast
1,766 Views
2 Replies
Message 1 of 3

Help drawing perpendicular lines from existing lines

jmmiller.southlandind
Enthusiast
Enthusiast

Greetings All. I am currently exploring and teaching myself various ways to add lines and other geometry to my models via the API.  My current exercise has me trying to find a solution on how to draw a perpendicular detail line, of a specified length, from the center of an existing detail in the direction that a user specifies via picking a point.

I have explored various other post on this forum regarding this topic. I have been able to successfully draw a perpendicular line from the user selected line. However, I can only currently achieve this via hard coding values in my code. When I do this my desired perpendicular line is always drawn in one direction.

I am failing to figure out how to have the new perpendicular line draw in the direction as it relates to the user’s picked point.

I would greatly appreciate any assistance in helping me obtain my goal. For reference I provided my simple code I am currently using as well as an image to help articulate what my end goal is.

Thank you in advance.

 

Lines Capture.PNG

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI.Selection;

namespace TabooBIM
{
    [TransactionAttribute(TransactionMode.Manual)]
    public class Cmd_CreatePerpendicularLine : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            //Get UIDocument and Document
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;

            try
            {
                //Pick Object
                Reference pickedObj = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
                XYZ pickedpoint = uidoc.Selection.PickPoint(ObjectSnapTypes.None, "Pick Direction Location");
                TaskDialog.Show("PointCheck", pickedpoint.ToString());
                 

             
                if (pickedObj != null)
                {
                  
                    ElementId eleId = pickedObj.ElementId;
                    Element ele = doc.GetElement(eleId);
                    LocationCurve locationCurve = ele.Location as LocationCurve;
                    XYZ startpoint = locationCurve.Curve.GetEndPoint(0);
                    XYZ endpoint = locationCurve.Curve.GetEndPoint(1);

                    
                    Line line1 = Line.CreateBound(startpoint,endpoint);
                    XYZ pntCenter = line1.Evaluate(0.5, true);
                    XYZ normal = line1.Direction.Normalize();
                    XYZ dir = new XYZ(0, 0, 1);
                    //XYZ dir = pickedpoint;
                    XYZ cross = normal.CrossProduct(dir);
                    XYZ pntEnd = pntCenter + cross.Multiply(25);
                    Line line2 = Line.CreateBound(pntCenter, new XYZ(pntEnd.X, pntEnd.Y, 10));

                    using (Transaction trans = new Transaction(doc, "Draw Line"))
                    {
                        trans.Start();

                        DetailLine myDetailLine = doc.Create.NewDetailCurve(doc.ActiveView, line2) as DetailLine;

                        trans.Commit();
                    }
                }
                return Result.Succeeded;
            }
            catch (Exception e)
            {
                message = e.Message;
                return Result.Failed;
            }
        }
    }
}

 

0 Likes
Accepted solutions (1)
1,767 Views
2 Replies
Replies (2)
Message 2 of 3

michael-coffey
Advocate
Advocate
Accepted solution

I believe I've solved your issue.  I'm creating a length of line from the distance of picked point to the center of line.  Edited to be in macro form.

		public void DrawPerpendicularLine()
		{
			UIDocument uidoc = this.ActiveUIDocument;
			Document doc = this.ActiveUIDocument.Document;
			
			try
            {
                //Pick Object
                Reference pickedObj = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
                XYZ pickedpoint = uidoc.Selection.PickPoint(ObjectSnapTypes.None, "Pick Direction Location");
                TaskDialog.Show("PointCheck", pickedpoint.ToString());
                 
                if (pickedObj != null)
                {
                  
                    ElementId eleId = pickedObj.ElementId;
                    Element ele = doc.GetElement(eleId);
                    LocationCurve locationCurve = ele.Location as LocationCurve;
                    XYZ startpoint = locationCurve.Curve.GetEndPoint(0);
                    XYZ endpoint = locationCurve.Curve.GetEndPoint(1);

                    
                    Line line1 = Line.CreateBound(startpoint,endpoint);
                    XYZ pntCenter = line1.Evaluate(0.5, true);
                    XYZ normal = line1.Direction.Normalize();
                    XYZ dir = new XYZ(0, 0, 1);
                    XYZ cross = normal.CrossProduct(dir);
                    
                    //calculate lenght from pickedpoint to center point
                    double length = pickedpoint.Subtract(pntCenter).GetLength();
                    bool flip = IsLeft(startpoint, endpoint, pickedpoint);
                    if (flip)
                    	length = length * -1;
                    
                    XYZ pntEnd = pntCenter + cross.Multiply(length);
                    Line line2 = Line.CreateBound(pntCenter, new XYZ(pntEnd.X, pntEnd.Y, 0)); //use 0 for Z value

                    using (Transaction trans = new Transaction(doc, "Draw Line"))
                    {
                        trans.Start();

                        DetailLine myDetailLine = doc.Create.NewDetailCurve(doc.ActiveView, line2) as DetailLine;

                        trans.Commit();
                    }
                }
            }
            catch (Exception e)
            {
                string message = e.Message;
            }
		}
		
		//adapted from https://stackoverflow.com/questions/1560492/how-to-tell-whether-a-point-is-to-the-right-or-left-side-of-a-line
		public bool IsLeft(XYZ a, XYZ b, XYZ c)
		{
     		return ((b.X - a.X)*(c.Y - a.Y) - (b.Y - a.Y)*(c.X - a.X)) > 0;
		}

 

0 Likes
Message 3 of 3

jmmiller.southlandind
Enthusiast
Enthusiast

Thank you @michael-coffey . Your solution did indeed solve my issue. 

0 Likes