System.NullReferenceException, Switching python code to c# language

System.NullReferenceException, Switching python code to c# language

MiguelGT17
Advocate Advocate
1,736 Views
12 Replies
Message 1 of 13

System.NullReferenceException, Switching python code to c# language

MiguelGT17
Advocate
Advocate

MiguelGT17_0-1646624520820.png

Greeting to all, when switching from python to c# code I'm facing a NullReferenceException. In fact, SharpDevelop builds the script successfully and the exception comes up when hitting the run button in macro manager. So far I've identified that the exception triggers in the code that is wrapped inside the if ...NumberOfSegments>1 and if...NumberOfSegments==1: 

MiguelGT17_1-1646626106229.png

Any thoughts on how to get this fixed?

Best regards

Transaction tr2=new Transaction(doc,"AFRY:Multi-Rebar Alignment");
tr2.Start();

view= doc.ActiveView;
cropbox=view.CropBox;
transform=cropbox.Transform;
XYZ bbMin=cropbox.Min;
XYZ bbMax=cropbox.Max;
Dictionary<int, Element> unTagged= new Dictionary<int, Element>(), rebTagged=new Dictionary<int, Element>();
Dictionary<int, XYZ> Top= new Dictionary<int, XYZ>(), Bottom=new Dictionary<int, XYZ>(), Right= new Dictionary<int, XYZ>(), Left=new Dictionary<int, XYZ>();

if (familyType=="Section") 
{
		
	for (int i = 0; i < rebars.Count; i++) 
	{
		
		//a). rebar bounding box midpoint in 3d revit model system (it might retrieve a partial bounding box if the whole element is not visible)
		Element reb=rebars[i];
		
		if ((reb as Rebar).IsRebarFreeForm()== true)
		{
			unTagged.Add(i,reb);
		}
		else if ((reb as Rebar).IsRebarFreeForm()== false) 
		{
		
			
			BoundingBoxXYZ rebBB=reb.get_BoundingBox(view);
			XYZ midPoint=(rebBB.Max + rebBB.Min)/2;
			
			//b). Transform the coord system into the local view coord system
			Transform inverseTf=transform.Inverse;
			XYZ rebLocInView=inverseTf.OfPoint(midPoint);
			
			//c) Determine the center point of the cropview w.r.t view system coord (using z=0)
			XYZ newMin=new XYZ(bbMin.X,bbMin.Y,0);
			XYZ newMax=new XYZ(bbMax.X,bbMax.Y,0);
			
			Curve line1=Line.CreateBound(newMax,newMin);
			XYZ centerPt=line1.Evaluate(0.5,true);
			
			//d) Get the direction of the distribution path from the rebar reinforcement
			//dissclosure: Free form rebars do not support getshapedrivenaccessor
			RebarShapeDrivenAccessor accessor=(reb as Rebar).GetShapeDrivenAccessor();
			XYZ dir=accessor.GetDistributionPath().Direction;
			
			//e).Get the curves of a typical rebar within the whole set
			IList<Curve> curves=accessor.ComputeDrivingCurves();
			
			//f).  filter rebars that have more than 1 segment (Null Reference from what is inside segments>1 or ==1!!)
			//try 
			//{

			if ( ((doc.GetElement((reb as Rebar).GetShapeId()) as RebarShape).GetRebarShapeDefinition() as RebarShapeDefinitionBySegments).NumberOfSegments >1 ) 
			{
				//f.1) Stirrups that follows a horizontal path direction: set try & catch for diagonal stirrup that follow hz dir
				if (Math.Round(Math.Abs(dir.X),4)== Math.Round(Math.Abs(view.RightDirection.X),4) && Math.Round(Math.Abs(dir.Y),4)==Math.Round(Math.Abs(view.RightDirection.Y),4))
				{
					rebTagged.Add(i,reb);
					Left.Add(i,rebLocInView);
					
				}
				
				//f.2) Stirrups that follow a vertical path direction for rebars
				if (Math.Round(Math.Abs(dir.Z),4)==Math.Round(Math.Abs(view.UpDirection.Z),4))
				{
					rebTagged.Add(i,reb);
					Top.Add(i,rebLocInView);
				}
			}
				
			if ( ((doc.GetElement((reb as Rebar).GetShapeId()) as RebarShape).GetRebarShapeDefinition() as RebarShapeDefinitionBySegments).NumberOfSegments == 1 ) 
			{
				//H.1).ANY REBAR ORIENTATION ALONG THE viewDirection: untagged()
				if (Math.Round(Math.Abs(dir.X),4)== Math.Round(Math.Abs(view.ViewDirection.X),4) && (Math.Round(Math.Abs(dir.Y),4)==Math.Round(Math.Abs(view.UpDirection.Y),4)) )
				{
					unTagged.Add(i, reb);
				}
				
				//H.2) straight Horizontal rebar along viewUpDirection (points along UpDir as well) --> This goes at Top or bottom
				if (Math.Round(Math.Abs(dir.X),4)== Math.Round(Math.Abs(view.UpDirection.X),4) && (Math.Round(Math.Abs(dir.Y),4)==Math.Round((Math.Abs(view.UpDirection.Y)),4)) && (Math.Round(Math.Abs((curves[0] as Line).Direction.Z)))==0 )
				{
					rebTagged.Add(i,reb);
					Top.Add(i,rebLocInView);
				}
				
				//H.3) straight vertical rebal along viewRight direction path
				if ( Math.Round(Math.Abs(dir.X),4) == Math.Round(Math.Abs(view.RightDirection.X),4) && Math.Round(Math.Abs(dir.Y),4) == Math.Round(Math.Abs(view.RightDirection.Y),4) && Math.Abs((curves[0] as Line).Direction.Z)==1)
				{
					
					rebTagged.Add(i,reb);
					Left.Add(i,rebLocInView);
					
				}
				
				
				// H.4) Horizontal rebars as points along the right side
				
				if (Math.Round(Math.Abs(dir.X),4) == Math.Round(Math.Abs(view.RightDirection.X),4) && Math.Round(Math.Abs(dir.Y),4) == Math.Round(Math.Abs(view.RightDirection.Y),4) && Math.Round(Math.Abs((curves[0] as Line).Direction.Z),4)==0 )
				{
					rebTagged.Add(i,reb);
					Left.Add(i,rebLocInView);
				}
			}	
			//} 
			//catch (Exception)
			//{
			//unTagged.Add(i,reb);
			//throw;
			//}
			

		}
	}
}
tr2.Commit();

 

