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: 

Copy dimensions from a View to another

20 REPLIES 20
SOLVED
Reply
Message 1 of 21
t.galland
5538 Views, 20 Replies

Copy dimensions from a View to another

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 !

20 REPLIES 20
Message 2 of 21
RPTHOMAS108
in reply to: t.galland

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)?

Message 3 of 21
t.galland
in reply to: RPTHOMAS108

Thank you for the responce.

 

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

Message 4 of 21
FAIR59
in reply to: t.galland

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.

  

Message 5 of 21
t.galland
in reply to: FAIR59

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.

 

Message 6 of 21
FAIR59
in reply to: t.galland

Copy/Paste is without rotation and mirroring??

 

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

Message 7 of 21
t.galland
in reply to: FAIR59

Yes copy/past was without mirroring and rotation.

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

 

Message 8 of 21
FAIR59
in reply to: t.galland

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?

Message 9 of 21
t.galland
in reply to: FAIR59

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 🙂

Message 10 of 21
FAIR59
in reply to: t.galland

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
in reply to: FAIR59

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

Message 12 of 21
FAIR59
in reply to: t.galland

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
in reply to: FAIR59

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 !

Message 14 of 21
brady0542
in reply to: t.galland

can you post the new code?

Message 15 of 21
t.galland
in reply to: brady0542

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

Message 16 of 21
t.galland
in reply to: brady0542

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();
}
Message 17 of 21
jeremytammik
in reply to: t.galland

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

Message 18 of 21
jeremytammik
in reply to: jeremytammik

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

Message 19 of 21
t.galland
in reply to: jeremytammik

Thank you for the feedback,

 

I was using Revit 2016 with the code pasted earlier.

 

If you need any file?

Message 20 of 21
jeremytammik
in reply to: t.galland

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

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