Revit Family API 添加对齐
没测试成功,留待以后研究。
url:http://greatverve.cnblogs.com/p/revit-family-api-add-alignment.html
[TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class cmdAddAlignment : IExternalCommand
{
//创建对齐,把一个面对齐到参考面。
void AddAlignment_ReferencePlane(Application app, Document doc, Extrusion pSolid, XYZ normal, string nameRefPlane)
{
View pViewPlan = Util.findElement(doc, typeof(ViewPlan), "Lower Ref. Level") as View;
ReferencePlane refPlane = Util.findElement(doc, typeof(ReferencePlane), nameRefPlane) as ReferencePlane;
PlanarFace pFace = findFace(app, pSolid, normal, refPlane);
doc.FamilyCreate.NewAlignment(pViewPlan, refPlane.Reference, pFace.Reference);
}
//对齐到楼层
void AddAlignment_Level(Document doc, Extrusion pSolid, XYZ normal, string nameLevel)
{
View pView = Util.findElement(doc, typeof(View), "Front") as View;
Level pLevel = Util.findElement(doc, typeof(Level), nameLevel) as Level;
PlanarFace pFace = Util.findFace(pSolid, normal);
doc.FamilyCreate.NewAlignment(pView, pLevel.PlaneReference, pFace.Reference);
}
void AddAlignments(Application app, Document doc, Extrusion pSolid)
{
AddAlignment_Level(doc, pSolid, new XYZ(0.0, 0.0, 1.0), "Upper Ref Level");
AddAlignment_Level(doc, pSolid, new XYZ(0.0, 0.0, -1.0), "Lower Ref. Level");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(1.0, 0.0, 0.0), "Right");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(-1.0, 0.0, 0.0), "Left");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(0.0, -1.0, 0.0), "Front");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(0.0, 1.0, 0.0), "Back");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(1.0, 0.0, 0.0), "OffsetV");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(0.0, 1.0, 0.0), "OffsetH");
}
// ===============================================================
// helper function: given a solid, find a planar
//Extrusion实体,给一个实体,给一个方向,找到与此方向一致的面。
// face with the given normal (version 2)
// this is a slightly enhaced version of the previous
// version and checks if the face is on the given reference plane.
// ===============================================================
PlanarFace findFace(Application app, Extrusion pBox, XYZ normal, ReferencePlane refPlane)
{
// get the geometry object of the given element
//
Options op = new Options();
op.ComputeReferences = true;
GeometryObjectArray geomObjs = pBox.get_Geometry(op).Objects;
// loop through the array and find a face with the given normal
//
foreach (GeometryObject geomObj in geomObjs)
{
if (geomObj is Solid) // solid is what we are interested in.
{
Solid pSolid = geomObj as Solid;
FaceArray faces = pSolid.Faces;
foreach (Face pFace in faces)
{
PlanarFace pPlanarFace = (PlanarFace)pFace;
// check to see if they have same normal
//face.Normal是面的向量。IsAlmostEqualTo();
if ((pPlanarFace != null) && pPlanarFace.Normal.IsAlmostEqualTo(normal))
{
// additionally, we want to check if the face is on the reference plane
//还要判断面是否在参考平面上。
XYZ p0 = refPlane.BubbleEnd;//终点?
XYZ p1 = refPlane.FreeEnd;//起点?
Line pCurve = app.Create.NewLineBound(p0, p1);
if (pPlanarFace.Intersect(pCurve) == SetComparisonResult.Subset)//子集
{
return pPlanarFace; // we found the face
}
}
}
}
// will come back later as needed.
//
//else if (geomObj is Instance)
//{
//}
//else if (geomObj is Curve)
//{
//}
//else if (geomObj is Mesh)
//{
//}
}
// if we come here, we did not find any.
return null;
}
public Result Execute(ExternalCommandData commandData, ref string messages, ElementSet elements)
{
UIApplication app = commandData.Application;
Document doc = app.ActiveUIDocument.Document;
Transaction ts = new Transaction(doc, "http://revit.5d6d.com");
ts.Start();
//
Extrusion pSolid = CreateSolid(app.Application, doc);
AddAlignments(app.Application, doc, pSolid);
ts.Commit();
return Result.Succeeded;
}
//创建封闭曲线
CurveArrArray createProfileLShape(Application _rvtApp)
{
//
// define a simple L-shape profile
//
// 5 tw 4
// +-+
// | | 3 h = height
// d | +---+ 2
// +-----+ td
// 0 1
// 6 w
//
// sizes (hard coded for simplicity)
// note: these need to match reference plane. otherwise, alignment won't work.
// as an exercise, try changing those values and see how it behaves.
//
double w = Util.mmToFeet(600.0); // those are hard coded for simplicity here. in practice, you may want to find out from the references)
double d = Util.mmToFeet(600.0);
double tw = Util.mmToFeet(150.0); // thickness added for Lab2
double td = Util.mmToFeet(150.0);
// define vertices
//
const int nVerts = 6; // the number of vertices
XYZ[] pts = new XYZ[] {
new XYZ(-w / 2.0, -d / 2.0, 0.0),
new XYZ(w / 2.0, -d / 2.0, 0.0),
new XYZ(w / 2.0, (-d / 2.0) + td, 0.0),
new XYZ((-w / 2.0) + tw, (-d / 2.0) + td, 0.0),
new XYZ((-w / 2.0) + tw, d / 2.0, 0.0),
new XYZ(-w / 2.0, d / 2.0, 0.0),
new XYZ(-w / 2.0, -d / 2.0, 0.0) }; // the last one is to make the loop simple
// define a loop. define individual edges and put them in a curveArray
//
CurveArray pLoop = _rvtApp.Create.NewCurveArray();
for (int i = 0; i < nVerts; ++i)
{
Line line = _rvtApp.Create.NewLineBound(pts[i], pts[i + 1]);
pLoop.Append(line);
}
// then, put the loop in the curveArrArray as a profile
//
CurveArrArray pProfile = _rvtApp.Create.NewCurveArrArray();
pProfile.Append(pLoop);
// if we come here, we have a profile now.
return pProfile;
}
Extrusion CreateSolid(Application app, Document doc)
{
CurveArrArray pProfile = createProfileLShape(app);
//这个参考平面模板中没有,可以切换到Front立面,自己画一个。
ReferencePlane pRefPlane = Util.findElement(doc, typeof(ReferencePlane), "Reference Plane") as ReferencePlane;
SketchPlane pSketchPlane = doc.FamilyCreate.NewSketchPlane(pRefPlane.Plane);
double dHeight = Util.mmToFeet(4000);
bool bIsSolid = true;
Extrusion pSolid = doc.FamilyCreate.NewExtrusion(bIsSolid, pProfile, pSketchPlane, dHeight);
return pSolid;
}
}
public class Util
{
//Revit内部单位feet转化为mm即毫米
public static double mmToFeet(double val) { return val / 304.8; }
public static double feetToMm(double val) { return val * 304.8; }
//通过类型与名称找Element
public static Element findElement(Document _rvtDoc, Type targetType, string targetName)
{
// get the elements of the given type
//
FilteredElementCollector collector = new FilteredElementCollector(_rvtDoc);
collector.WherePasses(new ElementClassFilter(targetType));
// parse the collection for the given name
// using LINQ query here.
//
var targetElems = from element in collector where element.Name.Equals(targetName) select element;
List<Element> elems = targetElems.ToList<Element>();
if (elems.Count > 0)
{ // we should have only one with the given name.
return elems[0];
}
// cannot find it.
return null;
}
// =============================================================
// helper function: find a planar face with the given normal
// =============================================================
public static PlanarFace findFace(Extrusion pBox, XYZ normal)
{
// get the geometry object of the given element
//
Options op = new Options();
op.ComputeReferences = true;
GeometryObjectArray geomObjs = pBox.get_Geometry(op).Objects;
// loop through the array and find a face with the given normal
//
foreach (GeometryObject geomObj in geomObjs)
{
if (geomObj is Solid) // solid is what we are interested in.
{
Solid pSolid = geomObj as Solid;
FaceArray faces = pSolid.Faces;
foreach (Face pFace in faces)
{
PlanarFace pPlanarFace = (PlanarFace)pFace;
if ((pPlanarFace != null) && pPlanarFace.Normal.IsAlmostEqualTo(normal)) // we found the face
{
return pPlanarFace;
}
}
}
// will come back later as needed.
//
//else if (geomObj is Instance)
//{
//}
//else if (geomObj is Curve)
//{
//}
//else if (geomObj is Mesh)
//{
//}
}
// if we come here, we did not find any.
return null;
}
#region Formatting and message handlers
public const string Caption = "Revit Family API Labs";
/// <summary>
/// MessageBox wrapper for informational message.
/// </summary>
public static void InfoMsg(string msg)
{
System.Diagnostics.Debug.WriteLine(msg);
WinForm.MessageBox.Show(msg, Caption, WinForm.MessageBoxButtons.OK, WinForm.MessageBoxIcon.Information);
}
/// <summary>
/// MessageBox wrapper for error message.
/// </summary>
public static void ErrorMsg(string msg)
{
WinForm.MessageBox.Show(msg, Caption, WinForm.MessageBoxButtons.OK, WinForm.MessageBoxIcon.Error);
}
#endregion // Formatting and message handlers
}
public class cmdAddAlignment : IExternalCommand
{
//创建对齐,把一个面对齐到参考面。
void AddAlignment_ReferencePlane(Application app, Document doc, Extrusion pSolid, XYZ normal, string nameRefPlane)
{
View pViewPlan = Util.findElement(doc, typeof(ViewPlan), "Lower Ref. Level") as View;
ReferencePlane refPlane = Util.findElement(doc, typeof(ReferencePlane), nameRefPlane) as ReferencePlane;
PlanarFace pFace = findFace(app, pSolid, normal, refPlane);
doc.FamilyCreate.NewAlignment(pViewPlan, refPlane.Reference, pFace.Reference);
}
//对齐到楼层
void AddAlignment_Level(Document doc, Extrusion pSolid, XYZ normal, string nameLevel)
{
View pView = Util.findElement(doc, typeof(View), "Front") as View;
Level pLevel = Util.findElement(doc, typeof(Level), nameLevel) as Level;
PlanarFace pFace = Util.findFace(pSolid, normal);
doc.FamilyCreate.NewAlignment(pView, pLevel.PlaneReference, pFace.Reference);
}
void AddAlignments(Application app, Document doc, Extrusion pSolid)
{
AddAlignment_Level(doc, pSolid, new XYZ(0.0, 0.0, 1.0), "Upper Ref Level");
AddAlignment_Level(doc, pSolid, new XYZ(0.0, 0.0, -1.0), "Lower Ref. Level");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(1.0, 0.0, 0.0), "Right");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(-1.0, 0.0, 0.0), "Left");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(0.0, -1.0, 0.0), "Front");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(0.0, 1.0, 0.0), "Back");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(1.0, 0.0, 0.0), "OffsetV");
AddAlignment_ReferencePlane(app, doc, pSolid, new XYZ(0.0, 1.0, 0.0), "OffsetH");
}
// ===============================================================
// helper function: given a solid, find a planar
//Extrusion实体,给一个实体,给一个方向,找到与此方向一致的面。
// face with the given normal (version 2)
// this is a slightly enhaced version of the previous
// version and checks if the face is on the given reference plane.
// ===============================================================
PlanarFace findFace(Application app, Extrusion pBox, XYZ normal, ReferencePlane refPlane)
{
// get the geometry object of the given element
//
Options op = new Options();
op.ComputeReferences = true;
GeometryObjectArray geomObjs = pBox.get_Geometry(op).Objects;
// loop through the array and find a face with the given normal
//
foreach (GeometryObject geomObj in geomObjs)
{
if (geomObj is Solid) // solid is what we are interested in.
{
Solid pSolid = geomObj as Solid;
FaceArray faces = pSolid.Faces;
foreach (Face pFace in faces)
{
PlanarFace pPlanarFace = (PlanarFace)pFace;
// check to see if they have same normal
//face.Normal是面的向量。IsAlmostEqualTo();
if ((pPlanarFace != null) && pPlanarFace.Normal.IsAlmostEqualTo(normal))
{
// additionally, we want to check if the face is on the reference plane
//还要判断面是否在参考平面上。
XYZ p0 = refPlane.BubbleEnd;//终点?
XYZ p1 = refPlane.FreeEnd;//起点?
Line pCurve = app.Create.NewLineBound(p0, p1);
if (pPlanarFace.Intersect(pCurve) == SetComparisonResult.Subset)//子集
{
return pPlanarFace; // we found the face
}
}
}
}
// will come back later as needed.
//
//else if (geomObj is Instance)
//{
//}
//else if (geomObj is Curve)
//{
//}
//else if (geomObj is Mesh)
//{
//}
}
// if we come here, we did not find any.
return null;
}
public Result Execute(ExternalCommandData commandData, ref string messages, ElementSet elements)
{
UIApplication app = commandData.Application;
Document doc = app.ActiveUIDocument.Document;
Transaction ts = new Transaction(doc, "http://revit.5d6d.com");
ts.Start();
//
Extrusion pSolid = CreateSolid(app.Application, doc);
AddAlignments(app.Application, doc, pSolid);
ts.Commit();
return Result.Succeeded;
}
//创建封闭曲线
CurveArrArray createProfileLShape(Application _rvtApp)
{
//
// define a simple L-shape profile
//
// 5 tw 4
// +-+
// | | 3 h = height
// d | +---+ 2
// +-----+ td
// 0 1
// 6 w
//
// sizes (hard coded for simplicity)
// note: these need to match reference plane. otherwise, alignment won't work.
// as an exercise, try changing those values and see how it behaves.
//
double w = Util.mmToFeet(600.0); // those are hard coded for simplicity here. in practice, you may want to find out from the references)
double d = Util.mmToFeet(600.0);
double tw = Util.mmToFeet(150.0); // thickness added for Lab2
double td = Util.mmToFeet(150.0);
// define vertices
//
const int nVerts = 6; // the number of vertices
XYZ[] pts = new XYZ[] {
new XYZ(-w / 2.0, -d / 2.0, 0.0),
new XYZ(w / 2.0, -d / 2.0, 0.0),
new XYZ(w / 2.0, (-d / 2.0) + td, 0.0),
new XYZ((-w / 2.0) + tw, (-d / 2.0) + td, 0.0),
new XYZ((-w / 2.0) + tw, d / 2.0, 0.0),
new XYZ(-w / 2.0, d / 2.0, 0.0),
new XYZ(-w / 2.0, -d / 2.0, 0.0) }; // the last one is to make the loop simple
// define a loop. define individual edges and put them in a curveArray
//
CurveArray pLoop = _rvtApp.Create.NewCurveArray();
for (int i = 0; i < nVerts; ++i)
{
Line line = _rvtApp.Create.NewLineBound(pts[i], pts[i + 1]);
pLoop.Append(line);
}
// then, put the loop in the curveArrArray as a profile
//
CurveArrArray pProfile = _rvtApp.Create.NewCurveArrArray();
pProfile.Append(pLoop);
// if we come here, we have a profile now.
return pProfile;
}
Extrusion CreateSolid(Application app, Document doc)
{
CurveArrArray pProfile = createProfileLShape(app);
//这个参考平面模板中没有,可以切换到Front立面,自己画一个。
ReferencePlane pRefPlane = Util.findElement(doc, typeof(ReferencePlane), "Reference Plane") as ReferencePlane;
SketchPlane pSketchPlane = doc.FamilyCreate.NewSketchPlane(pRefPlane.Plane);
double dHeight = Util.mmToFeet(4000);
bool bIsSolid = true;
Extrusion pSolid = doc.FamilyCreate.NewExtrusion(bIsSolid, pProfile, pSketchPlane, dHeight);
return pSolid;
}
}
public class Util
{
//Revit内部单位feet转化为mm即毫米
public static double mmToFeet(double val) { return val / 304.8; }
public static double feetToMm(double val) { return val * 304.8; }
//通过类型与名称找Element
public static Element findElement(Document _rvtDoc, Type targetType, string targetName)
{
// get the elements of the given type
//
FilteredElementCollector collector = new FilteredElementCollector(_rvtDoc);
collector.WherePasses(new ElementClassFilter(targetType));
// parse the collection for the given name
// using LINQ query here.
//
var targetElems = from element in collector where element.Name.Equals(targetName) select element;
List<Element> elems = targetElems.ToList<Element>();
if (elems.Count > 0)
{ // we should have only one with the given name.
return elems[0];
}
// cannot find it.
return null;
}
// =============================================================
// helper function: find a planar face with the given normal
// =============================================================
public static PlanarFace findFace(Extrusion pBox, XYZ normal)
{
// get the geometry object of the given element
//
Options op = new Options();
op.ComputeReferences = true;
GeometryObjectArray geomObjs = pBox.get_Geometry(op).Objects;
// loop through the array and find a face with the given normal
//
foreach (GeometryObject geomObj in geomObjs)
{
if (geomObj is Solid) // solid is what we are interested in.
{
Solid pSolid = geomObj as Solid;
FaceArray faces = pSolid.Faces;
foreach (Face pFace in faces)
{
PlanarFace pPlanarFace = (PlanarFace)pFace;
if ((pPlanarFace != null) && pPlanarFace.Normal.IsAlmostEqualTo(normal)) // we found the face
{
return pPlanarFace;
}
}
}
// will come back later as needed.
//
//else if (geomObj is Instance)
//{
//}
//else if (geomObj is Curve)
//{
//}
//else if (geomObj is Mesh)
//{
//}
}
// if we come here, we did not find any.
return null;
}
#region Formatting and message handlers
public const string Caption = "Revit Family API Labs";
/// <summary>
/// MessageBox wrapper for informational message.
/// </summary>
public static void InfoMsg(string msg)
{
System.Diagnostics.Debug.WriteLine(msg);
WinForm.MessageBox.Show(msg, Caption, WinForm.MessageBoxButtons.OK, WinForm.MessageBoxIcon.Information);
}
/// <summary>
/// MessageBox wrapper for error message.
/// </summary>
public static void ErrorMsg(string msg)
{
WinForm.MessageBox.Show(msg, Caption, WinForm.MessageBoxButtons.OK, WinForm.MessageBoxIcon.Error);
}
#endregion // Formatting and message handlers
}
我这个博客废弃不用了,今天想寻找外链的时候,突然想到这个博客权重很高。
有需要免费外链的,留言即可,我准备把这个博客变成免费的友情链接站点。