SphereLayer
This commit is contained in:
parent
545753b14b
commit
3f6e39b18d
@ -5,6 +5,7 @@
|
||||
- Server module
|
||||
- Change collector
|
||||
- Customizable accessors for colors
|
||||
- SphereLayer solid
|
||||
|
||||
### Changed
|
||||
- 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
|
||||
- \[Format breaking change!\] Stylesheets are moved into properties under `@stylesheet` key
|
||||
- VisionGroup builder accepts `null` as name for statics instead of `""`
|
||||
- gdml sphere is rendered as a SphereLayer instead of Sphere (#35)
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
@ -2,6 +2,7 @@ package hep.dataforge.vision.gdml.demo
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.vision.Application
|
||||
import hep.dataforge.vision.bootstrap.useBootstrap
|
||||
import hep.dataforge.vision.gdml.GdmlShowcase
|
||||
import hep.dataforge.vision.gdml.toVision
|
||||
import hep.dataforge.vision.solid.three.ThreePlugin
|
||||
@ -14,6 +15,8 @@ import react.dom.render
|
||||
private class GDMLDemoApp : Application {
|
||||
|
||||
override fun start(state: Map<String, Any>) {
|
||||
useBootstrap()
|
||||
|
||||
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
|
||||
|
||||
val context = Global.context("demo") .apply{
|
||||
|
@ -4,15 +4,11 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<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>
|
||||
<link rel="stylesheet" href="css/custom-bootstrap.css">
|
||||
<link rel="stylesheet" href="css/fileDrop.css">
|
||||
</head>
|
||||
<body class="application">
|
||||
<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>
|
||||
</html>
|
@ -2,6 +2,7 @@ package ru.mipt.npm.muon.monitor
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.vision.Application
|
||||
import hep.dataforge.vision.bootstrap.useBootstrap
|
||||
import hep.dataforge.vision.startApplication
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.features.json.JsonFeature
|
||||
@ -21,6 +22,8 @@ private class MMDemoApp : Application {
|
||||
}
|
||||
|
||||
override fun start(state: Map<String, Any>) {
|
||||
useBootstrap()
|
||||
|
||||
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
|
||||
|
||||
val context = Global.context("demo") {}
|
||||
|
@ -4,14 +4,10 @@
|
||||
<meta charset="utf-8">
|
||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
|
||||
<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>
|
||||
<link rel="stylesheet" href="css/custom-bootstrap.css">
|
||||
</head>
|
||||
<body class="application">
|
||||
<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>
|
||||
</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
|
||||
color("blue")
|
||||
}
|
||||
sphereLayer(50,40){
|
||||
theta = (PI/2).toFloat()
|
||||
rotationX = - PI * 3 / 4
|
||||
z = 110
|
||||
color(Colors.pink)
|
||||
}
|
||||
}
|
||||
|
||||
demo("dynamic", "Dynamic properties") {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<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>
|
||||
<body class="application">
|
||||
<div class="container" id="demo"></div>
|
||||
|
@ -8,4 +8,7 @@ dependencies {
|
||||
api(project(":visionforge-solid"))
|
||||
api(project(":ui:react"))
|
||||
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
|
||||
|
||||
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) {
|
||||
// div("card w-100") {
|
||||
// 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.setProperty
|
||||
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.useStyle
|
||||
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
|
||||
|
||||
public class GdmlTransformerSettings {
|
||||
public val random: Random = Random(222)
|
||||
|
||||
public enum class Action {
|
||||
ADD,
|
||||
REJECT,
|
||||
@ -38,11 +40,14 @@ public class GdmlTransformerSettings {
|
||||
|
||||
public var solidAction: (GdmlSolid) -> 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 val materialCache = HashMap<GdmlMaterial, Meta>()
|
||||
private val random = Random(222)
|
||||
|
||||
/**
|
||||
* A special group for local templates
|
||||
@ -105,7 +110,8 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
||||
val styleName = "materials.${material.name}"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -195,7 +201,9 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
||||
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
|
||||
thetaStart = solid.starttheta * aScale
|
||||
}
|
||||
@ -255,7 +263,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
||||
solid: GdmlSolid,
|
||||
name: String?,
|
||||
): 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)) {
|
||||
GdmlTransformerSettings.Action.ADD -> {
|
||||
addSolid(root, solid, name)
|
||||
|
@ -5,8 +5,8 @@ import hep.dataforge.vision.visitor.countDistinct
|
||||
import hep.dataforge.vision.visitor.flowStatistics
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import space.kscience.gdml.Gdml
|
||||
import nl.adaptivity.xmlutil.StAXReader
|
||||
import space.kscience.gdml.Gdml
|
||||
import java.io.File
|
||||
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()
|
||||
|
||||
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()
|
||||
|
||||
|
||||
|
@ -54,12 +54,8 @@ public class Sphere(
|
||||
@VisionBuilder
|
||||
public inline fun VisionContainerBuilder<Solid>.sphere(
|
||||
radius: Number,
|
||||
phi: Number = 2 * PI,
|
||||
theta: Number = PI,
|
||||
name: String? = null,
|
||||
action: Sphere.() -> Unit = {},
|
||||
): Sphere = Sphere(
|
||||
radius.toFloat(),
|
||||
phi = phi.toFloat(),
|
||||
theta = theta.toFloat()
|
||||
).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