0 Likes
Accepted solutions (1)
1,737 Views
12 Replies
Replies (12)
Message 2 of 13

RPTHOMAS108
Mentor
Mentor
Accepted solution

RebarShapeDefinition is the base class to:

 

RebarShapeDefinitionBySegments
RebarShapeDefinitionByArc (I imagine this one is quite rare however).

 

So perhaps your 'As' statement is leaving you with null where the type isn't RebarShapeDefinitionBySegments. It may not be this but the first step I would take is to break down some of those 'if' statements into more lines. So you can step through more deeply to the issue rather than not having much of an idea because the breakpoint encompasses a single line with many statements.

Message 3 of 13

mhannonQ65N2
Collaborator
Collaborator

Your problem is in ((doc.GetElement((reb as Rebar).GetShapeId()) as RebarShape). GetShapeId() returns an ElementId, not an element. You'll need to use Document.GetElement(id) to get the actual element.

0 Likes
Message 4 of 13

MiguelGT17
Advocate
Advocate

 

Element element=doc.GetElement(rebar.GetShapeId()); 
int segments;
if (element != null)
{
    RebarShape	shape=element as RebarShape;
    RebarShapeDefinition definition=shape.GetRebarShapeDefinition();							 
    RebarShapeDefinitionBySegments definitionSeg= definition as RebarShapeDefinitionBySegments;						 
    segments=definitionSeg.NumberOfSegments;
}

 

thanks for replying me Thomas, I've broken it down into those lines and the null exception still triggering from that part of the code. Would you say that's exactly how you usually get the number of segments from a rebar element?

0 Likes
Message 5 of 13

MiguelGT17
Advocate
Advocate

I'm quite sure this is how I get the element. I've working this way in python.

0 Likes
Message 6 of 13

mhannonQ65N2
Collaborator
Collaborator

I don't know how python does things but that method returns an ElementId in C#.

Message 7 of 13

MiguelGT17
Advocate
Advocate

Thanks Thomas for pointing that out, Indeed I needed to make sure the RebarShapeDefinitionBySegments variable was not null. It's a shame to not have the same power engine as Python to put all together at once 😕

 

 

Element element=doc.GetElement(rebar.GetShapeId()); 
RebarShape	shape=element as RebarShape;
RebarShapeDefinition definition=shape.GetRebarShapeDefinition();
RebarShapeDefinitionBySegments definitionSeg= definition as RebarShapeDefinitionBySegments;
if (definitionSeg != null)
{
    int segments = definitionSeg.NumberOfSegments;
    if ( segments > 1 )
    {
        //code
    }
    if (segments==1)
    {
        //code
    }

 

 

0 Likes
Message 8 of 13

MiguelGT17
Advocate
Advocate

Your are right, and this method reads an ElementId as well to grab the appropriate element

0 Likes
Message 9 of 13

MiguelGT17
Advocate
Advocate

Hi Thomas, appreciate the time you put into this topic. By the way, I could not even use the step by step debug, Do I need to change the shardevelop settings to see that command? 

MiguelGT17_0-1646684120083.png

 

0 Likes
Message 10 of 13

AGGilliam
Collaborator
Collaborator
After placing your breakpoint, make sure Revit is running and select Attach to Process, then select Revit. After you've attached to Revit you can run your command and start debugging. Although, you'll need to have the latest build of your code in your addins folder in order for it to work correctly.
Message 11 of 13

RPTHOMAS108
Mentor
Mentor

When you press the 'Edit' button the below controls are not visible, so use 'Edit', place your breakpoint, keep the editor open in the background, go back to the Macro Manager window, then press 'Step Into'.

 

220308a.png

220308.png

Message 12 of 13

AGGilliam
Collaborator
Collaborator

My apologies, just realized you mentioned the macro manager. My previous comment was for addins. I never use macros so I kind of forgot they existed.

Message 13 of 13

MiguelGT17
Advocate
Advocate

Many thanks to both of you! I'm set to go with that one

0 Likes