Exemple #1
0
        /// <summary>
        /// Retrieve the room plan view boundary
        /// polygon loops and convert to 2D integer-based.
        /// For optimisation and consistency reasons,
        /// convert all coordinates to integer values in
        /// millimetres. Revit precision is limited to
        /// 1/16 of an inch, which is abaut 1.2 mm, anyway.
        /// </summary>
        static JtLoops GetRoomLoops(Room room)
        {
            SpatialElementBoundaryOptions opt
                = new SpatialElementBoundaryOptions();

            opt.SpatialElementBoundaryLocation =
                SpatialElementBoundaryLocation.Center; // loops closed
            //SpatialElementBoundaryLocation.Finish; // loops not closed

            IList <IList <BoundarySegment> > loops = room.
                                                     GetBoundarySegments(opt);

            int nLoops = loops.Count;

            JtLoops jtloops = new JtLoops(nLoops);

            foreach (IList <BoundarySegment> loop in loops)
            {
                int nSegments = loop.Count;

                JtLoop jtloop = new JtLoop(nSegments);

                XYZ p0 = null; // loop start point
                XYZ p;         // segment start point
                XYZ q = null;  // segment end point

                foreach (BoundarySegment seg in loop)
                {
                    // Todo: handle non-linear curve.
                    // Especially: if two long lines have a
                    // short arc in between them, skip the arc
                    // and extend both lines.

                    p = seg.GetCurve().GetEndPoint(0);

                    jtloop.Add(new Point2dInt(p));

                    Debug.Assert(null == q || q.IsAlmostEqualTo(p),
                                 "expected last endpoint to equal current start point");

                    q = seg.GetCurve().GetEndPoint(1);

                    if (_debug_output)
                    {
                        Debug.Print("{0} --> {1}",
                                    Util.PointString(p),
                                    Util.PointString(q));
                    }
                    if (null == p0)
                    {
                        p0 = p; // save loop start point
                    }
                }
                Debug.Assert(q.IsAlmostEqualTo(p0),
                             "expected last endpoint to equal loop start point");

                jtloops.Add(jtloop);
            }
            return(jtloops);
        }
        /// <summary>
        /// Convert Clipper polygons to JtLoops
        /// </summary>
        JtLoops ConvertToLoops(Polygons union)
        {
            JtLoops loops = new JtLoops(union.Count);
            JtLoop  loop  = new JtLoop(union.First <Polygon>().Count);

            foreach (Polygon poly in union)
            {
                loop.Clear();
                foreach (IntPoint p in poly)
                {
                    loop.Add(new Point2dInt(
                                 (int)p.X, (int)p.Y));
                }
                loops.Add(loop);
            }
            return(loops);
        }
Exemple #3
0
        /// <summary>
        /// Retrieve all plan view boundary loops from
        /// all solids of given element united together.
        /// If the element is a family instance, transform
        /// its loops from the instance placement
        /// coordinate system back to the symbol
        /// definition one.
        /// If no geometry can be determined, use the
        /// bounding box instead.
        /// </summary>
        internal static JtLoops GetSolidPlanViewBoundaryLoops(
            Element e,
            bool transformInstanceCoordsToSymbolCoords,
            ref int nFailures)
        {
            Autodesk.Revit.Creation.Application creapp
                = e.Document.Application.Create;

            JtLoops loops = null;

            Options opt = new Options();

            GeometryElement geo = e.get_Geometry(opt);

            if (null != geo)
            {
                Document doc = e.Document;

                if (e is FamilyInstance)
                {
                    if (transformInstanceCoordsToSymbolCoords)
                    {
                        // Retrieve family instance geometry
                        // transformed back to symbol definition
                        // coordinate space by inverting the
                        // family instance placement transformation

                        LocationPoint lp = e.Location
                                           as LocationPoint;

                        Transform t = Transform.CreateTranslation(
                            -lp.Point);

                        Transform r = Transform.CreateRotationAtPoint(
                            XYZ.BasisZ, -lp.Rotation, lp.Point);

                        geo = geo.GetTransformed(t * r);
                    }
                    else
                    {
                        Debug.Assert(
                            1 == geo.Count <GeometryObject>(),
                            "expected as single geometry instance");

                        Debug.Assert(
                            geo.First <GeometryObject>() is GeometryInstance,
                            "expected as single geometry instance");

                        geo = (geo.First <GeometryObject>()
                               as GeometryInstance).GetInstanceGeometry();
                    }
                }

                loops = GetPlanViewBoundaryLoopsGeo(
                    creapp, geo, ref nFailures);
            }
            if (null == loops || 0 == loops.Count)
            {
                Debug.Print(
                    "Unable to determine geometry for "
                    + Util.ElementDescription(e)
                    + "; using bounding box instead.");

                BoundingBoxXYZ bb;

                if (e is FamilyInstance)
                {
                    bb = (e as FamilyInstance).Symbol
                         .get_BoundingBox(null);
                }
                else
                {
                    bb = e.get_BoundingBox(null);
                }
                JtLoop loop = new JtLoop(4);
                loop.Add(new Point2dInt(bb.Min));
                loop.Add(new Point2dInt(bb.Max.X, bb.Min.Y));
                loop.Add(new Point2dInt(bb.Max));
                loop.Add(new Point2dInt(bb.Min.X, bb.Max.Y));
                loops.Add(loop);
            }
            return(loops);
        }
