您的位置:首页 > 其它

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

2012-02-24 12:20 246 查看
 将二维的管线生成三维的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管线效果都差不多,附图一张:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: