/// <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>
        /// List all the loops retrieved 
        /// from the given element.
        /// </summary>
        static void ListLoops( Element e, JtLoops loops )
        {
            int nLoops = loops.Count;

              Debug.Print( "{0} has {1}{2}",
            Util.ElementDescription( e ),
            Util.PluralString( nLoops, "loop" ),
            Util.DotOrColon( nLoops ) );

              int i = 0;

              foreach( JtLoop loop in loops )
              {
            Debug.Print( "  {0}: {1}", i++,
              loop.ToString() );
              }
        }
        /// <summary>
        /// Retrieve all plan view boundary loops from 
        /// all solids of given element. This initial 
        /// version passes each solid encountered in the 
        /// given element to the ExtrusionAnalyzer one
        /// at a time, which obviously results in multiple
        /// loops, many of which are contained within the 
        /// others. An updated version unites all the 
        /// solids first and then uses the ExtrusionAnalyzer
        /// once only to obtain the true outside shadow
        /// contour.
        /// </summary>
        static JtLoops GetPlanViewBoundaryLoopsMultiple( 
            Element e,
            ref int nFailures)
        {
            Autodesk.Revit.Creation.Application creapp
            = e.Document.Application.Create;

              JtLoops loops = new JtLoops( 1 );

              //int nSolids = 0;

              Options opt = new Options();

              GeometryElement geo = e.get_Geometry( opt );

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

            if( e is FamilyInstance )
            {
              geo = geo.GetTransformed(
            Transform.Identity );
            }

            //GeometryInstance inst = null;

            foreach( GeometryObject obj in geo )
            {
              AddLoops( creapp, loops, obj, ref nFailures );

              //inst = obj as GeometryInstance;
            }

            //if( 0 == nSolids && null != inst )
            //{
            //  geo = inst.GetSymbolGeometry();

            //  foreach( GeometryObject obj in geo )
            //  {
            //    AddLoops( creapp, loops, obj, ref nFailures );
            //  }
            //}
              }
              return loops;
        }
        /// <summary>
        /// Add all plan view boundary loops from 
        /// given solid to the list of loops.
        /// The creation application argument is used to
        /// reverse the extrusion analyser output curves
        /// in case they are badly oriented.
        /// </summary>
        /// <returns>Number of loops added</returns>
        static int AddLoops( 
            Autodesk.Revit.Creation.Application creapp,
            JtLoops loops,
            GeometryObject obj,
            ref int nExtrusionAnalysisFailures)
        {
            int nAdded = 0;

              Solid solid = obj as Solid;

              if( null != solid
            && 0 < solid.Faces.Size )
              {
            //Plane plane = new Plane(XYZ.BasisX,
            //  XYZ.BasisY, XYZ.Zero); // 2016

            Plane plane = Plane.CreateByOriginAndBasis(
              XYZ.Zero, XYZ.BasisX, XYZ.BasisY ); // 2017

            ExtrusionAnalyzer extrusionAnalyzer = null;

            try
            {
              extrusionAnalyzer = ExtrusionAnalyzer.Create(
            solid, plane, XYZ.BasisZ );
            }
            catch( Autodesk.Revit.Exceptions
              .InvalidOperationException )
            {
              ++nExtrusionAnalysisFailures;
              return nAdded;
            }

            Face face = extrusionAnalyzer
              .GetExtrusionBase();

            loops.Add( GetLoop( creapp, face ) );

            ++nAdded;
              }
              return nAdded;
        }
        /// <summary>
        /// Retrieve all plan view boundary loops from 
        /// all solids of the given element geometry
        /// united together.
        /// </summary>
        internal static JtLoops GetPlanViewBoundaryLoopsGeo(
            Autodesk.Revit.Creation.Application creapp,
            GeometryElement geo,
            ref int nFailures)
        {
            Solid union = null;

              Plane plane = Plane.CreateByOriginAndBasis(
            XYZ.Zero, XYZ.BasisX, XYZ.BasisY );

              foreach( GeometryObject obj in geo )
              {
            Solid solid = obj as Solid;

            if( null != solid
              && 0 < solid.Faces.Size )
            {
              // Some solids, e.g. in the standard
              // content 'Furniture Chair - Office'
              // cause an extrusion analyser failure,
              // so skip adding those.

              try
              {
            ExtrusionAnalyzer extrusionAnalyzer
              = ExtrusionAnalyzer.Create(
                solid, plane, XYZ.BasisZ );
              }
              catch( Autodesk.Revit.Exceptions
            .InvalidOperationException )
              {
            solid = null;
            ++nFailures;
              }

              if( null != solid )
              {
            if( null == union )
            {
              union = solid;
            }
            else
            {
              try
              {
                union = BooleanOperationsUtils
                  .ExecuteBooleanOperation( union, solid,
                    BooleanOperationsType.Union );
              }
              catch( Autodesk.Revit.Exceptions
                .InvalidOperationException )
              {
                ++nFailures;
              }
            }
              }
            }
              }

              JtLoops loops = new JtLoops( 1 );

              AddLoops( creapp, loops, union, ref nFailures );

              return loops;
        }
示例#6
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;
    }
示例#7
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;
    }