Exemple #4
0
        /// <summary>
        /// Return a closed loop of integer-based points
        /// scaled to millimetres from a given Revit model
        /// face in feet.
        /// </summary>
        internal static JtLoop GetLoop(
            Autodesk.Revit.Creation.Application creapp,
            Face face)
        {
            JtLoop loop = null;

            foreach (EdgeArray a in face.EdgeLoops)
            {
                int nEdges = a.Size;

                List <Curve> curves
                    = new List <Curve>(nEdges);

                XYZ p0 = null; // loop start point
                XYZ p;         // edge start point
                XYZ q = null;  // edge end point

                // Test ValidateCurveLoops

                //CurveLoop loopIfc = new CurveLoop();

                foreach (Edge e in a)
                {
                    // This requires post-processing using
                    // SortCurvesContiguous:

                    Curve curve = e.AsCurve();

                    if (_debug_output)
                    {
                        p = curve.GetEndPoint(0);
                        q = curve.GetEndPoint(1);
                        Debug.Print("{0} --> {1}",
                                    Util.PointString(p),
                                    Util.PointString(q));
                    }

                    // This returns the curves already
                    // correctly oriented:

                    curve = e.AsCurveFollowingFace(
                        face);

                    if (_debug_output)
                    {
                        p = curve.GetEndPoint(0);
                        q = curve.GetEndPoint(1);
                        Debug.Print("{0} --> {1} following face",
                                    Util.PointString(p),
                                    Util.PointString(q));
                    }

                    curves.Add(curve);

                    // Throws an exception saying "This curve
                    // will make the loop not contiguous.
                    // Parameter name: pCurve"

                    //loopIfc.Append( curve );
                }

                // We never reach this point:

                //List<CurveLoop> loopsIfc
                //  = new List<CurveLoop>( 1 );

                //loopsIfc.Add( loopIfc );

                //IList<CurveLoop> loopsIfcOut = ExporterIFCUtils
                //  .ValidateCurveLoops( loopsIfc, XYZ.BasisZ );

                // This is no longer needed if we use
                // AsCurveFollowingFace instead of AsCurve:

                CurveUtils.SortCurvesContiguous(
                    creapp, curves, _debug_output);

                q = null;

                loop = new JtLoop(nEdges);

                foreach (Curve curve in curves)
                {
                    // Todo: handle non-linear curve.
                    // Especially: if two long lines have a
                    // short arc in between them, skip the arc
                    // and extend both lines.

                    p = curve.GetEndPoint(0);

                    Debug.Assert(null == q ||
                                 q.IsAlmostEqualTo(p, 1e-04),
                                 string.Format(
                                     "expected last endpoint to equal current start point, not distance {0}",
                                     (null == q ? 0 : p.DistanceTo(q))));

                    q = curve.GetEndPoint(1);

                    if (_debug_output)
                    {
                        Debug.Print("{0} --> {1}",
                                    Util.PointString(p),
                                    Util.PointString(q));
                    }

                    if (null == p0)
                    {
                        p0 = p; // save loop start point
                    }

                    int n = -1;

                    if (_tessellate_curves &&
                        _min_tessellation_curve_length_in_feet
                        < q.DistanceTo(p))
                    {
                        IList <XYZ> pts = curve.Tessellate();
                        n = pts.Count;

                        Debug.Assert(1 < n, "expected at least two points");
                        Debug.Assert(p.IsAlmostEqualTo(pts[0]), "expected tessellation start equal curve start point");
                        Debug.Assert(q.IsAlmostEqualTo(pts[n - 1]), "expected tessellation end equal curve end point");

                        if (2 == n)
                        {
                            n = -1; // this is a straight line
                        }
                        else
                        {
                            --n; // skip last point

                            for (int i = 0; i < n; ++i)
                            {
                                loop.Add(new Point2dInt(pts[i]));
                            }
                        }
                    }

                    // If tessellation is disabled,
                    // or curve is too short to tessellate,
                    // or has only two tessellation points,
                    // just add the start point:

                    if (-1 == n)
                    {
                        loop.Add(new Point2dInt(p));
                    }
                }
                Debug.Assert(q.IsAlmostEqualTo(p0, 1e-05),
                             string.Format(
                                 "expected last endpoint to equal current start point, not distance {0}",
                                 p0.DistanceTo(q)));
            }
            return(loop);
        }