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: 

null reference error when adding dimension

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
parkerjmay
2500 Views, 13 Replies

null reference error when adding dimension

hi,

 

 

getting started with revit api via revitpythonshell. getting null reference error when i try to add dimension between line endpoints:

 

app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document

 

t = Transaction(doc, 'undo')

t.Start()

 

#create line

line = Line.CreateBound(XYZ(0,0,0), XYZ(0,0,10))

 

#get endpt refs
references = ReferenceArray()
references.Append(line.GetEndPointReference(0))
references.Append(line.GetEndPointReference(1))

 

#create dimension
dim = doc.FamilyCreate.NewDimension(doc.ActiveView, line, references)

 

t.Commit()

 

ERROR:

 

System.NullReferenceException: Object reference not set to an instance of an object.

 

help appreciated,

josh

13 REPLIES 13
Message 2 of 14
ollikat
in reply to: parkerjmay

Hi

API documentation says about FamilyCreate property:

"An object that can be used to create new instances of Autodesk Revit API elements within a family document."

Instead of that, you are using project document here and thus it might have null in that property(?).
Message 3 of 14
parkerjmay
in reply to: ollikat

thx for quick response. I am in the family workspace so i must to use FamilyCreate instead of Create. btw, If i run in project workspace and replace FamilyCreate with Create I get the same error.

Message 4 of 14
ollikat
in reply to: parkerjmay

Hmmm....I'm a bit confused now.... 🙂

doc = __revit__.ActiveUIDocument.Document


I would suggest that please, double check that what is the document behind the "doc" variable. Because I would assume that "ActiveUIDocument.Document" always returns a project document(?).

Message 5 of 14
arnostlobel
in reply to: ollikat

Yes, That is correct that UIDocument "should" always return a valid Document. However, it is possible for Revit to not have a currently active document, thus that must be checked, especially if the API is invoked at times when such a possibility exists. This case actually indicates that the user operates upon a null object, for the exception comes from the System. Revit rarely let System exception to be thrown from inside Revit code. While it is possible, most of Revit exception are thrown as Revit Exception.

 

Before getting any further with this, I would like to ask parkerjmay to provide additional information for the exception he/she got. There should be more info on the exception object that could be useful, such as Source, Data, and StackTrace. That should give us a better picture of what is happening and where. If no more infeo can be gotten from the exception self, then at least knowing the exact line in code at which the exception is actually thrown would be useful too.

 

Also: What version of Revit are we talking about?

 

Thank you

Arnošt Löbel
Message 6 of 14
parkerjmay
in reply to: arnostlobel

Hi, Seems like the GetEndPointReference method is producing the null object. Here is a test I did with python shell to verify. Doc is valid object,  Line.CreateBound() method returns valid line, but line.GetEndPointReference(0) returns null object, Then system error gets thrown when I pass to doc.FamilyCreate.NewDimension(doc.ActiveView, line, references). 

 

IronPython 2.7.4 (2.7.0.40) on .NET 4.0.30319.18063 (64-bit)
>>> import clr
>>> clr.AddReference('RevitAPI')
>>> clr.AddReference('RevitAPIUI')
>>> from Autodesk.Revit.DB import *
>>> app = __revit__.Application
>>> doc = __revit__.ActiveUIDocument.Document
>>> print doc
<Autodesk.Revit.DB.Document object at 0x000000000000002E [Autodesk.Revit.DB.Document]>
>>> print type(doc)
<type 'Document'>
>>> print doc.ActiveView
<Autodesk.Revit.DB.ViewSection object at 0x000000000000002F [Autodesk.Revit.DB.ViewSection]>
>>> print type(doc.ActiveView)
<type 'ViewSection'>
>>> t = Transaction(doc, 'test')
>>> t.Start()
Autodesk.Revit.DB.TransactionStatus.Started
>>> refPoint = doc.FamilyCreate.NewReferencePoint(XYZ(0,0,0))
>>> print refPoint
<Autodesk.Revit.DB.ReferencePoint object at 0x0000000000000031 [Autodesk.Revit.DB.ReferencePoint]>
>>> line = Line.CreateBound(XYZ(0,0,0), XYZ(0,0,10))
>>> print line
<Autodesk.Revit.DB.Line object at 0x0000000000000032 [Autodesk.Revit.DB.Line]>
>>> print line.GetEndPointReference(0)
None
>>> print line.GetEndPointReference(1)
None
>>> print type(line)
<type 'Line'>
>>> dim = doc.FamilyCreate.NewDimension(doc.ActiveView, line, references)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'references' is not defined
>>> references = ReferenceArray()
>>> references.Append(line.GetEndPointReference(0))
>>> references.Append(line.GetEndPointReference(1))
>>> print references
<Autodesk.Revit.DB.ReferenceArray object at 0x0000000000000030 [Autodesk.Revit.DB.ReferenceArray]>
>>> dim = doc.FamilyCreate.NewDimension(doc.ActiveView, line, references)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
SystemError: Object reference not set to an instance of an object.

 

