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: 

Adjusting Wall.LocationCurve.Curve results in unexpected behaviour

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
Anonymous
1471 Views, 6 Replies

Adjusting Wall.LocationCurve.Curve results in unexpected behaviour

Hi,

we have a plugin, that should adjust walls lines slightly (move them, rotate them a bit and also should adjust the length of the walls a bit).

 

With  wall.Location.Move( xyzTranalation ) and wall.Location.Rotate(...) we could adjust the location and rotation of the walls, but not the length of the walls. So we decided to follow the approach, that is suggested on buildingcoder 10years ago:

 

https://thebuildingcoder.typepad.com/blog/2010/08/edit-wall-length.html

 

  // get the current wall location
  LocationCurve wallLocation = myWall.Location 
    as LocationCurve;
 
  // get the points
  XYZ pt1 = wallLocation.Curve.get_EndPoint( 0 );
  XYZ pt2 = wallLocation.Curve.get_EndPoint( 1 );
 
  // change one point, e.g. move 1000 mm on X axis
 
  pt2 = pt2.Add( new XYZ( 0.01 ), 0, 0 ) );
 
  // create a new LineBound
  Line newWallLine = app.Create.NewLineBound( 
    pt1, pt2 );
 
  // update the wall curve
  wallLocation.Curve = newWallLine;

This seems to work fine for single walls. But fails in many cases the wall have hosted elements like windows and even in complex scenarios with multiple walls (Note: the movement is just very less about some mm!) 

 

To show you, what I mean, I wrote a short macro embedded in the rvt that is attached.

The macro "LocationLineReset" just moves the wall inside the rvt by approx. 3mm using the suggested method from buildingcoder

 

Capture2.PNG

 

The result is the following:

Capture.PNG

 

 

This seem like a not expected behavior. The windows is now located outside the wall although the wall have moved just about 3mm. Is this a bug?

 

If I use the second macro "ShiftWall", which just does a wall.LocationCurve.Move( new XYZ(0.01, 0.01,0) ) which is an equivalent translation to the former marco, the result is fine.

 

If their would be a method to adjust the length of the wall different to resetting the wall.LocationCurve.Curve = Line.CreateBound( ... ) like mentioned on the buildingcoder page, this would solve our issue as well. Is their any such method? I couldn't find a solution neighter in API forum, buildincoder nor google.

 

Thanks

Harald

6 REPLIES 6
Message 2 of 7
jeremytammik
in reply to: Anonymous

Dear Harald,

 

Thank you for your interesting observation and careful analysis.

 

I looked at your macros and can reproduce what you say. 

 

Besides the macro you list, LocationLineReset, there is another one that slightly moves the existing location line instead of creating a new one, ShiftWall.

 

That latter macro completes successfully:

 

  public void LocationLineReset()
  {
    doc = this.Application.ActiveUIDocument.Document;
    Wall wall = doc.GetElement( new ElementId( 305891 ) ) as Wall;
    TransactionStatus status;
    using ( Transaction trans = new Transaction( doc, "bla" ) )
    {
      trans.Start();
      LocationCurve locationCurve = wall.Location as LocationCurve;
      Line wallLine = locationCurve.Curve as Line;
      
      XYZ startPoint = wallLine.GetEndPoint(0);
      XYZ endPoint = wallLine.GetEndPoint(1);

      XYZ minimalMoveVector = new XYZ( 0.01 /* =~ 3mm*/, 0.01, 0.0);
      startPoint += minimalMoveVector;
      endPoint += minimalMoveVector;
      
      locationCurve.Curve = Line.CreateBound( startPoint, endPoint );
      status = trans.Commit();
    }
    
    if( status != TransactionStatus.Committed ) 
      MessageBox.Show( "Commit failed" );
  }
  
  public void ShiftWall()
  {
    doc = this.Application.ActiveUIDocument.Document;
    Wall wall = doc.GetElement( new ElementId( 305891 ) ) as Wall;
    TransactionStatus status;
    bool bSuccess = false;
    using ( Transaction trans = new Transaction( doc, "bla" ) )
    {
      trans.Start();

      XYZ minimalMoveVector = new XYZ( 0.01 /* =~ 3mm*/, 0.01, 0.0);				
      bSuccess = wall.Location.Move( minimalMoveVector );
      
      status = trans.Commit();
    }
    
    if( status == TransactionStatus.Committed && bSuccess) 
      MessageBox.Show( "Shift succeeded" );
  }

 

