Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

API c# question

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
Anonymous
1884 Views, 4 Replies

API c# question

Hi there,

 

First of all I haven't found an answer to my question in an existing post, please feel free to redirect me there if you know one.

 

I'm currently coding a plugin for Revit 2015 that insert a family of my choice inside an existing project.

I want to insert the family directly on a face of an existing 3D item. But depending on the situation I must insert it on different type of faces, such as planar faces or cylindrical. Problem is, I can't get my code to function on either, I don't know how to check for the type of face prior to my operations.

That's my code for cylindrical faces

                Reference r = uidoc.Selection.PickObject(ObjectType.Face,
                  "Please pick a point on a face for family instance insertion");

                Element e = doc.GetElement(r.ElementId);
                GeometryObject obj = e.GetGeometryObjectFromReference(r);
                //PlanarFace face = obj as PlanarFace;
                CylindricalFace face = obj as CylindricalFace;
                    XYZ p = r.GlobalPoint;
                    XYZ v = face.Axis.CrossProduct(XYZ.BasisZ);
                    if (v.IsZeroLength())
                    {
                        v = face.Axis.CrossProduct(XYZ.BasisX);
                    }
                    doc.Create.NewFamilyInstance(r, p, v, symbol);

 And that's my code for planar faces

                Reference r = uidoc.Selection.PickObject(ObjectType.Face,
                  "Please pick a point on a face for family instance insertion");

                Element e = doc.GetElement(r.ElementId);
                GeometryObject obj = e.GetGeometryObjectFromReference(r);
                PlanarFace face = obj as PlanarFace;
                //CylindricalFace face = obj as CylindricalFace;
                    
                XYZ p = r.GlobalPoint;
                XYZ v = face.Normal.CrossProduct(XYZ.BasisZ);
                if (v.IsZeroLength())
                {
                    v = face.Normal.CrossProduct(XYZ.BasisX);
                }
                doc.Create.NewFamilyInstance(r, p, v, symbol);

 Almost nothing changes except for the declaration of v with the change : Axis/Normal

 

I've been using the code from Jeremy Tammik thebuildingcoder, I'm fairly new to programming and totally new to C#, and I've never used any API before.

 

I also have other questions :

Right now I'm typing the path and the name of the family item that I want to insert directly inside my code. Ideally, I'd like the user to pick the family when he starts the plugin, but I have no idea how to do that.

Last thing I'd like to know is, after my family is inserted, how do I run automatically an interference check to see if there is any collision. The plugin is aimed to people totally new to geomatics, that have never used any software like autocad, I want them to push the least buttons possible to achivieve their goal.

 

Thank you very much in advance for your time.

 

Jordi

Tags (2)
4 REPLIES 4
Message 2 of 5
jeremytammik
in reply to: Anonymous

Dear Jordi,

 

Happy Valentine's Day!

 

🙂

 

That sounds like a pretty cool project.

 

Congratulations on getting so far with it already.

 

I answered your queries pretty extensively on The Building Coder:

 

http://thebuildingcoder.typepad.com/blog/2015/02/determining-the-face-tangent-at-a-picked-point.html

 

I hope this helps.

 

Good luck!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 5
Anonymous
in reply to: jeremytammik

Hi Jeremy !

 

Thank you very much I'll take a look right away !

 

Cheers,

 

Jordi

Message 4 of 5
hasan_kassem
in reply to: Anonymous

@jeremytammik 

Good morning, 

i writed this code to set the numbering automatically, but in each time I re-execute my code it begin the numbering from 0 instead of lastassignednumber.

so where is the error ?

 

