SciProgCentre / visionforge

Visualization module for dataforge
Apache License 2.0
36 stars 8 forks source link

Issues when representing curved volumes #38

Closed lobis closed 3 years ago

lobis commented 3 years ago

When representing cylinders (tubes) there is a rendering issue where a "spike" or bump appears at one end, often clipping out of the adjacent volumes.

The default number of faces is IMHO too low in order to correctly render circles, I think it should be increased. Also a simple option to increase this value globally should be available to the user. Additionally I suggest doing the same for a global transparency value which IMHO should be less than 1 by default.

How it looks like in ROOT, after exporting to GDML (note: you will have to replace "cm" by "mm" in the .gdml in order to view it like this). ROOT

How it looks like on jupyter Jupyter bump

Jupyter Notebook code for this geometry:

@file:Repository("https://repo.kotlin.link")
@file:Repository("https://dl.bintray.com/pdvrieze/maven")
@file:DependsOn("space.kscience:visionforge-gdml-jupyter-jvm:0.2.0-dev-13")

val geometry = Gdml {
    // geometry variables
    val worldSize = 500
    // chamber
    val chamberHeight = 30 // length of the chamber
    val chamberDiameter = 102 // inner diameter of the copper chamber
    val chamberOuterSquareSide = 134 // chamber has a square footprint
    val chamberBackplateThickness = 15 // thickness of the backplate of the chamber
    // teflon disk
    val cathodeTeflonDiskHoleRadius = 15
    val cathodeTeflonDiskThickness = 5
    val cathodeCopperSupportOuterRadius = 45
    val cathodeCopperSupportInnerRadius = 8.5
    val cathodeCopperSupportThickness = 1
    // mylar cathode
    val mylarCathodeThickness = 0.004
    // patern
    val cathodePatternLineWidth = 0.3
    val cathodePatternDiskRadius = 4.25
    // readout
    val chamberTeflonWallThickness = 1
    val readoutKaptonThickness = 0.5
    val readoutCopperThickness = 0.2
    val readoutPlaneSide = 60

    structure {
        val worldMaterial = materials.composite("G4_AIR") {}
        val worldBox = solids.box("worldBox", worldSize, worldSize, worldSize) {}

        val shieldingMaterial = materials.composite("G4_Pb") {}
        val scintillatorMaterial = materials.composite("BC408") {}
        val captureMaterial = materials.composite("G4_Cd") {}

        // chamber
        val copperMaterial = materials.composite("G4_Cu") {}
        val chamberSolidBase = solids.box("chamberSolidBase", chamberOuterSquareSide, chamberOuterSquareSide, chamberHeight) {}
        val chamberSolidHole = solids.tube("chamberSolidHole", chamberDiameter / 2, chamberHeight) {}
        val chamberSolid = solids.subtraction("chamberSolid", chamberSolidBase, chamberSolidHole) {}
        val chamberBodyVolume = volume("chamberBodyVolume", copperMaterial, chamberSolid) {}
        val chamberBackplateSolid = solids.box("chamberBackplateSolid", chamberOuterSquareSide, chamberOuterSquareSide, chamberBackplateThickness)
        val chamberBackplateVolume = volume("chamberBackplateVolume", copperMaterial, chamberBackplateSolid) {}
        // chamber teflon walls
        val teflonMaterial = materials.composite("G4_TEFLON") {}
        val chamberTeflonWallSolid = solids.tube("chamberTeflonWallSolid", chamberDiameter / 2, chamberHeight) {
            rmin = chamberDiameter / 2.0 - chamberTeflonWallThickness
        }
        val chamberTeflonWallVolume = volume("chamberTeflonWallVolume", teflonMaterial, chamberTeflonWallSolid)
        // cathode
        val cathodeCopperDiskMaterial = materials.composite("G4_Cu") {}
        val cathodeWindowMaterial = materials.composite("G4_MYLAR") {}

        val cathodeTeflonDiskSolidBase = solids.tube("cathodeTeflonDiskSolidBase", chamberOuterSquareSide / 2, cathodeTeflonDiskThickness) {
            rmin = cathodeTeflonDiskHoleRadius
        }
        val cathodeCopperDiskSolid = solids.tube("cathodeCopperDiskSolid", cathodeCopperSupportOuterRadius, cathodeCopperSupportThickness) {
            rmin = cathodeCopperSupportInnerRadius
        }

        val cathodeTeflonDiskSolid = solids.subtraction("cathodeTeflonDiskSolid", cathodeTeflonDiskSolidBase, cathodeCopperDiskSolid) {}
        val cathodeTeflonDiskVolume = volume("cathodeTeflonDiskVolume", teflonMaterial, cathodeTeflonDiskSolid) {}

        val cathodeWindowSolid = solids.tube("cathodeWindowSolid", cathodeTeflonDiskHoleRadius, mylarCathodeThickness) {}
        val cathodeWindowVolume = volume("cathodeWindowVolume", cathodeWindowMaterial, cathodeWindowSolid) {}

        val cathodeFillingMaterial = materials.composite("G4_Galactic") {}
        val cathodeFillingSolidBase = solids.tube("cathodeFillingSolidBase", cathodeTeflonDiskHoleRadius, cathodeTeflonDiskThickness) {}

        val cathodeFillingSolid = solids.subtraction("cathodeFillingSolid", cathodeFillingSolidBase, cathodeCopperDiskSolid) {
            position = GdmlPosition(z = chamberHeight / 2 - mylarCathodeThickness / 2)
        }
        val cathodeFillingVolume = volume("cathodeFillingVolume", cathodeFillingMaterial, cathodeFillingSolid) {}

        // pattern
        val cathodePatternLineAux = solids.box(
                "cathodePatternLineAux",
                cathodePatternLineWidth,
                cathodeCopperSupportInnerRadius * 2,
                cathodeCopperSupportThickness
        ) {}
        val cathodePatternCentralHole = solids.tube(
                "cathodePatternCentralHole",
                cathodePatternDiskRadius - 0 * cathodePatternLineWidth,
                cathodeCopperSupportThickness * 1.1
        ) {}
        val cathodePatternLine = solids.subtraction("cathodePatternLine", cathodePatternLineAux, cathodePatternCentralHole) {}

        val cathodePatternDisk = solids.tube(
                "cathodePatternDisk",
                cathodePatternDiskRadius,
                cathodeCopperSupportThickness
        ) { rmin = cathodePatternDiskRadius - cathodePatternLineWidth }

        val cathodeCopperDiskSolidAux0 =
                solids.union("cathodeCopperDiskSolidAux0", cathodeCopperDiskSolid, cathodePatternLine) {
                    rotation = GdmlRotation(
                            "cathodePatternRotation0", x = 0, y = 0, z = 0
                    )
                }
        val cathodeCopperDiskSolidAux1 =
                solids.union("cathodeCopperDiskSolidAux1", cathodeCopperDiskSolidAux0, cathodePatternLine) {
                    rotation = GdmlRotation(
                            "cathodePatternRotation1", x = 0, y = 0, z = 45
                    )
                }
        val cathodeCopperDiskSolidAux2 =
                solids.union("cathodeCopperDiskSolidAux2", cathodeCopperDiskSolidAux1, cathodePatternLine) {
                    rotation = GdmlRotation(
                            "cathodePatternRotation2", x = 0, y = 0, z = 90
                    )
                }
        val cathodeCopperDiskSolidAux3 =
                solids.union("cathodeCopperDiskSolidAux3", cathodeCopperDiskSolidAux2, cathodePatternLine) {
                    rotation = GdmlRotation(
                            "cathodePatternRotation3", x = 0, y = 0, z = 135
                    )
                }

        val cathodeCopperDiskFinal =
                solids.union("cathodeCopperDiskFinal", cathodeCopperDiskSolidAux3, cathodePatternDisk) {}

        val cathodeCopperDiskVolume = volume("cathodeCopperDiskFinal", cathodeCopperDiskMaterial, cathodeCopperDiskFinal) {}

        val gasSolidOriginal = solids.tube(
                "gasSolidOriginal",
                chamberDiameter / 2 - chamberTeflonWallThickness,
                chamberHeight
        ) {}

        val kaptonReadoutMaterial = materials.composite("G4_KAPTON") {}
        val kaptonReadoutSolid = solids.box("kaptonReadoutSolid", chamberOuterSquareSide, chamberOuterSquareSide, readoutKaptonThickness)
        val kaptonReadoutVolume = volume("kaptonReadoutVolume", kaptonReadoutMaterial, kaptonReadoutSolid)

        val copperReadoutSolid = solids.box("copperReadoutSolid", readoutPlaneSide, readoutPlaneSide, readoutCopperThickness)
        val copperReadoutVolume = volume("copperReadoutVolume", copperMaterial, copperReadoutSolid)

        val gasSolidAux =
                solids.subtraction("gasSolidAux", gasSolidOriginal, copperReadoutSolid) {
                    position = GdmlPosition(z = -chamberHeight / 2 + readoutCopperThickness / 2)
                }

        val gasMaterial = materials.composite("G4_Ar") {}
        val gasSolid =
                solids.subtraction("gasSolid", gasSolidAux, cathodeWindowSolid) {
                    position = GdmlPosition(z = chamberHeight / 2 - mylarCathodeThickness / 2)
                    rotation = GdmlRotation(z = 45)
                }
        val gasVolume = volume("gasVolume", gasMaterial, gasSolid)

        // world setup
        world = volume("world", worldMaterial, worldBox) {
            physVolume(gasVolume) {
                name = "gas"
            }
            physVolume(kaptonReadoutVolume) {
                name = "kaptonReadout"
                position {
                    z = -chamberHeight / 2 - readoutKaptonThickness / 2
                }
            }
            physVolume(copperReadoutVolume) {
                name = "copperReadout"
                position {
                    z = -chamberHeight / 2 + readoutCopperThickness / 2
                }
                rotation { z = 45 }
            }
            physVolume(chamberBodyVolume) {
                name = "chamberBody"
            }
            physVolume(chamberBackplateVolume) {
                name = "chamberBackplate"
                position {
                    z = -chamberHeight / 2 - readoutKaptonThickness - chamberBackplateThickness / 2
                }
            }
            physVolume(chamberTeflonWallVolume) {
                name = "chamberTeflonWall"
            }
            physVolume(cathodeTeflonDiskVolume) {
                name = "cathodeTeflonDisk"
                position {
                    z = chamberHeight / 2 + cathodeTeflonDiskThickness / 2
                }
            }
            physVolume(cathodeCopperDiskVolume) {
                name = "cathodeCopperDisk"
                position {
                    z = chamberHeight / 2 + cathodeCopperSupportThickness / 2
                }
            }
            physVolume(cathodeWindowVolume) {
                name = "cathodeWindow"
                position {
                    z = chamberHeight / 2 - mylarCathodeThickness / 2
                }
            }
            physVolume(cathodeFillingVolume) {
                name = "cathodeFilling"
                position {
                    z = chamberHeight / 2 + cathodeTeflonDiskThickness / 2
                }
            }
        }
    }
}
altavir commented 3 years ago

The problem with transparency and increased detail is that it greatly impacts the performance on complex scene-graphs. But I agree that it should be an option. There are also two actual places, where one can increase the detail: during gdml to VF conversion and during the rendering. I think we can tweak both.

altavir commented 3 years ago

I've increased the default level for spheres and cones and now it looks much better: image It still could be adjusted in the converter (need to add some configuration options for that).