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 !
Solved! Go to Solution.
Solved by FAIR59. Go to Solution.
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)?
Thank you for the responce.
Both views are exactly the same and when I add the witness line, the entire dimension appear.
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.
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.
Copy/Paste is without rotation and mirroring??
So do you get the same result if you do only the first 1 transactions (Copy Elements) ?
Yes copy/past was without mirroring and rotation.
I get the same probleme when I do only the first transaction. Dimensions dosn't show.
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?
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 🙂
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.
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
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 !
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(); }
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:
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
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
Thank you for the feedback,
I was using Revit 2016 with the code pasted earlier.
If you need any file?
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