Here is the full error message:

 

System.NullReferenceException: Object reference not set to an instance of an object. at Autodesk.Revit.Creation.ItemFactoryBase.NewDimension(View view, Line line, ReferenceArray references) at Microsoft.Scripting.Interpreter.FuncCallInstruction`5.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.LightLambda.Run6[T0,T1,T2,T3,T4,T5,TRet](T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) at System.Dynamic.UpdateDelegates.UpdateAndExecute5[T0,T1,T2,T3,T4,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) at Microsoft.Scripting.Interpreter.DynamicInstruction`6.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1) at IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx) at IronPython.Compiler.RuntimeScriptCode.InvokeTarget(Scope sc...

 

Message 7 of 14
arnostlobel
in reply to: parkerjmay

So, to sum it up, the problem (problems, actually, as it appears) is/are as follows:

 

a)      Line.GetEndPointReference(0) returns a null object

b)      When this NULL added to the RefrencesArray and passed to the NewDimension method, it looks like the method fails to validated the array of references has all valid items, and causes an exception when trying to access the first item.

 

Is that correct?

 

Also, you did not pointed it out specifically, but is it correct to assume that Line.GetEndPointReference(1) returns also an invalid reference (i.e. NULL)?

 

To be frank, I actually do not know (yet) whether a newly created Line object is supposed to have references.  (I would assume that it would not, actually) but let’s worry about that later. Now I want to get as clear a picture of the problem as possible. Can you please confirm the above mentioned assumptions?

 

Thank you

Arnošt Löbel
Message 8 of 14
parkerjmay
in reply to: arnostlobel

that is corrent 

GetEndPointReference(0) and GetEndPointReference Method(1) are not valid.

Message 9 of 14
parkerjmay
in reply to: arnostlobel

regarding questionable use of GetEndPointReference, I am curious to know what is more typical way to create dimension from two points? thanks again for your help.
Message 10 of 14
arnostlobel
in reply to: parkerjmay

Hello Josh,

 

I would argue about the questionability of the GetEndPointReference method. Agreed, it could probably be better documented to state more clearly that the references can only be obtained from curves that actually exist in a Revit model, but otherwise the method works well, I believe. It is also documented that it may return null, so I would advise that needs to be tested by programmers who invoke it.

 

What is probably a bit confusing and maybe not spelled out well in the documentation, is the fact that dimensions are supposed to be created for something that does have references in the Revit model, meaning something that does physically exist. In my opinion it is not very different from other applications that feature associative dimensions, for to have a dimension associated it needs to be associated with something concrete.

 

I think the SDK sample in the CreateDimensions illustrates it well. If you happen to look in to it you’ll see that curves are first obtained from the model, then references from the curves are collected in an array, which is then given to the method that creates a dimension. I hope it’ll help.

 

Thank you

Arnošt Löbel
Message 11 of 14
parkerjmay
in reply to: arnostlobel

Hi arnostlobel, 

 

