forked from kscience/visionforge
Finalizing GDML
This commit is contained in:
parent
effa19a95e
commit
687393c243
@ -39,6 +39,9 @@ class DisplayObjectDelegateWrapper<T>(
|
|||||||
val write: Config.(name: Name, value: T) -> Unit = { name, value -> set(name, value) },
|
val write: Config.(name: Name, value: T) -> Unit = { name, value -> set(name, value) },
|
||||||
val read: (MetaItem<*>?) -> T?
|
val read: (MetaItem<*>?) -> T?
|
||||||
) : ReadWriteProperty<VisualObject, T> {
|
) : ReadWriteProperty<VisualObject, T> {
|
||||||
|
|
||||||
|
//private var cachedName: Name? = null
|
||||||
|
|
||||||
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
||||||
val name = key ?: property.name.toName()
|
val name = key ?: property.name.toName()
|
||||||
return if (inherited) {
|
return if (inherited) {
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package hep.dataforge.vis.hmr
|
||||||
|
|
||||||
|
import kotlin.browser.document
|
||||||
|
import kotlin.dom.hasClass
|
||||||
|
|
||||||
|
external val module: Module
|
||||||
|
|
||||||
|
external interface Module {
|
||||||
|
val hot: Hot?
|
||||||
|
}
|
||||||
|
|
||||||
|
external interface Hot {
|
||||||
|
val data: dynamic
|
||||||
|
|
||||||
|
fun accept()
|
||||||
|
fun accept(dependency: String, callback: () -> Unit)
|
||||||
|
fun accept(dependencies: Array<String>, callback: (updated: Array<String>) -> Unit)
|
||||||
|
|
||||||
|
fun dispose(callback: (data: dynamic) -> Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
external fun require(name: String): dynamic
|
||||||
|
|
||||||
|
abstract class ApplicationBase {
|
||||||
|
open val stateKeys: List<String> get() = emptyList()
|
||||||
|
|
||||||
|
abstract fun start(state: Map<String, Any>)
|
||||||
|
open fun dispose(): Map<String, Any> = emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startApplication(builder: () -> ApplicationBase) {
|
||||||
|
fun start(state: dynamic): ApplicationBase? {
|
||||||
|
return if (document.body?.hasClass("testApp") == true) {
|
||||||
|
val application = builder()
|
||||||
|
|
||||||
|
@Suppress("UnsafeCastFromDynamic")
|
||||||
|
application.start(state?.appState ?: emptyMap())
|
||||||
|
|
||||||
|
application
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var application: ApplicationBase? = null
|
||||||
|
|
||||||
|
val state: dynamic = module.hot?.let { hot ->
|
||||||
|
hot.accept()
|
||||||
|
|
||||||
|
hot.dispose { data ->
|
||||||
|
data.appState = application?.dispose()
|
||||||
|
application = null
|
||||||
|
}
|
||||||
|
|
||||||
|
hot.data
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.body != null) {
|
||||||
|
application = start(state)
|
||||||
|
} else {
|
||||||
|
application = null
|
||||||
|
document.addEventListener("DOMContentLoaded", { application = start(state) })
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
<title>Three js demo for particle physics</title>
|
<title>Three js demo for particle physics</title>
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
<script type="text/javascript" src="main.bundle.js"></script>
|
<script type="text/javascript" src="dataforge-vis-spatial-gdml-0.1.0-dev.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="testApp">
|
<body class="testApp">
|
||||||
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
|
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
|
||||||
|
@ -7,7 +7,12 @@ kotlin {
|
|||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-vis-spatial"))
|
api(project(":dataforge-vis-spatial"))
|
||||||
api("scientifik:gdml:0.1.2")
|
api("scientifik:gdml:0.1.3")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jsMain by getting{
|
||||||
|
dependencies{
|
||||||
|
api(project(":dataforge-vis-spatial-js"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObje
|
|||||||
solid.resolveFirstPosition(root)?.let { applyPosition(it) }
|
solid.resolveFirstPosition(root)?.let { applyPosition(it) }
|
||||||
solid.resolveFirstRotation(root)?.let { applyRotation(it) }
|
solid.resolveFirstRotation(root)?.let { applyRotation(it) }
|
||||||
}
|
}
|
||||||
addSolid(root, second) {}
|
addSolid(root, second)
|
||||||
solid.resolvePosition(root)?.let { applyPosition(it) }
|
solid.resolvePosition(root)?.let { applyPosition(it) }
|
||||||
solid.resolveRotation(root)?.let { applyRotation(it) }
|
solid.resolveRotation(root)?.let { applyRotation(it) }
|
||||||
}
|
}
|
||||||
@ -96,22 +96,24 @@ private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObje
|
|||||||
|
|
||||||
private fun VisualGroup.addVolume(
|
private fun VisualGroup.addVolume(
|
||||||
root: GDML,
|
root: GDML,
|
||||||
gdmlVolume: GDMLVolume,
|
group: GDMLGroup,
|
||||||
resolveColor: GDMLMaterial.() -> Meta
|
resolveColor: GDMLMaterial.() -> Meta
|
||||||
): VisualGroup {
|
): VisualGroup {
|
||||||
val solid =
|
if (group is GDMLVolume) {
|
||||||
gdmlVolume.solidref.resolve(root)
|
val solid = group.solidref.resolve(root)
|
||||||
?: error("Solid with tag ${gdmlVolume.solidref.ref} for volume ${gdmlVolume.name} not defined")
|
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
|
||||||
val material =
|
val material = group.materialref.resolve(root)
|
||||||
gdmlVolume.materialref.resolve(root)
|
?: error("Material with tag ${group.materialref.ref} for volume ${group.name} not defined")
|
||||||
?: error("Material with tag ${gdmlVolume.materialref.ref} for volume ${gdmlVolume.name} not defined")
|
|
||||||
|
|
||||||
addSolid(root, solid) {
|
addSolid(root, solid) {
|
||||||
color(material.resolveColor())
|
color(material.resolveColor())
|
||||||
|
}
|
||||||
|
//TODO render placements
|
||||||
}
|
}
|
||||||
|
|
||||||
gdmlVolume.physVolumes.forEach {
|
group.physVolumes.forEach {
|
||||||
val volume = it.volumeref.resolve(root) ?: error("Volume with ref ${it.volumeref.ref} could not be resolved")
|
val volume: GDMLGroup =
|
||||||
|
it.volumeref.resolve(root) ?: error("Volume with ref ${it.volumeref.ref} could not be resolved")
|
||||||
addVolume(root, volume, resolveColor).apply {
|
addVolume(root, volume, resolveColor).apply {
|
||||||
it.resolvePosition(root)?.let { pos -> applyPosition(pos) }
|
it.resolvePosition(root)?.let { pos -> applyPosition(pos) }
|
||||||
it.resolveRotation(root)?.let { rot -> applyRotation(rot) }
|
it.resolveRotation(root)?.let { rot -> applyRotation(rot) }
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
package hep.dataforge.vis.spatial.gdml.demo
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.vis.hmr.ApplicationBase
|
||||||
|
import hep.dataforge.vis.hmr.startApplication
|
||||||
|
import hep.dataforge.vis.spatial.gdml.toVisual
|
||||||
|
import hep.dataforge.vis.spatial.three.ThreePlugin
|
||||||
|
import hep.dataforge.vis.spatial.three.output
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.w3c.dom.HTMLDivElement
|
||||||
|
import org.w3c.dom.events.Event
|
||||||
|
import org.w3c.files.FileList
|
||||||
|
import org.w3c.files.FileReader
|
||||||
|
import org.w3c.files.get
|
||||||
|
import scientifik.gdml.GDML
|
||||||
|
import kotlin.browser.document
|
||||||
|
import kotlin.dom.clear
|
||||||
|
|
||||||
|
class GDMLDemoApp : ApplicationBase() {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle mouse drag according to https://www.html5rocks.com/en/tutorials/file/dndfiles/
|
||||||
|
*/
|
||||||
|
private fun handleDragOver(event: Event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
event.preventDefault()
|
||||||
|
event.asDynamic().dataTransfer.dropEffect = "copy"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data from text file
|
||||||
|
*/
|
||||||
|
private fun loadData(event: Event, block: suspend (String) -> Unit) {
|
||||||
|
event.stopPropagation()
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
|
||||||
|
val file = (event.asDynamic().dataTransfer.files as FileList)[0]
|
||||||
|
?: throw RuntimeException("Failed to load file")
|
||||||
|
|
||||||
|
FileReader().apply {
|
||||||
|
onload = {
|
||||||
|
val string = result as String
|
||||||
|
GlobalScope.launch {
|
||||||
|
block(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readAsText(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun start(state: Map<String, Any>) {
|
||||||
|
|
||||||
|
val context = Global.context("demo") {}
|
||||||
|
val three = context.plugins.load(ThreePlugin)
|
||||||
|
val canvas = document.getElementById("canvas") ?: error("Element with id canvas not found on page")
|
||||||
|
canvas.clear()
|
||||||
|
val output = three.output(canvas)
|
||||||
|
//val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
||||||
|
|
||||||
|
|
||||||
|
val action: suspend (String) -> Unit = {
|
||||||
|
val gdml = GDML.format.parse(GDML.serializer(), it)
|
||||||
|
val visual = gdml.toVisual()
|
||||||
|
output.render(visual)
|
||||||
|
}
|
||||||
|
|
||||||
|
(document.getElementById("drop_zone") as? HTMLDivElement)?.apply {
|
||||||
|
addEventListener("dragover", { handleDragOver(it) }, false)
|
||||||
|
addEventListener("drop", { loadData(it, action) }, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
startApplication(::GDMLDemoApp)
|
||||||
|
}
|
33
dataforge-vis-spatial-gdml/src/jsMain/web/index.html
Normal file
33
dataforge-vis-spatial-gdml/src/jsMain/web/index.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<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="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
|
<script type="text/javascript" src="main.bundle.js"></script>
|
||||||
|
</head>
|
||||||
|
<body class="testApp">
|
||||||
|
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
|
||||||
|
title="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
|
||||||
|
Загрузить данные
|
||||||
|
<br/>
|
||||||
|
(перетащить файл сюда)
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
<h1>GDML demo</h1>
|
||||||
|
</div>
|
||||||
|
<div class="container" id="canvas"></div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
|
||||||
|
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
|
||||||
|
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
|
||||||
|
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,28 @@
|
|||||||
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
|
import nl.adaptivity.xmlutil.StAXReader
|
||||||
|
import org.junit.Test
|
||||||
|
import scientifik.gdml.GDML
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
class BMNTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testRead() {
|
||||||
|
|
||||||
|
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
||||||
|
val file = File("D:\\Work\\Projects\\gdml.kt\\src\\commonTest\\resources\\gdml\\geofile_full.xml")
|
||||||
|
val stream = if(file.exists()){
|
||||||
|
file.inputStream()
|
||||||
|
} else {
|
||||||
|
url.openStream()
|
||||||
|
}
|
||||||
|
|
||||||
|
val xmlReader = StAXReader(stream, "UTF-8")
|
||||||
|
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||||
|
repeat(5) {
|
||||||
|
xml.toVisual()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,69 +1,21 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("scientifik.js")
|
id("scientifik.js")
|
||||||
id("kotlin-dce-js")
|
//id("kotlin-dce-js")
|
||||||
}
|
}
|
||||||
|
|
||||||
//val kotlinVersion: String by rootProject.extra
|
//val kotlinVersion: String by rootProject.extra
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-vis-spatial"))
|
api(project(":dataforge-vis-spatial"))
|
||||||
api(project(":dataforge-vis-spatial-gdml"))
|
api("info.laht.threekt:threejs-wrapper:0.106-npm-3")
|
||||||
api("info.laht.threekt:threejs-wrapper:0.106-npm-2")
|
|
||||||
testCompile(kotlin("test-js"))
|
testCompile(kotlin("test-js"))
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin{
|
kotlin{
|
||||||
sourceSets["main"].dependencies{
|
sourceSets["main"].dependencies{
|
||||||
api(npm("three","0.106.2"))
|
implementation(npm("three","0.106.2"))
|
||||||
implementation(npm("@hi-level/three-csg"))
|
implementation(npm("@hi-level/three-csg"))
|
||||||
implementation(npm("style-loader"))
|
implementation(npm("style-loader"))
|
||||||
implementation(npm("element-resize-event"))
|
implementation(npm("element-resize-event"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
//configure<KotlinFrontendExtension> {
|
|
||||||
// downloadNodeJsVersion = "latest"
|
|
||||||
//
|
|
||||||
// configure<NpmExtension> {
|
|
||||||
// dependency("three","0.106.2")
|
|
||||||
// dependency("@hi-level/three-csg")
|
|
||||||
// dependency("style-loader")
|
|
||||||
// dependency("element-resize-event")
|
|
||||||
// devDependency("karma")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// sourceMaps = true
|
|
||||||
//
|
|
||||||
// bundle<WebPackExtension>("webpack") {
|
|
||||||
// this as WebPackExtension
|
|
||||||
// bundleName = "main"
|
|
||||||
// contentPath = file("src/main/web")
|
|
||||||
// sourceMapEnabled = true
|
|
||||||
// //mode = "production"
|
|
||||||
// mode = "development"
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//tasks {
|
|
||||||
// "compileKotlin2Js"(Kotlin2JsCompile::class) {
|
|
||||||
// kotlinOptions {
|
|
||||||
// metaInfo = true
|
|
||||||
// outputFile = "${project.buildDir.path}/js/${project.name}.js"
|
|
||||||
// sourceMap = true
|
|
||||||
// moduleKind = "commonjs"
|
|
||||||
// main = "call"
|
|
||||||
// kotlinOptions.sourceMapEmbedSources = "always"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// "compileTestKotlin2Js"(Kotlin2JsCompile::class) {
|
|
||||||
// kotlinOptions {
|
|
||||||
// metaInfo = true
|
|
||||||
// outputFile = "${project.buildDir.path}/js/${project.name}-test.js"
|
|
||||||
// sourceMap = true
|
|
||||||
// moduleKind = "commonjs"
|
|
||||||
// kotlinOptions.sourceMapEmbedSources = "always"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,19 +0,0 @@
|
|||||||
package hep.dataforge.vis.spatial.demo
|
|
||||||
|
|
||||||
external val module: Module
|
|
||||||
|
|
||||||
external interface Module {
|
|
||||||
val hot: Hot?
|
|
||||||
}
|
|
||||||
|
|
||||||
external interface Hot {
|
|
||||||
val data: dynamic
|
|
||||||
|
|
||||||
fun accept()
|
|
||||||
fun accept(dependency: String, callback: () -> Unit)
|
|
||||||
fun accept(dependencies: Array<String>, callback: (updated: Array<String>) -> Unit)
|
|
||||||
|
|
||||||
fun dispose(callback: (data: dynamic) -> Unit)
|
|
||||||
}
|
|
||||||
|
|
||||||
external fun require(name: String): dynamic
|
|
@ -4,6 +4,8 @@ import hep.dataforge.context.ContextBuilder
|
|||||||
import hep.dataforge.meta.number
|
import hep.dataforge.meta.number
|
||||||
import hep.dataforge.vis.common.Colors
|
import hep.dataforge.vis.common.Colors
|
||||||
import hep.dataforge.vis.common.color
|
import hep.dataforge.vis.common.color
|
||||||
|
import hep.dataforge.vis.hmr.ApplicationBase
|
||||||
|
import hep.dataforge.vis.hmr.startApplication
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -136,3 +138,7 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
|
|
||||||
override fun dispose() = emptyMap<String, Any>()//mapOf("lines" to presenter.dispose())
|
override fun dispose() = emptyMap<String, Any>()//mapOf("lines" to presenter.dispose())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
startApplication(::ThreeDemoApp)
|
||||||
|
}
|
@ -50,7 +50,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
|
|||||||
|
|
||||||
return outputs.getOrPut(name) {
|
return outputs.getOrPut(name) {
|
||||||
if (type != VisualObject::class) error("Supports only DisplayObject")
|
if (type != VisualObject::class) error("Supports only DisplayObject")
|
||||||
val output = three.output(meta) {
|
val output = three.output(meta = meta) {
|
||||||
"axis" to {
|
"axis" to {
|
||||||
"size" to 500
|
"size" to 500
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
package hep.dataforge.vis.spatial.demo
|
|
||||||
|
|
||||||
import kotlin.browser.document
|
|
||||||
import kotlin.dom.hasClass
|
|
||||||
|
|
||||||
|
|
||||||
abstract class ApplicationBase {
|
|
||||||
abstract val stateKeys: List<String>
|
|
||||||
|
|
||||||
abstract fun start(state: Map<String, Any>)
|
|
||||||
abstract fun dispose(): Map<String, Any>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
var application: ApplicationBase? = null
|
|
||||||
|
|
||||||
val state: dynamic = module.hot?.let { hot ->
|
|
||||||
hot.accept()
|
|
||||||
|
|
||||||
hot.dispose { data ->
|
|
||||||
data.appState = application?.dispose()
|
|
||||||
application = null
|
|
||||||
}
|
|
||||||
|
|
||||||
hot.data
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.body != null) {
|
|
||||||
application = start(state)
|
|
||||||
} else {
|
|
||||||
application = null
|
|
||||||
document.addEventListener("DOMContentLoaded", { application = start(state) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun start(state: dynamic): ApplicationBase? {
|
|
||||||
return if (document.body?.hasClass("testApp") == true) {
|
|
||||||
val application = ThreeDemoApp()
|
|
||||||
|
|
||||||
@Suppress("UnsafeCastFromDynamic")
|
|
||||||
application.start(state?.appState ?: emptyMap<String, Any>())
|
|
||||||
|
|
||||||
application
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,32 @@
|
|||||||
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
|
import hep.dataforge.vis.spatial.Cylinder
|
||||||
|
import hep.dataforge.vis.spatial.detail
|
||||||
|
import info.laht.threekt.core.BufferGeometry
|
||||||
|
import info.laht.threekt.geometries.CylinderBufferGeometry
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
object ThreeCylinderFactory : MeshThreeFactory<Cylinder>(Cylinder::class) {
|
||||||
|
override fun buildGeometry(obj: Cylinder): BufferGeometry {
|
||||||
|
return obj.detail?.let {
|
||||||
|
val segments = it.toDouble().pow(0.5).toInt()
|
||||||
|
CylinderBufferGeometry(
|
||||||
|
radiusTop = obj.upperRadius!!,
|
||||||
|
radiusBottom = obj.radius!!,
|
||||||
|
height = obj.height!!,
|
||||||
|
radialSegments = segments,
|
||||||
|
heightSegments = segments,
|
||||||
|
openEnded = false,
|
||||||
|
thetaStart = obj.startAngle,
|
||||||
|
thetaLength = obj.angle
|
||||||
|
)
|
||||||
|
} ?: CylinderBufferGeometry(
|
||||||
|
radiusTop = obj.upperRadius!!,
|
||||||
|
radiusBottom = obj.radius!!,
|
||||||
|
height = obj.height!!,
|
||||||
|
openEnded = false,
|
||||||
|
thetaStart = obj.startAngle,
|
||||||
|
thetaLength = obj.angle
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ import hep.dataforge.meta.*
|
|||||||
import hep.dataforge.output.Output
|
import hep.dataforge.output.Output
|
||||||
import hep.dataforge.vis.common.Colors
|
import hep.dataforge.vis.common.Colors
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.spatial.demo.require
|
import hep.dataforge.vis.hmr.require
|
||||||
import info.laht.threekt.WebGLRenderer
|
import info.laht.threekt.WebGLRenderer
|
||||||
import info.laht.threekt.helpers.AxesHelper
|
import info.laht.threekt.helpers.AxesHelper
|
||||||
import info.laht.threekt.lights.AmbientLight
|
import info.laht.threekt.lights.AmbientLight
|
||||||
@ -39,7 +39,7 @@ class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output<V
|
|||||||
setSize(width, height)
|
setSize(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
three.addControls(camera,renderer.domElement, meta["controls"].node?:EmptyMeta)
|
three.addControls(camera, renderer.domElement, meta["controls"].node ?: EmptyMeta)
|
||||||
|
|
||||||
fun animate() {
|
fun animate() {
|
||||||
window.requestAnimationFrame {
|
window.requestAnimationFrame {
|
||||||
@ -63,5 +63,9 @@ class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output<V
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ThreePlugin.output(meta: Meta = EmptyMeta, override: MetaBuilder.() -> Unit = {}) =
|
fun ThreePlugin.output(element: Element? = null, meta: Meta = EmptyMeta, override: MetaBuilder.() -> Unit = {}) =
|
||||||
ThreeOutput(this, buildMeta(meta, override))
|
ThreeOutput(this, buildMeta(meta, override)).apply {
|
||||||
|
if(element!=null){
|
||||||
|
attach(element)
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
objectFactories[Box::class] = ThreeBoxFactory
|
objectFactories[Box::class] = ThreeBoxFactory
|
||||||
objectFactories[Convex::class] = ThreeConvexFactory
|
objectFactories[Convex::class] = ThreeConvexFactory
|
||||||
objectFactories[Sphere::class] = ThreeSphereFactory
|
objectFactories[Sphere::class] = ThreeSphereFactory
|
||||||
|
objectFactories[Cylinder::class] = ThreeCylinderFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findObjectFactory(type: KClass<out VisualObject>): ThreeFactory<*>? {
|
private fun findObjectFactory(type: KClass<out VisualObject>): ThreeFactory<*>? {
|
||||||
|
@ -25,7 +25,9 @@ fun VisualGroup.composite(type: CompositeType, builder: VisualGroup.() -> Unit):
|
|||||||
val group = VisualGroup().apply(builder)
|
val group = VisualGroup().apply(builder)
|
||||||
val children = group.toList()
|
val children = group.toList()
|
||||||
if (children.size != 2) error("Composite requires exactly two children")
|
if (children.size != 2) error("Composite requires exactly two children")
|
||||||
return Composite(this, children[0], children[1], type, group.properties.seal()).also { add(it) }
|
return Composite(this, children[0], children[1], type, group.properties.seal()).also {
|
||||||
|
this.add(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.union(builder: VisualGroup.() -> Unit) =
|
fun VisualGroup.union(builder: VisualGroup.() -> Unit) =
|
||||||
|
@ -16,13 +16,13 @@ class Cylinder(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
|
|||||||
var upperRadius by number(default = radius)
|
var upperRadius by number(default = radius)
|
||||||
var height by number()
|
var height by number()
|
||||||
var startAngle by number(0.0)
|
var startAngle by number(0.0)
|
||||||
var angle by number(2* PI)
|
var angle by number(2 * PI)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.cylinder(r: Number, height: Number, meta: Meta = EmptyMeta, block: Cylinder.()->Unit = {}):Cylinder{
|
fun VisualGroup.cylinder(r: Number, height: Number, meta: Meta = EmptyMeta, block: Cylinder.() -> Unit = {}): Cylinder {
|
||||||
val cylinder = Cylinder(this,meta)
|
val cylinder = Cylinder(this, meta)
|
||||||
cylinder.radius = r
|
cylinder.radius = r
|
||||||
cylinder.height = height
|
cylinder.height = height
|
||||||
cylinder.apply(block)
|
cylinder.apply(block)
|
||||||
return cylinder
|
return cylinder.also { add(it) }
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.output.Output
|
import hep.dataforge.output.Output
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
@ -28,60 +29,71 @@ var VisualObject.visible
|
|||||||
|
|
||||||
// 3D Object position
|
// 3D Object position
|
||||||
|
|
||||||
|
private val xPos = "pos.x".toName()
|
||||||
/**
|
/**
|
||||||
* x position property relative to parent. Not inherited
|
* x position property relative to parent. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject.x
|
var VisualObject.x
|
||||||
get() = properties["pos.x"].number ?: 0.0
|
get() = properties[xPos].number ?: 0.0
|
||||||
set(value) {
|
set(value) {
|
||||||
properties["pos.x"] = value
|
properties[xPos] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val yPos = "pos.y".toName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* y position property. Not inherited
|
* y position property. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject.y
|
var VisualObject.y
|
||||||
get() = properties["pos.y"].number ?: 0.0
|
get() = properties[yPos].number ?: 0.0
|
||||||
set(value) {
|
set(value) {
|
||||||
properties["pos.y"] = value
|
properties[yPos] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val zPos = "pos.z".toName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* z position property. Not inherited
|
* z position property. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject.z
|
var VisualObject.z
|
||||||
get() = properties["pos.z"].number ?: 0.0
|
get() = properties[zPos].number ?: 0.0
|
||||||
set(value) {
|
set(value) {
|
||||||
properties["pos.z"] = value
|
properties[zPos] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3D Object rotation
|
// 3D Object rotation
|
||||||
|
|
||||||
|
private val xRotation = "rotation.x".toName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* x rotation relative to parent. Not inherited
|
* x rotation relative to parent. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject.rotationX
|
var VisualObject.rotationX
|
||||||
get() = properties["rotation.x"].number ?: 0.0
|
get() = properties[xRotation].number ?: 0.0
|
||||||
set(value) {
|
set(value) {
|
||||||
properties["rotation.x"] = value
|
properties[xRotation] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val yRotation = "rotation.y".toName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* y rotation relative to parent. Not inherited
|
* y rotation relative to parent. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject.rotationY
|
var VisualObject.rotationY
|
||||||
get() = properties["rotation.y"].number ?: 0.0
|
get() = properties[yRotation].number ?: 0.0
|
||||||
set(value) {
|
set(value) {
|
||||||
properties["rotation.y"] = value
|
properties[yRotation] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val zRotation = "rotation.z".toName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* z rotation relative to parent. Not inherited
|
* z rotation relative to parent. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject.rotationZ
|
var VisualObject.rotationZ
|
||||||
get() = properties["rotation.z"].number ?: 0.0
|
get() = properties[zRotation].number ?: 0.0
|
||||||
set(value) {
|
set(value) {
|
||||||
properties["rotation.z"] = value
|
properties[zRotation] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class RotationOrder {
|
enum class RotationOrder {
|
||||||
|
Loading…
Reference in New Issue
Block a user