Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }