Set structural floor span direction using c#

Set structural floor span direction using c#

ramzy_ahmedhamdy
Explorer Explorer
1,800 Views
9 Replies
Message 1 of 10

Set structural floor span direction using c#

ramzy_ahmedhamdy
Explorer
Explorer

I’m working on a C# script to replace the sketch profile of a structural floor element by another Sketch profile by removing all curve elments in the old sketch profile then add new curves as a new sketch profile for the floor. The problem is a warning appears indicating “Structural floor span direction not specified” upon attempting to set the new sketch profile to the floor element. can any one help how can I set the floor span direction programmatically? 

Here's below the method I'm using 

public static void updateRevitFloors(UIDocument uidoc, Document revitDoc, ForgeTypeId targetUnitConvertor, List<Area2> rhinoAreas)
    {

 

 

        FilteredElementCollector collector = new FilteredElementCollector(revitDoc);
        ICollection<Element> revitFloorElements = collector.OfClass(typeof(Floor)).ToElements();

 

 

        foreach (var rhinoArea in rhinoAreas)
        {
            Element FloorElment = revitFloorElements.FirstOrDefault(x => x.Id.ToString() == rhinoArea.ID);

 

            if (FloorElment != null)
            {

 

 

                Floor fl = FloorElment as Floor;

 

 

                Element sketchElement = revitDoc.GetElement(fl.SketchId);

 

                if (sketchElement != null)
                {

 

                    Sketch sketch = sketchElement as Sketch;

 

                    #region get old Profile Curves To be Removed

 

                    // Get sketch elements
                    var sketchEleIds = sketch.GetAllElements();

 

                    var oldProfileCurves = new List<ElementId>();
                    foreach (var i in sketchEleIds)
                    {

 

                        oldProfileCurves.Add(i);

 

                    }
                    #endregion

 

 

                    SketchEditScope sketchEditScope = new SketchEditScope(revitDoc, "Edit Sketch");
                    sketchEditScope.Start(sketch.Id);

 

 

                    using (Transaction transaction = new Transaction(revitDoc, "Modify sketch"))
                    {
                        transaction.Start();

 

 

                        // Delete curves from the current sketch
                        foreach (var curve in oldProfileCurves)
                        {
                          revitDoc.Delete(curve as ElementId);
                        }

 

 

                        List<Rhino.Geometry.Curve[]> crvList = new List<Rhino.Geometry.Curve[]>();

 

                        foreach (Curve i in rhinoArea.outerCurves)
                        {
                            crvList.Add(i.DuplicateSegments());

 

                        }

 

 

                        foreach (Curve i in rhinoArea.innerCurves)
                        {
                            crvList.Add(i.DuplicateSegments());

 

 

                        }
                        IEnumerable<Rhino.Geometry.Curve> flatCrvList = crvList.SelectMany(x => x);

 

 

                        foreach (var rhinoCrv in flatCrvList)
                        {
                            Autodesk.Revit.DB.Curve c = RhinoInside.Revit.Convert.Geometry.GeometryEncoder.ToCurve(rhinoCrv);
                            revitDoc.Create.NewModelCurve(c, sketch.SketchPlane);
                        }

 

 

                        fl.SpanDirectionAngle = 90 * Math.PI / 180;

 

                        transaction.Commit();
                    }

 

                    sketchEditScope.Commit(new RoomWarningSwallower());
                }
            }
        }

 

    }

0 Likes
1,801 Views
9 Replies
Replies (9)
Message 2 of 10

jeremy_tammik
Alumni
Alumni

This sounds like a task that is worth exploring manually in the end user interface before addressing it programmatically via the API. Can you achieve what you want manually in the UI? What exact steps to you take to do so? Please research the result of each step you take using RevitLookup and other database exploration tools to determine how they affect the BIM from an API point of view. With that information in hand, you have a good basis for a programmatic solution.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 10

ramzy_ahmedhamdy
Explorer
Explorer

Thank you  Jeremy for your kind end prompt response.  Here's below snap shot from the warning appearing when I try to edit the sketch profile of the floor.
8fc79dc34234a827826a801a3536becbd650d8d8.png

0 Likes
Message 4 of 10

ramzy_ahmedhamdy
Explorer
Explorer

Here's An additional screen shoot for how the end user can set this span direction manually.

Capture.PNG

 

0 Likes
Message 5 of 10

Speed_CAD
Collaborator
Collaborator

Hi,

 

I'm not sure, but it seems to me that for this case the solution would be to confirm the transaction to edit the slab sketch and then open another transaction to edit the spandirection angle. I don't know if it works within a transaction group, I haven't tested it, you would have to check if it works with TransactionGroup.

