Share

Client graphics texture-based color mapping

Description

This test applies texture coordinates expressing distance from the origin to 'the triangle mesh of whatever Part you have open. It then creates either a discrete-band or continuous color mapper and allows you to adjust the values of the mapper to change the range of values that map to various colors.

Code Samples

To operate: 1. Open a part 2. Run Demo - it should show discrete bands moving across the model 3. Click on any of the other "convenience functions" and hit F5 to exercise them.
Dim lastOffset As Double
Dim mapperType As Integer

'convenience "links"
Sub Demo()
    ThisApplication.ActiveView.DisplayMode = kWireframeRendering
    Call OffsetSurfaceBy(0#)
    Call UpdateValues(1 / 1.01, 0, 30)
    Call UpdateValues(1, -0.01, 20)
    Call UpdateValues(1, 0.01, 20)
    Call UpdateValues(1 / 1.01, 0, 50)
    Call UpdateValues(1, -0.01, 20)
    Call UpdateValues(1, 0.01, 20)
    Call UpdateValues(1 * 1.01, 0, 50)
End Sub

Sub narrowBands()
    Call UpdateValues(1 / 1.01, 0, 1)
End Sub

Sub widenBands()
    Call UpdateValues(1 * 1.01, 0, 1)
End Sub

Sub slideBandsUp()
    Call UpdateValues(1, 0.01, 1)
End Sub

Sub slideBandsDown()
    Call UpdateValues(1, -0.01, 1)
End Sub

Sub setContinuousMode()
    mapperType = 1
    Call OffsetSurfaceBy(0#)
End Sub

Sub setDiscreteMode()
    mapperType = 0
    Call OffsetSurfaceBy(0#)
End Sub

'internal functions
'randomly change colors in ColorMapper
Sub UpdateColors()
    Dim oDoc As Document
    Set oDoc = ThisApplication.ActiveDocument

    Dim oDataSets As GraphicsDataSets
    Set oDataSets = oDoc.GraphicsDataSetsCollection.Item("CG_Test")

    Dim oCompDef As ComponentDefinition
    Set oCompDef = oDoc.ComponentDefinition

    Dim oClientGraphics As ClientGraphics
    Set oClientGraphics = oCompDef.ClientGraphicsCollection.Item("CG_Test")

    Dim oGraphicsNode As GraphicsNode
    Set oGraphicsNode = oClientGraphics.ItemById(100)

    Dim oTriangleSet As TriangleGraphics
    Set oTriangleSet = oGraphicsNode.Item(1)
    Dim oColorMapper As GraphicsColorMapper
    Set oColorMapper = oTriangleSet.ColorMapper

    For i = 1 To 100
        Dim cmColors() As Byte
        Call oColorMapper.GetColors(cmColors)
        For j = 0 To oColorMapper.ColorCount * 3 - 1
            cmColors(j) = 255 * Rnd() * i / 100#
        Next
        Call oColorMapper.PutColors(cmColors)
        ThisApplication.ActiveView.Update
    Next
End Sub

'change values in ColorMapper
Sub UpdateValues(factor As Double, offset As Double, count As Integer)
    Dim oDoc As Document
    Set oDoc = ThisApplication.ActiveDocument

    Dim oDataSets As GraphicsDataSets
    Set oDataSets = oDoc.GraphicsDataSetsCollection.Item("CG_Test")

    Dim oCompDef As ComponentDefinition
    Set oCompDef = oDoc.ComponentDefinition

    Dim oClientGraphics As ClientGraphics
    Set oClientGraphics = oCompDef.ClientGraphicsCollection.Item("CG_Test")

    Dim oGraphicsNode As GraphicsNode
    Set oGraphicsNode = oClientGraphics.ItemById(100)

    Dim oTriangleSet As TriangleGraphics
    Set oTriangleSet = oGraphicsNode.Item(1)
    Dim oColorMapper As GraphicsColorMapper
    Set oColorMapper = oTriangleSet.ColorMapper

    For i = 1 To count
        Dim v() As Double
        Call oColorMapper.GetValues(v)
        Dim vMid As Double
        vMid = v(oColorMapper.ValueCount / 2)
        For j = 0 To oColorMapper.ValueCount - 1
            v(j) = (v(j) - vMid) * factor + vMid + offset * (v(oColorMapper.ValueCount - 1) - v(0))
        Next
        Call oColorMapper.PutValues(v)
        ThisApplication.ActiveView.Update
    Next
End Sub

Function min(a, b)
    min = a
    If (b < a) Then
        min = b
    End If
End Function

Function max(a, b)
    max = a
    If (b > a) Then
        max = b
    End If
End Function

'display part thickness by adding display of surfaces offset by given distance --
'wherever they stick through the part, it's thinner than that distance at that point
Public Sub OffsetSurfaceBy(offset As Double)
    ' Get the surface body from the active document.
    Dim oPartDoc As PartDocument
    Set oPartDoc = ThisApplication.ActiveDocument
    Dim oSurfBody As SurfaceBody
    Set oSurfBody = oPartDoc.ComponentDefinition.SurfaceBodies.Item(1)
    Set oSurfBody = oPartDoc.ComponentDefinitions.Item(1).SurfaceBodies.Item(1)

    ' Delete the graphics data set and client graphics, if they exist.
    Dim oDataSets As GraphicsDataSets
    On Error Resume Next
    Set oDataSets = oPartDoc.GraphicsDataSetsCollection.Item("CG_Test")
    If Err.Number = 0 Then
        oDataSets.Delete
        oPartDoc.ComponentDefinition.ClientGraphicsCollection.Item("CG_Test").Delete
        oSurfBody.Visible = True
        ThisApplication.ActiveView.Update
    End If
    On Error GoTo 0

'    If offset = 0 Then
'        Exit Sub
'    End If

    ' Determine the highest tolerance of the existing facet sets.
    Dim ToleranceCount As Long
    Dim ExistingTolerances() As Double
    Call oSurfBody.GetExistingFacetTolerances(ToleranceCount, ExistingTolerances)

    Dim i As Long
    Dim BestTolerance As Double
    For i = 0 To ToleranceCount - 1
        If i = 0 Then
            BestTolerance = ExistingTolerances(i)
        ElseIf ExistingTolerances(i) < BestTolerance Then
            BestTolerance = ExistingTolerances(i)
        End If
    Next

    ' Get a set of existing facets.
    Dim iVertexCount As Long
    Dim iFacetCount As Long
    Dim adVertexCoords() As Double
    Dim adNormalVectors() As Double
    Dim aiVertexIndices() As Long
    Call oSurfBody.GetExistingFacets(BestTolerance, iVertexCount, iFacetCount, _
                                    adVertexCoords, adNormalVectors, aiVertexIndices)

    ' Offset vertices by given distance along anti-normals
    For i = 0 To (iVertexCount * 3 - 1)
        adVertexCoords(i) = adVertexCoords(i) - adNormalVectors(i) * offset
    Next

    ' Start a transaction.
    Dim oTrans As Transaction
    Set oTrans = ThisApplication.TransactionManager.StartTransaction(oPartDoc, "Z Height Colors")

    ' Create the graphics data sets collection.
    Set oDataSets = oPartDoc.GraphicsDataSetsCollection.Add("CG_Test")

    ' Create the coordinate set and set it using the coordinates from the facets.
    Dim oGraphicsCoordSet As GraphicsCoordinateSet
    Set oGraphicsCoordSet = oDataSets.CreateCoordinateSet(1)
    Call oGraphicsCoordSet.PutCoordinates(adVertexCoords)

    ' Create the index set and set it using the indices from the facets.
    Dim oGraphicsIndexSet As GraphicsIndexSet
    Set oGraphicsIndexSet = oDataSets.CreateIndexSet(2)
    Call oGraphicsIndexSet.PutIndices(aiVertexIndices)

    ' Create the normal set and set it using the normals from the facets.
    Dim oGraphicsNormalSet As GraphicsNormalSet
    Set oGraphicsNormalSet = oDataSets.CreateNormalSet(3)
    Call oGraphicsNormalSet.PutNormals(adNormalVectors)

    ' Allocate the array that will contain the color information.
    ' This array contains RGB values for each vertex.
    Dim abtColors() As Byte
    ReDim abtColors(0 To iVertexCount * 3 - 1) As Byte

    ' Load the array with color information for each vertex.
    For i = 0 To iVertexCount - 1
        ' Set the color information for the current vertex.
        ' currently, all vertices are a constant color, but ...
        abtColors(i * 3) = 200
        abtColors(i * 3 + 1) = 0
        abtColors(i * 3 + 2) = 0
    Next

    ' Create the color set and set it using the array of rgb values just created.
    Dim oGraphicsColorSet As GraphicsColorSet
    Set oGraphicsColorSet = oDataSets.CreateColorSet(4)
    Call oGraphicsColorSet.PutColors(abtColors)

    ' Create a scalar data texture coordinate set representing distance from origin
    Dim oTCSet As GraphicsTextureCoordinateSet
    Set oTCSet = oDataSets.CreateTextureCoordinateSet(5)
    Dim tc() As Double
    ReDim tc(1 To iVertexCount) As Double
    Dim tcMax As Double
    tcMax = 0
    Dim tcMin As Double
    tcMin = 1000000#
    For i = 1 To iVertexCount
        tc(i) = Sqr(adVertexCoords(3 * (i - 1)) * adVertexCoords(3 * (i - 1)) + adVertexCoords(3 * (i - 1) + 1) * adVertexCoords(3 * (i - 1) + 1) + adVertexCoords(3 * (i - 1) + 2) * adVertexCoords(3 * (i - 1) + 2))
        tcMin = min(tcMin, tc(i))
        tcMax = max(tcMax, tc(i))
    Next
    Call oTCSet.PutCoordinates(tc)

    ' Create the client graphics collection.
    Dim oClientGraphics As ClientGraphics
    Set oClientGraphics = oPartDoc.ComponentDefinition.ClientGraphicsCollection.Add("CG_Test")

    ' Create a graphics node.
    Dim oGraphicNode As GraphicsNode
    Set oGraphicNode = oClientGraphics.AddNode(100)

    ' Create the triangle graphics.
    Dim oTriangles As TriangleGraphics
    Set oTriangles = oGraphicNode.AddTriangleGraphics

    '============================================

    Dim oColorMapper As GraphicsColorMapper
    Set oColorMapper = oDataSets.CreateColorMapper

    '============================================

    'construct ColorMapper:
    '  black - red - orange - yellow - green - cyan - blue - magenta - black
    '      minV                          ...                        maxV
    Dim nColors As Integer
    nColors = 9

    Dim cmColors() As Byte
    ReDim cmColors(1 To nColors * 3) As Byte
    For i = 1 To nColors * 3
        cmColors(i) = 0
    Next
    'black
    cmColors(4) = 255       'red
    cmColors(7) = 255       'orange
    cmColors(7 + 1) = 125
    cmColors(10) = 255      'yellow
    cmColors(10 + 1) = 255
    cmColors(13 + 1) = 255  'green
    cmColors(16 + 1) = 255  'cyan
    cmColors(16 + 2) = 255
    cmColors(19 + 2) = 255  'blue
    cmColors(22) = 255      'magenta
    cmColors(22 + 2) = 255
    'black

    Dim nValues As Integer
    If (mapperType = 0) Then
        nValues = nColors - 1   'discrete value boundaries
    Else
        nValues = nColors       'continuous value points
    End If

    Dim cmValues() As Double
    ReDim cmValues(1 To nValues) As Double
    For i = 1 To nValues
        cmValues(i) = tcMin + (tcMax - tcMin) * (i - 1#) / (nValues - 1#)
    Next

    '============================================

    Call oColorMapper.PutColors(cmColors)
    Call oColorMapper.PutValues(cmValues)


    ' Set various properties of the triangle graphics.
    oTriangles.CoordinateSet = oGraphicsCoordSet
    oTriangles.CoordinateIndexSet = oGraphicsIndexSet
    oTriangles.NormalSet = oGraphicsNormalSet
    oTriangles.NormalBinding = kPerVertexNormals
    oTriangles.NormalIndexSet = oGraphicsIndexSet
'    oTriangles.ColorSet = oGraphicsColorSet
'    oTriangles.ColorBinding = kPerVertexColors
'    oTriangles.ColorIndexSet = oGraphicsIndexSet
    oTriangles.TextureCoordinateSet = oTCSet
    oTriangles.TextureCoordinateIndexSet = oGraphicsIndexSet
    oTriangles.ColorMapper = oColorMapper

    ' End the transaction.
    oTrans.End

    ' Update the view.
    ThisApplication.ActiveView.Update
End Sub

Public Sub increaseOffset()
    lastOffset = lastOffset * 1.1
    Dim offset As Double
    offset = lastOffset
    Call OffsetSurfaceBy(offset)
End Sub

Public Sub DecreaseOffset()
    lastOffset = lastOffset * 0.9
    Dim offset As Double
    offset = lastOffset
    Call OffsetSurfaceBy(offset)
End Sub

Public Sub OffsetSurface()
    Dim oPartDoc As PartDocument
    Set oPartDoc = ThisApplication.ActiveDocument

    Dim lenunits As UnitsTypeEnum
    lenunits = oPartDoc.UnitsOfMeasure.LengthUnits
    Dim unitscale As Double
    Dim unitname As String
    If lenunits = kInchLengthUnits Then
        unitscale = 2.54
        unitname = "inches"
    Else
    If lenunits = kMillimeterLengthUnits Then
        unitscale = 0.1
        unitname = "millimeters"
    Else
    If lenunits = kCentimeterLengthUnits Then
        unitscale = 1#
        unitname = "centimeters"
    End If
    End If
    End If

    Dim offset As Double
    offset = 0
    On Error Resume Next
    offset = InputBox("Enter offset (in " + unitname + "):", "Offset", lastOffset / unitscale)
    On Error GoTo 0

    lastOffset = offset * unitscale

    Call OffsetSurfaceBy(lastOffset)
End Sub


Was this information helpful?