Thanks in advance,

 

 

 

 

 

 

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.DB.ExtensibleStorage;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Number
{
[Transaction(TransactionMode.Manual)]
public class Code : IExternalCommand
{
private const string SchemaGUID = "633FEF1C-4DF3-4C07-A812-D392C8015194";
private const string MinRangePropertyName = "MinRange";
private const string MaxRangePropertyName = "MaxRange";
private const string LastAssignedNumberPropertyName = "LastAssignedNumber";

private int currentNumber;
private int minRange;
private int maxRange;
private ICollection<ElementId> addedElementIds = new List<ElementId>();

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIApplication uiApp = commandData.Application;
UIDocument uiDoc = uiApp.ActiveUIDocument;
Document doc = uiDoc.Document;

addedElementIds = GetWallElement(doc);

if (!RetrieveRangeValues(doc))
{
// Range values not found, prompt the user to enter the range
using (Window window = new Window(doc))
{
window.ShowDialog();

minRange = window.minRange;
maxRange = window.maxRange;
currentNumber = minRange;

StoreRangeValues(doc);
}
}
else
{
currentNumber = RetrieveLastAssignedNumber(doc);
if (currentNumber < minRange || currentNumber > maxRange)
{
// Handle the case where the last assigned number is outside the specified range
// You can display an error message or take appropriate action here
}

TaskDialog.Show("Range", "Your entered range is between: \n" + minRange.ToString() + " - " + maxRange.ToString() + "\n" +
"Current Number: " + currentNumber);
}

// Subscribe to the Idling event
uiApp.Idling += HandleIdlingEvent;

return Result.Succeeded;
}

private void HandleIdlingEvent(object sender, IdlingEventArgs e)
{
UIApplication uiApp = sender as UIApplication;
Document doc = uiApp.ActiveUIDocument.Document;

try
{
// Check for newly added walls in the document
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfCategory(BuiltInCategory.OST_Walls);

ICollection<ElementId> currentElementIds = collector.ToElementIds();

// Find the added wall element ids by comparing the current element ids with the previously stored ids
IEnumerable<ElementId> newElementIds = currentElementIds.Except(addedElementIds);

if (newElementIds.Any())
{
using (Transaction trans = new Transaction(doc, "Assign Number to Walls"))
{
trans.Start();

foreach (ElementId elementId in newElementIds)
{
Element element = doc.GetElement(elementId);

if (element is Wall wall)
{
// Get the custom "Number" parameter
Parameter parameter = wall.LookupParameter("Number");

if (parameter != null && parameter.StorageType == StorageType.String)
{
parameter.Set(currentNumber.ToString());
currentNumber++;
}
}
}

trans.Commit();

// Update the added element ids for the next idling event
addedElementIds = currentElementIds;

// Store the last assigned number
StoreLastAssignedNumber(doc, currentNumber);
}
}
}
catch (Exception ex)
{
TaskDialog.Show("Error", ex.Message);
}
}

public ICollection<ElementId> GetWallElement(Document doc)
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfCategory(BuiltInCategory.OST_Walls);
return collector.ToElementIds().ToList();
}

private bool RetrieveRangeValues(Document doc)
{
try
{
Schema schema = Schema.Lookup(new Guid(SchemaGUID));

if (schema != null)
{
Entity entity = doc.ProjectInformation.GetEntity(schema);

if (entity.IsValid())
{
minRange = entity.Get<int>(schema.GetField(MinRangePropertyName));
maxRange = entity.Get<int>(schema.GetField(MaxRangePropertyName));
currentNumber = entity.Get<int>(schema.GetField(LastAssignedNumberPropertyName));

currentNumber = RetrieveLastAssignedNumber(doc); // Retrieve the last assigned number

return true;
}
}
}
catch (Exception ex)
{
TaskDialog.Show("Error", ex.Message);
}

return false;
}

private int RetrieveLastAssignedNumber(Document doc)
{
try
{
Schema schema = Schema.Lookup(new Guid(SchemaGUID));

if (schema != null)
{
Entity entity = doc.ProjectInformation.GetEntity(schema);

if (entity.IsValid())
{
return entity.Get<int>(schema.GetField(LastAssignedNumberPropertyName));
}
}
}
catch (Exception ex)
{
TaskDialog.Show("Error", ex.Message);
}

// Return a default value if the last assigned number cannot be retrieved
return 0;
}

private void StoreRangeValues(Document doc)
{
try
{
Schema schema = Schema.Lookup(new Guid(SchemaGUID));

if (schema == null)
{
SchemaBuilder schemaBuilder = new SchemaBuilder(new Guid(SchemaGUID));

schemaBuilder.SetSchemaName("NumberSchema");
schemaBuilder.SetReadAccessLevel(AccessLevel.Public);
schemaBuilder.SetWriteAccessLevel(AccessLevel.Public);

FieldBuilder minRangeField = schemaBuilder.AddSimpleField(MinRangePropertyName, typeof(int));
FieldBuilder maxRangeField = schemaBuilder.AddSimpleField(MaxRangePropertyName, typeof(int));
FieldBuilder lastAssignedNumberField = schemaBuilder.AddSimpleField(LastAssignedNumberPropertyName, typeof(int));

schema = schemaBuilder.Finish();
}

using (Transaction trans = new Transaction(doc, "Store Range Values"))
{
trans.Start();

Entity entity = new Entity(schema);

entity.Set<int>(schema.GetField(MinRangePropertyName), minRange);
entity.Set<int>(schema.GetField(MaxRangePropertyName), maxRange);

doc.ProjectInformation.SetEntity(entity);

trans.Commit();
}
}
catch (Exception ex)
{
TaskDialog.Show("Error", ex.Message);
}
}

private void StoreLastAssignedNumber(Document doc, int number)
{
try
{
Schema schema = Schema.Lookup(new Guid(SchemaGUID));

if (schema != null)
{
Entity entity = doc.ProjectInformation.GetEntity(schema);

if (entity.IsValid())
{
entity.Set<int>(schema.GetField(LastAssignedNumberPropertyName), number);
}
else
{
entity = new Entity(schema);
entity.Set<int>(schema.GetField(LastAssignedNumberPropertyName), number);
doc.ProjectInformation.SetEntity(entity);
}
}
}
catch (Exception ex)
{
TaskDialog.Show("Error", ex.Message);
}
}
}
}

 

Message 5 of 5

TLDR; but:

  

As far as I remember, my SetoutPoints performs some pretty nifty, persistent and customisable automatic numbering:

  

https://github.com/jeremytammik/SetoutPoints

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report