diff --git a/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt b/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt index a292396f..a45345cc 100644 --- a/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt +++ b/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt @@ -1,9 +1,7 @@ package space.kscience.visionforge.examples import space.kscience.dataforge.context.Context -import space.kscience.gdml.Gdml -import space.kscience.gdml.LUnit -import space.kscience.gdml.decodeFromStream +import space.kscience.gdml.GdmlShowCase import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.solid.Solids @@ -14,9 +12,7 @@ fun main() { } context.makeVisionFile(resourceLocation = ResourceLocation.EMBED) { vision("canvas") { - Gdml.decodeFromStream(javaClass.getResourceAsStream("/gdml/babyIAXO.gdml")!!, true).toVision { - lUnit = LUnit.MM - } + GdmlShowCase.babyIaxo().toVision() } } } \ 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 449bd09d..ec53b430 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 @@ -187,11 +187,28 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { solid.deltaphi * aScale, name ) - is GdmlCone -> cone(solid.rmax1, solid.z, solid.rmax2, name = name) { - require(solid.rmin1 == 0.0) { "Empty cones are not supported" } - require(solid.rmin2 == 0.0) { "Empty cones are not supported" } - startAngle = solid.startphi.toFloat() - angle = solid.deltaphi.toFloat() + is GdmlCone -> if (solid.rmin1.toDouble() == 0.0 && solid.rmin2.toDouble() == 0.0) { + cone( + bottomRadius = solid.rmax1, + height = solid.z, + upperRadius = solid.rmax2, + name = name + ) { + startAngle = solid.startphi.toFloat() + angle = solid.deltaphi.toFloat() + } + } else { + coneSurface( + bottomOuterRadius = solid.rmax1, + bottomInnerRadius = solid.rmin1, + height = solid.z, + topOuterRadius = solid.rmax2, + topInnerRadius = solid.rmin2, + name = name + ) { + startAngle = solid.startphi.toFloat() + angle = solid.deltaphi.toFloat() + } } is GdmlXtru -> extrude(name) { shape { @@ -396,7 +413,8 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { return final } - fun transform(root: Gdml): SolidGroup = finalize(volume(root, root.world.resolve(root) ?: error("GDML root is not resolved"))) + fun transform(root: Gdml): SolidGroup = + finalize(volume(root, root.world.resolve(root) ?: error("GDML root is not resolved"))) } 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 e07cdee3..a0cc0342 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 @@ -8,7 +8,7 @@ import kotlin.math.cos import kotlin.math.sin /** - * A cylinder or cut cone segment + * A solid cylinder or cut cone segment */ @Serializable @SerialName("solid.cone") diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Tube.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt similarity index 71% rename from visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Tube.kt rename to visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt index 00c060ca..ecc3e227 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Tube.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt @@ -10,22 +10,24 @@ import kotlin.math.cos import kotlin.math.sin /** - * Straight tube segment + * A conical or cylindrical surface */ @Serializable -@SerialName("solid.tube") -public class Tube( - public var radius: Float, +@SerialName("solid.coneSurface") +public class ConeSurface( + public var bottomRadius: Float, + public var bottomInnerRadius: Float, public var height: Float, - public var innerRadius: Float = 0f, + public var topRadius: Float, + public var topInnerRadius: Float, public var startAngle: Float = 0f, public var angle: Float = PI2, ) : SolidBase(), GeometrySolid { init { - require(radius > 0) - require(height > 0) - require(innerRadius >= 0) + require(bottomRadius > 0) { "Cone surface bottom radius must be positive" } + require(height > 0) { "Cone surface height must be positive" } + require(bottomInnerRadius >= 0) { "Cone surface bottom inner radius must be non-negative" } //require(startAngle >= 0) require(angle in (0f..(PI2))) } @@ -44,8 +46,8 @@ public class Tube( geometryBuilder.apply { //creating shape in x-y plane with z = 0 - val bottomOuterPoints = shape(radius, -height / 2) - val upperOuterPoints = shape(radius, height / 2) + val bottomOuterPoints = shape(bottomRadius, -height / 2) + val upperOuterPoints = shape(topRadius, height / 2) //outer face (1 until segments).forEach { face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1]) @@ -54,7 +56,7 @@ public class Tube( if (angle == PI2) { face4(bottomOuterPoints.last(), bottomOuterPoints[0], upperOuterPoints[0], upperOuterPoints.last()) } - if (innerRadius == 0f) { + if (bottomInnerRadius == 0f) { val zeroBottom = Point3D(0f, 0f, 0f) val zeroTop = Point3D(0f, 0f, height) (1 until segments).forEach { @@ -69,8 +71,8 @@ public class Tube( face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last()) } } else { - val bottomInnerPoints = shape(innerRadius, -height / 2) - val upperInnerPoints = shape(innerRadius, height / 2) + val bottomInnerPoints = shape(bottomInnerRadius, -height / 2) + val upperInnerPoints = shape(topInnerRadius, height / 2) //outer face (1 until segments).forEach { // inner surface @@ -116,24 +118,41 @@ public class Tube( } } } - } + @VisionBuilder public inline fun VisionContainerBuilder.tube( r: Number, height: Number, - innerRadius: Number = 0f, + innerRadius: Number, startAngle: Number = 0f, angle: Number = 2 * PI, name: String? = null, - block: Tube.() -> Unit = {}, -): Tube = Tube( - r.toFloat(), - height.toFloat(), - innerRadius.toFloat(), - startAngle.toFloat(), - angle.toFloat() -).apply( - block -).also { set(name, it) } \ No newline at end of file + block: ConeSurface.() -> Unit = {}, +): ConeSurface = ConeSurface( + bottomRadius = r.toFloat(), + bottomInnerRadius = innerRadius.toFloat(), + height = height.toFloat(), + topRadius = r.toFloat(), + topInnerRadius = innerRadius.toFloat(), + startAngle = startAngle.toFloat(), + angle = angle.toFloat() +).apply(block).also { set(name, it) } + +@VisionBuilder +public inline fun VisionContainerBuilder.coneSurface( + bottomOuterRadius: Number, + bottomInnerRadius: Number, + height: Number, + topOuterRadius: Number, + topInnerRadius: Number, + name: String? = null, + block: ConeSurface.() -> Unit = {}, +): ConeSurface = ConeSurface( + bottomRadius = bottomOuterRadius.toFloat(), + bottomInnerRadius = bottomInnerRadius.toFloat(), + height = height.toFloat(), + topRadius = topOuterRadius.toFloat(), + topInnerRadius = topInnerRadius.toFloat(), +).apply(block).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt index fc296244..536770ec 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt @@ -29,9 +29,9 @@ public class Solids(meta: Meta) : VisionPlugin(meta) { subclass(SolidGroup.serializer()) subclass(SolidReferenceGroup.serializer()) subclass(Composite.serializer()) - subclass(Tube.serializer()) subclass(Box.serializer()) subclass(ConeSegment.serializer()) + subclass(ConeSurface.serializer()) subclass(Convex.serializer()) subclass(Extruded.serializer()) subclass(PolyLine.serializer()) diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt index c79ee93a..034cf430 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt @@ -89,6 +89,7 @@ public class ThreeCanvas( width = "100%" height = "100%" display = "block" + zIndex = "1000" } } @@ -126,6 +127,7 @@ public class ThreeCanvas( mousePosition.x = ((event.clientX - rect.left) / canvas.clientWidth) * 2 - 1 mousePosition.y = -((event.clientY - rect.top) / canvas.clientHeight) * 2 + 1 } + event.preventDefault() }, false) canvas.onresize = { diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCylinderFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCylinderFactory.kt index 57206c3e..6ee0cd18 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCylinderFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCylinderFactory.kt @@ -2,18 +2,18 @@ package space.kscience.visionforge.solid.three import info.laht.threekt.core.BufferGeometry import info.laht.threekt.geometries.CylinderBufferGeometry -import space.kscience.visionforge.solid.ConeSegment +import space.kscience.visionforge.solid.ConeSurface import space.kscience.visionforge.solid.detail import kotlin.math.PI import kotlin.math.pow -public object ThreeCylinderFactory : MeshThreeFactory(ConeSegment::class) { - override fun buildGeometry(obj: ConeSegment): BufferGeometry { +public object ThreeCylinderFactory : MeshThreeFactory(ConeSurface::class) { + override fun buildGeometry(obj: ConeSurface): BufferGeometry { val cylinder = obj.detail?.let { val segments = it.toDouble().pow(0.5).toInt() CylinderBufferGeometry( - radiusTop = obj.upperRadius, - radiusBottom = obj.radius, + radiusTop = obj.topRadius, + radiusBottom = obj.bottomRadius, height = obj.height, radialSegments = segments, heightSegments = segments, @@ -22,8 +22,8 @@ public object ThreeCylinderFactory : MeshThreeFactory(ConeSegment:: thetaLength = obj.angle ) } ?: CylinderBufferGeometry( - radiusTop = obj.upperRadius, - radiusBottom = obj.radius, + radiusTop = obj.topRadius, + radiusBottom = obj.bottomRadius, height = obj.height, openEnded = false, thetaStart = obj.startAngle, diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt index 7aa84885..b4eb66fd 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt @@ -35,7 +35,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { objectFactories[Box::class] = ThreeBoxFactory objectFactories[Convex::class] = ThreeConvexFactory objectFactories[Sphere::class] = ThreeSphereFactory - objectFactories[ConeSegment::class] = ThreeCylinderFactory + objectFactories[ConeSurface::class] = ThreeCylinderFactory objectFactories[PolyLine::class] = ThreeLineFactory objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory }