/// <summary>
        /// Return polygon loops representing the size
        /// and location of given sheet and all the
        /// viewports it contains, regardless of type.
        /// </summary>
        static JtLoops GetSheetViewportLoops(
            SheetModelCollections modelCollections,
            ViewSheet sheet)
        {
            Document doc = sheet.Document;

            List <Viewport> viewports = sheet
                                        .GetAllViewports()
                                        .Select <ElementId, Viewport>(
                id => doc.GetElement(id) as Viewport)
                                        .ToList <Viewport>();

            int n = viewports.Count;

            modelCollections.ViewsInSheet[sheet.Id]
                = new List <ViewData>(n);

            JtLoops sheetViewportLoops = new JtLoops(n + 1);

            // sheet.get_BoundingBox( null ) returns (-100,-100),(100,100)

            BoundingBoxUV bb = sheet.Outline;                  // model coordinates (0,0), (2.76,1.95)

            JtBoundingBox2dInt ibb = new JtBoundingBox2dInt(); // millimeters (0,0),(840,...)

            ibb.ExpandToContain(new Point2dInt(bb.Min));
            ibb.ExpandToContain(new Point2dInt(bb.Max));

            JtLoop loop = new JtLoop(ibb.Corners);

            sheetViewportLoops.Add(loop);

            foreach (Viewport vp in viewports)
            {
                XYZ center = vp.GetBoxCenter(); // not used

                Outline outline = vp.GetBoxOutline();

                ibb.Init();

                ibb.ExpandToContain(
                    new Point2dInt(outline.MinimumPoint));

                ibb.ExpandToContain(
                    new Point2dInt(outline.MaximumPoint));

                loop = new JtLoop(ibb.Corners);

                sheetViewportLoops.Add(loop);

                ViewData d = new ViewData();
                d.Id = vp.ViewId;
                d.ViewportBoundingBox = loop.BoundingBox;

                modelCollections.ViewsInSheet[sheet.Id].Add(
                    d);
            }
            return(sheetViewportLoops);
        }
        /// <summary>
        /// Determine the visible elements belonging to the
        /// specified categories in the views displayed by
        /// the given sheet and return their graphics and
        /// instance placements.
        /// Ignore all but the first geometry loop retrieved.
        /// </summary>
        /// <param name="modelCollections">Data container</param>
        /// <param name="sheet">The view sheet</param>
        /// <param name="categoryFilter">The desired categories</param>
        static void GetBimGraphics(
            SheetModelCollections modelCollections,
            ViewSheet sheet,
            ElementFilter categoryFilter)
        {
            bool list_ignored_elements = false;

            Document doc = sheet.Document;

            Autodesk.Revit.Creation.Application creapp
                = doc.Application.Create;

            Options opt = new Options();

            // There is no need and no possibility to set
            // the detail level when retrieving view geometry.
            // An attempt to specify the detail level will
            // cause writing the opt.View property to throw
            // "DetailLevel is already set. When DetailLevel
            // is set view-specific geometry can't be
            // extracted."
            //
            //opt.DetailLevel = ViewDetailLevel.Coarse;

            Debug.Print(sheet.Name);

            foreach (ViewPlan v in sheet.GetAllPlacedViews()
                     .Select <ElementId, View>(id =>
                                               doc.GetElement(id) as View)
                     .OfType <ViewPlan>()
                     .Where <ViewPlan>(v => IsFloorPlan(v)))
            {
                Debug.Print("  " + v.Name);

                modelCollections.BimelsInViews.Add(
                    v.Id, new List <ObjData>());

                opt.View = v;

                JtBoundingBox2dInt bimelBb
                    = new JtBoundingBox2dInt();

                FilteredElementCollector els
                    = new FilteredElementCollector(doc, v.Id)
                      .WherePasses(categoryFilter);

                foreach (Element e in els)
                {
                    GeometryElement geo = e.get_Geometry(opt);

                    FamilyInstance f = e as FamilyInstance;

                    if (null != f)
                    {
                        LocationPoint lp = e.Location
                                           as LocationPoint;

                        // Simply ignore family instances that
                        // have no location point or no location at
                        // all, e.g. panel.
                        // No, we should not ignore them, but
                        // treat tham as non-transformable parts.

                        if (null == lp)
                        {
                            if (list_ignored_elements)
                            {
                                Debug.Print(string.Format(
                                                "    ...  {0} has no location",
                                                e.Name));
                            }
                            f = null;

                            geo = geo.GetTransformed(
                                Transform.Identity);
                        }
                        else
                        {
                            FamilySymbol s = f.Symbol;

                            if (modelCollections.Symbols.ContainsKey(s.Id))
                            {
                                if (list_ignored_elements)
                                {
                                    Debug.Print("    ... symbol already handled "
                                                + e.Name + " --> " + s.Name);
                                }

                                // Symbol already defined, just add instance

                                JtPlacement2dInt placement
                                    = new JtPlacement2dInt(f);

                                // Expand bounding box around all BIM
                                // elements, ignoring the size of the
                                // actual geometry, assuming is is small
                                // in comparison and the insertion point
                                // lies within it.

                                bimelBb.ExpandToContain(
                                    placement.Translation);

                                InstanceData d = new InstanceData();
                                d.Id        = f.Id;
                                d.Symbol    = f.Symbol.Id;
                                d.Placement = placement;

                                modelCollections.BimelsInViews[v.Id]
                                .Add(d);

                                continue;
                            }

                            // Retrieve family instance geometry
                            // transformed back to symbol definition
                            // coordinate space by inverting the
                            // family instance placement transformation

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

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

                            geo = geo.GetTransformed(t * r);
                        }
                    }

                    int nEmptySolids    = 0;
                    int nNonEmptySolids = 0;
                    int nCurves         = 0;
                    int nOther          = 0;

                    foreach (GeometryObject obj in geo)
                    {
                        // This was true before calling GetTransformed.
                        //Debug.Assert( obj is Solid || obj is GeometryInstance, "expected only solids and instances" );

                        // This was true before calling GetTransformed.
                        //Debug.Assert( ( obj is GeometryInstance ) == ( e is FamilyInstance ), "expected all family instances to have geometry instance" );

                        Debug.Assert(obj is Solid || obj is Line || obj is Arc, "expected only solids, lines and arcs after calling GetTransformed on instances");

                        // Todo: handle arcs, e.g. tessellate

                        Debug.Assert(Visibility.Visible == obj.Visibility, "expected only visible geometry objects");

                        Debug.Assert(obj.IsElementGeometry, "expected only element geometry");
                        //bool isElementGeometry = obj.IsElementGeometry;

                        Solid solid = obj as Solid;

                        if (null != solid)
                        {
                            if (0 < solid.Edges.Size)
                            {
                                ++nNonEmptySolids;
                            }
                            else
                            {
                                ++nEmptySolids;
                            }
                        }
                        else if (obj is Curve)
                        {
                            ++nCurves;
                        }
                        else
                        {
                            ++nOther;
                        }
                    }

                    Debug.Print("    {0}: {1} non-emtpy solids, "
                                + "{2} empty, {3} curves, {4} other",
                                e.Name, nNonEmptySolids, nEmptySolids,
                                nCurves, nOther);

                    JtLoops loops = null;

                    if (1 == nNonEmptySolids &&
                        0 == nEmptySolids + nCurves + nOther)
                    {
                        int nFailures = 0;

                        loops = CmdUploadRooms
                                .GetPlanViewBoundaryLoopsGeo(
                            creapp, geo, ref nFailures);
                    }
                    else
                    {
                        double z     = double.MinValue;
                        bool   first = true;

                        foreach (GeometryObject obj in geo)
                        {
                            // Do we need the graphics style?
                            // It might give us horrible things like
                            // colours etc.

                            ElementId id = obj.GraphicsStyleId;

                            //Debug.Print( "      " + obj.GetType().Name );

                            Solid solid = obj as Solid;

                            if (null == solid)
                            {
                                #region Debug code to ensure horizontal co-planar curves
#if DEBUG
                                Debug.Assert(obj is Line || obj is Arc, "expected only lines and arcs here");

                                Curve c = obj as Curve;

                                if (first)
                                {
                                    z = c.GetEndPoint(0).Z;

                                    Debug.Assert(Util.IsEqual(z, c.GetEndPoint(1).Z),
                                                 "expected a plan view with all Z values equal");

                                    first = false;
                                }
                                else
                                {
                                    Debug.Assert(Util.IsEqual(z, c.GetEndPoint(0).Z),
                                                 "expected a plan view with all Z values equal");

                                    Debug.Assert(Util.IsEqual(z, c.GetEndPoint(1).Z),
                                                 "expected a plan view with all Z values equal");
                                }

                                Debug.Print("      {0} {1}",
                                            obj.GetType().Name,
                                            Util.CurveEndpointString(c));
#endif // DEBUG
                                #endregion // Debug code to ensure horizontal co-planar curves
                            }
                            else if (1 == solid.Faces.Size)
                            {
                                Debug.Print(
                                    "      solid with 1 face");

                                foreach (Face face in solid.Faces)
                                {
                                    #region Debug code to print out face edges
#if DEBUG
                                    foreach (EdgeArray loop in
                                             face.EdgeLoops)
                                    {
                                        foreach (Edge edge in loop)
                                        {
                                            // This returns the curves already
                                            // correctly oriented:

                                            Curve c = edge
                                                      .AsCurveFollowingFace(face);

                                            Debug.Print("        {0}: {1} {2}",
                                                        edge.GetType().Name,
                                                        c.GetType().Name,
                                                        Util.CurveEndpointString(c));
                                        }
                                    }
#endif // DEBUG
                                    #endregion // Debug code to print out face edges

                                    if (null == loops)
                                    {
                                        loops = new JtLoops(1);
                                    }
                                    loops.Add(CmdUploadRooms.GetLoop(
                                                  creapp, face));
                                }
                            }
                            else
                            {
                                #region Debug code for exceptional cases
#if DEBUG_2
                                Debug.Assert(1 >= solid.Faces.Size, "expected at most one visible face in plan view for my simple solids");

                                int n = solid.Edges.Size;

                                if (0 < n)
                                {
                                    Debug.Print(
                                        "      solid with {0} edges", n);

                                    Face[] face2 = new Face[] { null, null };
                                    Face   face  = null;

                                    foreach (Edge edge in solid.Edges)
                                    {
                                        if (null == face2[0])
                                        {
                                            face2[0] = edge.GetFace(0);
                                            face2[1] = edge.GetFace(1);
                                        }
                                        else if (null == face)
                                        {
                                            if (face2.Contains <Face>(edge.GetFace(0)))
                                            {
                                                face = edge.GetFace(0);
                                            }
                                            else if (face2.Contains <Face>(edge.GetFace(1)))
                                            {
                                                face = edge.GetFace(1);
                                            }
                                            else
                                            {
                                                Debug.Assert(false,
                                                             "expected all edges to belong to one face");
                                            }
                                        }
                                        else
                                        {
                                            Debug.Assert(face == edge.GetFace(0) ||
                                                         face == edge.GetFace(1),
                                                         "expected all edges to belong to one face");
                                        }

                                        Curve c = edge.AsCurve();

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

                                        //Curve curve = e.AsCurveFollowingFace(
                                        //  face );

                                        Debug.Print("        {0}: {1} {2}",
                                                    edge.GetType().Name,
                                                    c.GetType().Name,
                                                    Util.CurveEndpointString(c));
                                    }
                                }
#endif // DEBUG
                                #endregion // Debug code for exceptional cases
                            }
                        }
                    }

                    // Save the part or instance and
                    // the geometry retrieved for it.
                    // This is where we drop all geometry but
                    // the first loop.

                    if (null != loops)
                    {
                        GeomData gd = new GeomData();
                        gd.Loop = loops[0];

                        if (null == f)
                        {
                            // Add part with absolute geometry

                            gd.Id = e.Id;

                            modelCollections.BimelsInViews[v.Id].Add(
                                gd);

                            // Expand bounding box around all BIM
                            // elements.

                            bimelBb.ExpandToContain(
                                gd.Loop.BoundingBox);
                        }
                        else
                        {
                            // Define symbol and add instance

                            JtPlacement2dInt placement
                                = new JtPlacement2dInt(f);

                            InstanceData id = new InstanceData();
                            id.Id        = f.Id;
                            id.Symbol    = f.Symbol.Id;
                            id.Placement = placement;

                            modelCollections.BimelsInViews[v.Id].Add(
                                id);

                            gd.Id = f.Symbol.Id;

                            modelCollections.Symbols.Add(
                                f.Symbol.Id, gd);

                            // Expand bounding box around all BIM
                            // elements.

                            JtBoundingBox2dInt bb     = gd.Loop.BoundingBox;
                            Point2dInt         vtrans = placement.Translation;
                            bimelBb.ExpandToContain(bb.Min + vtrans);
                            bimelBb.ExpandToContain(bb.Max + vtrans);
                        }
                    }
                }

                // Set up BIM bounding box for this view

                modelCollections.ViewsInSheet[sheet.Id].Find(
                    v2 => v2.Id.IntegerValue.Equals(
                        v.Id.IntegerValue)).BimBoundingBox
                    = bimelBb;
            }
        }
