zoukankan      html  css  js  c++  java
  • 创建Multipatch三维图形

    创建Multipatch三维图形
    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的函数参数

    使用方法:打开ARcscene,打开tool-macros-visualbasic Editer

    ProjectArcSceneObjectsThisDocument上双击,然后将下列代码贴入:运行之后便会形成房屋形状。

  • 相关阅读:
    2thweek.training.c。链表典型题
    队列—summer training B.
    栈—summertraining#2.A题
    周题:UVa10736题。Foreign Exchange
    UVA_11877.第三次比赛C题:The Coco Cola
    uva10465 Homer Simpson(水题)
    uva348 Optimal Array Multiplication Sequence(DP)
    uva116 Unidirectional TSP(DP)
    uva 607 Scheduling Lectures(DP)
    uva11598 Optimal Segments(DP 求方案)
  • 原文地址:https://www.cnblogs.com/xianyin05/p/1437799.html
Copyright © 2011-2022 走看看