创建Multipatch三维图形  |
| By 3s4d 发表于 2008-6-2 9:39:00 |
学习总结Multipatch对象学习,3D建模 Multipatch是一系列几何对象组成的 可以表示3D效果的对象实体。 其中组成Multipatch的几何对象大致可以分为以下几种: 1,三角带;2,三角扇形;3,环状(内环和外环); 通过IMultipatch接口可以控制并创建一个Multipatch对象,这个接口提供了多种具体的方法和实现属性; 同时也可以使用IConstructMultiPatch接口来进行Multipatch的创建工作, 如下六个方法依据不同的方式进行创建Multipatch(Extrude为压缩的意思): ConstructExtrude ConstructExtrudeAbsolute ConstructExtrudeAlongLine ConstructExtrudeBetween ConstructExtrudeFromTo ConstructExtrudeRelative IGeneralMultiPatchCreator这个接口是用来创建具有纹理信息的Multipatch对象的,也就是所谓的textured纹理Multipatch对象; 当依据上述接口、方法创建完Multipatch后,可以使用IGeneralMultiPatchInfo 接口来对所创建的Multipatch进行信息查询, 如组成Multipatch的几何图形信息,个数,类型等等
这两天研究了Multipatch,自己创建了一个简单的3D模型在ArSence下,对Multipatch有了新的认识,整理一下学习笔记,希望和大家一起学习. 说明如下: 目的:创建一个简单Multipatch对象模型。 开发环境:ArSence下的VBA 实现效果:一个3D房子模型。 代码如下所示: 1。 ''VBA下的按钮实现函数 ''当按钮点击事件发生时将调用 GetMultipatch函数,以便创建三维模型 Private Sub UIButtonControl1_Click() Call GetMultipatch End Sub 2。GetMultipatch函数实现过程 ''这个函数中首先需要创建3D符号,所以需要调用IMarker3DSymbol接口实现 ''然后将创建好的IMarker3DSymbol符号作为一个Element元素添加到Sence的地图窗口中 Public Sub GetMultipatch() ''创建新的3D符号 Dim pMarker3DSymbol As IMarker3DSymbol: Set pMarker3DSymbol = New Marker3DSymbol Set pMarker3DSymbol.Shape = GetGeometry() ''设置3D符号几何形体(Multipatch)
''AppRef为当前正在运行的应用程序 ''需要注意的是,本实例所创建的3DMultipatch是一个点的3DSymbol,所以使用Point创建 Dim pSxApp As IApplication: Set pSxApp = New AppRef ''获取当前地图应用程序Application Dim pPt As IPoint: Set pPt = New Point: pPt.X = 0#: pPt.Y = 0#: pPt.Z = 0# AddGraphic pSxApp, pPt, pMarker3DSymbol, , False ''设定坐标原点,并加入Element对象元素 End Sub 3。''创建3D符号填充的几何形体,使用 GetGeometry函数实现,具体如下所示; Function GetGeometry() As IGeometry ''创建Multipatch的点对象 ''创建第一个Part中的点对象(东面的墙) Dim pT1 As IPoint, pT2 As IPoint, pT3 As IPoint, pT4 As IPoint Set pT1 = New Point pT1.X = 10: pT1.Y = 0: pT1.Z = 0 Set pT2 = New Point pT2.X = 10: pT2.Y = 0: pT2.Z = 3 Set pT3 = New Point pT3.X = 10: pT3.Y = 6: pT3.Z = 3 Set pT4 = New Point pT4.X = 10: pT4.Y = 6: pT4.Z = 0 ''创建第二个Part中的点对象(北面的墙) Dim ppt1 As IPoint, ppt2 As IPoint Set ppt1 = New Point ppt1.X = 0: ppt1.Y = 6: ppt1.Z = 0 Set ppt2 = New Point ppt2.X = 0: ppt2.Y = 6: ppt2.Z = 3 ''创建第三个Part中的点对象(西面的墙) Dim ppt3 As IPoint, ppt4 As IPoint Set ppt3 = New Point ppt3.X = 0: ppt3.Y = 0: ppt3.Z = 3 Set ppt4 = New Point ppt4.X = 0: ppt4.Y = 0: ppt4.Z = 0 ''创建第四个Part中的点对象(南面的墙) ''其中南面的墙也是正面的,设计了一个门和一个窗户 ''所以第四部分是由外环和内环组成的(本例子中窗子作为了内环处理的) ''下面是创建外环的点对象 Dim inpt1 As IPoint, inpt2 As IPoint, inpt3 As IPoint, inpt4 As IPoint Set inpt1 = New Point Set inpt2 = New Point Set inpt3 = New Point Set inpt4 = New Point ''创建门组成的点 inpt1.X = 2: inpt1.Y = 0: inpt1.Z = 0 inpt2.X = 2: inpt2.Y = 0: inpt2.Z = 2 inpt3.X = 4: inpt3.Y = 0: inpt3.Z = 2 inpt4.X = 4: inpt4.Y = 0: inpt4.Z = 0 ''创建第五部分 内环窗子的组成点对象 Dim interpt1 As IPoint, interpt2 As IPoint, interpt3 As IPoint, interpt4 As IPoint Set interpt1 = New Point Set interpt2 = New Point Set interpt3 = New Point Set interpt4 = New Point interpt1.X = 6: interpt1.Y = 0: interpt1.Z = 1 interpt2.X = 6: interpt2.Y = 0: interpt2.Z = 2 interpt3.X = 8: interpt3.Y = 0: interpt3.Z = 2 interpt4.X = 8: interpt4.Y = 0: interpt4.Z = 1 ''创建第六、七、八、九部分 构建房顶 三角形 的点对象 Dim pRoofTop As IPoint Dim pRoofD1 As IPoint, pRoofD2 As IPoint, pRoofD3 As IPoint, pRoofD4 As IPoint
Set pRoofTop = New Point: Set pRoofD2 = New Point Set pRoofD1 = New Point: Set pRoofD3 = New Point: Set pRoofD4 = New Point pRoofTop.X = 5: pRoofTop.Y = 3: pRoofTop.Z = 5 pRoofD1.X = 10: pRoofD1.Y = 0: pRoofD1.Z = 3 pRoofD2.X = 10: pRoofD2.Y = 6: pRoofD2.Z = 3 pRoofD3.X = 0: pRoofD3.Y = 6: pRoofD3.Z = 3 pRoofD4.X = 0: pRoofD4.Y = 0: pRoofD4.Z = 3 ''以下的点对象是用来创建 纹理贴图使用的,表示纹理图片的贴图的位置 Dim s As Integer, t As Integer s = 1: t = 10 Dim pTxLL0 As IPoint, pTxLR0 As IPoint, pTxUR0 As IPoint, pTxUL0 As IPoint Set pTxLL0 = New Point: Set pTxLR0 = New Point: Set pTxUR0 = New Point:: Set pTxUL0 = New Point pTxUL0.X = 6#: pTxUL0.Y = 0#: pTxUR0.X = s: pTxUR0.Y = 0# pTxLL0.X = 6#: pTxLL0.Y = t: pTxLR0.X = s: pTxLR0.Y = t ''创建Multipatch几何形体对象 ''使用pGenralMultipatch对象进行初始化所要创建的几何对象要素 ''首先需要使用Init方法来初始化Multipatch,使用IGeneralMultiPatchCreator接口 Dim pGenralMultipatch As IGeneralMultiPatchCreator Set pGenralMultipatch = New GeneralMultiPatchCreator ''本实例中Init方法有以下几个参数,解释如下: ''41表示Multipatch所包含的点的个数,本实例所创建的房子对象需要41个点对象。包括重复的点对象,如两个面的相交面 公用的点也需要重新计算近来 ''9表示Multipatch对象包含的部分数量,本实例中包含东、西、南、北、前面前的内环窗子部分、以及四个屋顶的三角扇形部分,共9个 ''参数中的3个False可以采用默认的方式 ''39表示的是纹理贴图所用的点数,一般情况下是与Multipatch所包含点个数是相同的;这个数量可以控制纹理贴图效果; ''GetMateriallist函数是添加纹理图像的函数,本例子中共添加了7个bmp格式的影像 pGenralMultipatch.Init 41, 9, False, False, True, 39, GetMaterialList Dim dictWalls As Scripting.Dictionary: Set dictWalls = GetWall ''创建第一个部分,其中 第一个0表示创建的部分,第二个0表示贴纹理所使用的纹理序号,第3,4个表示纹理贴图的点号 ''其中PartSetUp表示创建Multipatch的part设置 ''说明如下:pGenralMultipatch为当前的Multipatch对象 ''esriPatchTypeRing表示所创建的类型 ''第一个0表示创建的部分序号 ''第二个0表示纹理序号 ''第3,4个表示纹理点对象序号 PartSetUp pGenralMultipatch, 0, esriPatchTypeRing, 0, 0, 0 ''表示对当前部分进行点对象的设置 ''参数说明如下:pGenralMultipatch为当前的Multipatch对象 ''第一个数字参数表示当前这个部分所包含的点的序号,第二个参数表示当前部分所包含的点 ''第三个参数表示纹理贴图所包含的点 PointSetUp pGenralMultipatch, 0, pT1, pTxLL0 PointSetUp pGenralMultipatch, 1, pT2, pTxLR0 PointSetUp pGenralMultipatch, 2, pT3, pTxUR0 PointSetUp pGenralMultipatch, 3, pT4, pTxUL0 PointSetUp pGenralMultipatch, 4, pT1, pTxLL0 ''创建第2个部分 PartSetUp pGenralMultipatch, 1, esriPatchTypeRing, 1, 5, 5 PointSetUp pGenralMultipatch, 5, pT3, pTxLL0 PointSetUp pGenralMultipatch, 6, pT4, pTxLR0 PointSetUp pGenralMultipatch, 7, ppt1, pTxUR0 PointSetUp pGenralMultipatch, 8, ppt2, pTxUL0 PointSetUp pGenralMultipatch, 9, pT3, pTxLL0 Set GetGeometry = pGenralMultipatch.CreateMultiPatch ''创建第3个部分 PartSetUp pGenralMultipatch, 2, esriPatchTypeRing, 2, 10, 10 PointSetUp pGenralMultipatch, 10, ppt1, pTxLL0 PointSetUp pGenralMultipatch, 11, ppt2, pTxLR0 PointSetUp pGenralMultipatch, 12, ppt3, pTxUR0 PointSetUp pGenralMultipatch, 13, ppt4, pTxUL0 PointSetUp pGenralMultipatch, 14, ppt1, pTxLL0 Set GetGeometry = pGenralMultipatch.CreateMultiPatch ''4个部分 PartSetUp pGenralMultipatch, 3, esriPatchTypeOuterRing, 3, 15, 15 PointSetUp pGenralMultipatch, 15, ppt3, pTxLL0 PointSetUp pGenralMultipatch, 16, ppt4, pTxLR0 PointSetUp pGenralMultipatch, 17, inpt1, pTxUR0 PointSetUp pGenralMultipatch, 18, inpt2, pTxUL0 PointSetUp pGenralMultipatch, 19, inpt3, pTxLL0 PointSetUp pGenralMultipatch, 20, inpt4, inpt4 PointSetUp pGenralMultipatch, 21, pT1, pT1 PointSetUp pGenralMultipatch, 22, pT2, pT2 PointSetUp pGenralMultipatch, 23, ppt3, ppt3 Set GetGeometry = pGenralMultipatch.CreateMultiPatch ''5个部分 PartSetUp pGenralMultipatch, 4, esriPatchTypeInnerRing, -1, 24, 24 PointSetUp pGenralMultipatch, 24, interpt1, interpt1 PointSetUp pGenralMultipatch, 25, interpt2, interpt2 PointSetUp pGenralMultipatch, 26, interpt3, interpt3 PointSetUp pGenralMultipatch, 27, interpt4, interpt4 PointSetUp pGenralMultipatch, 28, interpt1, interpt1 ''第6个部分 PartSetUp pGenralMultipatch, 5, esriPatchTypeTriangles, 5, 29, 29 PointSetUp pGenralMultipatch, 29, pRoofTop, pRoofTop PointSetUp pGenralMultipatch, 30, pRoofD1, pRoofD1 PointSetUp pGenralMultipatch, 31, pRoofD2, pRoofD2 ''第7个部分 PartSetUp pGenralMultipatch, 6, esriPatchTypeTriangles, 4, 32, 32 PointSetUp pGenralMultipatch, 32, pRoofTop, pRoofTop PointSetUp pGenralMultipatch, 33, pRoofD2, pRoofD2 PointSetUp pGenralMultipatch, 34, pRoofD3, pRoofD3 ''第8个部分 PartSetUp pGenralMultipatch, 7, esriPatchTypeTriangles, 5, 35, 35 PointSetUp pGenralMultipatch, 35, pRoofTop, pRoofTop PointSetUp pGenralMultipatch, 36, pRoofD3, pRoofD3 PointSetUp pGenralMultipatch, 37, pRoofD4, pRoofD4 ''第9个部分 PartSetUp pGenralMultipatch, 8, esriPatchTypeTriangles, 0, 38, 38 PointSetUp pGenralMultipatch, 38, pRoofTop, pRoofTop PointSetUp pGenralMultipatch, 39, pRoofD4, pRoofD4 PointSetUp pGenralMultipatch, 40, pRoofD1, pRoofD1 ''创建Multipatch对象 Set GetGeometry = pGenralMultipatch.CreateMultiPatch End Function 4。''向IGeometryMaterial中添加纹理图片 ''以后以便向part中添加这个图片纹理 'The texture images are saved in a sub-folder called TextureFolder under the ArcScene document: Function GetMaterialList() As IGeometryMaterialList On Error GoTo eh
'create new materials: ''纹理存放的路径 Dim sTexFolder As String: sTexFolder = "D:\ArcGIS\DeveloperKit\SamplesCOM\3D_Analyst\TexturedMultipatchVisual_Basic\TexturedMultipatchVisual_Basic\Visual_Basic\TextureFolder\"
'material 1: Dim pMaterial1 As IGeometryMaterial: Set pMaterial1 = New GeometryMaterial pMaterial1.TextureImage = sTexFolder & "tile_roo.jpg" 'the mission tile
' material 2: Dim pMaterial2 As IGeometryMaterial: Set pMaterial2 = New GeometryMaterial pMaterial2.TextureImage = sTexFolder & "block2.jpg"
' material 3: Dim pMaterial3 As IGeometryMaterial: Set pMaterial3 = New GeometryMaterial pMaterial3.TextureImage = sTexFolder & "brick1.jpg"
'material 4: Dim pMaterial4 As IGeometryMaterial: Set pMaterial4 = New GeometryMaterial pMaterial4.TextureImage = sTexFolder & "concrete1.jpg"
'material 5: Dim pMaterial5 As IGeometryMaterial: Set pMaterial5 = New GeometryMaterial pMaterial5.TextureImage = sTexFolder & "stucco3.jpg"
'material 6: Dim pMaterial6 As IGeometryMaterial: Set pMaterial6 = New GeometryMaterial 'pMaterial6.TextureImage = sTexFolder & "dessau.jpg" pMaterial6.TextureImage = sTexFolder & "worlitz.jpg" 'create a new material list and add the material to the material list: Set GetMaterialList = New GeometryMaterialList GetMaterialList.AddMaterial pMaterial1 GetMaterialList.AddMaterial pMaterial2 GetMaterialList.AddMaterial pMaterial3 GetMaterialList.AddMaterial pMaterial4 GetMaterialList.AddMaterial pMaterial5 GetMaterialList.AddMaterial pMaterial6 End Function 5,第五部分 ''设置Part每个部分的属性信息 ''具体参数如下PartSetUp函数所示: ''pCreator为创建Multipatch的对象,partIndex表示部分part的索引号,parttype表示part部分的类型信息,materialindex表示texture(纹理)的索引号 ''partPointIndex表示当前所要设置part的点的组成,partTexturePointIndex表示当前part的纹理贴图所用的点的索引号 Public Sub PartSetUp(ByRef pCreator As IGeneralMultiPatchCreator, _ partIndex As Integer, partType As esriPatchType, materialIndex As Integer, _ partPointIndex As Integer, Optional partTexturePointIndex As Integer) With pCreator .SetPatchType partIndex, partType .SetMaterialIndex partIndex, materialIndex .SetPatchPointIndex partIndex, partPointIndex If Not IsMissing(partTexturePointIndex) Then .SetPatchTexturePointIndex partIndex, partTexturePointIndex End If End With End Sub 6,第六部分 '‘设置点的属性信息: ''参数如下所示: ''pCreator表示当前创建MultiPatch的对象,pointIndex表示点的索引号 Public Sub PointSetUp(ByRef pCreator As IGeneralMultiPatchCreator, _ pointIndex As Integer, pPtZ As IPoint, Optional pTexPt As IPoint = Nothing) pCreator.SetPoint pointIndex, pPtZ If Not pTexPt Is Nothing Then pCreator.SetTexturePoint pointIndex, pTexPt End Sub 7,第七部分 ''添加Multipatch 为element,并显示在sence上 Public Sub AddGraphic(pApp As IApplication, _ pGeom As IGeometry, _ Optional pSym As ISymbol, _ Optional bAddToSelection As Boolean = False, _ Optional bSelect As Boolean = True, _ Optional sElementName As String) ' TODO this needs to change
On Error GoTo AddGraphic_ERR
If pGeom.IsEmpty Then Exit Sub
Dim pElement As IElement
Select Case pGeom.GeometryType Case esriGeometryPoint Set pElement = New MarkerElement Dim pPointElement As IMarkerElement: Set pPointElement = pElement If Not pSym Is Nothing Then pPointElement.Symbol = pSym Case esriGeometryPolyline Set pElement = New LineElement Dim pLineElement As ILineElement: Set pLineElement = pElement If Not pSym Is Nothing Then pLineElement.Symbol = pSym Case esriGeometryPolygon Set pElement = New PolygonElement Dim pFillElement As IFillShapeElement: Set pFillElement = pElement If Not pSym Is Nothing Then pFillElement.Symbol = pSym Case esriGeometryMultiPatch Set pElement = New MultiPatchElement Set pFillElement = pElement If Not pSym Is Nothing Then pFillElement.Symbol = pSym End Select
pElement.Geometry = pGeom If Len(sElementName) > 0 Then Dim pElemProps As IElementProperties: Set pElemProps = pElement pElemProps.Name = sElementName End If
Dim pGLayer As IGraphicsLayer If (TypeOf pApp Is IMxApplication) Then Dim pMxDoc As IMxDocument: Set pMxDoc = pApp.Document Dim pActiveView As IActiveView: Set pActiveView = pMxDoc.FocusMap Set pGLayer = pMxDoc.FocusMap.BasicGraphicsLayer Dim pGCon As IGraphicsContainer: Set pGCon = pGLayer
pGCon.AddElement pElement, 0
Dim pGCS As IGraphicsContainerSelect Set pGCS = pGCon ' unselect all other elements before selecting this one: If Not bAddToSelection Then pGCS.UnselectAllElements pGCS.SelectElement pElement
' redraw graphics for entire view extent, rather than just extent of this element, in case there were ' other graphics present that became unselected and lost their selection handles pActiveView.PartialRefresh esriViewGraphics, pElement, pActiveView.Extent Else Dim pSxDoc As ISxDocument: Set pSxDoc = pApp.Document Set pGLayer = pSxDoc.Scene.BasicGraphicsLayer 'set lighting to true: Dim pLyrExt As ILayerExtensions: Set pLyrExt = pGLayer Dim p3DProp As I3DProperties: Set p3DProp = pLyrExt.Extension(0) p3DProp.Illuminate = False Dim pGCon3D As IGraphicsContainer3D: Set pGCon3D = pGLayer
pGCon3D.DeleteAllElements pGCon3D.AddElement pElement
Dim pGS As IGraphicsSelection: Set pGS = pGCon3D If (bSelect) Then ' unselect all other elements before selecting this one If Not bAddToSelection Then pGS.UnselectAllElements pGS.SelectElement pElement End If
pSxDoc.Scene.SceneGraph.RefreshViewers End If
Exit Sub AddGraphic_ERR: Debug.Print "AddGraphic_ERR: " & Err.Description Debug.Assert 0 End Sub
''注意事项: ''Multipatch其实是表示多个几何要素所组成的格外一个几何对象,大多情况下是带有高程值的 ''在上述的例子中,一个Multipatch所表示的就是由四个矩形和4个三角形所组成的 ''当我们想为一个不带有高程信息的一个平面对象赋予一定的纹理的时候,一定要设置组成平面的点的Z值;Z=0才能显示出来; ''同时,还需要注意pGenralMultipatch.Init 41, 9, False, False, True, 39, GetMaterialList这条语句,里面的数字参数设置会改变一定的显示效果,需要注意; ''还有就是要 注意PartSetUp pGenralMultipatch, 4, esriPatchTypeInnerRing, -1, 24, 24 PointSetUp pGenralMultipatch, 24, interpt1, interpt1 ''设置part与point的函数参数
写的多了点,大家如果有兴趣可以看看 就算是给小弟挑挑毛病把 哈哈 和大家一起学习,有什么好的学习经验要分享阿 嘿嘿 谢谢 |
| |
|
| Re:创建Multipatch三维图形 |
| By Joseph(游客)发表评论于2008-6-25 4:27:00 |
请问如果要修改Multipatch的texture 属性怎么做呀? 谢谢以下为3s4d的回复: IGeometryMaterialList 这个接口 |
| |
|
| |
站点公告
页面载入中.... |
站点日历
|
最新日志
页面载入中.... |
最新评论
|
最新留言
页面载入中.... |
友情链接 |
站点统计
页面载入中.... |
日志搜索
页面载入中.... |
用户登陆
页面载入中.... |
| | | |