Ejemplo n.º 1
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);
        }
        /// <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;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Upload model, sheet, views it contains and
        /// their BIM elements to a CouchDB data repository.
        /// </summary>
        static public void DbUploadSheet(
            ViewSheet sheet,
            JtLoops sheetViewportLoops,
            SheetModelCollections modelCollections)
        {
            bool pre_existing = false;

            RoomEditorDb  rdb = new RoomEditorDb();
            CouchDatabase db  = rdb.Db;

            // Sheet

            Document doc = sheet.Document;

            Element e = GetProjectInfo(doc);

            DbModel dbModel = GetDbModel(db, e);

            DbSheet dbSheet = rdb.GetOrCreate <DbSheet>(
                ref pre_existing, sheet.UniqueId);

            dbSheet.Description = Util.SheetDescription(sheet);
            dbSheet.Name        = sheet.Name;
            dbSheet.ModelId     = e.UniqueId;
            dbSheet.Width       = sheetViewportLoops[0].BoundingBox.Width;
            dbSheet.Height      = sheetViewportLoops[0].BoundingBox.Height;

            dbSheet = pre_existing
        ? db.UpdateDocument <DbSheet>(dbSheet)
        : db.CreateDocument <DbSheet>(dbSheet);

            // Symbols

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

            foreach (KeyValuePair <ElementId, GeomData> p
                     in geometryLookup)
            {
                ElementId id = p.Key;

                e = doc.GetElement(id);

                DbSymbol symbol = rdb.GetOrCreate <DbSymbol>(
                    ref pre_existing, e.UniqueId);

                symbol.Description = Util.ElementDescription(e);
                symbol.Name        = e.Name;
                symbol.Loop        = p.Value.Loop.SvgPath;

                symbol = pre_existing
          ? db.UpdateDocument <DbSymbol>(symbol)
          : db.CreateDocument <DbSymbol>(symbol);
            }

            // Views and BIM elements

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

            View               view;
            DbView             dbView;
            DbBimel            dbBimel;
            DbInstance         dbInstance = null;
            DbPart             dbPart     = null;
            JtBoundingBox2dInt bbFrom;
            JtBoundingBox2dInt bbTo;

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

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

                    continue;
                }

                view = doc.GetElement(vid) as View;

                dbView = rdb.GetOrCreate <DbView>(
                    ref pre_existing, view.UniqueId);

                dbView.Description = Util.ElementDescription(view);
                dbView.Name        = view.Name;
                dbView.SheetId     = dbSheet.Id;

                bbFrom = viewData.BimBoundingBox;
                bbTo   = viewData.ViewportBoundingBox;

                dbView.X      = bbTo.Min.X;
                dbView.Y      = bbTo.Min.Y;
                dbView.Width  = bbTo.Width;
                dbView.Height = bbTo.Height;

                dbView.BimX      = bbFrom.Min.X;
                dbView.BimY      = bbFrom.Min.Y;
                dbView.BimWidth  = bbFrom.Width;
                dbView.BimHeight = bbFrom.Height;

                dbView = pre_existing
          ? db.UpdateDocument <DbView>(dbView)
          : db.CreateDocument <DbView>(dbView);

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

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

                foreach (ObjData bimel in bimels)
                {
                    e = doc.GetElement(bimel.Id);

                    InstanceData inst = bimel as InstanceData;

                    if (null != inst)
                    {
                        dbInstance = rdb.GetOrCreate <DbInstance>(
                            ref pre_existing, e.UniqueId);

                        dbInstance.SymbolId = doc.GetElement(
                            inst.Symbol).UniqueId;

                        dbInstance.Transform = inst.Placement
                                               .SvgTransform;

                        dbBimel = dbInstance;
                    }
                    else
                    {
                        Debug.Assert(bimel is GeomData,
                                     "expected part with geometry");

                        dbPart = rdb.GetOrCreate <DbPart>(
                            ref pre_existing, e.UniqueId);

                        dbPart.Loop = ((GeomData)bimel).Loop
                                      .SvgPath;

                        dbBimel = dbPart;
                    }
                    dbBimel.Description = Util.ElementDescription(e);
                    dbBimel.Name        = e.Name;
                    JtUidSet uids = new JtUidSet(dbBimel.ViewIds);
                    uids.Add(view.UniqueId);
                    dbBimel.ViewIds    = uids.Uids;
                    dbBimel.Properties = Util.GetElementProperties(e);

                    if (null != inst)
                    {
                        dbInstance = pre_existing
              ? db.UpdateDocument <DbInstance>(dbInstance)
              : db.CreateDocument <DbInstance>(dbInstance);
                    }
                    else
                    {
                        dbPart = pre_existing
              ? db.UpdateDocument <DbPart>(dbPart)
              : db.CreateDocument <DbPart>(dbPart);
                    }
                }
            }
        }