I would assume that during the process of resetting the wall location line from scratch, the window position gets completely lost.

 

When you simply perform a small adjustment to the existing location line, the window position is retained and adjusted accordingly.

 

Therefore, I would suggest using the latter approach whenever possible.

 

You could even make use of the latter approach in several steps, adjust first one and then the other location line endpoint.

 

I hope this enables you to handle all required situations.

 

Best regards,

 

Jeremy

 

 

 



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

Message 3 of 7
jeremytammik
in reply to: Anonymous

Rereading your question in more details, I now address the question you raise at the end:

 

> Is there any method to adjust the length of the wall except resetting the `wall.LocationCurve.Curve` by creating a new curve using `Line.CreateBound`? That would solve our issue as well.

 

Yes, absolutely. You can modify just one of the line endpoints without changing the other one, and you can also change both endpoints at the same time by moving them by different translation vectors...

 

... or so I thought, until this very moment. 

 

Now I looked a the Revit API documentation Curve and Line member methods, expecting to point out the SetEndPoint methods to you, only to discover they do not exist:

 

https://www.revitapidocs.com/2020/92a388f3-4949-465c-b938-2906ff6bdf5b.htm

  

Oh dear.

  

In that case, you really do have to create a new curve from scratch, and the problem you describe arises.

 

The only other way I could think of to try to modify an existing curve's length is to change its start and end parameters.

 

In theory, this can be achieved by calling MakeBound. However, all my attempts to use that method to modify the wall length had no result. Here is the final attempt:

 

  public void ShortenWall()
  {
    Document doc = this.Application.ActiveUIDocument.Document;
    Wall wall = doc.GetElement( new ElementId( 305891 ) ) as Wall;
    TransactionStatus status;
    using ( Transaction trans = new Transaction( doc ) )
    {
      trans.Start( "Shorten Wall");
      
      LocationCurve lc = wall.Location as LocationCurve;
      Line ll = lc.Curve as Line;
      
      double pstart = ll.GetEndParameter(0);
      double pend = ll.GetEndParameter(1);
      double pdelta = 0.05 * (pend - pstart);
      
      lc.Curve.MakeBound(pstart + pdelta, pend - pdelta); // no observable change to wall
      
      (wall.Location as LocationCurve).Curve.MakeUnbound();
      
      (wall.Location as LocationCurve).Curve.MakeBound( // no observable change to wall
        pstart + pdelta, pend - pdelta);
  
      status = trans.Commit();
    }
    
    if( status == TransactionStatus.Committed) 
      MessageBox.Show( "Shorten Wall succeeded" );
  }

 

Sorry for the bad news.

 

I can raise an issue with the development team for this for you and see what they have to say about it.

 

Best regards,

 

Jeremy

 



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

Message 4 of 7
FAIR59
in reply to: Anonymous

You can adjust the curve of a wall with hosted elements, if the "curve definition" stays the same, i.e. just changing the start- and end parameters.

	LocationCurve lc = wall.Location as LocationCurve;
	Curve ll = lc.Curve;
      
	double pstart = ll.GetEndParameter(0);
	double pend = ll.GetEndParameter(1);
	double pdelta = 0.001 * (pend - pstart);
      
	ll.MakeUnbound();
	ll.MakeBound(pstart + pdelta, pend - pdelta);
      
	lc.Curve = ll;

 

Message 5 of 7
jeremytammik
in reply to: FAIR59

Great! Brilliant! So my code was just lacking the assignment! Thank you!

 



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

Message 6 of 7
Anonymous
in reply to: FAIR59

Thank you and Jeremy for solving the issue! 

 

Just a minor question, can we expect that the wall line parameter scales the position of the start/end point uniformly to feet? E.g. if we want to adjust the length of the wall by 0.1 feet, can we always do the following:

        double pstart = ll.GetEndParameter(0);
	double pend = ll.GetEndParameter(1);
      
	ll.MakeUnbound();
	ll.MakeBound( pstart, pend + 0.1 /* moves always the end point by 0.1 feet */);       
	lc.Curve = ll;

In my example it did, but I am not sure if this is an invariant we can rely on?

Thanks again

Message 7 of 7
FAIR59
in reply to: Anonymous

see the remarks in the online documentation of the GetEndParameter method:

https://www.revitapidocs.com/2016/0f4b2c25-35f8-4e3c-c71a-0d41fb6935ce.htm 

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

Post to forums  

Rail Community


Autodesk Design & Make Report