public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; Selection sel = uidoc.Selection; ISelectionFilter f = new JtElementsOfClassSelectionFilter <Dimension>(); Reference elemRef = sel.PickObject( ObjectType.Element, f, "Pick a dimension"); Dimension dim = doc.GetElement(elemRef) as Dimension; XYZ p = GetDimensionStartPoint(dim); List <XYZ> pts = GetDimensionPoints(dim, p); int n = pts.Count; Debug.Print("Dimension origin at {0} followed " + "by {1} further point{2}{3} {4}", Util.PointString(p), n, Util.PluralSuffix(n), Util.DotOrColon(n), string.Join(", ", pts.Select( q => Util.PointString(q)))); List <double> d = new List <double>(n); XYZ q0 = p; foreach (XYZ q in pts) { d.Add(q.X - q0.X); q0 = q; } Debug.Print( "Horizontal distances in metres: " + string.Join(", ", d.Select(x => Util.RealString(Util.FootToMetre(x))))); using (Transaction tx = new Transaction(doc)) { tx.Start("Draw Point Markers"); SketchPlane sketchPlane = dim.View.SketchPlane; double size = 0.3; DrawMarker(p, size, sketchPlane); pts.ForEach(q => DrawMarker(q, size, sketchPlane)); tx.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; Selection sel = uidoc.Selection; View view = doc.ActiveView; ISelectionFilter f = new JtElementsOfClassSelectionFilter <Grid>(); Reference elemRef = sel.PickObject( ObjectType.Element, f, "Pick a grid"); Grid grid = doc.GetElement(elemRef) as Grid; IList <Curve> gridCurves = grid.GetCurvesInView( DatumExtentType.Model, view); using (Transaction tx = new Transaction(doc)) { tx.Start("Modify Grid Endpoints"); foreach (Curve c in gridCurves) { XYZ start = c.GetEndPoint(0); XYZ end = c.GetEndPoint(1); XYZ newStart = start + 10 * XYZ.BasisY; XYZ newEnd = end - 10 * XYZ.BasisY; Line newLine = Line.CreateBound(newStart, newEnd); grid.SetCurveInView( DatumExtentType.Model, view, newLine); } tx.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; // Select two walls and the dimension line point: Selection sel = uidoc.Selection; ReferenceArray refs = new ReferenceArray(); try { ISelectionFilter f = new JtElementsOfClassSelectionFilter <Wall>(); refs.Append(sel.PickObject( ObjectType.Element, f, "Please select first wall")); refs.Append(sel.PickObject( ObjectType.Element, f, "Please pick dimension line " + "point on second wall")); //rFace = sel.PickObject( ObjectType.Face, // "Please select face on second wall at dimension line point" ); // //rPoint = sel.PickObject( ObjectType.PointOnElement, // "Please select point on first wall" ); } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { message = "No two walls selected"; return(Result.Failed); } // Ensure the two selected walls are straight and // parallel; determine their mutual normal vector // and a point on each wall for distance // calculations: Wall[] walls = new Wall[2]; List <int> ids = new List <int>(2); XYZ[] pts = new XYZ[2]; Line[] lines = new Line[2]; IntersectionResult ir; XYZ normal = null; int i = 0; foreach (Reference r in refs) { // 'Autodesk.Revit.DB.Reference.Element' is // obsolete: Property will be removed. Use // Document.GetElement(Reference) instead. //Wall wall = r.Element as Wall; // 2011 Wall wall = doc.GetElement(r) as Wall; // 2012 walls[i] = wall; ids.Add(wall.Id.IntegerValue); // Obtain location curve and // check that it is straight: LocationCurve lc = wall.Location as LocationCurve; Curve curve = lc.Curve; lines[i] = curve as Line; if (null == lines[i]) { message = _prompt; return(Result.Failed); } // Obtain normal vectors // and ensure that they are equal, // i.e. walls are parallel: if (null == normal) { normal = Util.Normal(lines[i]); } else { if (!Util.IsParallel(normal, Util.Normal(lines[i]))) { message = _prompt; return(Result.Failed); } } // Obtain pick points and project // onto wall location lines: XYZ p = r.GlobalPoint; ir = lines[i].Project(p); if (null == ir) { message = string.Format( "Unable to project pick point {0} " + "onto wall location line.", i); return(Result.Failed); } pts[i] = ir.XYZPoint; Debug.Print( "Wall {0} id {1} at {2}, {3} --> point {4}", i, wall.Id.IntegerValue, Util.PointString(lines[i].GetEndPoint(0)), Util.PointString(lines[i].GetEndPoint(1)), Util.PointString(pts[i])); if (0 < i) { // Project dimension point selected on second wall // back onto first wall, and ensure that normal // points from second wall to first: ir = lines[0].Project(pts[1]); if (null == ir) { message = string.Format( "Unable to project selected dimension " + "line point {0} on second wall onto " + "first wall's location line.", Util.PointString(pts[1])); return(Result.Failed); } pts[0] = ir.XYZPoint; } ++i; } XYZ v = pts[0] - pts[1]; if (0 > v.DotProduct(normal)) { normal = -normal; } // Shoot a ray back from the second // picked wall towards first: Debug.Print( "Shooting ray from {0} in direction {1}", Util.PointString(pts[1]), Util.PointString(normal)); View3D view = Get3DView(doc); if (null == view) { message = "No 3D view named '{3D}' found; " + "run the View > 3D View command once " + "to generate it."; return(Result.Failed); } //refs = doc.FindReferencesByDirection( // pts[1], normal, view ); // 2011 //IList<ReferenceWithContext> refs2 // = doc.FindReferencesWithContextByDirection( // pts[1], normal, view ); // 2012 // In the Revit 2014 API, the call to // FindReferencesWithContextByDirection causes a // warning saying: // "FindReferencesWithContextByDirection is obsolete: // This method is deprecated in Revit 2014. // Use the ReferenceIntersector class instead." ReferenceIntersector ri = new ReferenceIntersector( walls[0].Id, FindReferenceTarget.Element, view); ReferenceWithContext ref2 = ri.FindNearest(pts[1], normal); if (null == ref2) { message = "ReferenceIntersector.FindNearest" + " returned null!"; return(Result.Failed); } #region Obsolete code to determine the closest reference #if NEED_TO_DETERMINE_CLOSEST_REFERENCE // Store the references to the wall surfaces: Reference[] surfrefs = new Reference[2] { null, null }; // Find the two closest intersection // points on each of the two walls: double[] minDistance = new double[2] { double.MaxValue, double.MaxValue }; //foreach( Reference r in refs ) foreach (ReferenceWithContext rc in refs2) { // 'Autodesk.Revit.DB.Reference.Element' is // obsolete: Property will be removed. Use // Document.GetElement(Reference) instead. //Element e = r.Element; // 2011 Reference r = rc.GetReference(); Element e = doc.GetElement(r); // 2012 if (e is Wall) { i = ids.IndexOf(e.Id.IntegerValue); if (-1 < i && ElementReferenceType.REFERENCE_TYPE_SURFACE == r.ElementReferenceType) { //GeometryObject g = r.GeometryObject; // 2011 GeometryObject g = e.GetGeometryObjectFromReference(r); // 2012 if (g is PlanarFace) { PlanarFace face = g as PlanarFace; Line line = (e.Location as LocationCurve) .Curve as Line; Debug.Print( "Wall {0} at {1}, {2} surface {3} " + "normal {4} proximity {5}", e.Id.IntegerValue, Util.PointString(line.GetEndPoint(0)), Util.PointString(line.GetEndPoint(1)), Util.PointString(face.Origin), Util.PointString(face.Normal), rc.Proximity); // First reference: assert it is a face on this wall // and the distance is half the wall thickness. // Second reference: the first reference on the other // wall; assert the distance between the two references // equals the distance between the wall location lines // minus half of the sum of the two wall thicknesses. if (rc.Proximity < minDistance[i]) { surfrefs[i] = r; minDistance[i] = rc.Proximity; } } } } } if (null == surfrefs[0]) { message = "No suitable face intersection " + "points found on first wall."; return(Result.Failed); } if (null == surfrefs[1]) { message = "No suitable face intersection " + "points found on second wall."; return(Result.Failed); } CmdDimensionWallsIterateFaces .CreateDimensionElement(doc.ActiveView, pts[0], surfrefs[0], pts[1], surfrefs[1]); #endif // NEED_TO_DETERMINE_CLOSEST_REFERENCE #endregion // Obsolete code to determine the closest reference CmdDimensionWallsIterateFaces .CreateDimensionElement(doc.ActiveView, pts[0], ref2.GetReference(), pts[1], refs.get_Item(1)); return(Result.Succeeded); }
/// <summary> /// Run the automatic or interactive /// selection process. /// </summary> public Result Pick() { // Retrieve all T elements in the entire model. _a = new List <T>( new FilteredElementCollector(_doc) .OfClass(typeof(T)) .ToElements() .Cast <T>()); int n = _a.Count; // If there are less than two, // there is nothing we can do. if (2 > n) { return(Result.Failed); } // If there are exactly two, pick those. if (2 == n) { return(Result.Succeeded); } // There are more than two to choose from. // Check for a pre-selection. _a.Clear(); Selection sel = _uidoc.Selection; ICollection <ElementId> ids = sel.GetElementIds(); n = ids.Count; Debug.Print("{0} pre-selected elements.", n); // If two or more T elements were pre- // selected, use the first two encountered. if (1 < n) { foreach (ElementId id in ids) { T e = _doc.GetElement(id) as T; Debug.Assert(null != e, "only elements of type T can be picked"); _a.Add(e); if (2 == _a.Count) { Debug.Print("Found two pre-selected " + "elements of desired type and " + "ignoring everything else."); break; } } } // None or less than two elements were pre- // selected, so prompt for an interactive // post-selection instead. if (2 != _a.Count) { _a.Clear(); // Select first element. ISelectionFilter filter = new JtElementsOfClassSelectionFilter <T>(); try { Reference r = sel.PickObject( ObjectType.Element, filter, "Please pick first element."); _a.Add(_doc.GetElement(r.ElementId) as T); } catch (Autodesk.Revit.Exceptions .OperationCanceledException) { return(Result.Cancelled); } // Select second element. try { Reference r = sel.PickObject( ObjectType.Element, filter, "Please pick second element."); _a.Add(_doc.GetElement(r.ElementId) as T); } catch (Autodesk.Revit.Exceptions .OperationCanceledException) { return(Result.Cancelled); } } return(Result.Succeeded); }
///// <summary> ///// Allow selection of curve elements only. ///// </summary> //class CurveElementSelectionFilter : ISelectionFilter //{ // public bool AllowElement( Element e ) // { // return e is CurveElement; // } // public bool AllowReference( Reference r, XYZ p ) // { // return true; // } //} public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; // Select all model curves in the entire model. List <CurveElement> curves = new List <CurveElement>( new FilteredElementCollector(doc) .OfClass(typeof(CurveElement)) .ToElements() .Cast <CurveElement>()); int n = curves.Count; // If there are less than two, // there is nothing we can do. if (2 > n) { message = _prompt; return(Result.Failed); } // If there are exactly two, pick those. if (2 < n) { // Else, check for a pre-selection. curves.Clear(); Selection sel = uidoc.Selection; ICollection <ElementId> ids = sel.GetElementIds(); n = ids.Count; Debug.Print("{0} pre-selected elements.", n); // If two or more model curves were pre- // selected, use the first two encountered. if (1 < n) { foreach (ElementId id in ids) { CurveElement c = doc.GetElement(id) as CurveElement; if (null != c) { curves.Add(c); if (2 == curves.Count) { Debug.Print("Found two model curves, " + "ignoring everything else."); break; } } } } // Else, prompt for an // interactive post-selection. if (2 != curves.Count) { curves.Clear(); ISelectionFilter f = new JtElementsOfClassSelectionFilter <CurveElement>(); try { Reference r = sel.PickObject( ObjectType.Element, f, "Please pick first model curve."); curves.Add(doc.GetElement(r.ElementId) as CurveElement); } catch (Autodesk.Revit.Exceptions .OperationCanceledException) { return(Result.Cancelled); } try { Reference r = sel.PickObject( ObjectType.Element, f, "Please pick second model curve."); curves.Add(doc.GetElement(r.ElementId) as CurveElement); } catch (Autodesk.Revit.Exceptions .OperationCanceledException) { return(Result.Cancelled); } } } // Extract data from the two selected curves. Curve c0 = curves[0].GeometryCurve; Curve c1 = curves[1].GeometryCurve; double sp0 = c0.GetEndParameter(0); double ep0 = c0.GetEndParameter(1); double step0 = (ep0 - sp0) / _nSegments; double sp1 = c1.GetEndParameter(0); double ep1 = c1.GetEndParameter(1); double step1 = (ep1 - sp1) / _nSegments; Debug.Print("Two curves' step size [start, end]:" + " {0} [{1},{2}] -- {3} [{4},{5}]", Util.RealString(step0), Util.RealString(sp0), Util.RealString(ep0), Util.RealString(step1), Util.RealString(sp1), Util.RealString(ep1)); // Modify document within a transaction. using (Transaction tx = new Transaction(doc)) { Creator creator = new Creator(doc); tx.Start("MidCurve"); // Current segment start points. double t0 = sp0; double t1 = sp1; XYZ p0 = c0.GetEndPoint(0); XYZ p1 = c1.GetEndPoint(0); XYZ p = Util.Midpoint(p0, p1); Debug.Assert( p0.IsAlmostEqualTo(c0.Evaluate(t0, false)), "expected equal start points"); Debug.Assert( p1.IsAlmostEqualTo(c1.Evaluate(t1, false)), "expected equal start points"); // Current segment end points. t0 += step0; t1 += step1; XYZ q0, q1, q; Line line; for (int i = 0; i < _nSegments; ++i, t0 += step0, t1 += step1) { q0 = c0.Evaluate(t0, false); q1 = c1.Evaluate(t1, false); q = Util.Midpoint(q0, q1); Debug.Print( "{0} {1} {2} {3}-{4} {5}-{6} {7}-{8}", i, Util.RealString(t0), Util.RealString(t1), Util.PointString(p0), Util.PointString(q0), Util.PointString(p1), Util.PointString(q1), Util.PointString(p), Util.PointString(q)); // Create approximating curve segment. line = Line.CreateBound(p, q); creator.CreateModelCurve(line); p0 = q0; p1 = q1; p = q; } tx.Commit(); } return(Result.Succeeded); }