Mauricio Jorquera
0 Likes
Message 6 of 10

studio-a-int
Advocate
Advocate

Use the below method to change the Floor Span Direction Angle

public void SetFloorDirection(Autodesk.Revit.DB.Document activeDoc)
{
// Code provided courtesy of:
// Studio A International, LLC
// http://www.studio-a-int.com
// The code selects one Floor element in Active Document
// and changes Floor Span Direction Angle
Double rad = 57.29573672;
FilteredElementCollector collectorElements = new FilteredElementCollector(activeDoc).WhereElementIsNotElementType();
ICollection<Element> allFloorElements = collectorElements.OfClass(typeof(Autodesk.Revit.DB.Floor)).ToElements();
Autodesk.Revit.DB.Floor floorSelected = allFloorElements.FirstOrDefault() as Autodesk.Revit.DB.Floor;
using (Transaction tr = new Transaction(activeDoc, "Change Floor Span Direction Angle"))
{
tr.Start();
var currentSDA = floorSelected.SpanDirectionAngle;
floorSelected.SpanDirectionAngle = currentSDA + rad; // Use the angle of your choice
activeDoc.Regenerate();
tr.Commit();
}

}

0 Likes
Message 7 of 10

ctm_mka
Collaborator
Collaborator

@ramzy_ahmedhamdy  i see nothing wrong with your code, you set the span direction at teh correct place, my guess is something to do with SketchEditScope, maybe thats out of place? Second, have you considered creating a new floor and then deleting the old floor rather that editing (i had no problem setting span direction when creating new floor)? the code would look something like this:

//grab sketch and modify as needed, create curveloop from all curves
//then transaction  to create/modify
Floor newfloor = null;
using (Transaction tr = new Transaction(_doc))
{
      tr.Start("Create new floors");
      newfloor = Floor.Create(_doc, CurveArrary, fl.FloorType.Id, fl.LevelId);
       _doc.Delete(fl.Id);
       newfloor.SpanDirectionAngle = 45;
       tr.Commit();
}

 

0 Likes
Message 8 of 10

RPTHOMAS108
Mentor
Mentor

Interesting problem you have and likely not as straightforward as believed.

 

1) Every slab needs a span direction model line added to sketch so if you are editing an existing sketch you need to maintain the current span direction model line but you can't always identity which model line it is it seems!

2) The span direction model line is either (A) one of the sketched edges or (B) a single isolated line within the sketch.

3) I believe you can only easily identify type (B) since it is a model line named 'Span Direction Edges'. When a model line acts both as floor profile and span direction I believe this can't be identified (it is just called model line). All sketched lines are of category sketch (so also not helpful).

4) You can't create (A) or (B) via the API directly as far as I know. You can perhaps copy an existing one into the sketch perhaps.

5) The methods that create floors within the API will automatically add (A) or (B) to sketch when slab is made (so you can always create new floors with API).

6) Going back to original problem you are deleting all the lines and re-sketching. So it may be possible to paste in a type (B) span direction line (can only have one per sketch). You can perhaps first ensure one exists in the model by creating a circular slab with the API i.e. one where the model line used for span direction can't be used for slab profile. It may be the API always opts for (B) anyway when creating slabs I can't recall. Probably if your span direction is changed via parameter to something other than 0 or 90 with respect to first image below then you also get a (B) model line added to sketch i.e. since angle is not common to existing edge.

 

Item (6) would be a bit untested it is easier to recreate the slab but I assume your motivation for editing the sketch is that you want to keep the existing element identity and/or parameter values.

 

RPTHOMAS108_0-1707169140320.png

Type A

RPTHOMAS108_1-1707169184013.png

Type B

 

Lastly if you can't identify the model line used for span direction within the sketch (where you need to edit out some of the lines) then logically the only thing you can do to edit sketch is delete all the lines (as two span direction lines can't exist in a sketch).

 

Considering all of above here is a possible quick solution: find all lines in your original sketch and change the angle of the slab span to not match any of these lines prior to editing the sketch. Edit the lines of the sketch knowing that the span direction model line also contained within is now not end joined with any of the profile edge model lines being removed (also it should now have name 'Span Direction Edges' that identifies it). After finishing editing slab restore original span direction.

 

You can also identify the type (B) line by comparing the model lines you have before and after changing the span direction to not match any of the current edge directions.

Message 9 of 10

ramzy_ahmedhamdy
Explorer
Explorer

