diff --git a/CHANGELOG.md b/CHANGELOG.md index 1685272b..91d20f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Customizable accessors for colors - SphereLayer solid - Hexagon interface and GenericHexagon implementation (Box inherits Hexagon) +- Increased the default detail level for spheres and cones to 32 ### Changed - Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate. diff --git a/demo/playground/src/jvmMain/kotlin/gdmCurve.kt b/demo/playground/src/jvmMain/kotlin/gdmCurve.kt new file mode 100644 index 00000000..12981241 --- /dev/null +++ b/demo/playground/src/jvmMain/kotlin/gdmCurve.kt @@ -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 + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt index e8fb8815..ac0e9e4b 100644 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt @@ -2,17 +2,16 @@ package space.kscience.visionforge.gdml import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.toName import space.kscience.gdml.* -import space.kscience.visionforge.set -import space.kscience.visionforge.setProperty +import space.kscience.visionforge.* +import space.kscience.visionforge.html.VisionOutput import space.kscience.visionforge.solid.* 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.sin import kotlin.random.Random @@ -445,4 +444,8 @@ public fun SolidGroup.gdml(gdml: Gdml, key: String? = null, transformer: GdmlTra val visual = gdml.toVision(transformer) //println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)) set(key, visual) -} \ No newline at end of file +} + +@VisionBuilder +@DFExperimental +public inline fun VisionOutput.gdml(block: Gdml.() -> Unit): SolidGroup = Gdml(block).toVision() \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt index ef529207..211e3af2 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt @@ -10,6 +10,7 @@ import kotlin.math.sin /** * A solid cylinder or cut cone segment + * The default segment number is 32 */ @Serializable @SerialName("solid.cone") @@ -22,7 +23,7 @@ public class ConeSegment( ) : SolidBase(), GeometrySolid { override fun toGeometry(geometryBuilder: GeometryBuilder) { - val segments = detail ?: 8 + val segments = detail ?: 32 require(segments >= 4) { "The number of segments in cone segment is too small" } val angleStep = angle / (segments - 1) diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt index b654ee90..caa8c746 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt @@ -11,6 +11,7 @@ import kotlin.math.sin /** * A conical or cylindrical surface + * The default segment number is 32 */ @Serializable @SerialName("solid.coneSurface") @@ -33,7 +34,7 @@ public class ConeSurface( } override fun toGeometry(geometryBuilder: GeometryBuilder) { - val segments = detail ?: 8 + val segments = detail ?: 32 require(segments >= 4) { "The number of segments in tube is too small" } val angleStep = angle / (segments - 1) diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt index f3ace5b3..c4d67f97 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt @@ -28,7 +28,7 @@ public class Sphere( 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" } val phiStep = phi / segments val thetaStep = theta / segments diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt index 6443bdd0..83e358e2 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt @@ -35,7 +35,7 @@ public class SphereLayer( return Point3D(x, y, z) } - val segments = detail ?: 8 + val segments = detail ?: 32 require(segments >= 4) { "The detail for sphere must be >= 4" } val phiStep = phi / segments val thetaStep = theta / segments