revit-api - REVIT 将地板草图转移到家庭中的空隙挤压
问题描述
努力使用一些 Revit 代码来复制楼板的轮廓并将其用作族中空心拉伸的草图轮廓。
这是完整的夏普开发代码。它在我的自定义项目模板中工作了一半,当我尝试在从 revit 默认模板生成的开箱即用项目中使用它时,它会给出错误“revit 或其外部应用程序之一引发了托管异常”
在我的模板中,它无法正确地将曲线拆分为辅助数组。它说数组元素正在被更改,但是当循环再次运行时,元素 i 又回到了它的原始内容???TaskDialog 清楚地表明元素已更改,直到循环再次迭代。
完整代码:要工作,它需要一个名为“Void - Custom”的通用族在项目中。靠近最后一页和一半代码的“如果找到”是 for 循环未按预期运行的地方。
/*
* Created by SharpDevelop.
* User: arautio
* Date: 4/30/2019
* Time: 11:10 AM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using System.Text;
using System.IO;
using System.Diagnostics;
namespace ARC
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.DB.Macros.AddInId("3411F411-6FC1-4A4D-9CFD-37ABB2028A15")]
public partial class ThisApplication
{
private void Module_Startup(object sender, EventArgs e)
{
}
private void Module_Shutdown(object sender, EventArgs e)
{
}
#region Revit Macros generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(Module_Startup);
this.Shutdown += new System.EventHandler(Module_Shutdown);
}
#endregion
public void FloorGrating()
{
StringBuilder sb = new StringBuilder();
Dictionary<Floor, List<ModelCurve>> dict_SketchLines = new Dictionary<Floor, List<ModelCurve>>();
UIDocument uidoc = this.ActiveUIDocument;
Document document = uidoc.Document;
View activev = document.ActiveView;
ElementId levelId = null;
levelId = activev.LevelId;
Element levelem = document.GetElement( levelId );
Level lev = document.ActiveView.GenLevel;
Reference refsel = uidoc.Selection.PickObject(ObjectType.Element, "Select Floor to Add Grating To");
Element elem = document.GetElement(refsel.ElementId);
Floor f = elem as Floor;
List<ElementId> _deleted = null;
using (Transaction t = new Transaction(document, "temp"))
{
t.Start();
document.Regenerate();
_deleted = document.Delete(elem.Id).ToList();
t.RollBack();
}
bool SketchLinesFound = false;
List<ModelCurve> _sketchCurves = new List<ModelCurve>();
foreach (var id in _deleted)
{
ModelCurve mc = document.GetElement(id) as ModelCurve;
if (mc != null)
{
_sketchCurves.Add(mc);
SketchLinesFound = true;
}
else
{
if (SketchLinesFound) break;
}
}
dict_SketchLines.Add(f, _sketchCurves);
foreach (Floor key in dict_SketchLines.Keys)
{
List<ModelCurve> _curves = dict_SketchLines[key];
sb.AppendLine(string.Format("floor {0} has sketchlines:", key.Id));
foreach (ModelCurve mc in _curves)
{
sb.AppendLine(string.Format("{0} <{1}>", mc.GetType(), mc.Id));
sb.AppendLine(string.Format("<{0}>", mc.GeometryCurve.IsBound.ToString()));
if (mc.GetType().ToString() == "Autodesk.Revit.DB.ModelArc" && mc.GeometryCurve.IsBound == false)
{
TaskDialog.Show("Revit", "Circle Found");
}
try
{
sb.AppendLine(string.Format("<{0} -- {1}>", mc.GeometryCurve.GetEndPoint(0), mc.GeometryCurve.GetEndPoint(1)));
}
catch
{
}
}
sb.AppendLine();
}
//TaskDialog.Show("debug", sb.ToString());
Document docfamily;
Family fam;
string ftitle = document.Title;
string fpath = document.PathName;
int ftitlelen = ftitle.Length + 4;
int fpathlen = fpath.Length;
int finpathlen = fpathlen - ftitlelen;
string sfinpath = fpath.Substring(0,finpathlen);
string famname = "GratingVoid";
string fext = ".rfa";
int counter = 1;
while (counter < 100)
{
famname = ("GratingVoid" + counter as String);
Family family = FindElementByName(document,typeof(Family),famname)as Family;
if( null == family )
{
sfinpath = (sfinpath + famname + fext);
counter = 1000;
}
counter += 1;
}
FilteredElementCollector collector0 = new FilteredElementCollector(document);
ICollection<Element> collection0 = collector0.WhereElementIsNotElementType().ToElements();
List<FamilySymbol> fsym0 = new FilteredElementCollector(document).OfClass(typeof(FamilySymbol)).Cast<FamilySymbol>().ToList();
FamilySymbol famsymb0 = null;
foreach (FamilySymbol symb in fsym0)
{
if (symb.Name == "Void - Custom")
{
famsymb0 = symb as FamilySymbol;
}
}
fam = famsymb0.Family;
docfamily = document.EditFamily(fam);
try
{
docfamily.SaveAs(@sfinpath);
}
catch
{
TaskDialog.Show("Revit", "Could Not Save Void Family");
}
using (Transaction trans = new Transaction(docfamily))
{
trans.Start("family");
bool circleflag = false;
ElementId delid = null;
FilteredElementCollector collector = new FilteredElementCollector( docfamily );
foreach(Element element in collector.OfClass(typeof(GenericForm)))
{
delid = element.Id;
}
docfamily.Delete(delid);
CurveArray loccurva = new CurveArray();
foreach (Floor key in dict_SketchLines.Keys)
{
List<ModelCurve> _curves = dict_SketchLines[key];
foreach (ModelCurve mc in _curves)
{
if (mc.GetType().ToString() == "Autodesk.Revit.DB.ModelArc" && mc.GeometryCurve.IsBound == false)
{
circleflag = true;
}
LocationCurve lcurve = mc.Location as LocationCurve;
Curve c = lcurve.Curve as Curve;
loccurva.Append(c);
}
}
try
{
if (circleflag == true && loccurva.Size == 2)
{
Curve tempc;
if (loccurva.get_Item(0).GetType().ToString() == "Autodesk.Revit.DB.Arc")
{
tempc = loccurva.get_Item(0);
}
else
{
tempc = loccurva.get_Item(1);
}
loccurva.Clear();
loccurva.Append(tempc);
}
CurveArrArray newcurarr = new CurveArrArray();
newcurarr.Append(loccurva);
SortCurvesContiguousArray(newcurarr);
TaskDialog.Show("Revit CurveArray Array Size" , newcurarr.Size.ToString());
foreach (CurveArray ca in newcurarr)
{
TaskDialog.Show("Revit CurveArray within Array Size" , ca.Size.ToString());
}
// Below is edited for error control - leaving out the secondary loops for now
CurveArrArray switcharr = new CurveArrArray();
//switcharr.Append(newcurarr.get_Item(1));
switcharr.Append(newcurarr.get_Item(0));
//SortCurvesContiguousArray(loccurva);
//CurveArrArray newcurarr = new CurveArrArray();
//newcurarr.Append(loccurva);
double end = 1;
SketchPlane sketch = FindElementByName( docfamily,typeof( SketchPlane ), "Ref. Level" ) as SketchPlane;
docfamily.FamilyCreate.NewExtrusion(false, switcharr, sketch, end);
}
catch
{
TaskDialog.Show("Revit", "Could Not Write to Curve Array or Create Extrusion");
}
trans.Commit();
}
docfamily.Save();
docfamily.LoadFamily(document, new CustomFamilyLoadOption());
docfamily.Close();
File.Delete(sfinpath);
Family familynew = FindElementByName(document,typeof(Family),famname)as Family;
if( null == familynew )
{
TaskDialog.Show("Revit", "Family Does Not Exist");
}
FilteredElementCollector collector1 = new FilteredElementCollector(document);
ICollection<Element> collection = collector1.WhereElementIsNotElementType().ToElements();
List<FamilySymbol> fsym = new FilteredElementCollector(document).OfClass(typeof(FamilySymbol)).Cast<FamilySymbol>().ToList();
FamilySymbol famsymb = null;
foreach (FamilySymbol symb in fsym)
{
if (symb.Name == famname)
{
famsymb = symb as FamilySymbol;
}
}
using (Transaction trans = new Transaction(document))
{
trans.Start("PlaceVoid");
if( ! famsymb.IsActive )
{
famsymb.Activate();
}
XYZ p = new XYZ(0,0,0);
FamilyInstance gratingvoid = document.Create.NewFamilyInstance( p, famsymb, lev, lev, StructuralType.NonStructural );
document.Regenerate();
trans.Commit();
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
static public Element FindElementByName(Document doc,Type targetType,string targetName)
{
return new FilteredElementCollector( doc ).OfClass( targetType ).FirstOrDefault<Element>(e => e.Name.Equals( targetName ) );
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
public class CustomFamilyLoadOption : IFamilyLoadOptions
{
public bool OnFamilyFound(bool familyInUse, out bool overwriteParameterValues)
{
overwriteParameterValues = true;
return true;
}
public bool OnSharedFamilyFound(Family sharedFamily,bool familyInUse,out FamilySource source, out bool overwriteParameterValues)
{
source = FamilySource.Family;
overwriteParameterValues = true;
return true;
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
const double _inch = 1.0 / 12.0;
const double _sixteenth = _inch / 16.0;
static Curve CreateReversedCurve(Curve orig )
{
//if( !IsSupported( orig ) )
//{
// throw new NotImplementedException("CreateReversedCurve for type " + orig.GetType().Name );
//}
if( orig is Line )
{
//return creapp.NewLineBound(orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ) );
return Line.CreateBound(orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ) );
}
else if( orig is Arc )
{
// return creapp.NewArc( orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ), orig.Evaluate( 0.5, true ) );
return Arc.Create( orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ), orig.Evaluate( 0.5, true ) );
}
else
{
throw new Exception(
"CreateReversedCurve - Unreachable" );
}
}
public static void SortCurvesContiguousArray(CurveArrArray curvesarr)
{
double _precision1 = 1.0 / 12.0 / 16.0; // around 0.00520833
double _precision2 = 0.001; // limit for CurveLoop.Create(...)
int cn = curvesarr.Size;
int ci = 0;
while (ci < cn)
{
CurveArray curves = curvesarr.get_Item(ci);
ci +=1;
// account for multiple curve loops with secondary array
CurveArray loop1 = new CurveArray();
CurveArray loop2 = new CurveArray();
int n = curves.Size;
int split = 1;
// Walk through each curve (after the first)
// to match up the curves in order
for (int i = 0; i < n; ++i)
{
TaskDialog.Show("Revit I Loop Run", i.ToString());
Curve curve = curves.get_Item(i);
if (curve.GetType().ToString() == "Autodesk.Revit.DB.Arc" && curve.IsBound == false)
{
break;
}
XYZ beginPoint = curve.GetEndPoint(0);
XYZ endPoint = curve.GetEndPoint(1);
XYZ p,q;
// Find curve with start point = end point
bool found = (i + 1 >= n);
for (int j = i + 1; j < n; ++j)
{
p = curves.get_Item(j).GetEndPoint(0);
q = curves.get_Item(j).GetEndPoint(1);
// If there is a match end->start,
// this is the next curve
if (p.DistanceTo(endPoint) < _precision1)
{
if (p.DistanceTo(endPoint) > _precision2)
{
XYZ intermediate = new XYZ((endPoint.X + p.X) / 2.0, (endPoint.Y + p.Y) / 2.0, (endPoint.Z + p.Z) / 2.0);
curves.set_Item(i, Line.CreateBound(beginPoint, intermediate));
curves.set_Item(j, Line.CreateBound(intermediate, q));
}
if (i + 1 != j)
{
Curve tmp = curves.get_Item(i + 1);
curves.set_Item(i + 1, curves.get_Item(j));
curves.set_Item(j, tmp);
}
found = true;
break;
}
// If there is a match end->end,
// reverse the next curve
if (q.DistanceTo(endPoint) < _precision1)
{
if (q.DistanceTo(endPoint) > _precision2)
{
XYZ intermediate = new XYZ((endPoint.X + q.X) / 2.0, (endPoint.Y + q.Y) / 2.0, (endPoint.Z + q.Z) / 2.0);
curves.set_Item(i, Line.CreateBound(beginPoint, intermediate));
curves.set_Item(j, Line.CreateBound(p, intermediate));
}
if (i + 1 == j)
{
curves.set_Item(i + 1, CreateReversedCurve(curves.get_Item(j)));
}
else
{
Curve tmp = curves.get_Item(i + 1);
curves.set_Item(i + 1, CreateReversedCurve(curves.get_Item(j)));
curves.set_Item(j, tmp);
}
found = true;
break;
}
}
if (!found)
{
// if not found, must be part of a new loop - move it to the back and keep going and add to second array
TaskDialog.Show("Revit No Match Found for item", i.ToString());
TaskDialog.Show("Revit", "Moveing it to back of list");
Curve tmp1 = curves.get_Item(i);
TaskDialog.Show("Revit tmp1 Current i item endpt", tmp1.GetEndPoint(0).ToString());
loop2.Append(tmp1);
Curve tmp2 = curves.get_Item(n - split);
TaskDialog.Show("Revit tmp2 Back of list item endpt", tmp2.GetEndPoint(0).ToString());
// set current item to rear
curves.set_Item(i, tmp2);
// set rear item to current
curves.set_Item(n - split, tmp1);
TaskDialog.Show("Revit new item i endpt", curves.get_Item(i).GetEndPoint(0).ToString());
TaskDialog.Show("Revit moved item endpt", curves.get_Item(n - split).GetEndPoint(0).ToString());
// error testing - try to append in a different manner and check values
//curves.set_Item(i, Line.CreateBound(curves.get_Item(i).GetEndPoint(0), curves.get_Item(i).GetEndPoint(1)));
//curves.set_Item(n - split, Line.CreateBound(curves.get_Item(n - split).GetEndPoint(0), curves.get_Item(n - split).GetEndPoint(1)));
//Curve ncurve = Line.CreateBound(curves.get_Item(n - split).GetEndPoint(0), curves.get_Item(n - split).GetEndPoint(1));
//TaskDialog.Show("Revit Appended to Loop2 Endpoint", ncurve.GetEndPoint(0).ToString());
//loop2.Append(ncurve);
//set the split off counter so items not fitting in first loop can be split to new array.
split += 1;
//reset the counter back so item moved from rear can be checked in next run of for loop
i -= 2;
}
//set counter to end for loop when all items that do not fit in first loop are processed
if (i >= n - (split + 1))
{
TaskDialog.Show("Revit", "End Of Looping");
TaskDialog.Show("Revit - The Split Number", split.ToString());
i = n;
}
}
int counter = 0;
// recreate array with only items from first loop found
while (counter <= (n - split))
{
loop1.Append(curves.get_Item(counter));
counter += 1;
}
TaskDialog.Show("Revit loop1 Size", loop1.Size.ToString());
curvesarr.Clear();
curvesarr.Append(loop1);
if (loop2.Size > 0)
{
string stringinfo = "";
// run the loop detection on a second array that was split from the first
TaskDialog.Show("Revit loop2 Size", loop2.Size.ToString());
CurveArrArray tmpcurvesarr = new CurveArrArray();
tmpcurvesarr.Append(loop2);
SortCurvesContiguousArray(tmpcurvesarr);
loop2.Clear();
loop2 = tmpcurvesarr.get_Item(0);
curvesarr.Append(loop2);
foreach (Curve ccc in loop2)
{
stringinfo = (stringinfo + " " + ccc.GetEndPoint(0).ToString() + " - " + ccc.GetEndPoint(1).ToString());
}
TaskDialog.Show("Revit", stringinfo);
}
}
}
}
}
感谢您的任何帮助。
谢恩
解决方案
推荐阅读
- android - 伪本地化在语言中找不到英语 (XA)
- r - R中有没有办法计算两个不同事件之间的事件发生次数?
- reactjs - 如何将我的反应代码移植到移动应用程序中
- pentaho - 读取数据到表输入 pentaho
- r - 是否有任何方法专门替换 R 中的重复模式?
- python - Python flask @app.errorhandler(Exception) 得到完整的错误,而不仅仅是描述
- python - Python,作为函数参数的用户输入不起作用:TypeError:'str' object is not callable
- r - 如何使 geom_sf() 指向北?
- javascript - 如何根据ID插入数据?
- javascript - 在 javascript / node.js 中创建图像叠加层