Thank you so much for you explanation. it truly helped me to address this problem. i just set the (Structural) parameter to be false before editing the profile then set it again to true after modifying the profile and it worked fine :D. Below is the final solution from my side.


public static void updateRevitFloors(UIDocument uidoc, Document revitDoc, ForgeTypeId targetUnitConvertor)
{
List<RevitArea> rhinoAreas = RevitRhino.getRhinoAreas();
rhinoAreas = rhinoAreas.Where(x => x.type == "Area").ToList();

FilteredElementCollector collector = new FilteredElementCollector(revitDoc);
ICollection<Element> revitFloorElements = collector.OfClass(typeof(Floor)).ToElements();


foreach (var rhinoArea in rhinoAreas)
{
Element FloorElment = revitFloorElements.FirstOrDefault(x => x.Id.ToString() == rhinoArea.ID);

if (FloorElment != null)
{

Floor fl = FloorElment as Floor;

using (Transaction tr = new Transaction(revitDoc,"changeToArch"))
{
tr.Start("change");

fl.LookupParameter("Structural").Set(0);

tr.Commit();


}

using (SketchEditScope sketchEditScope2 = new SketchEditScope(revitDoc, "Edit Sketch"))
{
if (sketchEditScope2.IsSketchEditingSupported(fl.SketchId))
{
Element sketchElement = revitDoc.GetElement(fl.SketchId);
Sketch sketch = sketchElement as Sketch;

 


sketchEditScope2.Start(sketch.Id);


using (TransactionGroup trnsGroup = new TransactionGroup(revitDoc, "StartTransGroup"))
{

trnsGroup.Start();

using (Transaction transaction = new Transaction(revitDoc, "Modify sketch"))
{


transaction.Start();

#region Remove old SketchProfile

// Get sketch elements
var sketchEleIds = sketch.GetAllElements();

revitDoc.Delete(sketchEleIds.ToArray());

 

#endregion


List<Rhino.Geometry.Curve[]> crvList = new List<Rhino.Geometry.Curve[]>();


var revitPlane = sketch.SketchPlane.GetPlane();
var rhinoPlane = RhinoInside.Revit.Convert.Geometry.GeometryDecoder.ToPlane(revitPlane);

foreach (Curve i in rhinoArea.outerCurves)
{

var loop = Curve.ProjectToPlane(i, rhinoPlane);
var segments = loop.DuplicateSegments();
crvList.Add(segments);

}

foreach (Curve i in rhinoArea.innerCurves)
{
var loop = Curve.ProjectToPlane(i, rhinoPlane);
var segments = loop.DuplicateSegments();
crvList.Add(segments);

}

IEnumerable<Rhino.Geometry.Curve> flatCrvList = crvList.SelectMany(x => x);
foreach (var i in flatCrvList)
{
Autodesk.Revit.DB.Curve c = RhinoInside.Revit.Convert.Geometry.GeometryEncoder.ToCurve(i);
revitDoc.Create.NewModelCurve(c, sketch.SketchPlane);
}

using (var uiApplication = new Autodesk.Revit.UI.UIApplication(revitDoc.Application))
{
EventHandler<ARUI.Events.DialogBoxShowingEventArgs> DialogBoxShowing = null;

try
{
uiApplication.DialogBoxShowing += DialogBoxShowing = (sender, args) =>
{
if (args.DialogId == "TaskDialog_Sketch_Edits_Discarded")
args.OverrideResult(1001 /*IDYES*/);
};

revitDoc.Regenerate();

 

transaction.Commit();

 

 

 

}

catch (Autodesk.Revit.Exceptions.InvalidOperationException) { return; }
finally { uiApplication.DialogBoxShowing -= DialogBoxShowing; }
}

 


}


//using (Transaction trns2 = new Transaction(revitDoc, "modifySpanDirection"))
//{
// trns2.Start();
// fl.SpanDirectionAngle = 0;
// trns2.Commit();

//}

 

trnsGroup.Commit();

}


sketchEditScope2.Commit(new RoomWarningSwallower());

 


}

 

 

}

using (Transaction tr = new Transaction(revitDoc, "changeToSTR"))
{
tr.Start("change");

fl.LookupParameter("Structural").Set(1);

tr.Commit();


}

 


}


// create new floor
else
{

}
}

}

Message 10 of 10

Speed_CAD
Collaborator
Collaborator

Hi ramzy_ahmedhamdy, Good solution.

 

If you modify the Structural parameter inside TransactionGroup, it doesn't work? I ask this because if it worked it would be cleaner for the user in case they need to do Undo.

Mauricio Jorquera
0 Likes