public static List<DecalData> GetDecalsFromDocument(Document doc) { var ids = ExternalFileUtils.GetAllExternalFileReferences(doc); var decalIds = (from id in ids let ext = ExternalFileUtils.GetExternalFileReference(doc, id) where ext != null && ext.ExternalFileReferenceType == ExternalFileReferenceType.Decal select id); var collector = new FilteredElementCollector(doc); var elems = collector.OfCategory(BuiltInCategory.OST_GenericModel) .WhereElementIsNotElementType().ToElements(); var decals = elems.Where(e => decalIds.Contains(e.GetTypeId())).ToList(); var result = new List<DecalData>(); var op = new Options(); op.DetailLevel = ViewDetailLevel.Medium; foreach (var decal in decals) { var points = new List<PointData>(); var geoElement = decal.get_Geometry(op); foreach (GeometryObject go in geoElement) { if (go is Line line) { var ptStart = line.GetEndPoint(0); points.Add(new PointData(ptStart.X, ptStart.Y, ptStart.Z)); } } if (points.Count != 4) continue; var ext = ExternalFileUtils.GetExternalFileReference(doc, decal.GetTypeId()); if (ext == null) continue; result.Add(new DecalData { Points = points, MapFileName = ModelPathUtils.ConvertModelPathToUserVisiblePath(ext.GetPath()) }); } return result; }
/// <summary> /// Remove DWF links from model and return /// the total number of deleted elements. /// </summary> int RemoveDwfLinkUsingExternalFileUtils( Document doc) { List <ElementId> idsToDelete = new List <ElementId>(); ICollection <ElementId> ids = ExternalFileUtils .GetAllExternalFileReferences(doc); foreach (ElementId id in ids) { Element e = doc.GetElement(id); Debug.Print(Util.ElementDescription(e)); ExternalFileReference xr = ExternalFileUtils .GetExternalFileReference(doc, id); ExternalFileReferenceType xrType = xr.ExternalFileReferenceType; if (xrType == ExternalFileReferenceType.DWFMarkup) { ModelPath xrPath = xr.GetPath(); string path = ModelPathUtils .ConvertModelPathToUserVisiblePath(xrPath); if (path.EndsWith(".dwf") || path.EndsWith(".dwfx")) { idsToDelete.Add(id); } } } int n = idsToDelete.Count; ICollection <ElementId> idsDeleted = null; if (0 < n) { using (Transaction t = new Transaction(doc)) { t.Start("Delete DWFx Links"); idsDeleted = doc.Delete(idsToDelete); t.Commit(); } } int m = (null == idsDeleted) ? 0 : idsDeleted.Count; Debug.Print(string.Format( "Selected {0} DWF external file reference{1}, " + "{2} element{3} successfully deleted.", n, Util.PluralSuffix(n), m, Util.PluralSuffix(m))); return(m); }
/// <summary> /// Returns the cut lines. /// </summary> /// <param name="viewId">The view identifier.</param> public static void CutLines(ElementId viewId) { Utils.Log(string.Format("UtilsSectionView.CutLines started...", "")); var uidoc = DocumentManager.Instance.CurrentUIDocument; var doc = uidoc.Document; var view = doc.GetElement(viewId) as View; var app = doc.Application; Options opt = new Options(); opt.View = view; BoundingBoxXYZ crop = view.CropBox; IList <DetailCurve> detailCurves = new List <DetailCurve>(); IList <Curve> linkedCurves = new List <Curve>(); Transform tr = view.CropBox.Transform; string path = Path.Combine(Path.GetTempPath(), "Copy.rvt"); var rliCollection = new FilteredElementCollector(doc) .OfClass(typeof(RevitLinkInstance)) .WhereElementIsNotElementType() .Cast <RevitLinkInstance>(); Document link = null; RevitServices.Transactions.TransactionManager.Instance.ForceCloseTransaction(); CloseCopy(); Utils.Log(string.Format("Preparing Revit Links...", "")); if (rliCollection.Count() > 0) { #region RevitLinkInstances foreach (RevitLinkInstance rli in rliCollection) { ElementId efrId = rli.GetTypeId(); var status = ExternalFileUtils.GetExternalFileReference(doc, efrId).GetLinkedFileStatus(); Utils.Log(string.Format("Status {0}...", status)); if (status == LinkedFileStatus.InClosedWorkset || status == LinkedFileStatus.Invalid || status == LinkedFileStatus.LocallyUnloaded || status == LinkedFileStatus.NotFound || status == LinkedFileStatus.Unloaded) { continue; } app.CopyModel(ModelPathUtils.ConvertUserVisiblePathToModelPath(rli.GetLinkDocument().PathName), path, true); link = app.OpenDocumentFile(path); // access projectlocations // test if the the project location in the host file exists in the linked document // if exists retrieve the transform object via project position // apply the transform to the total transform of the revit link instance Utils.Log(string.Format("Processing {0}...", path)); Transform rliTransform = rli.GetTotalTransform(); // TODO: include angle in the calculation // TODO: include different project location from the Link Instance // TODO: test for different locations of the same instance tr.Origin = rliTransform.Inverse.OfPoint(view.Origin); tr.BasisX = rliTransform.Inverse.OfVector(-view.RightDirection); tr.BasisY = XYZ.BasisZ; tr.BasisZ = tr.BasisX.CrossProduct(tr.BasisY); BoundingBoxXYZ bb = new BoundingBoxXYZ(); bb.Transform = tr; XYZ min = view.CropBox.Min; XYZ max = view.CropBox.Max; bb.Min = new XYZ(min.X, min.Y, 0); bb.Max = new XYZ(max.X, max.Y, -min.Z); IList <ElementId> detailCurveIds = new List <ElementId>(); var linkedViewId = ElementId.InvalidElementId; // TODO: create other view family types, currently works only for sections using (Transaction q = new Transaction(link, "Cut1")) { q.Start(); ElementId vftId = new FilteredElementCollector(link) .OfClass(typeof(ViewFamilyType)) .WhereElementIsElementType() .Cast <ViewFamilyType>() .First(x => x.ViewFamily == ViewFamily.Section) .Id; View linkedView = ViewSection.CreateSection(link, vftId, bb); link.Regenerate(); foreach (Curve c in CutCurvesInView(link, linkedView.Id)) { //linkedCurves.Add(c.CreateTransformed(Transform.CreateTranslation(translation))); linkedCurves.Add(c.CreateTransformed(rliTransform)); } q.RollBack(); } link.Close(false); Utils.Log(string.Format("Completed", "")); } #endregion } Utils.Log(string.Format("Processing current document...", "")); using (Transaction t = new Transaction(doc, "Cut")) { t.Start(); #region Current Document Detail Curves IList <ElementId> toDelete = new List <ElementId>(); foreach (Group g in new FilteredElementCollector(doc, view.Id) .OfClass(typeof(Group)) .WhereElementIsNotElementType() .Cast <Group>() .Where(x => x.GroupType.Name == view.Name)) { g.Pinned = false; toDelete.Add(g.Id); } if (toDelete.Count > 0) { doc.Delete(toDelete); toDelete.Clear(); } Utils.Log(string.Format("Deleted {0} groups.", toDelete.Count)); GraphicsStyle gs = new FilteredElementCollector(doc) .OfClass(typeof(GraphicsStyle)) .WhereElementIsNotElementType() .Cast <GraphicsStyle>() .First(x => x.GraphicsStyleCategory.Name == "Medium Lines"); // TODO make it usable for different languages as well Utils.Log(string.Format("Preparing for extracting curves...", "")); foreach (Curve c in CutCurvesInView(doc, view.Id)) { try { var dc = doc.Create.NewDetailCurve(view, c); if (null != dc) { detailCurves.Add(dc); } } catch { continue; } } if (linkedCurves.Count > 0) { foreach (Curve c in linkedCurves.Where(x => x.Length > doc.Application.ShortCurveTolerance)) { try { var dc = doc.Create.NewDetailCurve(view, c); if (null != dc) { detailCurves.Add(dc); } } catch { continue; } } } foreach (DetailCurve dc in detailCurves) { dc.LineStyle = gs; } // this is necessary otherwise a warning pops up for editing a group outside of scope doc.Regenerate(); #endregion #region Group foreach (GroupType gt in new FilteredElementCollector(doc) .OfClass(typeof(GroupType)) .WhereElementIsElementType() .Where(x => x.Name == view.Name)) { toDelete.Add(gt.Id); } if (toDelete.Count > 0) { doc.Delete(toDelete); } if (detailCurves.Count > 0) { Group g = doc.Create.NewGroup(detailCurves.Select(x => x.Id).ToList()); g.GroupType.Name = view.Name; g.Pinned = true; } #endregion t.Commit(); } CloseCopy(); Utils.Log(string.Format("UtilsSectionView.CutLines completed.", "")); }