Two Clicks to Create and Rotate Family Instances

public void createAndOrient()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;
    Application app = doc.Application;

    // Get the family symbol named "North Arrow 2"
    FamilySymbol famSym = new FilteredElementCollector(doc).OfClass(typeof(FamilySymbol)).Where(q => q.Name == "North Arrow 2").First() as FamilySymbol;

    // use a transaction group so that all the individual transactions are merged into a single entry in the Undo menu
    // this is optional
    using (TransactionGroup tg = new TransactionGroup(doc,"Create and Orient Instances"))
    {
        tg.Start();
        // create an infinite loop so user can create multiple instances in a single command
        // ESC when prompted to select a point will thrown an exception which is how the loop is exited
        while (true)
        {
            try
            {                
                XYZ pickPoint = uidoc.Selection.PickPoint("Click to specify instance location. ESC to stop placing instances.");

                FamilyInstance familyInstance = null;    
                // Create the instance with the default orientation
                // This is done in its own transaction so that the user can see the new instance when they are prompted for the orientation
                using (Transaction t = new Transaction(doc,"Place Instance"))
                {
                    t.Start();
                    familyInstance = doc.Create.NewFamilyInstance(pickPoint, famSym, doc.ActiveView);
                    t.Commit();
                }

                XYZ orientPoint = uidoc.Selection.PickPoint("Click to specify orientation. ESC to stop placing instances.");

                // Create a line between the two points
                // A transaction is not needed because the line is a transient element created in the application, not in the document
                Line orientLine = app.Create.NewLineBound(pickPoint, orientPoint);

                // Compute the angle between the vertical direction (XZY.BasisY) and the orientLine
                double angle = XYZ.BasisY.AngleTo(orientLine.Direction);

                // For diagnostics in Task dialog below
                double angleDegrees = angle * 180 / Math.PI;

                // AngleTo always returns the smaller angle between the two lines (for example, it will always return 10 degrees, never 350)
                // so if the orient point is to the left of the pick point, then correct the angle by subtracting it from 2PI (Revit measures angles in degrees)
                if (orientPoint.X < pickPoint.X)
                    angle = 2 * Math.PI - angle;

                // To show the need for angle corrections
                double angleDegreesCorrected = angle * 180 / Math.PI;
                //TaskDialog.Show("info","Angle directly from AngleTo = " + angleDegrees + "\n Angle after X correction = " + angleDegreesCorrected);

                // Create an axis in the Z direction 
                Line axis = app.Create.NewLineBound(pickPoint, new XYZ(pickPoint.X, pickPoint.Y, pickPoint.Z + 10));

                using (Transaction t = new Transaction(doc,"Orient Instance"))
                {
                    t.Start();
                    ElementTransformUtils.RotateElement(doc, familyInstance.Id, axis, -angle);
                    t.Commit();
                }
            }
            catch
            {
                // Get here when the user hits ESC when prompted for selection
                // "break" exits from the while loop
                break;
            }
        }
    // Consolidate all the transactions for the individual creation / rotation transactions into a single Undo item	
    tg.Assimilate();
    }
}

How to Delete Line Styles


public void deleteLineStyle()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;
    Category linesCat = doc.Settings.Categories.get_Item("Lines");

    IList<Category> categoryList = linesCat.SubCategories.Cast<Category>().Where(c => c.Name.StartsWith("A-") || c.Name.StartsWith("S-")).ToList();
    IList<ElementId> idsToDelete = new List<ElementId>();
    foreach (Category cat in categoryList)
    {
        idsToDelete.Add(cat.Id);
    }

    using (Transaction t = new Transaction(doc,"Delete LineStyle"))
    {
        t.Start();
        doc.Delete(idsToDelete);
        t.Commit();
    }
}

Images for your Revit Elements

Here is some code and a video showing how you can associate images with elements in your Revit model and display them when the elements are selected.


public void showElementImage()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;

    // dictionary stores element id values and their corresponding image file URLs
    Dictionary<int,string> dictionary = new Dictionary<int, string>();
    dictionary.Add(181736,"http://3.bp.blogspot.com/_dpc8BBT2JGI/TP92yqwD0HI/AAAAAAAABVI/IKFc4lbNXZY/s1600/IMG_6487.JPG");
    dictionary.Add(181750,"http://2.bp.blogspot.com/-8n-blC0CVeE/T_C-zHQCB3I/AAAAAAAATOg/gmPLrT71qwY/s1600/Yusupov+fancy+floor.jpg");
    dictionary.Add(181784,"http://animatedpizzagifs.com/images/psycadelic-pizza-love.gif");

    // prompt user to select elements
    ElementId id = uidoc.Selection.PickObject(ObjectType.Element).ElementId;

    // give message if no dictionary entry exists for this id value
    if (!dictionary.ContainsKey(id.IntegerValue))
    {
        TaskDialog.Show("Error","No image exists for element id = " + id.IntegerValue);
        return;
    }

    // create a Windows Form
    using (System.Windows.Forms.Form myForm = new System.Windows.Forms.Form())
    {
        // Create a label to indicate the element id
        System.Windows.Forms.Label label = new System.Windows.Forms.Label();
        label.Text = "Image for element id " + id.IntegerValue;
        label.AutoSize = true;
        label.Location = new System.Drawing.Point(5, 5);

        // create a picture box to show the image
        System.Windows.Forms.PictureBox picture = new System.Windows.Forms.PictureBox();
        // the location of the image is the dictionary entry for this element id value
        picture.ImageLocation = dictionary[id.IntegerValue];
        picture.Location = new System.Drawing.Point(5, 25);
        picture.Width = 500;
        picture.Height = 500;
        // stretch or shrink to fit the PictureBox
        picture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;

        // add controls to the form
        myForm.Controls.Add(label);
        myForm.Controls.Add(picture);

        // set the size & location of the form and display it 
        myForm.Height = picture.Top + picture.Height + 50;
        myForm.Width = picture.Left + picture.Width + 50;
        myForm.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
        myForm.ShowDialog();
    }
}