Copy dimensions from a View to another

Copy dimensions from a View to another

t.galland
Contributor Contributor
7,739 Views
20 Replies
Message 1 of 21

Copy dimensions from a View to another

t.galland
Contributor
Contributor

Hello,

 

I'm trying to create a new plug-in on Revit 2016/2017 with the API. The idea is to copy a set of element from small revit file to a central one to compile them.

Here is the code I'm using :

UIDocument mainUiDoc;
Document mainDoc;
string mainPath;
UIDocument secUiDoc;
Document secDoc;

try
{
    mainUiDoc = app.ActiveUIDocument;
    mainDoc = mainUiDoc.Document;
    ViewPlan mainView = (ViewPlan)mainDoc.ActiveView;
    mainPath = mainDoc.PathName;


    XYZ extremitePoint;



    Selection sel = mainUiDoc.Selection;
    extremitePoint = sel.PickPoint("Selectionner le coin sup. gauche de la feuille");
    secUiDoc = app.OpenAndActivateDocument(((RevitFile)Main._roomData["revit"]).Path);
    secDoc = secUiDoc.Document;

    FilteredElementCollector collector = new FilteredElementCollector(secDoc);
    ViewPlan secView = collector.OfClass(typeof(ViewPlan)).Cast<ViewPlan>().First(
        x => x.ViewType == ViewType.FloorPlan &&
        x.IsTemplate == false &&
        x.Name.Contains(((RevitFile)Main._roomData["revit"]).Typology, StringComparison.OrdinalIgnoreCase));

    secUiDoc.ActiveView = secView;

    FilterableValueProvider provider = new ParameterValueProvider(new ElementId(BuiltInParameter.ALL_MODEL_TYPE_NAME));
    FilterRule rule = new FilterStringRule(provider, new FilterStringContains(), "BY_GO", false);
    ElementParameterFilter epf = new ElementParameterFilter(rule, true);
    ICollection<ElementId> npText = new FilteredElementCollector(secDoc, secView.Id).WherePasses(epf).ToElementIds();
    using (TransactionGroup tx = new TransactionGroup(mainDoc, "Insert"))
    {
        ICollection<ElementId> pastedElements;
        tx.Start();
        using (Transaction tr = new Transaction(mainDoc, "Copy elements"))
        {
            tr.Start();
            FailureHandlingOptions failOpt = tr.GetFailureHandlingOptions();
            failOpt.SetFailuresPreprocessor(new WarningSwallower());
            tr.SetFailureHandlingOptions(failOpt);


            pastedElements = ElementTransformUtils.CopyElements(secView, npText, mainView,null, new CopyPasteOptions());
            mainDoc.Regenerate();
            tr.Commit();
        }
        using (Transaction tr = new Transaction(mainDoc, "translate elements"))
        {
            tr.Start();
            pastedElements = new FilteredElementCollector(mainDoc, pastedElements).WherePasses(epf).ToElementIds();
            BoundingBoxXYZ floor = new FilteredElementCollector(mainDoc, pastedElements).OfClass(typeof(Floor)).First().get_BoundingBox(null);
            XYZ originePoint = floor.Min;
            XYZ translation = extremitePoint - originePoint;
            translation = new XYZ(translation.X, translation.Y, 0);
            ElementTransformUtils.MoveElements(mainDoc, pastedElements, translation);
            tr.Commit();
        }
        using (Transaction tr = new Transaction(mainDoc, "rotate elements"))
        {
            tr.Start();
            BoundingBoxXYZ floor = new FilteredElementCollector(mainDoc, pastedElements).OfClass(typeof(Floor)).First().get_BoundingBox(null);
            XYZ originePoint = floor.Min;
            Line rotation = Line.CreateBound(extremitePoint, new XYZ(extremitePoint.X, extremitePoint.Y, extremitePoint.Z+10));
            ElementTransformUtils.RotateElements(mainDoc, pastedElements, rotation, - (double)Main._roomData["rotation"] * Math.PI / 180);
            tr.Commit();
        }
        using (Transaction tr = new Transaction(mainDoc, "miror elements"))
        {
            tr.Start();
            pastedElements = new FilteredElementCollector(mainDoc, pastedElements).WherePasses(epf).ToElementIds();
            BoundingBoxXYZ floor = new FilteredElementCollector(mainDoc, pastedElements).OfClass(typeof(Floor)).First().get_BoundingBox(null);
            Plane mirror = null;
            switch ((string)Main._roomData["Symétries"])
            {
                case "nulle":
                    break;
                case "horizontale":
                    mirror = new Plane(new XYZ(1, 0, 0), new XYZ((floor.Max.X + floor.Min.X) / 2, (floor.Max.Y + floor.Min.Y) / 2, 0));
                    ElementTransformUtils.MirrorElements(mainDoc, pastedElements, mirror, false);
                    break;
                case "verticale":
                    mirror = new Plane(new XYZ(0, 1, 0), new XYZ((floor.Max.X + floor.Min.X) / 2, (floor.Max.Y + floor.Min.Y) / 2, 0));
                    ElementTransformUtils.MirrorElements(mainDoc, pastedElements, mirror, false);
                    break;
                default:
                    break;
            }
            tr.Commit();
        }
        tx.Assimilate();
    }

When I use it, everything is good except the dimensions. They are inside the new document (I can get them with there id and RevitLookup) but they are hidden. If I select on of them and add a witness line the dimension is now visible again. I tried to close and reopen Revit and place the vien on a sheet bt nothing.

Any idea ?

Thank you !

0 Likes
Accepted solutions (1)
7,740 Views
20 Replies
Replies (20)
Message 2 of 21

RPTHOMAS108
Mentor
Mentor

Do the views have the same discipline, category visibility and detail levels?


You say only the dimensions do not appear but in the case of detail level the original references may be attached to parts of the element not visible in the new view. If you then add a witness line does only that part of the dimension appear or does the entire dimension appear (with all other witness lines)?

0 Likes
Message 3 of 21

t.galland
Contributor
Contributor

Thank you for the responce.

 

Both views are exactly the same and when I add the witness line, the entire dimension appear.

0 Likes
Message 4 of 21

FAIR59
Advisor
Advisor

You are issuing a doc.Regenerate command for an inactive document. I think it's possible that in Revit's inner code such a command only gets executed partially. Mind you, i'am only guessing.

But since you don't need to activate your second document (based on your published code), I suggest you open the second document with

app.Application.OpenDocumentFile(). Then your main document remains the active document, and doc.regenerate should work as expected.

 

Secondly I would call the doc.Regenerate at the start of the 2nd transaction.

 

Hope this helps.

  

0 Likes
Message 5 of 21

t.galland
Contributor
Contributor

I updated the code as follow but I still get the same result.

mainUiDoc = app.ActiveUIDocument;
mainDoc = mainUiDoc.Document;
ViewPlan mainView = (ViewPlan)mainDoc.ActiveView;
mainPath = mainDoc.PathName;


XYZ extremitePoint;



Selection sel = mainUiDoc.Selection;
extremitePoint = sel.PickPoint("Selectionner le coin sup. gauche de la feuille");
secDoc = app.Application.OpenDocumentFile(((RevitFile)Main._roomData["revit"]).Path);
                

FilteredElementCollector collector = new FilteredElementCollector(secDoc);
ViewPlan secView = collector.OfClass(typeof(ViewPlan)).Cast<ViewPlan>().First(
    x => x.ViewType == ViewType.FloorPlan &&
    x.IsTemplate == false &&
    x.Name.Contains(((RevitFile)Main._roomData["revit"]).Typology, StringComparison.OrdinalIgnoreCase));

FilterableValueProvider provider = new ParameterValueProvider(new ElementId(BuiltInParameter.ALL_MODEL_TYPE_NAME));
FilterRule rule = new FilterStringRule(provider, new FilterStringContains(), "BY_GO", false);
ElementParameterFilter epf = new ElementParameterFilter(rule, true);
ICollection<ElementId> npText = new FilteredElementCollector(secDoc, secView.Id).WherePasses(epf).ToElementIds();
using (TransactionGroup tx = new TransactionGroup(mainDoc, "Insert"))
{
    ICollection<ElementId> pastedElements;
    tx.Start();
    using (Transaction tr = new Transaction(mainDoc, "Copy elements"))
    {
        tr.Start();
        //FailureHandlingOptions failOpt = tr.GetFailureHandlingOptions();
        //failOpt.SetFailuresPreprocessor(new WarningSwallower());
        //tr.SetFailureHandlingOptions(failOpt);


        pastedElements = ElementTransformUtils.CopyElements(secView, npText, mainView, null, new CopyPasteOptions());
        tr.Commit();
    }
    using (Transaction tr = new Transaction(mainDoc, "translate elements"))
    {
        tr.Start();
        mainDoc.Regenerate();
        pastedElements = new FilteredElementCollector(mainDoc, pastedElements).WherePasses(epf).ToElementIds();
        BoundingBoxXYZ floor = new FilteredElementCollector(mainDoc, pastedElements).OfClass(typeof(Floor)).First().get_BoundingBox(null);
        XYZ originePoint = floor.Min;
        XYZ translation = extremitePoint - originePoint;
        translation = new XYZ(translation.X, translation.Y, 0);
        ElementTransformUtils.MoveElements(mainDoc, pastedElements, translation);
        tr.Commit();
    }
    using (Transaction tr = new Transaction(mainDoc, "rotate elements"))
    {
        tr.Start();
        Line rotation = Line.CreateBound(extremitePoint, new XYZ(extremitePoint.X, extremitePoint.Y, extremitePoint.Z + 10));
        ElementTransformUtils.RotateElements(mainDoc, pastedElements, rotation, -(double)Main._roomData["rotation"] * Math.PI / 180);
        tr.Commit();
    }
    using (Transaction tr = new Transaction(mainDoc, "miror elements"))
    {
        tr.Start();
        pastedElements = new FilteredElementCollector(mainDoc, pastedElements).WherePasses(epf).ToElementIds();
        BoundingBoxXYZ floor = new FilteredElementCollector(mainDoc, pastedElements).OfClass(typeof(Floor)).First().get_BoundingBox(null);
        Plane mirror = null;
        switch ((string)Main._roomData["Symétries"])
        {
            case "nulle":
                break;
            case "horizontale":
                mirror = new Plane(new XYZ(1, 0, 0), new XYZ((floor.Max.X + floor.Min.X) / 2, (floor.Max.Y + floor.Min.Y) / 2, 0));
                ElementTransformUtils.MirrorElements(mainDoc, pastedElements, mirror, false);
                break;
            case "verticale":
                mirror = new Plane(new XYZ(0, 1, 0), new XYZ((floor.Max.X + floor.Min.X) / 2, (floor.Max.Y + floor.Min.Y) / 2, 0));
                ElementTransformUtils.MirrorElements(mainDoc, pastedElements, mirror, false);
                break;
            default:
                break;
        }
        tr.Commit();
    }
    using (Transaction tr = new Transaction(mainDoc, "identify elements"))
    {
        tr.Start();
        foreach (ElementId id in pastedElements)
        {
            foreach (Parameter parametre in mainDoc.GetElement(id).Parameters)
            {
                switch (parametre.Definition.Name)
                {
                    case "BY_IdBatiment":
                        parametre.Set((string)Main._roomData["BY_IdBatiment"]);
                        break;
                    case "BY_IdCage":
                        parametre.Set((string)Main._roomData["BY_IdCage"]);
                        break;
                    case "BY_IdEtage":
                        parametre.Set((string)Main._roomData["BY_IdEtage"]);
                        break;
                    case "BY_IdLogement":
                        parametre.Set((string)Main._roomData["BY_IdLogement"]);
                        break;
                    default:
                        break;
                }
            }
                            
        }
        tr.Commit();
    }
    tx.Assimilate();
}
//app.OpenAndActivateDocument(mainPath);
secDoc.Close(false);

I tried to copy/paste manually and everything is good. The dimensions are showing normaly.

 

0 Likes
Message 6 of 21

FAIR59
Advisor
Advisor

Copy/Paste is without rotation and mirroring??

 

So do you get the same result if you do only the first 1 transactions (Copy Elements) ?

0 Likes
Message 7 of 21

t.galland
Contributor
Contributor

Yes copy/past was without mirroring and rotation.

I get the same probleme when I do only the first transaction. Dimensions dosn't show.

 

0 Likes
Message 8 of 21

FAIR59
Advisor
Advisor

I'm fast running out of things to try, but what happens if you copy the elements in the 2nd transaction instead of translating them?

0 Likes
Message 9 of 21

t.galland
Contributor
Contributor

I got an error because the ids are not generated before the commit of the transaction 😞

I'm out of ideas too, that's why I asked here ^^ Hoping for someone to have the solution 🙂

0 Likes
Message 10 of 21

FAIR59
Advisor
Advisor

I've run some tests myself, and found the root of the problem. I'm afraid it's a bug. The CopyElements method places the annotation items ( detail lines, textnotes and dimensions)  NOT on the sketchplane  of the ActiveView, but on the sketchplane of a level.

 

And since you can't set the SketchPlane of the annotation items, I don't see any solution.

 

Message 11 of 21

t.galland
Contributor
Contributor

So if I well understood, unless Autodesk solve this bug, there is nothing to do ?

0 Likes
Message 12 of 21

FAIR59
Advisor
Advisor
Accepted solution

Yes, Autodesk has to fix this. 

 

The workaround for dimensions to model elements, is rather simple. Create a new Dimension, using the References from the non-visible dimension.

 

						Dimension dim ;
						doc.Create.NewDimension(mainView,dim.Curve as Line,dim.References, dim.DimensionType);

  

PS: don't forget to delete the non-visible dimension

Message 13 of 21

t.galland
Contributor
Contributor

I'm gonna try this and keep you in touch !

thx  !

 

EDIT : It's perfect, I did a loop foreach dim and use your code. Thank's a lot for your help !

0 Likes
Message 14 of 21

brady0542
Contributor
Contributor

can you post the new code?

0 Likes
Message 15 of 21

t.galland
Contributor
Contributor

Sure, I'll post it tomorrow. I'm not at home for now !

0 Likes
Message 16 of 21

t.galland
Contributor
Contributor

Here is the loop I'm using :

 

using (var tr = new Transaction(mainDoc, "Place dimensions"))
{
    tr.Start();
    var dimensions = new FilteredElementCollector(mainDoc, pastedElements).OfClass(typeof(Dimension)).ToElementIds();
                        
    foreach (var id in dimensions)
    {
        pastedElements.Remove(id);
        var dim = (Dimension)mainDoc.GetElement(id);
        var newDim = mainDoc.Create.NewDimension(mainView, dim.Curve as Line, dim.References, dim.DimensionType);
        mainDoc.Delete(id);
        pastedElements.Add(newDim.Id);
    }
    tr.Commit();
}
0 Likes
Message 17 of 21

jeremytammik
Autodesk
Autodesk

Dear Thibaud,

 

Thank you for your report, and many thanks to FAIR59 for his in-depth research and simple fix.

 

Sorry to hear about this.

 

I logged the issue REVIT-129029 [Dimensions are not displayed after copy and paste between documents -- 13180620]

 with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

Best regards,

 

Jeremy



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

0 Likes
Message 18 of 21

jeremytammik
Autodesk
Autodesk

Dear Thibaud,

 

Thank you for your patience.

 

The development team analysed the issue REVIT-129029 [Dimensions are not displayed after copy and paste between documents -- 13180620] and say:

 

I just wrote a simple code to copy and paste a wall and its dimension from one document to another document.

 

Result: can't reproduce this issue, both the wall and the dimension are shown in the another document.

 

Please ask the customer to provide the Revit source and target documents used to do the copy.

 

I want debug the code the customer provided in his documents.

 

Thank you!

 

Best regards,

 

Jeremy



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

0 Likes
Message 19 of 21

t.galland
Contributor
Contributor

Thank you for the feedback,

 

I was using Revit 2016 with the code pasted earlier.

 

If you need any file?

0 Likes
Message 20 of 21

jeremytammik
Autodesk
Autodesk

Dear Thibaud,

 

Thank you for your update.

 

Yes, please. The development team is asking for the source and target documents.

 

Thank you!

 

Best regards,

 

Jeremy



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

0 Likes