基于MultiPatch的三维管线的生成方法

 将二维的管线生成三维的MultiPatch有两种思路,第一种是用TriangleStrip来依次构造出管线首尾处的点;另一种方式是首先构造出管线的一个底面,然后用IConstructMultiPatch接口将该底面拉伸成MultiPatch管线。

1.方法一:用TriangleStrip创建MultiPatch类型的管线

/// <summary>
        /// 用TriangleStrip创建MultiPatch类型的管线
        /// </summary>
        /// <param name="FromPnt">管线起点坐标</param>
        /// <param name="ToPnt">管线终点坐标</param>
        /// <param name="R">管线半径</param>
        /// <param name="division">管线划分的片数,越大管线越逼近圆柱形</param>
        /// <param name="sr">坐标系统</param>
        /// <returns>生成的MultiPatch管线</returns>
        public static IGeometry DrawPipeByCoords(IPoint FromPnt, IPoint ToPnt, double R, int division, ISpatialReference sr)
        {
            if ((FromPnt as IZAware).ZSimple && (ToPnt as IZAware).ZSimple)
            {
                IVector3D VectorPipe = new Vector3DClass();
                VectorPipe.SetComponents(ToPnt.X - FromPnt.X, ToPnt.Y - FromPnt.Y, ToPnt.Z - FromPnt.Z);
                VectorPipe.Normalize();
                IVector3D VectorZ = new Vector3DClass();
                VectorZ.SetComponents(0, 0, 1);
                IVector3D VectorCross = VectorPipe.CrossProduct(VectorZ) as IVector3D;
                VectorCross.Magnitude = R;
                double Angle = 2 * Math.PI / division;
                IGeometryCollection GeoCollection = new MultiPatchClass();
                IPointCollection TriStripPoints = new TriangleStripClass();
                object Missing = Type.Missing;

                for (int i = 0; i < division; i++)
                {
                    VectorCross.Rotate(Angle, VectorPipe);//旋转底面上的向量
                    IPoint PntA = ConstructPnt3D(FromPnt.X + VectorCross.XComponent, FromPnt.Y + VectorCross.YComponent, FromPnt.Z + VectorCross.ZComponent, sr);
                    IPoint PntB = ConstructPnt3D(ToPnt.X + VectorCross.XComponent, ToPnt.Y + VectorCross.YComponent, ToPnt.Z + VectorCross.ZComponent, sr);                    
                    TriStripPoints.AddPoint(PntA, ref Missing, ref Missing);
                    TriStripPoints.AddPoint(PntB, ref Missing, ref Missing);
                }
                TriStripPoints.AddPoint(TriStripPoints.get_Point(0), ref Missing, ref Missing);
                TriStripPoints.AddPoint(TriStripPoints.get_Point(1), ref Missing, ref Missing);
                GeoCollection.AddGeometry(TriStripPoints as IGeometry, ref Missing, ref Missing);
                IGeometry GeoPipe3D = GeoCollection as IGeometry;
                GeoPipe3D.SpatialReference = sr;
                return GeoPipe3D;
            }
            else
            {
                return null;
            }
        }


 

2.方法二:用拉伸的方法创建MultiPatch类型的管线

/// <summary>
        /// 用拉伸的方法创建MultiPatch类型的管线
        /// </summary>
        /// <param name="FromPnt">管线起点坐标</param>
        /// <param name="ToPnt">管线终点坐标</param>
        /// <param name="R">管线半径</param>
        /// <param name="division">管线划分的片数,越大管线越逼近圆柱形</param>
        /// <param name="sr">坐标系统</param>
        /// <returns>生成的MultiPatch管线</returns>
        public static IGeometry ExtrudePipeByCoords(IPoint FromPnt, IPoint ToPnt, double R, int division, ISpatialReference sr)
        {
            object Missing = Type.Missing;
            IPointCollection PntsPG = new PolygonClass();
            IVector3D VectorZ = new Vector3DClass();//Z轴向量
            VectorZ.SetComponents(0, 0, 1);
            IVector3D VectorXOY = new Vector3DClass();
            VectorXOY.SetComponents(1, 0, 0);
            double Angle = 2 * Math.PI / division;

            for (int i = 0; i < division; i++)
            {
                VectorXOY.Rotate(Angle, VectorZ);
                IPoint Pnt = ConstructPnt3D(VectorXOY.XComponent, VectorXOY.YComponent, VectorXOY.ZComponent, sr);
                PntsPG.AddPoint(Pnt, ref Missing, ref Missing);
            }

            (PntsPG as IPolygon).Close();//自动闭合Polygon
            double length = GetTwoPntsDistance(FromPnt, ToPnt);//获得要拉伸的长度
            IConstructMultiPatch ConstructPath = new MultiPatchClass();
            MakeZAware(PntsPG as IGeometry);//注意要设置要拉伸的Geometry的ZAware属性为true,否则拉伸不成功
            ConstructPath.ConstructExtrude(length, PntsPG as IGeometry);//在Z轴方向上将Polygong拉伸成管线
            IVector3D VectorPipe = new Vector3DClass();//真实世界中管线的方向
            VectorPipe.SetComponents(ToPnt.X - FromPnt.X, ToPnt.Y - FromPnt.Y, ToPnt.Z - FromPnt.Z);
            double RotateAngle = GetTwoVectorsAngleInRadian(VectorZ, VectorPipe);//获得Z轴向量与真实世界中管线向量的夹角,用作旋转使用
            IVector3D VectorAxis = VectorZ.CrossProduct(VectorPipe) as IVector3D;//旋转轴向量

            ITransform3D transforms3D = ConstructPath as ITransform3D;
            transforms3D.RotateVector3D(VectorAxis, RotateAngle);
            transforms3D.Move3D(FromPnt.X, FromPnt.Y, FromPnt.Z);
            IGeometry GeoPipe3D = ConstructPath as IGeometry;
            GeoPipe3D.SpatialReference = sr;
            return GeoPipe3D;
        }

两种方法生成的MultiPatch管线效果都差不多,附图一张:

基于MultiPatch的三维管线的生成方法_第1张图片


你可能感兴趣的:(三维,管线,MultiPatch)