SphereLayer

This commit is contained in:
Alexander Nozik 2021-03-04 09:47:41 +03:00
parent 545753b14b
commit 3f6e39b18d
21 changed files with 1207 additions and 41 deletions

View File

@ -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

View File

@ -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{

View File

@ -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>

View File

@ -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") {}

View File

@ -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>

View 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)
}

File diff suppressed because it is too large Load Diff

View File

@ -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") {

View File

@ -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>

View File

@ -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"))
}

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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) }

View File

@ -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) }