Example #3
0
        /// <summary>
        /// Display sheet, the views it contains, the BIM
        /// parts and  family instances they display in a
        /// temporary form generated on the fly.
        /// </summary>
        /// <param name="owner">Owner window</param>
        /// <param name="caption">Form caption</param>
        /// <param name="modal">Modal versus modeless</param>
        /// <param name="roomLoops">Sheet and viewport boundary loops</param>
        /// <param name="geometryLoopss">Family symbol and part geometry</param>
        /// <param name="familyInstances">Family instances</param>
        public static Bitmap DisplaySheet(
            ElementId sheetId,
            JtLoops sheetViewportLoops,
            SheetModelCollections modelCollections)
        {
            // Source rectangle.

            JtBoundingBox2dInt bbFrom = sheetViewportLoops
                                        .BoundingBox;

            // Adjust target rectangle height to the
            // displayee loop height.

            int width  = _form_width;
            int height = (int)(width * bbFrom.AspectRatio + 0.5);

            // Specify transformation target rectangle
            // including a margin.

            int top    = 0;
            int left   = 0;
            int bottom = height - (_margin + _margin);

            Point[] parallelogramPoints = new Point[] {
                new Point(left + _margin, bottom),         // upper left
                new Point(left + width - _margin, bottom), // upper right
                new Point(left + _margin, top + _margin)   // lower left
            };

            // Transform from native loop coordinate system
            // (sheet) to target display coordinates form).

            Matrix transformSheetBbToForm = new Matrix(
                bbFrom.Rectangle, parallelogramPoints);

            Bitmap   bmp      = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bmp);

            graphics.Clear(System.Drawing.Color.White);

            // Display sheet and viewport rectangles.

            DrawLoopsOnGraphics(graphics,
                                sheetViewportLoops.GetGraphicsPathLines(),
                                transformSheetBbToForm);

            // Iterate over the views and display the
            // elements for each one appropriately
            // scaled and translated to fit.

            List <ViewData> views = modelCollections
                                    .ViewsInSheet[sheetId];

            Dictionary <ElementId, GeomData> geometryLookup
                = modelCollections.Symbols;

            Matrix             transformBimToViewport;
            JtBoundingBox2dInt bbTo;
            JtLoop             loop;

            foreach (ViewData view in views)
            {
                ElementId vid = view.Id;

                if (!modelCollections.BimelsInViews
                    .ContainsKey(vid))
                {
                    // This is not a floor plan view, so
                    // we have nothing to display in it.

                    continue;
                }

                // Determine transform from model space in mm
                // to the viewport associated with this view.

                bbFrom = view.BimBoundingBox;
                bbTo   = view.ViewportBoundingBox;

                Debug.Print(view.ToString());

                // Adjust target rectangle height to the
                // displayee loop height.

                //height = (int) ( width * bbFrom.AspectRatio + 0.5 );

                // Specify transformation target rectangle
                // including a margin, and center the target
                // rectangle vertically.

                top    = bbTo.Min.Y + _margin2;
                left   = bbTo.Min.X + _margin2;
                bottom = bbTo.Max.Y - _margin2;
                width  = bbTo.Width - (_margin2 + _margin2);

                parallelogramPoints = new Point[] {
                    new Point(left, top),         // upper left
                    new Point(left + width, top), // upper right
                    new Point(left, bottom)       // lower left
                };

                // Transform from native loop coordinate system
                // (sheet) to target display coordinates form).

                transformBimToViewport = new Matrix(
                    bbFrom.Rectangle, parallelogramPoints);

                // Retrieve the list of BIM elements
                // displayed in this view.

                List <ObjData> bimels = modelCollections
                                        .BimelsInViews[vid];

                List <Point[]> loops = new List <Point[]>(1);
                loops.Add(new Point[] { });

                Matrix placement = new Matrix();

                foreach (ObjData bimel in bimels)
                {
                    placement.Reset();

                    InstanceData inst = bimel as InstanceData;

                    if (null != inst)
                    {
                        loop = geometryLookup[inst.Symbol].Loop;
                        Point2dInt v = inst.Placement.Translation;
                        placement.Rotate(inst.Placement.Rotation);
                        placement.Translate(v.X, v.Y, MatrixOrder.Append);
                    }
                    else
                    {
                        Debug.Assert(bimel is GeomData, "expected part with geometry");

                        loop = ((GeomData)bimel).Loop;
                    }
                    loops[0] = loop.GetGraphicsPathLines();

                    placement.Multiply(transformBimToViewport, MatrixOrder.Append);
                    placement.Multiply(transformSheetBbToForm, MatrixOrder.Append);

                    DrawLoopsOnGraphics(graphics, loops, placement);
                }
            }
            return(bmp);
        }