You are right, that is the problem. Line must already exist in the model before calling GetEndPointReference. It seems strange to have to create 'physical' geometry before dimensioning only because my understanding of best practice for creating an adaptive family, is to (1) create reference objects (lines, planes, pts), (2) constrain reference objects with dimensions, (3) attach geometry to your 'framework' of reference objects. So now I'm trying to generate simple adaptive box and having a hard time b/c I'm being forced to create geometry first. Am I missing something...? 

 

Thanks for your help!

Message 12 of 14
arnostlobel
in reply to: parkerjmay

Family creation and operations is not really a domain of may expertise, thus I'd be dancing on very thin ice if trying to talk about it. However, it seems correct what you assumed when expecting to start with adding dimensions to reference objects. In fact, it is what our SDK sample does when creating a new family. I was not familiar with that example, but found it in the SDK under FamilyCreation\Window folder. Maybe the code there is more close to what you've been looking for.

Thank you
Arnošt Löbel
Message 13 of 14
Wrath_
in reply to: parkerjmay

I`ve read the whole discussion, but have understood nothing...

How can I get reference, for example, of location line of the beam? I need to create dimension between location lines of some beams

I`ve already created such macros, but I lost it and cannot create it again, beacause of NullReference exception, which I haven`t encountered before.

Hope, someone will help me.)

Message 14 of 14
chhadidg73
in reply to: Wrath_

Hello,

 

nothing that I found and tried worked so far, but I have a workaround now, that works. Just want to share it. Maybe someone would like to use it as well.

 

1. Create the sweep profile.

2. Put the dimensions on the sweep.

 

Here is my code:

 


// Thickness of middle plate
FamilyParameter param1 = famdoc.FamilyManager.AddParameter(Variables.Mapping["diameter"], BuiltInParameterGroup.PG_GEOMETRY, ParameterType.Length, false);
famdoc.FamilyManager.Set(param1, width);
FamilyParameter param2 = famdoc.FamilyManager.AddParameter(Variables.Mapping["tw"], BuiltInParameterGroup.PG_GEOMETRY, ParameterType.Length, false);
famdoc.FamilyManager.Set(param2, tw);

 

// Find the sweep - just returns the sweep you created before
List<Sweep> sweeps = Utility.GetElements<Sweep>(famdoc);

 

// Get the points to draw the dimension lines
XYZ A1 = sweeps[0].ProfileSketch.Profile.get_Item(0).get_Item(0).GetEndPoint(0);
XYZ A2 = sweeps[0].ProfileSketch.Profile.get_Item(0).get_Item(0).GetEndPoint(1);
XYZ A3 = sweeps[0].ProfileSketch.Profile.get_Item(1).get_Item(0).GetEndPoint(0);

l1 = Line.CreateBound(A1, A2);

 

// Here it comes. Delete the sweep and roll back - now you can access the reference of the endpoints of the arcs

// Dirty, but it works

ICollection<ElementId> delIds = null;

using (SubTransaction delTrans = new SubTransaction(famdoc))
{
   try
   {
      delTrans.Start();
      delIds = famdoc.Delete(sweeps[0].Id);
      delTrans.RollBack();
   }
   catch (Exception ex)
   {
      MessageBox.Show(ex.ToString());
   }
}


// Get the model lines in the profile and use the end points for reference the sketch dimensions
// diameter
List<ModelArc> mArcs = new List<ModelArc>();

foreach (ElementId id in delIds)
{
   Element ele = famdoc.GetElement(id);
   if (ele is ModelArc)
   {
      mArcs.Add(ele as ModelArc);
   }
}

refArray.Append(mArcs[0].GeometryCurve.GetEndPointReference(0));
refArray.Append(mArcs[0].GeometryCurve.GetEndPointReference(1));

d1 = famdoc.FamilyCreate.NewDimension(PlanView, l1, refArray);
d1.FamilyLabel = param1;
refArray.Clear();

 

Hopefully this helps someone.

 

regards

Christian

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community