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>(); 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 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.LookupParameter("Angle").Set( 45.0 * Math.PI / 180.0); //fitting0.get_Parameter( bipDiameter ) // does not exist // .Set( diameter ); fitting0.LookupParameter("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 ); // 2014 //fitting1.get_Parameter( "Nominal Radius" ).Set( 0.5 * diameter ); // 2014 fitting1.LookupParameter("Angle").Set(45.0 * Math.PI / 180.0); // 2015 fitting1.LookupParameter("Nominal Radius").Set(0.5 * diameter); // 2015 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 ); // 2014 pipe = Pipe.Create(doc, systemTypeId, pipe_type_standard.Id, levelId, q0, q1); // 2015 } 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 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 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; }
///// <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; }
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>(); //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; }
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); }
///// <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 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; } }