Example #4
0
        /// <summary>
        /// Display room and furniture in a temporary form
        /// generated on the fly.
        /// </summary>
        /// <param name="roomLoops">Room boundary loops</param>
        /// <param name="geometryLoops">Family symbol geometry</param>
        /// <param name="familyInstances">Family instances</param>
        public static Bitmap DisplayRoom(
            JtLoops roomLoops,
            Dictionary <string, JtLoop> geometryLoops,
            List <JtPlacement2dInt> familyInstances)
        {
            JtBoundingBox2dInt bbFrom = roomLoops.BoundingBox;

            // Adjust target rectangle height to the
            // displayee loop height.

            int width  = _form_width;
            int height = (int)(width * bbFrom.AspectRatio + 0.5);

            //SizeF fsize = new SizeF( width, height );

            //SizeF scaling = new SizeF( 1, 1 );
            //PointF translation = new PointF( 0, 0 );

            //GetTransform( fsize, bbFrom,
            //  ref scaling, ref translation, true );

            //Matrix transform1 = new Matrix(
            //  new Rectangle(0,0,width,height),
            //  bbFrom.GetParallelogramPoints());
            //transform1.Invert();

            // the bounding box fills the rectangle
            // perfectly and completely, inverted and
            // non-uniformly distorted:

            //Point2dInt pmin = bbFrom.Min;
            //Rectangle rect = new Rectangle(
            //  pmin.X, pmin.Y, bbFrom.Width, bbFrom.Height );
            //Point[] parallelogramPoints = new Point [] {
            //  new Point( 0, 0 ), // upper left
            //  new Point( width, 0 ), // upper right
            //  new Point( 0, height ) // lower left
            //};

            // the bounding box fills the rectangle
            // perfectly and completely, inverted and
            // non-uniformly distorted:

            // Specify transformation target rectangle
            // including a margin.

            int bottom = height - (_margin + _margin);

            Point[] parallelogramPoints = new Point[] {
                new Point(_margin, bottom),         // upper left
                new Point(width - _margin, bottom), // upper right
                new Point(_margin, _margin)         // lower left
            };

            // Transform from native loop coordinate system
            // to target display coordinates.

            Matrix transform = new Matrix(
                bbFrom.Rectangle, parallelogramPoints);

            Bitmap   bmp      = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bmp);

            graphics.Clear(System.Drawing.Color.White);

            DrawLoopsOnGraphics(graphics,
                                roomLoops.GetGraphicsPathLines(), transform);

            if (null != familyInstances)
            {
                List <Point[]> loops = new List <Point[]>(1);
                loops.Add(new Point[] { });

                foreach (JtPlacement2dInt i in familyInstances)
                {
                    Point2dInt v         = i.Translation;
                    Matrix     placement = new Matrix();
                    placement.Rotate(i.Rotation);
                    placement.Translate(v.X, v.Y, MatrixOrder.Append);
                    placement.Multiply(transform, MatrixOrder.Append);
                    loops[0] = geometryLoops[i.SymbolId]
                               .GetGraphicsPathLines();

                    DrawLoopsOnGraphics(graphics, loops, placement);
                }
            }
            return(bmp);
        }
 /// <summary>
 /// Expand bounding box to contain
 /// the given other bounding box.
 /// </summary>
 public void ExpandToContain(JtBoundingBox2dInt b)
 {
     ExpandToContain(b.Min);
     ExpandToContain(b.Max);
 }
 /// <summary>
 /// Expand bounding box to contain 
 /// the given other bounding box.
 /// </summary>
 public void ExpandToContain( JtBoundingBox2dInt b )
 {
   ExpandToContain( b.Min );
   ExpandToContain( b.Max );
 }