几何元素练习Solid,Edge,Face,GeometryObject


几何元素练习Solid,Edge,Face,

GeometryObject 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using WinForm = System.Windows.Forms;


using Autodesk.Revit.UI;

using Autodesk.Revit.DB;

using Autodesk.Revit.Attributes;


using Autodesk.Revit.DB.Mechanical;

using Autodesk.Revit.UI.Selection;

using Autodesk.Revit.ApplicationServices;


using Autodesk.Revit.DB.Structure;

using Autodesk.Revit.DB.ExtensibleStorage;


using System.Xml;


namespace RevitCodes

{

    [TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)]

    public class cmdOpening : IExternalCommand

    {

        public Result Execute(ExternalCommandData commandData, ref string messages, ElementSet elements)

        {

            UIApplication uiApp = commandData.Application;

            Document doc = uiApp.ActiveUIDocument.Document;

            Selection sel = uiApp.ActiveUIDocument.Selection;


            Transaction ts = new Transaction(doc, "http://revit.5d6d.com");

            ts.Start();

            //

            Face face = null;

            //选择一面墙

            Reference ref1 = uiApp.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "选择一面墙");

            Element elem1 = doc.GetElement(ref1);

            Wall wall = elem1 as Wall;

            //选择一个风管

            Reference ref2 = uiApp.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "选择一个风管");

            Element elem2 = doc.GetElement(ref2);

            Duct duct = elem2 as Duct;


            ////得到风管曲线

            IList<XYZ> list = new List<XYZ>();

            ConnectorSetIterator csi = duct.ConnectorManager.Connectors.ForwardIterator();

            while (csi.MoveNext())

            {

                Connector conn = csi.Current as Connector;

                list.Add(conn.Origin);

            }

            Curve curve = Line.get_Bound(list.ElementAt(0), list.ElementAt(1)) as Curve;


            Options opt = new Options();

            opt.ComputeReferences = true;

            opt.DetailLevel = Autodesk.Revit.DB.DetailLevels.Medium;

            //取得风管边线

            GeometryElement eDuct = duct.get_Geometry(opt);

            int i = 0;

            Curve curveOne = null;

            Curve curveTwo = null;

            foreach (GeometryObject obj in eDuct.Objects)

            {

                Solid solid = obj as Solid;

                foreach (Edge edge in solid.Edges)

                {

                    Curve curveEdge = edge.AsCurve();

                    Curve curveDuct = curve;

                    XYZ xyz1 = GetVector(curveEdge);

                    XYZ xyz2 = GetVector(curveDuct);

                    if (IsParallel(xyz1, xyz2))//与风管curve平行

                    {

                        if (i == 0)//求对角线

                            curveOne = curveEdge;

                        if (i == 2)

                            curveTwo = curveEdge;

                        i += 1;

                    }

                }

            }

            //取得墙曲线

            GeometryElement e = wall.get_Geometry(opt);

            foreach (GeometryObject obj in e.Objects)

            {

                Solid solid = obj as Solid;

                if (solid != null && solid.Faces.Size > 0)

                {

                    face = FindBigFace(solid);//面积最大的面作为墙的主面吧。

                }

            }


            //求交点1

            IntersectionResultArray intersectionR = new IntersectionResultArray();//交点集合

            SetComparisonResult comparisonR;//Comparison比较

            comparisonR = face.Intersect(curveOne, out intersectionR);

            XYZ intersectionResult = null;//交点坐标

            if (SetComparisonResult.Disjoint != comparisonR)//Disjoint不交

            {

                if (!intersectionR.IsEmpty)

                {

                    intersectionResult = intersectionR.get_Item(0).XYZPoint;

                }

            }

            //求交点2

            IntersectionResultArray intersectionR1 = new IntersectionResultArray();//交点集合

            SetComparisonResult comparisonR1;//Comparison比较

            comparisonR1 = face.Intersect(curveTwo, out intersectionR1);

            XYZ intersectionResult1 = null;//交点坐标

            if (SetComparisonResult.Disjoint != comparisonR1)//Disjoint不交

            {

                if (!intersectionR1.IsEmpty)

                {

                    intersectionResult1 = intersectionR1.get_Item(0).XYZPoint;

                }

            }

            doc.Create.NewOpening(wall, intersectionResult, intersectionResult1);


            ts.Commit();


            return Result.Succeeded;

        }


        //判断向量是否平行

        public bool IsParallel(XYZ firstVec, XYZ secondVec)

        {

            return (IsSameDirection(firstVec, secondVec) || IsOppositeDirection(firstVec, secondVec));

        }


        //求曲线向量

        public XYZ GetVector(Line line) { return line.get_EndPoint(1) - line.get_EndPoint(0); }

        public XYZ GetVector(Curve line) { return line.get_EndPoint(1) - line.get_EndPoint(0); }


        /// <summary>

        /// 判断两向量是否同向

        /// </summary>

        /// <param name="firstVec"></param>

        /// <param name="secondVec"></param>

        /// <returns></returns>

        public bool IsSameDirection(XYZ firstVec, XYZ secondVec)

        {

            XYZ first = firstVec.Normalize();

            XYZ second = secondVec.Normalize();


            double dot = first.DotProduct(second);

            return (IsEqual(dot, 1));

        }


        const double precision = 0.00001;    // 精度


        /// <summary>

        /// 判断两double数值是否相等

        /// </summary>

        /// <param name="d1"></param>

        /// <param name="d2"></param>

        /// <returns></returns>

        public static bool IsEqual(double d1, double d2)

        {

            double diff = Math.Abs(d1 - d2);

            return diff < precision;

        }


        /// <summary>

        /// 判断两向量是否反向

        /// </summary>

        /// <param name="firstVec"></param>

        /// <param name="secondVec"></param>

        /// <returns></returns>

        public static bool IsOppositeDirection(XYZ firstVec, XYZ secondVec)

        {

            XYZ first = firstVec.Normalize();

            XYZ second = secondVec.Normalize();


            double dot = first.DotProduct(second);

            return (IsEqual(dot, -1));

        }

        //求交点

        void FindInterFace(Solid solid, Curve curve)

        {

            foreach (Face face in solid.Faces)

            {

                //求交点

                IntersectionResultArray intersectionR = new IntersectionResultArray();//交点集合

                SetComparisonResult comparisonR;//Comparison比较

                comparisonR = face.Intersect(curve, out intersectionR);

                XYZ intersectionResult = null;//交点坐标

                if (SetComparisonResult.Disjoint != comparisonR)//Disjoint不交

                {

                    if (!intersectionR.IsEmpty)

                    {

                        intersectionResult = intersectionR.get_Item(0).XYZPoint;

                    }

                }

                if (intersectionResult != null)

                {

                    TaskDialog.Show("inter", intersectionResult.X + "," + intersectionResult.Y + "," + intersectionResult.Z);

                }

            }

        }

        //找到面积最大的面

        Face FindBigFace(Solid solid)

        {

            double maxArea = 0;

            Face maxFace = null;

            foreach (Face face in solid.Faces)

            {

                if (face.Area > maxArea)

                {

                    maxArea = face.Area;

                    maxFace = face;

                }

            }

            return maxFace;

        }

        //找到墙的下底面

        Face FindBottomFace(Solid solid)

        {

            PlanarFace pf = null;

            foreach (Face face in solid.Faces)

            {

                pf = face as PlanarFace;

                if (null != pf)

                {

                    if (Math.Abs(pf.Normal.X) < 0.01 && Math.Abs(pf.Normal.Y) < 0.01 && pf.Normal.Z < 0)

                    {

                        TaskDialog.Show("Wall Bottom Face", "Area is " + pf.Area.ToString() + "; Origin = (" + pf.Origin.X.ToString() + "  " + pf.Origin.Y.ToString() + "  " + pf.Origin.Z.ToString() + ")");


                        break;

                    }

                }

            }

            return pf;

        }

    }


}