Increased the default detail level for spheres and cones to 32. Fix for #38

This commit is contained in:
Alexander Nozik 2021-05-07 19:14:46 +03:00
parent 03b666017b
commit 2798439582
7 changed files with 241 additions and 9 deletions

View File

@ -7,6 +7,7 @@
- Customizable accessors for colors - Customizable accessors for colors
- SphereLayer solid - SphereLayer solid
- Hexagon interface and GenericHexagon implementation (Box inherits Hexagon) - Hexagon interface and GenericHexagon implementation (Box inherits Hexagon)
- Increased the default detail level for spheres and cones to 32
### Changed ### Changed
- Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate. - Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate.

View File

@ -0,0 +1,226 @@
package space.kscience.visionforge.examples
import space.kscience.dataforge.context.Context
import space.kscience.gdml.*
import space.kscience.visionforge.gdml.gdml
import space.kscience.visionforge.solid.Solids
fun main() {
val context = Context {
plugin(Solids)
}
context.makeVisionFile {
vision("canvas") {
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(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(chamberOuterSquareSide, chamberOuterSquareSide, chamberHeight)
val chamberSolidHole = solids.tube(chamberDiameter / 2, chamberHeight)
val chamberSolid = solids.subtraction(chamberSolidBase, chamberSolidHole)
val chamberBodyVolume = volume(copperMaterial, chamberSolid)
val chamberBackplateSolid =
solids.box(chamberOuterSquareSide, chamberOuterSquareSide, chamberBackplateThickness)
val chamberBackplateVolume = volume(copperMaterial, chamberBackplateSolid)
// chamber teflon walls
val teflonMaterial = materials.composite("G4_TEFLON")
val chamberTeflonWallSolid = solids.tube(chamberDiameter / 2, chamberHeight) {
rmin = chamberDiameter / 2.0 - chamberTeflonWallThickness
}
val chamberTeflonWallVolume = volume(teflonMaterial, chamberTeflonWallSolid)
// cathode
val cathodeCopperDiskMaterial = materials.composite("G4_Cu")
val cathodeWindowMaterial = materials.composite("G4_MYLAR")
val cathodeTeflonDiskSolidBase =
solids.tube(chamberOuterSquareSide / 2, cathodeTeflonDiskThickness) {
rmin = cathodeTeflonDiskHoleRadius
}
val cathodeCopperDiskSolid =
solids.tube(cathodeCopperSupportOuterRadius, cathodeCopperSupportThickness) {
rmin = cathodeCopperSupportInnerRadius
}
val cathodeTeflonDiskSolid = solids.subtraction(cathodeTeflonDiskSolidBase, cathodeCopperDiskSolid)
val cathodeTeflonDiskVolume = volume(teflonMaterial, cathodeTeflonDiskSolid)
val cathodeWindowSolid = solids.tube(cathodeTeflonDiskHoleRadius, mylarCathodeThickness)
val cathodeWindowVolume = volume(cathodeWindowMaterial, cathodeWindowSolid)
val cathodeFillingMaterial = materials.composite("G4_Galactic")
val cathodeFillingSolidBase = solids.tube(cathodeTeflonDiskHoleRadius, cathodeTeflonDiskThickness)
val cathodeFillingSolid = solids.subtraction(cathodeFillingSolidBase, cathodeCopperDiskSolid) {
position(z = chamberHeight / 2 - mylarCathodeThickness / 2)
}
val cathodeFillingVolume = volume(cathodeFillingMaterial, cathodeFillingSolid)
// pattern
val cathodePatternLineAux = solids.box(
cathodePatternLineWidth,
cathodeCopperSupportInnerRadius * 2,
cathodeCopperSupportThickness
)
val cathodePatternCentralHole = solids.tube(
cathodePatternDiskRadius - 0 * cathodePatternLineWidth,
cathodeCopperSupportThickness * 1.1
)
val cathodePatternLine = solids.subtraction(cathodePatternLineAux, cathodePatternCentralHole)
val cathodePatternDisk = solids.tube(
cathodePatternDiskRadius,
cathodeCopperSupportThickness
) { rmin = cathodePatternDiskRadius - cathodePatternLineWidth }
val cathodeCopperDiskSolidAux0 =
solids.union(cathodeCopperDiskSolid, cathodePatternLine) {
rotation(x = 0, y = 0, z = 0)
}
val cathodeCopperDiskSolidAux1 =
solids.union(cathodeCopperDiskSolidAux0, cathodePatternLine) {
rotation = GdmlRotation(
"cathodePatternRotation1", x = 0, y = 0, z = 45
)
}
val cathodeCopperDiskSolidAux2 =
solids.union(cathodeCopperDiskSolidAux1, cathodePatternLine) {
rotation = GdmlRotation(
"cathodePatternRotation2", x = 0, y = 0, z = 90
)
}
val cathodeCopperDiskSolidAux3 =
solids.union(cathodeCopperDiskSolidAux2, cathodePatternLine) {
rotation = GdmlRotation(
"cathodePatternRotation3", x = 0, y = 0, z = 135
)
}
val cathodeCopperDiskFinal =
solids.union(cathodeCopperDiskSolidAux3, cathodePatternDisk)
val cathodeCopperDiskVolume =
volume(cathodeCopperDiskMaterial, cathodeCopperDiskFinal)
val gasSolidOriginal = solids.tube(
chamberDiameter / 2 - chamberTeflonWallThickness,
chamberHeight
)
val kaptonReadoutMaterial = materials.composite("G4_KAPTON")
val kaptonReadoutSolid = solids.box(
chamberOuterSquareSide,
chamberOuterSquareSide,
readoutKaptonThickness)
val kaptonReadoutVolume = volume( kaptonReadoutMaterial, kaptonReadoutSolid)
val copperReadoutSolid =
solids.box(readoutPlaneSide, readoutPlaneSide, readoutCopperThickness)
val copperReadoutVolume = volume(copperMaterial, copperReadoutSolid)
val gasSolidAux =
solids.subtraction(gasSolidOriginal, copperReadoutSolid) {
position(z = -chamberHeight / 2 + readoutCopperThickness / 2)
}
val gasMaterial = materials.composite("G4_Ar")
val gasSolid =
solids.subtraction( gasSolidAux, cathodeWindowSolid) {
position(z = chamberHeight / 2 - mylarCathodeThickness / 2)
rotation(z = 45)
}
val gasVolume = volume(gasMaterial, gasSolid)
// world setup
world = volume(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
}
}
}
}
}
}
}
}

