SphereLayer
This commit is contained in:
parent
545753b14b
commit
3f6e39b18d
@ -5,6 +5,7 @@
|
|||||||
- Server module
|
- Server module
|
||||||
- Change collector
|
- Change collector
|
||||||
- Customizable accessors for colors
|
- Customizable accessors for colors
|
||||||
|
- SphereLayer solid
|
||||||
|
|
||||||
### 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.
|
||||||
@ -13,6 +14,7 @@
|
|||||||
- Threejs support moved to a separate module
|
- Threejs support moved to a separate module
|
||||||
- \[Format breaking change!\] Stylesheets are moved into properties under `@stylesheet` key
|
- \[Format breaking change!\] Stylesheets are moved into properties under `@stylesheet` key
|
||||||
- VisionGroup builder accepts `null` as name for statics instead of `""`
|
- VisionGroup builder accepts `null` as name for statics instead of `""`
|
||||||
|
- gdml sphere is rendered as a SphereLayer instead of Sphere (#35)
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package hep.dataforge.vision.gdml.demo
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.vision.Application
|
import hep.dataforge.vision.Application
|
||||||
|
import hep.dataforge.vision.bootstrap.useBootstrap
|
||||||
import hep.dataforge.vision.gdml.GdmlShowcase
|
import hep.dataforge.vision.gdml.GdmlShowcase
|
||||||
import hep.dataforge.vision.gdml.toVision
|
import hep.dataforge.vision.gdml.toVision
|
||||||
import hep.dataforge.vision.solid.three.ThreePlugin
|
import hep.dataforge.vision.solid.three.ThreePlugin
|
||||||
@ -14,6 +15,8 @@ import react.dom.render
|
|||||||
private class GDMLDemoApp : Application {
|
private class GDMLDemoApp : Application {
|
||||||
|
|
||||||
override fun start(state: Map<String, Any>) {
|
override fun start(state: Map<String, Any>) {
|
||||||
|
useBootstrap()
|
||||||
|
|
||||||
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
|
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
|
||||||
|
|
||||||
val context = Global.context("demo") .apply{
|
val context = Global.context("demo") .apply{
|
||||||
|
@ -4,15 +4,11 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Three js demo for particle physics</title>
|
<title>Three js demo for particle physics</title>
|
||||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="css/main.css">
|
|
||||||
<link rel="stylesheet" href="css/fileDrop.css">
|
|
||||||
<script type="text/javascript" src="gdml.js"></script>
|
<script type="text/javascript" src="gdml.js"></script>
|
||||||
|
<link rel="stylesheet" href="css/custom-bootstrap.css">
|
||||||
|
<link rel="stylesheet" href="css/fileDrop.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="application">
|
<body class="application">
|
||||||
<div class="container-fluid max-vh-100" id = "app"> </div>
|
<div class="container-fluid max-vh-100" id = "app"> </div>
|
||||||
|
|
||||||
<script type="text/javascript" src ="js/jquery-3.4.1.min.js"></script>
|
|
||||||
<script type="text/javascript" src ="js/bootstrap.bundle.min.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -2,6 +2,7 @@ package ru.mipt.npm.muon.monitor
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.vision.Application
|
import hep.dataforge.vision.Application
|
||||||
|
import hep.dataforge.vision.bootstrap.useBootstrap
|
||||||
import hep.dataforge.vision.startApplication
|
import hep.dataforge.vision.startApplication
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.features.json.JsonFeature
|
import io.ktor.client.features.json.JsonFeature
|
||||||
@ -21,6 +22,8 @@ private class MMDemoApp : Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun start(state: Map<String, Any>) {
|
override fun start(state: Map<String, Any>) {
|
||||||
|
useBootstrap()
|
||||||
|
|
||||||
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
|
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
|
||||||
|
|
||||||
val context = Global.context("demo") {}
|
val context = Global.context("demo") {}
|
||||||
|
@ -4,14 +4,10 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
|
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
|
||||||
<title>Three js demo for particle physics</title>
|
<title>Three js demo for particle physics</title>
|
||||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="css/main.css">
|
|
||||||
<script type="text/javascript" src="muon-monitor.js"></script>
|
<script type="text/javascript" src="muon-monitor.js"></script>
|
||||||
|
<link rel="stylesheet" href="css/custom-bootstrap.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="application">
|
<body class="application">
|
||||||
<div class="container-fluid max-vh-100" id = "app"> </div>
|
<div class="container-fluid max-vh-100" id = "app"> </div>
|
||||||
|
|
||||||
<script type="text/javascript" src ="js/jquery-3.4.1.min.js"></script>
|
|
||||||
<script type="text/javascript" src ="js/bootstrap.bundle.min.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
24
demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt
Normal file
24
demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package hep.dataforge.vision.examples
|
||||||
|
|
||||||
|
import hep.dataforge.misc.DFExperimental
|
||||||
|
import hep.dataforge.vision.VisionForge
|
||||||
|
import hep.dataforge.vision.gdml.toVision
|
||||||
|
import hep.dataforge.vision.html.ResourceLocation
|
||||||
|
import hep.dataforge.vision.html.fragment
|
||||||
|
import hep.dataforge.vision.invoke
|
||||||
|
import hep.dataforge.vision.solid.Solids
|
||||||
|
import space.kscience.gdml.Gdml
|
||||||
|
import space.kscience.gdml.LUnit
|
||||||
|
import space.kscience.gdml.decodeFromStream
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
fun main() = VisionForge(Solids) {
|
||||||
|
val content = VisionForge.fragment {
|
||||||
|
vision("canvas") {
|
||||||
|
Gdml.decodeFromStream(Gdml.javaClass.getResourceAsStream("/gdml/babyIAXO.gdml")!!, true).toVision {
|
||||||
|
lUnit = LUnit.MM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
makeVisionFile(content, resourceLocation = ResourceLocation.EMBED)
|
||||||
|
}
|
1065
demo/playground/src/jvmMain/resources/gdml/babyIAXO.gdml
Normal file
1065
demo/playground/src/jvmMain/resources/gdml/babyIAXO.gdml
Normal file
File diff suppressed because it is too large
Load Diff
@ -52,6 +52,12 @@ fun VisionLayout<Solid>.showcase() {
|
|||||||
rotationX = PI / 4
|
rotationX = PI / 4
|
||||||
color("blue")
|
color("blue")
|
||||||
}
|
}
|
||||||
|
sphereLayer(50,40){
|
||||||
|
theta = (PI/2).toFloat()
|
||||||
|
rotationX = - PI * 3 / 4
|
||||||
|
z = 110
|
||||||
|
color(Colors.pink)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
demo("dynamic", "Dynamic properties") {
|
demo("dynamic", "Dynamic properties") {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
<script type="text/javascript" src="spatial-showcase.js"></script>
|
<script type="text/javascript" src="solid-showcase.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="application">
|
<body class="application">
|
||||||
<div class="container" id="demo"></div>
|
<div class="container" id="demo"></div>
|
||||||
|
@ -8,4 +8,7 @@ dependencies {
|
|||||||
api(project(":visionforge-solid"))
|
api(project(":visionforge-solid"))
|
||||||
api(project(":ui:react"))
|
api(project(":ui:react"))
|
||||||
implementation(npm("file-saver", "2.0.2"))
|
implementation(npm("file-saver", "2.0.2"))
|
||||||
|
implementation(npm("bootstrap","4.6.0"))
|
||||||
|
implementation(npm("jquery","3.5.1"))
|
||||||
|
implementation(npm("popper.js","1.16.1"))
|
||||||
}
|
}
|
@ -1,5 +1,10 @@
|
|||||||
package hep.dataforge.vision.bootstrap
|
package hep.dataforge.vision.bootstrap
|
||||||
|
|
||||||
|
public fun useBootstrap(){
|
||||||
|
kotlinext.js.require("bootstrap/dist/css/bootstrap.min.css")
|
||||||
|
kotlinext.js.require("bootstrap")
|
||||||
|
}
|
||||||
|
|
||||||
//public inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
|
//public inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
|
||||||
// div("card w-100") {
|
// div("card w-100") {
|
||||||
// div("card-body") {
|
// div("card-body") {
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@ import hep.dataforge.names.toName
|
|||||||
import hep.dataforge.vision.set
|
import hep.dataforge.vision.set
|
||||||
import hep.dataforge.vision.setProperty
|
import hep.dataforge.vision.setProperty
|
||||||
import hep.dataforge.vision.solid.*
|
import hep.dataforge.vision.solid.*
|
||||||
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
|
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY
|
||||||
import hep.dataforge.vision.styleSheet
|
import hep.dataforge.vision.styleSheet
|
||||||
import hep.dataforge.vision.useStyle
|
import hep.dataforge.vision.useStyle
|
||||||
import space.kscience.gdml.*
|
import space.kscience.gdml.*
|
||||||
@ -27,6 +27,8 @@ private inline operator fun Number.times(d: Double) = toDouble() * d
|
|||||||
private inline operator fun Number.times(f: Float) = toFloat() * f
|
private inline operator fun Number.times(f: Float) = toFloat() * f
|
||||||
|
|
||||||
public class GdmlTransformerSettings {
|
public class GdmlTransformerSettings {
|
||||||
|
public val random: Random = Random(222)
|
||||||
|
|
||||||
public enum class Action {
|
public enum class Action {
|
||||||
ADD,
|
ADD,
|
||||||
REJECT,
|
REJECT,
|
||||||
@ -38,11 +40,14 @@ public class GdmlTransformerSettings {
|
|||||||
|
|
||||||
public var solidAction: (GdmlSolid) -> Action = { Action.PROTOTYPE }
|
public var solidAction: (GdmlSolid) -> Action = { Action.PROTOTYPE }
|
||||||
public var volumeAction: (GdmlGroup) -> Action = { Action.PROTOTYPE }
|
public var volumeAction: (GdmlGroup) -> Action = { Action.PROTOTYPE }
|
||||||
|
|
||||||
|
public var paint: SolidMaterial.(material: GdmlMaterial) -> Unit = { _->
|
||||||
|
color(random.nextInt(16777216))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
||||||
//private val materialCache = HashMap<GdmlMaterial, Meta>()
|
//private val materialCache = HashMap<GdmlMaterial, Meta>()
|
||||||
private val random = Random(222)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A special group for local templates
|
* A special group for local templates
|
||||||
@ -105,7 +110,8 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
|||||||
val styleName = "materials.${material.name}"
|
val styleName = "materials.${material.name}"
|
||||||
|
|
||||||
obj.useStyle(styleName) {
|
obj.useStyle(styleName) {
|
||||||
MATERIAL_COLOR_KEY put random.nextInt(16777216)
|
val vfMaterial = settings.run { SolidMaterial().apply { paint(material)}}
|
||||||
|
MATERIAL_KEY put vfMaterial.toMeta()
|
||||||
"Gdml.material" put material.name
|
"Gdml.material" put material.name
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +201,9 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
|||||||
scaleZ = solid.scale.z.toFloat()
|
scaleZ = solid.scale.z.toFloat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is GdmlSphere -> sphere(solid.rmax * lScale, solid.deltaphi * aScale, solid.deltatheta * aScale, name) {
|
is GdmlSphere -> sphereLayer(solid.rmax * lScale, solid.rmin * lScale, name) {
|
||||||
|
phi = solid.deltaphi * aScale
|
||||||
|
theta = solid.deltatheta * aScale
|
||||||
phiStart = solid.startphi * aScale
|
phiStart = solid.startphi * aScale
|
||||||
thetaStart = solid.starttheta * aScale
|
thetaStart = solid.starttheta * aScale
|
||||||
}
|
}
|
||||||
@ -255,7 +263,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
|||||||
solid: GdmlSolid,
|
solid: GdmlSolid,
|
||||||
name: String?,
|
name: String?,
|
||||||
): Solid? {
|
): Solid? {
|
||||||
require(name != ""){"Can't use empty solid name. Use null instead."}
|
require(name != "") { "Can't use empty solid name. Use null instead." }
|
||||||
return when (settings.solidAction(solid)) {
|
return when (settings.solidAction(solid)) {
|
||||||
GdmlTransformerSettings.Action.ADD -> {
|
GdmlTransformerSettings.Action.ADD -> {
|
||||||
addSolid(root, solid, name)
|
addSolid(root, solid, name)
|
||||||
|
@ -5,8 +5,8 @@ import hep.dataforge.vision.visitor.countDistinct
|
|||||||
import hep.dataforge.vision.visitor.flowStatistics
|
import hep.dataforge.vision.visitor.flowStatistics
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import space.kscience.gdml.Gdml
|
|
||||||
import nl.adaptivity.xmlutil.StAXReader
|
import nl.adaptivity.xmlutil.StAXReader
|
||||||
|
import space.kscience.gdml.Gdml
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ suspend fun main() {
|
|||||||
File("D:\\Work\\Projects\\dataforge-vis\\visionforge-gdml\\src\\jvmTest\\resources\\gdml\\BM@N.gdml").inputStream()
|
File("D:\\Work\\Projects\\dataforge-vis\\visionforge-gdml\\src\\jvmTest\\resources\\gdml\\BM@N.gdml").inputStream()
|
||||||
|
|
||||||
val xmlReader = StAXReader(stream, "UTF-8")
|
val xmlReader = StAXReader(stream, "UTF-8")
|
||||||
val xml = Gdml.format.parse(Gdml.serializer(), xmlReader)
|
val xml = Gdml.format.decodeFromReader(Gdml.serializer(), xmlReader)
|
||||||
val vision = xml.toVision()
|
val vision = xml.toVision()
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,12 +54,8 @@ public class Sphere(
|
|||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun VisionContainerBuilder<Solid>.sphere(
|
public inline fun VisionContainerBuilder<Solid>.sphere(
|
||||||
radius: Number,
|
radius: Number,
|
||||||
phi: Number = 2 * PI,
|
|
||||||
theta: Number = PI,
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
action: Sphere.() -> Unit = {},
|
action: Sphere.() -> Unit = {},
|
||||||
): Sphere = Sphere(
|
): Sphere = Sphere(
|
||||||
radius.toFloat(),
|
radius.toFloat(),
|
||||||
phi = phi.toFloat(),
|
|
||||||
theta = theta.toFloat()
|
|
||||||
).apply(action).also { set(name, it) }
|
).apply(action).also { set(name, it) }
|
@ -0,0 +1,77 @@
|
|||||||
|
package hep.dataforge.vision.solid
|
||||||
|
|
||||||
|
import hep.dataforge.vision.VisionBuilder
|
||||||
|
import hep.dataforge.vision.VisionContainerBuilder
|
||||||
|
import hep.dataforge.vision.set
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("solid.sphereLayer")
|
||||||
|
public class SphereLayer(
|
||||||
|
public var outerRadius: Float,
|
||||||
|
public var innerRadius: Float,
|
||||||
|
public var phiStart: Float = 0f,
|
||||||
|
public var phi: Float = PI2,
|
||||||
|
public var thetaStart: Float = 0f,
|
||||||
|
public var theta: Float = PI.toFloat(),
|
||||||
|
) : SolidBase(), GeometrySolid {
|
||||||
|
|
||||||
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>): Unit = geometryBuilder.run {
|
||||||
|
require(outerRadius > 0) { "Outer radius must be positive" }
|
||||||
|
require(innerRadius >= 0) { "inner radius must be non-negative" }
|
||||||
|
|
||||||
|
fun point3DfromSphCoord(r: Float, theta: Float, phi: Float): Point3D {
|
||||||
|
// This transformation matches three.js sphere implementation
|
||||||
|
val y = r * cos(theta)
|
||||||
|
val z = r * sin(theta) * sin(phi)
|
||||||
|
val x = -r * sin(theta) * cos(phi)
|
||||||
|
return Point3D(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
val segments = detail ?: 8
|
||||||
|
require(segments >= 4) { "The detail for sphere must be >= 4" }
|
||||||
|
val phiStep = phi / segments
|
||||||
|
val thetaStep = theta / segments
|
||||||
|
for (i in 0 until segments) { // theta iteration
|
||||||
|
val theta1 = thetaStart + i * thetaStep
|
||||||
|
val theta2 = theta1 + thetaStep
|
||||||
|
for (j in 0 until segments) { // phi iteration
|
||||||
|
val phi1 = phiStart + j * phiStep
|
||||||
|
val phi2 = phi1 + phiStep
|
||||||
|
//outer points
|
||||||
|
val outerPoint1 = point3DfromSphCoord(outerRadius, theta1, phi1)
|
||||||
|
val outerPoint2 = point3DfromSphCoord(outerRadius, theta1, phi2)
|
||||||
|
val outerPoint3 = point3DfromSphCoord(outerRadius, theta2, phi2)
|
||||||
|
val outerPoint4 = point3DfromSphCoord(outerRadius, theta2, phi1)
|
||||||
|
// 1-2-3-4 gives the same face but with opposite orientation
|
||||||
|
face4(outerPoint1, outerPoint4, outerPoint3, outerPoint2)
|
||||||
|
if (innerRadius > 0) {
|
||||||
|
val innerPoint1 = point3DfromSphCoord(innerRadius, theta1, phi1)
|
||||||
|
val innerPoint2 = point3DfromSphCoord(innerRadius, theta1, phi2)
|
||||||
|
val innerPoint3 = point3DfromSphCoord(innerRadius, theta2, phi2)
|
||||||
|
val innerPoint4 = point3DfromSphCoord(innerRadius, theta2, phi1)
|
||||||
|
face4(innerPoint1, innerPoint2, innerPoint3, innerPoint4)
|
||||||
|
//the cup
|
||||||
|
if (i == segments - 1 && theta != PI.toFloat() && innerRadius != outerRadius) {
|
||||||
|
face4(outerPoint4, innerPoint4, innerPoint3, outerPoint3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisionBuilder
|
||||||
|
public inline fun VisionContainerBuilder<Solid>.sphereLayer(
|
||||||
|
outerRadius: Number,
|
||||||
|
innerRadius: Number,
|
||||||
|
name: String? = null,
|
||||||
|
action: SphereLayer.() -> Unit = {},
|
||||||
|
): SphereLayer = SphereLayer(
|
||||||
|
outerRadius.toFloat(),
|
||||||
|
innerRadius.toFloat(),
|
||||||
|
).apply(action).also { set(name, it) }
|
Loading…
Reference in New Issue
Block a user