public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; List<Element> floors = new List<Element>(); if( !Util.GetSelectedElementsOrAll( floors, uidoc, typeof( Floor ) ) ) { Selection sel = uidoc.Selection; message = ( 0 < sel.GetElementIds().Count ) ? "Please select some floor elements." : "No floor elements found."; return Result.Failed; } List<Face> faces = new List<Face>(); Options opt = app.Application.Create.NewGeometryOptions(); foreach( Floor floor in floors ) { GeometryElement geo = floor.get_Geometry( opt ); //GeometryObjectArray objects = geo.Objects; // 2012 //foreach( GeometryObject obj in objects ) // 2012 foreach( GeometryObject obj in geo ) // 2013 { Solid solid = obj as Solid; if( solid != null ) { GetSideFaces( faces, solid ); } } } int n = faces.Count; Debug.Print( "{0} side face{1} found.", n, Util.PluralSuffix( n ) ); using ( Transaction t = new Transaction( doc ) ) { t.Start( "Draw Face Triangle Normals" ); Creator creator = new Creator( doc ); foreach ( Face f in faces ) { creator.DrawFaceTriangleNormals( f ); } t.Commit(); } return Result.Succeeded; }
static Transform _t = Transform.CreateTranslation( _offset ); // 2014 #endregion Fields #region Methods 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; List<Element> walls = new List<Element>(); if( !Util.GetSelectedElementsOrAll( walls, uidoc, typeof( Wall ) ) ) { Selection sel = uidoc.Selection; //message = ( 0 < sel.Elements.Size ) // 2014 message = ( 0 < sel.GetElementIds().Count ) // 2015 ? "Please select some wall elements." : "No wall elements found."; return Result.Failed; } using( Transaction tx = new Transaction( doc ) ) { tx.Start( "Create model curve copies of analytical model curves" ); Creator creator = new Creator( doc ); foreach( Wall wall in walls ) { AnalyticalModel am = wall.GetAnalyticalModel(); foreach( AnalyticalCurveType ct in _curveTypes ) { IList<Curve> curves = am.GetCurves( ct ); int n = curves.Count; Debug.Print( "{0} {1} curve{2}.", n, ct, Util.PluralSuffix( n ) ); foreach( Curve curve in curves ) { //creator.CreateModelCurve( curve.get_Transformed( _t ) ); // 2013 creator.CreateModelCurve( curve.CreateTransformed( _t ) ); // 2014 } } } tx.Commit(); } return Result.Succeeded; }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; FamilyInstance beam = Util.SelectSingleElementOfType( uidoc, typeof( FamilyInstance ), "a beam", false ) as FamilyInstance; BuiltInCategory bic = BuiltInCategory.OST_StructuralFraming; if( null == beam || null == beam.Category || !beam.Category.Id.IntegerValue.Equals( (int) bic ) ) { message = "Please select a single beam element."; } else { LocationCurve curve = beam.Location as LocationCurve; if( null == curve ) { message = "No curve available"; return Result.Failed; } XYZ p = curve.Curve.GetEndPoint( 0 ); XYZ q = curve.Curve.GetEndPoint( 1 ); XYZ v = 0.1 * (q - p); p = p - v; q = q + v; Creator creator = new Creator( doc ); creator.CreateModelLine( p, q ); } return Result.Succeeded; }
/// <summary> /// Improved implementation by Alexander Ignatovich /// supporting curved wall with curved window, /// second attempt, published April 10, 2015: /// </summary> public Result Execute3( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Creator creator = new Creator(doc); Wall wall = e as Wall; if (wall == null) { return(Result.Cancelled); } using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the external wall face for the profile // a little bit simpler than in the last // implementation in Execute2. Reference sideFaceReference = HostObjectUtils.GetSideFaces( wall, ShellLayerType.Exterior) .First(); Face face = wall.GetGeometryObjectFromReference( sideFaceReference) as Face; // The plane and normal of the wall external face. XYZ normal = wall.Orientation.Normalize(); Transform ftx = face.ComputeDerivatives(UV.Zero); XYZ forigin = ftx.Origin; XYZ fnormal = ftx.BasisZ; Debug.Print( "wall orientation {0}, face origin {1}, face normal {2}", Util.PointString(normal), Util.PointString(forigin), Util.PointString(fnormal)); // Offset distance. double d = 5; // Offset curve copies for visibility. XYZ voffset = d * normal; Transform offset = Transform.CreateTranslation( voffset); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color(255, 0, 0); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); foreach (var curveLoop in curveLoops) { //CurveLoop curveLoopOffset = CurveLoop.CreateViaOffset( // curveLoop, d, normal ); CurveArray curves = creapp.NewCurveArray(); foreach (Curve curve in curveLoop) { curves.Append(curve.CreateTransformed( offset)); } var isCounterClockwize = curveLoop .IsCounterclockwise(normal); // Create model lines for an curve loop if it is made Curve wallCurve = ((LocationCurve)wall.Location).Curve; if (wallCurve is Line) { //Plane plane = creapp.NewPlane( curves ); // 2016 //Plane plane = curveLoopOffset.GetPlane(); // 2017 Plane plane = Plane.CreateByNormalAndOrigin( // 2019 normal, forigin + voffset); Debug.Print( "plane origin {0}, plane normal {1}", Util.PointString(plane.Origin), Util.PointString(plane.Normal)); SketchPlane sketchPlane = SketchPlane.Create(doc, plane); ModelCurveArray curveElements = credoc .NewModelCurveArray(curves, sketchPlane); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } else { foreach (var curve in curves.Cast <Curve>()) { var curveElements = creator.CreateModelCurves(curve); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } } } tx.Commit(); } return(Result.Succeeded); }
Transform.CreateTranslation(_offset); // 2014 #endif // CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES 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; Options opt = app.Create.NewGeometryOptions(); XyzEqualityComparer comparer = new XyzEqualityComparer(1e-6); #if CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES Creator creator = new Creator(doc); Transaction t = new Transaction(doc); t.Start("Create model curve copies of top face edges"); #endif // CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES IList <Face> topFaces = new List <Face>(); int n; int nWalls = 0; //foreach( Element e in uidoc.Selection.Elements ) // 2014 foreach (ElementId id in uidoc.Selection.GetElementIds()) // 2015 { Element e = doc.GetElement(id); Wall wall = e as Wall; if (null == wall) { Debug.Print("Skipped " + Util.ElementDescription(e)); continue; } // Get the side faces IList <Reference> sideFaces = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Exterior); // Access the first side face Element e2 = doc.GetElement(sideFaces[0]); Debug.Assert(e2.Id.Equals(e.Id), "expected side face element to be the wall itself"); Face face = e2.GetGeometryObjectFromReference( sideFaces[0]) as Face; if (null == face) { Debug.Print("No side face found for " + Util.ElementDescription(e)); continue; } // When there are opening such as doors or // windows in the wall, we need to find the // outer loop. // For one possible approach to extract the // outermost loop, please refer to // http://thebuildingcoder.typepad.com/blog/2008/12/2d-polygon-areas-and-outer-loop.html // Determine the outer loop of the side face // by finding the polygon with the largest area XYZ normal; double area, dist, maxArea = 0; EdgeArray outerLoop = null; foreach (EdgeArray ea in face.EdgeLoops) { if (CmdWallProfileArea.GetPolygonPlane( ea.GetPolygon(), out normal, out dist, out area) && Math.Abs(area) > Math.Abs(maxArea)) { maxArea = area; outerLoop = ea; } } n = 0; #if GET_FACES_FROM_OUTER_LOOP // With the outermost loop, calculate the top faces foreach (Edge edge in outerLoop) { // For each edge, get the neighbouring // face and check its normal for (int i = 0; i < 2; ++i) { PlanarFace pf = edge.get_Face(i) as PlanarFace; if (null == pf) { Debug.Print("Skipped non-planar face on " + Util.ElementDescription(e)); continue; } if (Util.PointsUpwards(pf.Normal, 0.9)) { if (topFaces.Contains(pf)) { Debug.Print("Duplicate face on " + Util.ElementDescription(e)); } else { topFaces.Add(pf); ++n; } } } } #endif // GET_FACES_FROM_OUTER_LOOP List <XYZ> sideVertices = outerLoop.GetPolygon(); // Go over all the faces of the wall and // determine which ones fulfill the following // two criteria: (i) planar face pointing // upwards, and (ii) neighbour of the side // face outer loop. Solid solid = wall.get_Geometry(opt) .OfType <Solid>() .First <Solid>(sol => null != sol); foreach (Face f in solid.Faces) { if (IsTopFace(f)) { IList <XYZ> faceVertices = f.Triangulate().Vertices; //if( sideVertices.Exists( v // => faceVertices.Contains<XYZ>( v, comparer ) ) ) //{ // topFaces.Add( f ); // ++n; //} foreach (XYZ v in faceVertices) { if (sideVertices.Contains <XYZ>( v, comparer)) { topFaces.Add(f); ++n; #if CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES // Display face for debugging purposes foreach (EdgeArray ea in f.EdgeLoops) { IEnumerable <Curve> curves = ea.Cast <Edge>() .Select <Edge, Curve>( x => x.AsCurve()); foreach (Curve curve in curves) { //creator.CreateModelCurve( curve.get_Transformed( _t ) ); // 2013 creator.CreateModelCurve(curve.CreateTransformed(_t)); // 2014 } } #endif // CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES break; } } } } Debug.Print(string.Format( "{0} top face{1} found on {2} ({3})", n, Util.PluralSuffix(n), Util.ElementDescription(e)), nWalls++); } #if CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES t.Commit(); #endif // CREATE_MODEL_CURVES_FOR_TOP_FACE_EDGES string s = string.Format( "{0} wall{1} successfully processed", nWalls, Util.PluralSuffix(nWalls)); n = topFaces.Count; TaskDialog.Show("Wall Top Faces", string.Format( "{0} with {1} top face{2}.", s, n, Util.PluralSuffix(n))); return(Result.Succeeded); }
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; Wall wall = Util.SelectSingleElementOfType( uidoc, typeof( Wall ), "a curtain wall", false ) as Wall; if( null == wall ) { message = "Please select a single " + "curtain wall element."; return Result.Failed; } else { LocationCurve locationcurve = wall.Location as LocationCurve; Curve curve = locationcurve.Curve; // move whole geometry over by length of wall: XYZ p = curve.GetEndPoint( 0 ); XYZ q = curve.GetEndPoint( 1 ); XYZ v = q - p; Transform tv = Transform.CreateTranslation( v ); //curve = curve.get_Transformed( tv ); // 2013 curve = curve.CreateTransformed( tv ); // 2014 Creator creator = new Creator( doc ); creator.CreateModelCurve( curve ); Options opt = app.Create.NewGeometryOptions(); opt.IncludeNonVisibleObjects = true; GeometryElement e = wall.get_Geometry( opt ); foreach( GeometryObject obj in e ) { curve = obj as Curve; if( null != curve ) { //curve = curve.get_Transformed( tv ); // 2013 curve = curve.CreateTransformed( tv ); // 2014 creator.CreateModelCurve( curve ); } } return Result.Succeeded; } }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; Element e = Util.SelectSingleElement( uidoc, "an element"); if (null == e) { message = "No element selected"; return(Result.Failed); } // Trying to call this property returns the // compile time error: Property, indexer, or // event 'BoundingBox' is not supported by // the language; try directly calling // accessor method 'get_BoundingBox( View )' //BoundingBoxXYZ b = e.BoundingBox[null]; View v = null; BoundingBoxXYZ b = e.get_BoundingBox(v); if (null == b) { v = commandData.View; b = e.get_BoundingBox(v); } if (null == b) { Util.InfoMsg( Util.ElementDescription(e) + " has no bounding box."); } else { using (Transaction tx = new Transaction(doc)) { tx.Start("Draw Model Line Bounding Box Outline"); Debug.Assert(b.Transform.IsIdentity, "expected identity bounding box transform"); string in_view = (null == v) ? "model space" : "view " + v.Name; Util.InfoMsg(string.Format( "Element bounding box of {0} in " + "{1} extends from {2} to {3}.", Util.ElementDescription(e), in_view, Util.PointString(b.Min), Util.PointString(b.Max))); Creator creator = new Creator(doc); creator.DrawPolygon(new List <XYZ>( Util.GetBottomCorners(b))); Transform rotation = Transform.CreateRotation( XYZ.BasisZ, 60 * Math.PI / 180.0); b = RotateBoundingBox(b, rotation); Util.InfoMsg(string.Format( "Bounding box rotated by 60 degrees " + "extends from {0} to {1}.", Util.PointString(b.Min), Util.PointString(b.Max))); creator.DrawPolygon(new List <XYZ>( Util.GetBottomCorners(b))); tx.Commit(); } } return(Result.Succeeded); }
/// <summary> /// Improved implementation by Alexander Ignatovich /// supporting curved wall with curved window, /// second attempt, published April 10, 2015: /// </summary> public Result Execute3( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Creator creator = new Creator(doc); Wall wall = e as Wall; if (wall == null) { return(Result.Cancelled); } using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the external wall face for the profile // a little bit simpler than in the last realization Reference sideFaceReference = HostObjectUtils.GetSideFaces( wall, ShellLayerType.Exterior) .First(); Face face = wall.GetGeometryObjectFromReference( sideFaceReference) as Face; // The normal of the wall external face. XYZ normal = wall.Orientation; // Offset curve copies for visibility. Transform offset = Transform.CreateTranslation( 5 * normal); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color(255, 0, 0); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); foreach (var curveLoop in curveLoops) { CurveArray curves = creapp.NewCurveArray(); foreach (Curve curve in curveLoop) { curves.Append(curve.CreateTransformed( offset)); } var isCounterClockwize = curveLoop .IsCounterclockwise(normal); // Create model lines for an curve loop if it is made if (((LocationCurve)wall.Location).Curve is Line) { Plane plane = creapp.NewPlane(curves); SketchPlane sketchPlane = SketchPlane.Create(doc, plane); ModelCurveArray curveElements = credoc .NewModelCurveArray(curves, sketchPlane); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } else { foreach (var curve in curves.Cast <Curve>()) { var curveElements = creator.CreateModelCurves(curve); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } } } tx.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; // retrieve selected floors, or all floors, if nothing is selected: List<Element> floors = new List<Element>(); if( !Util.GetSelectedElementsOrAll( floors, uidoc, typeof( Floor ) ) ) { Selection sel = uidoc.Selection; message = ( 0 < sel.Elements.Size ) ? "Please select some floor elements." : "No floor elements found."; return Result.Failed; } Options opt = app.Application.Create.NewGeometryOptions(); List<List<XYZ>> polygons = GetFloorBoundaryPolygons( floors, opt ); int n = polygons.Count; Debug.Print( "{0} boundary loop{1} found.", n, Util.PluralSuffix( n ) ); Creator creator = new Creator( doc ); using( Transaction t = new Transaction( doc ) ) { t.Start( "Draw Slab Boundaries" ); creator.DrawPolygons( polygons ); t.Commit(); } return Result.Succeeded; }
/// <summary> /// Improved implementation by Alexander Ignatovich /// supporting curved wall with curved window, /// second attempt, published April 10, 2015: /// </summary> public Result Execute3( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall" ); Element e = uidoc.Document.GetElement( r ); Creator creator = new Creator( doc ); Wall wall = e as Wall; if( wall == null ) { return Result.Cancelled; } using( Transaction tx = new Transaction( doc ) ) { tx.Start( "Wall Profile" ); // Get the external wall face for the profile // a little bit simpler than in the last realization Reference sideFaceReference = HostObjectUtils.GetSideFaces( wall, ShellLayerType.Exterior ) .First(); Face face = wall.GetGeometryObjectFromReference( sideFaceReference ) as Face; // The normal of the wall external face. XYZ normal = wall.Orientation; // Offset curve copies for visibility. Transform offset = Transform.CreateTranslation( 5 * normal ); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color( 255, 0, 0 ); // Get edge loops as curve loops. IList<CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); foreach( var curveLoop in curveLoops ) { CurveArray curves = creapp.NewCurveArray(); foreach( Curve curve in curveLoop ) curves.Append( curve.CreateTransformed( offset ) ); var isCounterClockwize = curveLoop .IsCounterclockwise( normal ); // Create model lines for an curve loop if it is made if( ( (LocationCurve) wall.Location ).Curve is Line ) { Plane plane = creapp.NewPlane( curves ); SketchPlane sketchPlane = SketchPlane.Create( doc, plane ); ModelCurveArray curveElements = credoc .NewModelCurveArray( curves, sketchPlane ); if( isCounterClockwize ) { SetModelCurvesColor( curveElements, view, colorRed ); } } else { foreach( var curve in curves.Cast<Curve>() ) { var curveElements = creator.CreateModelCurves( curve ); if( isCounterClockwize ) { SetModelCurvesColor( curveElements, view, colorRed ); } } } } tx.Commit(); } 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; }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; List<Element> floors = new List<Element>(); if( !Util.GetSelectedElementsOrAll( floors, uidoc, typeof( Floor ) ) ) { Selection sel = uidoc.Selection; message = ( 0 < sel.Elements.Size ) ? "Please select some floor elements." : "No floor elements found."; return Result.Failed; } Options opt = app.Application.Create.NewGeometryOptions(); List<List<XYZ>> polygons = CmdSlabBoundary.GetFloorBoundaryPolygons( floors, opt ); List<List<UV>> flat_polygons = Flatten( polygons ); int i = 0, n = flat_polygons.Count; double[] areas = new double[n]; double a, maxArea = 0.0; foreach( List<UV> polygon in flat_polygons ) { a = GetSignedPolygonArea( polygon ); if( Math.Abs( maxArea ) < Math.Abs( a ) ) { maxArea = a; } areas[i++] = a; } Debug.Print( "{0} boundary loop{1} found.", n, Util.PluralSuffix( n ) ); for( i = 0; i < n; ++i ) { Debug.Print( " Loop {0} area is {1} square feet{2}", i, Util.RealString( areas[i] ), ( areas[i].Equals( maxArea ) ? ", outer loop of largest floor slab" : "" ) ); } Creator creator = new Creator( doc ); creator.DrawPolygons( polygons ); return Result.Succeeded; }
static Transform _t = Transform.CreateTranslation(_offset); // 2014 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; List <Element> walls = new List <Element>(); //XYZ p; //List<XYZ> wall_start_points // = walls.Select<Element, XYZ>( e => { // Util.GetElementLocation( out p, e ); // return p; } ) // .ToList<XYZ>(); if (!Util.GetSelectedElementsOrAll( walls, uidoc, typeof(Wall))) { Selection sel = uidoc.Selection; //message = ( 0 < sel.Elements.Size ) // 2014 message = (0 < sel.GetElementIds().Count) // 2015 ? "Please select some wall elements." : "No wall elements found."; return(Result.Failed); } using (Transaction tx = new Transaction(doc)) { tx.Start("Create model curve copies of analytical model curves"); Creator creator = new Creator(doc); foreach (Wall wall in walls) { AnalyticalModel am = wall.GetAnalyticalModel(); foreach (AnalyticalCurveType ct in _curveTypes) { IList <Curve> curves = am.GetCurves(ct); int n = curves.Count; Debug.Print("{0} {1} curve{2}.", n, ct, Util.PluralSuffix(n)); foreach (Curve curve in curves) { //creator.CreateModelCurve( curve.get_Transformed( _t ) ); // 2013 creator.CreateModelCurve(curve.CreateTransformed(_t)); // 2014 } } } tx.Commit(); } 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); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; List <Element> floors = new List <Element>(); if (!Util.GetSelectedElementsOrAll( floors, uidoc, typeof(Floor))) { Selection sel = uidoc.Selection; message = (0 < sel.GetElementIds().Count) ? "Please select some floor elements." : "No floor elements found."; return(Result.Failed); } Options opt = app.Application.Create.NewGeometryOptions(); List <List <XYZ> > polygons = CmdSlabBoundary.GetFloorBoundaryPolygons( floors, opt); List <List <UV> > flat_polygons = Flatten(polygons); int i = 0, n = flat_polygons.Count; double[] areas = new double[n]; double a, maxArea = 0.0; foreach (List <UV> polygon in flat_polygons) { a = GetSignedPolygonArea(polygon); if (Math.Abs(maxArea) < Math.Abs(a)) { maxArea = a; } areas[i++] = a; } Debug.Print( "{0} boundary loop{1} found.", n, Util.PluralSuffix(n)); for (i = 0; i < n; ++i) { Debug.Print( " Loop {0} area is {1} square feet{2}", i, Util.RealString(areas[i]), (areas[i].Equals(maxArea) ? ", outer loop of largest floor slab" : "")); } Creator creator = new Creator(doc); creator.DrawPolygons(polygons); return(Result.Succeeded); }
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 pipes in the entire model. //List<Pipe> pipes = new List<Pipe>( // new FilteredElementCollector( doc ) // .OfClass( typeof( Pipe ) ) // .ToElements() // .Cast<Pipe>() ); //int n = pipes.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. // pipes.Clear(); // Selection sel = uidoc.Selection; // //n = sel.Elements.Size; // 2014 // ICollection<ElementId> ids // = sel.GetElementIds(); // 2015 // n = ids.Count; // 2015 // Debug.Print( "{0} pre-selected elements.", // n ); // // If two or more model pipes were pre- // // selected, use the first two encountered. // if( 1 < n ) // { // //foreach( Element e in sel.Elements ) // 2014 // foreach( ElementId id in ids ) // 2015 // { // Pipe c = doc.GetElement( id ) as Pipe; // if( null != c ) // { // pipes.Add( c ); // if( 2 == pipes.Count ) // { // Debug.Print( "Found two model pipes, " // + "ignoring everything else." ); // break; // } // } // } // } // // Else, prompt for an // // interactive post-selection. // if( 2 != pipes.Count ) // { // pipes.Clear(); // try // { // Reference r = sel.PickObject( // ObjectType.Element, // new PipeElementSelectionFilter(), // "Please pick first pipe." ); // pipes.Add( doc.GetElement( r.ElementId ) // as Pipe ); // } // catch( Autodesk.Revit.Exceptions // .OperationCanceledException ) // { // return Result.Cancelled; // } // try // { // Reference r = sel.PickObject( // ObjectType.Element, // new PipeElementSelectionFilter(), // "Please pick second pipe." ); // pipes.Add( doc.GetElement( r.ElementId ) // as Pipe ); // } // catch( Autodesk.Revit.Exceptions // .OperationCanceledException ) // { // return Result.Cancelled; // } // } //} JtPairPicker <Pipe> picker = new JtPairPicker <Pipe>(uidoc); Result rc = picker.Pick(); if (Result.Failed == rc) { message = _prompt; } if (Result.Succeeded != rc) { return(rc); } IList <Pipe> pipes = picker.Selected; // Check for same pipe system type. ElementId systemTypeId = pipes[0].MEPSystem.GetTypeId(); Debug.Assert(pipes[1].MEPSystem.GetTypeId() .IntegerValue.Equals( systemTypeId.IntegerValue), "expected two similar pipes"); // Check for same pipe level. ElementId levelId = pipes[0].LevelId; Debug.Assert( pipes[1].LevelId.IntegerValue.Equals( levelId.IntegerValue), "expected two pipes on same level"); // Extract data from the two selected pipes. double wall_thickness = GetWallThickness(pipes[0]); Debug.Print("{0} has wall thickness {1}", Util.ElementDescription(pipes[0]), Util.RealString(wall_thickness)); Curve c0 = pipes[0].GetCurve(); Curve c1 = pipes[1].GetCurve(); if (!(c0 is Line) || !(c1 is Line)) { message = _prompt + " Expected straight pipes."; return(Result.Failed); } XYZ p00 = c0.GetEndPoint(0); XYZ p01 = c0.GetEndPoint(1); XYZ p10 = c1.GetEndPoint(0); XYZ p11 = c1.GetEndPoint(1); XYZ v0 = p01 - p00; XYZ v1 = p11 - p10; if (!Util.IsParallel(v0, v1)) { message = _prompt + " Expected parallel pipes."; return(Result.Failed); } // Select the two pipe endpoints // that are farthest apart. XYZ p0 = p00.DistanceTo(p10) > p01.DistanceTo(p10) ? p00 : p01; XYZ p1 = p10.DistanceTo(p0) > p11.DistanceTo(p0) ? p10 : p11; XYZ pm = 0.5 * (p0 + p1); XYZ v = p1 - p0; if (Util.IsParallel(v, v0)) { message = "The selected pipes are colinear."; return(Result.Failed); } // Normal vector of the plane defined by the // two parallel and offset pipes, which is // the plane hosting the rolling offset XYZ z = v.CrossProduct(v1); // Vector perpendicular to v0 and v0 and // z, i.e. vector pointing from the first pipe // to the second in the cross sectional view. XYZ w = z.CrossProduct(v1).Normalize(); // Offset distance perpendicular to pipe direction double distanceAcross = Math.Abs( v.DotProduct(w)); // Distance between endpoints parallel // to pipe direction double distanceAlong = Math.Abs( v.DotProduct(v1.Normalize())); Debug.Assert(Util.IsEqual(v.GetLength(), Math.Sqrt(distanceAcross * distanceAcross + distanceAlong * distanceAlong)), "expected Pythagorean equality here"); // The required offset pipe angle. double angle = 45 * Math.PI / 180.0; // The angle on the other side. double angle2 = 0.5 * Math.PI - angle; double length = distanceAcross * Math.Tan(angle2); double halfLength = 0.5 * length; // How long should the pipe stubs become? double remainingPipeLength = 0.5 * (distanceAlong - length); if (0 > v1.DotProduct(v)) { v1.Negate(); } v1 = v1.Normalize(); XYZ q0 = p0 + remainingPipeLength * v1; XYZ q1 = p1 - remainingPipeLength * v1; using (Transaction tx = new Transaction(doc)) { // Determine pipe diameter for creating // matching pipes and fittings Pipe pipe = pipes[0]; double diameter = pipe .get_Parameter(bipDiameter) // "Diameter" .AsDouble(); // Pipe type for calls to doc.Create.NewPipe PipeType pipe_type_standard = new FilteredElementCollector(doc) .OfClass(typeof(PipeType)) .Cast <PipeType>() .Where <PipeType>(e => e.Name.Equals("Standard")) .FirstOrDefault <PipeType>(); Debug.Assert( pipe_type_standard.Id.IntegerValue.Equals( pipe.PipeType.Id.IntegerValue), "expected all pipes in this simple " + "model to use the same pipe type"); tx.Start("Rolling Offset"); if (_place_model_line) { // Trim or extend existing pipes (pipes[0].Location as LocationCurve).Curve = Line.CreateBound(p0, q0); (pipes[1].Location as LocationCurve).Curve = Line.CreateBound(p1, q1); // Add a model line for the rolling offset pipe Creator creator = new Creator(doc); Line line = Line.CreateBound(q0, q1); creator.CreateModelCurve(line); pipe = null; } else if (_place_fittings) { // Set active work plane to the rolling // offset plane... removed again, since // this has no effect at all on the // fitting placement or rotation. // //Plane plane = new Plane( z, q0 ); // //SketchPlane sp = SketchPlane.Create( // doc, plane ); // //uidoc.ActiveView.SketchPlane = sp; //uidoc.ActiveView.ShowActiveWorkPlane(); FamilySymbol symbol = new FilteredElementCollector(doc) .OfClass(typeof(FamilySymbol)) .OfCategory(BuiltInCategory.OST_PipeFitting) .Cast <FamilySymbol>() .Where <FamilySymbol>(e => e.Family.Name.Contains("Elbow - Generic")) .FirstOrDefault <FamilySymbol>(); // Set up first 45 degree elbow fitting FamilyInstance fitting0 = doc.Create .NewFamilyInstance(q0, symbol, StructuralType.NonStructural); fitting0.get_Parameter("Angle").Set( 45.0 * Math.PI / 180.0); //fitting0.get_Parameter( bipDiameter ) // does not exist // .Set( diameter ); fitting0.get_Parameter("Nominal Radius") .Set(0.5 * diameter); Line axis = Line.CreateBound(p0, q0); angle = z.AngleTo(XYZ.BasisZ); ElementTransformUtils.RotateElement( doc, fitting0.Id, axis, Math.PI - angle); Connector con0 = Util.GetConnectorClosestTo( fitting0, p0); // Trim or extend existing pipe (pipes[0].Location as LocationCurve).Curve = Line.CreateBound(p0, con0.Origin); // Connect pipe to fitting Util.Connect(con0.Origin, pipe, fitting0); // Set up second 45 degree elbow fitting FamilyInstance fitting1 = doc.Create .NewFamilyInstance(q1, symbol, StructuralType.NonStructural); fitting1.get_Parameter("Angle").Set( 45.0 * Math.PI / 180.0); fitting1.get_Parameter("Nominal Radius") .Set(0.5 * diameter); axis = Line.CreateBound( q1, q1 + XYZ.BasisZ); ElementTransformUtils.RotateElement( doc, fitting1.Id, axis, Math.PI); axis = Line.CreateBound(q1, p1); ElementTransformUtils.RotateElement( doc, fitting1.Id, axis, Math.PI - angle); Connector con1 = Util.GetConnectorClosestTo( fitting1, p1); (pipes[1].Location as LocationCurve).Curve = Line.CreateBound(con1.Origin, p1); Util.Connect(con1.Origin, fitting1, pipes[1]); con0 = Util.GetConnectorClosestTo( fitting0, pm); con1 = Util.GetConnectorClosestTo( fitting1, pm); // Connecting one fitting to the other does // not insert a pipe in between. If the // system is edited later, however, the two // fittings snap together. // //con0.ConnectTo( con1 ); // Create rolling offset pipe segment //pipe = doc.Create.NewPipe( con0.Origin, // 2014 // con1.Origin, pipe_type_standard ); pipe = Pipe.Create(doc, pipe_type_standard.Id, levelId, con0, con1); // 2015 pipe.get_Parameter(bipDiameter) .Set(diameter); // Connect rolling offset pipe segment // with elbow fittings at each end Util.Connect(con0.Origin, fitting0, pipe); Util.Connect(con1.Origin, pipe, fitting1); } else { if (_use_static_pipe_create) { // Element id arguments to Pipe.Create. ElementId idSystem; ElementId idType; ElementId idLevel; // All these values are invalid for idSystem: ElementId idSystem1 = pipe.MEPSystem.Id; ElementId idSystem2 = ElementId.InvalidElementId; ElementId idSystem3 = PipingSystem.Create( doc, pipe.MEPSystem.GetTypeId(), "Tbc") .Id; // This throws an argument exception saying // The systemTypeId is not valid piping system type. // Parameter name: systemTypeId //pipe = Pipe.Create( doc, idSystem, // idType, idLevel, q0, q1 ); // Retrieve pipe system type, e.g. // hydronic supply. PipingSystemType pipingSystemType = new FilteredElementCollector(doc) .OfClass(typeof(PipingSystemType)) .OfType <PipingSystemType>() .FirstOrDefault(st => st.SystemClassification == MEPSystemClassification .SupplyHydronic); if (null == pipingSystemType) { message = "Could not find hydronic supply piping system type"; return(Result.Failed); } idSystem = pipingSystemType.Id; Debug.Assert(pipe.get_Parameter( BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM) .AsElementId().IntegerValue.Equals( idSystem.IntegerValue), "expected same piping system element id"); // Retrieve the PipeType. PipeType pipeType = new FilteredElementCollector(doc) .OfClass(typeof(PipeType)) .OfType <PipeType>() .FirstOrDefault(); if (null == pipeType) { message = "Could not find pipe type"; return(Result.Failed); } idType = pipeType.Id; Debug.Assert(pipe.get_Parameter( BuiltInParameter.ELEM_TYPE_PARAM) .AsElementId().IntegerValue.Equals( idType.IntegerValue), "expected same pipe type element id"); Debug.Assert(pipe.PipeType.Id.IntegerValue .Equals(idType.IntegerValue), "expected same pipe type element id"); // Retrieve the reference level. // pipe.LevelId is not the correct source! idLevel = pipe.get_Parameter( BuiltInParameter.RBS_START_LEVEL_PARAM) .AsElementId(); // Create the rolling offset pipe. pipe = Pipe.Create(doc, idSystem, idType, idLevel, q0, q1); } else { pipe = doc.Create.NewPipe(q0, q1, pipe_type_standard); } pipe.get_Parameter(bipDiameter) .Set(diameter); // Connect rolling offset pipe segment // directly with the neighbouring original // pipes // //Util.Connect( q0, pipes[0], pipe ); //Util.Connect( q1, pipe, pipes[1] ); // NewElbowFitting performs the following: // - select appropriate fitting family and type // - place and orient a family instance // - set its parameters appropriately // - connect it with its neighbours Connector con0 = Util.GetConnectorClosestTo( pipes[0], q0); Connector con = Util.GetConnectorClosestTo( pipe, q0); doc.Create.NewElbowFitting(con0, con); Connector con1 = Util.GetConnectorClosestTo( pipes[1], q1); con = Util.GetConnectorClosestTo( pipe, q1); doc.Create.NewElbowFitting(con, con1); } tx.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; List<Element> walls = new List<Element>(); if( !Util.GetSelectedElementsOrAll( walls, uidoc, typeof( Wall ) ) ) { Selection sel = uidoc.Selection; message = ( 0 < sel.Elements.Size ) ? "Please select some wall elements." : "No wall elements found."; return Result.Failed; } Options opt = app.Application.Create.NewGeometryOptions(); List<List<XYZ>> polygons = CmdWallProfile.GetWallProfilePolygons( walls, opt ); int i = 0, n = polygons.Count; double[] areas = new double[n]; double d, a, maxArea = 0.0; XYZ normal; foreach( List<XYZ> polygon in polygons ) { GetPolygonPlane( polygon, out normal, out d, out a ); if( Math.Abs( maxArea ) < Math.Abs( a ) ) { maxArea = a; } areas[i++] = a; #if DEBUG // transform the 3D polygon into a horizontal plane // so we can use the 2D GetSignedPolygonArea() and // compare its results with the 3D calculation. // todo: compare the relative speed of // transforming 3d to 2d and using 2d area // calculation versus direct 3d area calculation. Transform t = GetTransformToZ( normal ); List<XYZ> polygonHorizontal = ApplyTransform( polygon, t ); List<UV> polygon2d = CmdSlabBoundaryArea.Flatten( polygonHorizontal ); double a2 = CmdSlabBoundaryArea.GetSignedPolygonArea( polygon2d ); Debug.Assert( Util.IsEqual( a, a2 ), "expected same area from 2D and 3D calculations" ); #endif } Debug.Print( "{0} boundary loop{1} found.", n, Util.PluralSuffix( n ) ); for( i = 0; i < n; ++i ) { Debug.Print( " Loop {0} area is {1} square feet{2}", i, Util.RealString( areas[i] ), ( areas[i].Equals( maxArea ) ? ", outer loop of largest wall" : "" ) ); } Creator creator = new Creator( doc ); creator.DrawPolygons( polygons ); return Result.Succeeded; }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; List<Element> walls = new List<Element>(); if( !Util.GetSelectedElementsOrAll( walls, uidoc, typeof( Wall ) ) ) { Selection sel = uidoc.Selection; message = ( 0 < sel.Elements.Size ) ? "Please select some wall elements." : "No wall elements found."; return Result.Failed; } Options opt = app.Application.Create.NewGeometryOptions(); List<List<XYZ>> polygons = GetWallProfilePolygons( walls, opt ); int n = polygons.Count; Debug.Print( "{0} boundary loop{1} found.", n, Util.PluralSuffix( n ) ); Creator creator = new Creator( doc ); creator.DrawPolygons( polygons ); return Result.Succeeded; }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = app.ActiveUIDocument.Document; // Retrieve selected walls, or all walls, // if nothing is selected: List <Element> walls = new List <Element>(); if (!Util.GetSelectedElementsOrAll( walls, uidoc, typeof(Wall))) { Selection sel = uidoc.Selection; message = (0 < sel.GetElementIds().Count) ? "Please select some wall elements." : "No wall elements found."; return(Result.Failed); } //int i; // 2011 int n; double halfThickness, layerOffset; //Creator creator = new Creator( doc ); XYZ lcstart, lcend, v, w, p, q; using (Transaction tx = new Transaction(doc)) { tx.Start("Draw wall layer sepearation lines"); foreach (Wall wall in walls) { string desc = Util.ElementDescription(wall); LocationCurve curve = wall.Location as LocationCurve; if (null == curve) { message = desc + ": No wall curve found."; return(Result.Failed); } // Wall centre line and thickness: lcstart = curve.Curve.GetEndPoint(0); lcend = curve.Curve.GetEndPoint(1); halfThickness = 0.5 * wall.WallType.Width; v = lcend - lcstart; v = v.Normalize(); // one foot long w = XYZ.BasisZ.CrossProduct(v).Normalize(); if (wall.Flipped) { w = -w; } p = lcstart - 2 * v; q = lcend + 2 * v; Creator.CreateModelLine(doc, p, q); q = p + halfThickness * w; Creator.CreateModelLine(doc, p, q); // Exterior edge p = lcstart - v + halfThickness * w; q = lcend + v + halfThickness * w; Creator.CreateModelLine(doc, p, q); //CompoundStructure structure = wall.WallType.CompoundStructure; // 2011 CompoundStructure structure = wall.WallType.GetCompoundStructure(); // 2012 if (null == structure) { message = desc + ": No compound structure " + "found. Is this a stacked wall?"; return(Result.Failed); } //CompoundStructureLayerArray layers = structure.Layers; // 2011 IList <CompoundStructureLayer> layers = structure.GetLayers(); // 2012 //i = 0; // 2011 //n = layers.Size; // 2011 n = layers.Count; // 2012 Debug.Print( "{0} with thickness {1}" + " has {2} layer{3}{4}", desc, Util.MmString(2 * halfThickness), n, Util.PluralSuffix(n), Util.DotOrColon(n)); if (0 == n) { // Interior edge p = lcstart - v - halfThickness * w; q = lcend + v - halfThickness * w; Creator.CreateModelLine(doc, p, q); } else { layerOffset = halfThickness; foreach (CompoundStructureLayer layer in layers) { Debug.Print( " Layer {0}: function {1}, " + "thickness {2}", //++i, // 2011 layers.IndexOf(layer), // 2012 layer.Function, Util.MmString(layer.Width)); //layerOffset -= layer.Thickness; // 2011 layerOffset -= layer.Width; // 2012 p = lcstart - v + layerOffset * w; q = lcend + v + layerOffset * w; Creator.CreateModelLine(doc, p, q); } } tx.Commit(); } } return(Result.Succeeded); }
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 pipes in the entire model. List<Pipe> pipes = new List<Pipe>( new FilteredElementCollector( doc ) .OfClass( typeof( Pipe ) ) .ToElements() .Cast<Pipe>() ); int n = pipes.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. pipes.Clear(); Selection sel = uidoc.Selection; n = sel.Elements.Size; Debug.Print( "{0} pre-selected elements.", n ); // If two or more model pipes were pre- // selected, use the first two encountered. if( 1 < n ) { foreach( Element e in sel.Elements ) { Pipe c = e as Pipe; if( null != c ) { pipes.Add( c ); if( 2 == pipes.Count ) { Debug.Print( "Found two model pipes, " + "ignoring everything else." ); break; } } } } // Else, prompt for an // interactive post-selection. if( 2 != pipes.Count ) { pipes.Clear(); try { Reference r = sel.PickObject( ObjectType.Element, new PipeElementSelectionFilter(), "Please pick first pipe." ); pipes.Add( doc.GetElement( r.ElementId ) as Pipe ); } catch( Autodesk.Revit.Exceptions .OperationCanceledException ) { return Result.Cancelled; } try { Reference r = sel.PickObject( ObjectType.Element, new PipeElementSelectionFilter(), "Please pick second pipe." ); pipes.Add( doc.GetElement( r.ElementId ) as Pipe ); } catch( Autodesk.Revit.Exceptions .OperationCanceledException ) { return Result.Cancelled; } } } // Extract data from the two selected pipes. Curve c0 = ( pipes[0].Location as LocationCurve ).Curve; Curve c1 = ( pipes[1].Location as LocationCurve ).Curve; if( !( c0 is Line ) || !( c1 is Line ) ) { message = _prompt + " Expected straight pipes."; return Result.Failed; } XYZ p00 = c0.GetEndPoint( 0 ); XYZ p01 = c0.GetEndPoint( 1 ); XYZ p10 = c1.GetEndPoint( 0 ); XYZ p11 = c1.GetEndPoint( 1 ); XYZ v0 = p01 - p00; XYZ v1 = p11 - p10; if( !Util.IsParallel( v0, v1 ) ) { message = _prompt + " Expected parallel pipes."; return Result.Failed; } // Select the two pipe endpoints // that are farthest apart. XYZ p0 = p00.DistanceTo( p10 ) > p01.DistanceTo( p10 ) ? p00 : p01; XYZ p1 = p10.DistanceTo( p0 ) > p11.DistanceTo( p0 ) ? p10 : p11; XYZ pm = 0.5 * ( p0 + p1 ); XYZ v = p1 - p0; if( Util.IsParallel( v, v0 ) ) { message = "The selected pipes are colinear."; return Result.Failed; } // Normal vector of the plane defined by the // two parallel and offset pipes, which is // the plane hosting the rolling offset XYZ z = v.CrossProduct( v1 ); // Vector perpendicular to v0 and v0 and // z, i.e. vector pointing from the first pipe // to the second in the cross sectional view. XYZ w = z.CrossProduct( v1 ).Normalize(); // Offset distance perpendicular to pipe direction double distanceAcross = Math.Abs( v.DotProduct( w ) ); // Distance between endpoints parallel // to pipe direction double distanceAlong = Math.Abs( v.DotProduct( v1.Normalize() ) ); Debug.Assert( Util.IsEqual( v.GetLength(), Math.Sqrt( distanceAcross * distanceAcross + distanceAlong * distanceAlong ) ), "expected Pythagorean equality here" ); // The required offset pipe angle. double angle = 45 * Math.PI / 180.0; // The angle on the other side. double angle2 = 0.5 * Math.PI - angle; double length = distanceAcross * Math.Tan( angle2 ); double halfLength = 0.5 * length; // How long should the pipe stubs become? double remainingPipeLength = 0.5 * ( distanceAlong - length ); if( 0 > v1.DotProduct( v ) ) { v1.Negate(); } v1 = v1.Normalize(); XYZ q0 = p0 + remainingPipeLength * v1; XYZ q1 = p1 - remainingPipeLength * v1; using( Transaction tx = new Transaction( doc ) ) { // Determine pipe diameter for creating // matching pipes and fittings Pipe pipe = pipes[0]; double diameter = pipe .get_Parameter( bipDiameter ) // "Diameter" .AsDouble(); // Pipe type for calls to doc.Create.NewPipe PipeType pipe_type_standard = new FilteredElementCollector( doc ) .OfClass( typeof( PipeType ) ) .Cast<PipeType>() .Where<PipeType>( e => e.Name.Equals( "Standard" ) ) .FirstOrDefault<PipeType>(); Debug.Assert( pipe_type_standard.Id.IntegerValue.Equals( pipe.PipeType.Id.IntegerValue ), "expected all pipes in this simple " + "model to use the same pipe type" ); tx.Start( "Rolling Offset" ); if( _place_model_line ) { // Trim or extend existing pipes ( pipes[0].Location as LocationCurve ).Curve = Line.CreateBound( p0, q0 ); ( pipes[1].Location as LocationCurve ).Curve = Line.CreateBound( p1, q1 ); // Add a model line for the rolling offset pipe Creator creator = new Creator( doc ); Line line = Line.CreateBound( q0, q1 ); creator.CreateModelCurve( line ); pipe = null; } else if( _place_fittings ) { // Set active work plane to the rolling // offset plane... removed again, since // this has no effect at all on the // fitting placement or rotation. // //Plane plane = new Plane( z, q0 ); // //SketchPlane sp = SketchPlane.Create( // doc, plane ); // //uidoc.ActiveView.SketchPlane = sp; //uidoc.ActiveView.ShowActiveWorkPlane(); FamilySymbol symbol = new FilteredElementCollector( doc ) .OfClass( typeof( FamilySymbol ) ) .OfCategory( BuiltInCategory.OST_PipeFitting ) .Cast<FamilySymbol>() .Where<FamilySymbol>( e => e.Family.Name.Contains( "Elbow - Generic" ) ) .FirstOrDefault<FamilySymbol>(); // Set up first 45 degree elbow fitting FamilyInstance fitting0 = doc.Create .NewFamilyInstance( q0, symbol, StructuralType.NonStructural ); fitting0.get_Parameter( "Angle" ).Set( 45.0 * Math.PI / 180.0 ); //fitting0.get_Parameter( bipDiameter ) // does not exist // .Set( diameter ); fitting0.get_Parameter( "Nominal Radius" ) .Set( 0.5 * diameter ); Line axis = Line.CreateBound( p0, q0 ); angle = z.AngleTo( XYZ.BasisZ ); ElementTransformUtils.RotateElement( doc, fitting0.Id, axis, Math.PI - angle ); Connector con0 = Util.GetConnectorClosestTo( fitting0, p0 ); // Trim or extend existing pipe ( pipes[0].Location as LocationCurve ).Curve = Line.CreateBound( p0, con0.Origin ); // Connect pipe to fitting Util.Connect( con0.Origin, pipe, fitting0 ); // Set up second 45 degree elbow fitting FamilyInstance fitting1 = doc.Create .NewFamilyInstance( q1, symbol, StructuralType.NonStructural ); fitting1.get_Parameter( "Angle" ).Set( 45.0 * Math.PI / 180.0 ); fitting1.get_Parameter( "Nominal Radius" ) .Set( 0.5 * diameter ); axis = Line.CreateBound( q1, q1 + XYZ.BasisZ ); ElementTransformUtils.RotateElement( doc, fitting1.Id, axis, Math.PI ); axis = Line.CreateBound( q1, p1 ); ElementTransformUtils.RotateElement( doc, fitting1.Id, axis, Math.PI - angle ); Connector con1 = Util.GetConnectorClosestTo( fitting1, p1 ); ( pipes[1].Location as LocationCurve ).Curve = Line.CreateBound( con1.Origin, p1 ); Util.Connect( con1.Origin, fitting1, pipes[1] ); con0 = Util.GetConnectorClosestTo( fitting0, pm ); con1 = Util.GetConnectorClosestTo( fitting1, pm ); // Connecting one fitting to the other does // not insert a pipe in between. If the // system is edited later, however, the two // fittings snap together. // //con0.ConnectTo( con1 ); // Create rolling offset pipe segment pipe = doc.Create.NewPipe( con0.Origin, con1.Origin, pipe_type_standard ); pipe.get_Parameter( bipDiameter ) .Set( diameter ); // Connect rolling offset pipe segment // with elbow fittings at each end Util.Connect( con0.Origin, fitting0, pipe ); Util.Connect( con1.Origin, pipe, fitting1 ); } else { if( _use_static_pipe_create ) { // Element id arguments to Pipe.Create. ElementId idSystem; ElementId idType; ElementId idLevel; // All these values are invalid for idSystem: ElementId idSystem1 = pipe.MEPSystem.Id; ElementId idSystem2 = ElementId.InvalidElementId; ElementId idSystem3 = PipingSystem.Create( doc, pipe.MEPSystem.GetTypeId(), "Tbc" ) .Id; // This throws an argument exception saying // The systemTypeId is not valid piping system type. // Parameter name: systemTypeId //pipe = Pipe.Create( doc, idSystem, // idType, idLevel, q0, q1 ); // Retrieve pipe system type, e.g. // hydronic supply. PipingSystemType pipingSystemType = new FilteredElementCollector( doc ) .OfClass( typeof( PipingSystemType ) ) .OfType<PipingSystemType>() .FirstOrDefault( st => st.SystemClassification == MEPSystemClassification .SupplyHydronic ); if( null == pipingSystemType ) { message = "Could not find hydronic supply piping system type"; return Result.Failed; } idSystem = pipingSystemType.Id; Debug.Assert( pipe.get_Parameter( BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM ) .AsElementId().IntegerValue.Equals( idSystem.IntegerValue ), "expected same piping system element id" ); // Retrieve the PipeType. PipeType pipeType = new FilteredElementCollector( doc ) .OfClass( typeof( PipeType ) ) .OfType<PipeType>() .FirstOrDefault(); if( null == pipeType ) { message = "Could not find pipe type"; return Result.Failed; } idType = pipeType.Id; Debug.Assert( pipe.get_Parameter( BuiltInParameter.ELEM_TYPE_PARAM ) .AsElementId().IntegerValue.Equals( idType.IntegerValue ), "expected same pipe type element id" ); Debug.Assert( pipe.PipeType.Id.IntegerValue .Equals( idType.IntegerValue ), "expected same pipe type element id" ); // Retrieve the reference level. // pipe.LevelId is not the correct source! idLevel = pipe.get_Parameter( BuiltInParameter.RBS_START_LEVEL_PARAM ) .AsElementId(); // Create the rolling offset pipe. pipe = Pipe.Create( doc, idSystem, idType, idLevel, q0, q1 ); } else { pipe = doc.Create.NewPipe( q0, q1, pipe_type_standard ); } pipe.get_Parameter( bipDiameter ) .Set( diameter ); // Connect rolling offset pipe segment // directly with the neighbouring original // pipes // //Util.Connect( q0, pipes[0], pipe ); //Util.Connect( q1, pipe, pipes[1] ); // NewElbowFitting performs the following: // - select appropriate fitting family and type // - place and orient a family instance // - set its parameters appropriately // - connect it with its neighbours Connector con0 = Util.GetConnectorClosestTo( pipes[0], q0 ); Connector con = Util.GetConnectorClosestTo( pipe, q0 ); doc.Create.NewElbowFitting( con0, con ); Connector con1 = Util.GetConnectorClosestTo( pipes[1], q1 ); con = Util.GetConnectorClosestTo( pipe, q1 ); doc.Create.NewElbowFitting( con, con1 ); } tx.Commit(); } return Result.Succeeded; }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; List <Element> walls = new List <Element>(); if (!Util.GetSelectedElementsOrAll( walls, uidoc, typeof(Wall))) { Selection sel = uidoc.Selection; message = (0 < sel.GetElementIds().Count) ? "Please select some wall elements." : "No wall elements found."; return(Result.Failed); } Options opt = app.Application.Create.NewGeometryOptions(); List <List <XYZ> > polygons = CmdWallProfile.GetWallProfilePolygons( walls, opt); int i = 0, n = polygons.Count; double[] areas = new double[n]; double d, a, maxArea = 0.0; XYZ normal; foreach (List <XYZ> polygon in polygons) { GetPolygonPlane(polygon, out normal, out d, out a); if (Math.Abs(maxArea) < Math.Abs(a)) { maxArea = a; } areas[i++] = a; #if DEBUG // transform the 3D polygon into a horizontal plane // so we can use the 2D GetSignedPolygonArea() and // compare its results with the 3D calculation. // todo: compare the relative speed of // transforming 3d to 2d and using 2d area // calculation versus direct 3d area calculation. Transform t = GetTransformToZ(normal); List <XYZ> polygonHorizontal = ApplyTransform(polygon, t); List <UV> polygon2d = CmdSlabBoundaryArea.Flatten( polygonHorizontal); double a2 = CmdSlabBoundaryArea.GetSignedPolygonArea( polygon2d); Debug.Assert(Util.IsEqual(a, a2), "expected same area from 2D and 3D calculations"); #endif } Debug.Print( "{0} boundary loop{1} found.", n, Util.PluralSuffix(n)); for (i = 0; i < n; ++i) { Debug.Print( " Loop {0} area is {1} square feet{2}", i, Util.RealString(areas[i]), (areas[i].Equals(maxArea) ? ", outer loop of largest wall" : "")); } Creator creator = new Creator(doc); using (Transaction tx = new Transaction(doc)) { tx.Start("Draw wall profile loops"); creator.DrawPolygons(polygons); tx.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = app.ActiveUIDocument.Document; // retrieve selected walls, or all walls, // if nothing is selected: List<Element> walls = new List<Element>(); if( !Util.GetSelectedElementsOrAll( walls, uidoc, typeof( Wall ) ) ) { Selection sel = uidoc.Selection; message = ( 0 < sel.Elements.Size ) ? "Please select some wall elements." : "No wall elements found."; return Result.Failed; } //int i; // 2011 int n; double halfThickness, layerOffset; Creator creator = new Creator( doc ); XYZ lcstart, lcend, v, w, p, q; foreach( Wall wall in walls ) { string desc = Util.ElementDescription( wall ); LocationCurve curve = wall.Location as LocationCurve; if( null == curve ) { message = desc + ": No wall curve found."; return Result.Failed; } // wall centre line and thickness: lcstart = curve.Curve.GetEndPoint( 0 ); lcend = curve.Curve.GetEndPoint( 1 ); halfThickness = 0.5 * wall.WallType.Width; v = lcend - lcstart; v = v.Normalize(); // one foot long w = XYZ.BasisZ.CrossProduct( v ).Normalize(); if( wall.Flipped ) { w = -w; } p = lcstart - 2 * v; q = lcend + 2 * v; creator.CreateModelLine( p, q ); q = p + halfThickness * w; creator.CreateModelLine( p, q ); // exterior edge p = lcstart - v + halfThickness * w; q = lcend + v + halfThickness * w; creator.CreateModelLine( p, q ); //CompoundStructure structure = wall.WallType.CompoundStructure; // 2011 CompoundStructure structure = wall.WallType.GetCompoundStructure(); // 2012 //CompoundStructureLayerArray layers = structure.Layers; // 2011 IList<CompoundStructureLayer> layers = structure.GetLayers(); // 2012 //i = 0; // 2011 //n = layers.Size; // 2011 n = layers.Count; // 2012 Debug.Print( "{0} with thickness {1}" + " has {2} layer{3}{4}", desc, Util.MmString( 2 * halfThickness ), n, Util.PluralSuffix( n ), Util.DotOrColon( n ) ); if( 0 == n ) { // interior edge p = lcstart - v - halfThickness * w; q = lcend + v - halfThickness * w; creator.CreateModelLine( p, q ); } else { layerOffset = halfThickness; foreach( CompoundStructureLayer layer in layers ) { Debug.Print( " Layer {0}: function {1}, " + "thickness {2}", //++i, // 2011 layers.IndexOf( layer ), // 2012 layer.Function, Util.MmString( layer.Width ) ); //layerOffset -= layer.Thickness; // 2011 layerOffset -= layer.Width; // 2012 p = lcstart - v + layerOffset * w; q = lcend + v + layerOffset * w; creator.CreateModelLine( p, q ); } } } return Result.Succeeded; }
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; Wall wall = Util.SelectSingleElementOfType( uidoc, typeof(Wall), "a curtain wall", false) as Wall; if (null == wall) { message = "Please select a single " + "curtain wall element."; return(Result.Failed); } else { LocationCurve locationcurve = wall.Location as LocationCurve; Curve curve = locationcurve.Curve; // move whole geometry over by length of wall: XYZ p = curve.GetEndPoint(0); XYZ q = curve.GetEndPoint(1); XYZ v = q - p; Transform tv = Transform.CreateTranslation(v); //curve = curve.get_Transformed( tv ); // 2013 curve = curve.CreateTransformed(tv); // 2014 Creator creator = new Creator(doc); creator.CreateModelCurve(curve); Options opt = app.Create.NewGeometryOptions(); opt.IncludeNonVisibleObjects = true; GeometryElement e = wall.get_Geometry(opt); using (Transaction t = new Transaction(doc)) { t.Start("Create Model Curves"); foreach (GeometryObject obj in e) { curve = obj as Curve; if (null != curve) { //curve = curve.get_Transformed( tv ); // 2013 curve = curve.CreateTransformed(tv); // 2014 creator.CreateModelCurve(curve); } } t.Commit(); } return(Result.Succeeded); } }