View File

@ -2,17 +2,16 @@ package space.kscience.visionforge.gdml
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaBuilder import space.kscience.dataforge.meta.MetaBuilder
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import space.kscience.dataforge.names.toName import space.kscience.dataforge.names.toName
import space.kscience.gdml.* import space.kscience.gdml.*
import space.kscience.visionforge.set import space.kscience.visionforge.*
import space.kscience.visionforge.setProperty import space.kscience.visionforge.html.VisionOutput
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
import space.kscience.visionforge.styleSheet
import space.kscience.visionforge.useStyle
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.sin import kotlin.math.sin
import kotlin.random.Random import kotlin.random.Random
@ -446,3 +445,7 @@ public fun SolidGroup.gdml(gdml: Gdml, key: String? = null, transformer: GdmlTra
//println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)) //println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual))
set(key, visual) set(key, visual)
} }
@VisionBuilder
@DFExperimental
public inline fun VisionOutput.gdml(block: Gdml.() -> Unit): SolidGroup = Gdml(block).toVision()

View File

@ -10,6 +10,7 @@ import kotlin.math.sin
/** /**
* A solid cylinder or cut cone segment * A solid cylinder or cut cone segment
* The default segment number is 32
*/ */
@Serializable @Serializable
@SerialName("solid.cone") @SerialName("solid.cone")
@ -22,7 +23,7 @@ public class ConeSegment(
) : SolidBase(), GeometrySolid { ) : SolidBase(), GeometrySolid {
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) { override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
val segments = detail ?: 8 val segments = detail ?: 32
require(segments >= 4) { "The number of segments in cone segment is too small" } require(segments >= 4) { "The number of segments in cone segment is too small" }
val angleStep = angle / (segments - 1) val angleStep = angle / (segments - 1)

View File

@ -11,6 +11,7 @@ import kotlin.math.sin
/** /**
* A conical or cylindrical surface * A conical or cylindrical surface
* The default segment number is 32
*/ */
@Serializable @Serializable
@SerialName("solid.coneSurface") @SerialName("solid.coneSurface")
@ -33,7 +34,7 @@ public class ConeSurface(
} }
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) { override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
val segments = detail ?: 8 val segments = detail ?: 32
require(segments >= 4) { "The number of segments in tube is too small" } require(segments >= 4) { "The number of segments in tube is too small" }
val angleStep = angle / (segments - 1) val angleStep = angle / (segments - 1)

View File

@ -28,7 +28,7 @@ public class Sphere(
return Point3D(x, y, z) return Point3D(x, y, z)
} }
val segments = this.detail ?: 8 val segments = this.detail ?: 32
require(segments >= 4) { "The detail for sphere must be >= 4" } require(segments >= 4) { "The detail for sphere must be >= 4" }
val phiStep = phi / segments val phiStep = phi / segments
val thetaStep = theta / segments val thetaStep = theta / segments

View File

@ -35,7 +35,7 @@ public class SphereLayer(
return Point3D(x, y, z) return Point3D(x, y, z)
} }
val segments = detail ?: 8 val segments = detail ?: 32
require(segments >= 4) { "The detail for sphere must be >= 4" } require(segments >= 4) { "The detail for sphere must be >= 4" }
val phiStep = phi / segments val phiStep = phi / segments
val thetaStep = theta / segments val thetaStep = theta / segments