diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8c73f7d9..4b57e1c0 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,15 +8,15 @@ on:
jobs:
build:
runs-on: ubuntu-latest
- timeout-minutes: 40
+ timeout-minutes: 30
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3.5.3
- name: Set up JDK 11
- uses: actions/setup-java@v2.5.0
+ uses: actions/setup-java@v3.12.0
with:
java-version: 11
distribution: liberica
- name: execute build
- uses: gradle/gradle-build-action@v2
+ uses: gradle/gradle-build-action@v2.7.1
with:
arguments: build
diff --git a/CHANGELOG.md b/CHANGELOG.md
index afc740a3..dbb44a80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
- MeshLine for thick lines
### Changed
+- Color accessor property is now `colorProperty`. Color uses `invoke` instead of `set`
- API update for server and pages
- Edges moved to solids module for easier construction
- Visions **must** be rooted in order to subscribe to updates.
@@ -20,6 +21,7 @@
### Removed
### Fixed
+- Jupyter integration for IDEA and Jupyter lab.
### Security
diff --git a/build.gradle.kts b/build.gradle.kts
index 30eea98f..68c3569b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -13,7 +13,7 @@ val fxVersion by extra("11")
allprojects {
group = "space.kscience"
- version = "0.3.0-dev-9"
+ version = "0.3.0-dev-13"
}
subprojects {
diff --git a/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt b/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt
index 8015aea6..ef72de52 100644
--- a/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt
+++ b/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt
@@ -4,12 +4,18 @@ import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.parseAsName
import space.kscience.dataforge.names.plus
+import space.kscience.dataforge.names.withIndex
+import space.kscience.kmath.complex.Quaternion
+import space.kscience.kmath.geometry.fromRotationMatrix
+import space.kscience.kmath.linear.VirtualMatrix
import space.kscience.visionforge.MutableVisionContainer
import space.kscience.visionforge.isEmpty
import space.kscience.visionforge.set
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
-import kotlin.math.*
+import kotlin.math.PI
+import kotlin.math.cos
+import kotlin.math.sin
private val volumesName = Name.EMPTY //"volumes".asName()
@@ -27,17 +33,15 @@ private data class RootToSolidContext(
val colorCache: MutableMap = mutableMapOf(),
)
-// converting to XYZ to Tait–Bryan angles according to https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+// apply rotation from a matrix
private fun Solid.rotate(rot: DoubleArray) {
- val xAngle = atan2(-rot[5], rot[8])
- val yAngle = atan2(rot[2], sqrt(1.0 - rot[2].pow(2)))
- val zAngle = atan2(-rot[1], rot[0])
- rotation = Point3D(xAngle, yAngle, zAngle)
+ val matrix = VirtualMatrix(3, 3) { i, j -> rot[i * 3 + j] }
+ quaternion = Quaternion.fromRotationMatrix(matrix)
}
private fun Solid.translate(trans: DoubleArray) {
val (x, y, z) = trans
- position = Point3D(x, y, z)
+ position = Float32Vector3D(x, y, z)
}
private fun Solid.useMatrix(matrix: DGeoMatrix?) {
@@ -72,7 +76,7 @@ private fun Solid.useMatrix(matrix: DGeoMatrix?) {
val fScale by matrix.meta.doubleArray()
translate(fTranslation)
rotate(fRotationMatrix)
- scale = Point3D(fScale[0], fScale[1], fScale[2])
+ scale = Float32Vector3D(fScale[0], fScale[1], fScale[2])
}
}
}
@@ -208,9 +212,9 @@ private fun SolidGroup.addShape(
require(fNz > 1) { "The polyhedron geometry requires at least two planes" }
val baseRadius = fRmax[0]
shape {
- (0..fNedges).forEach {
- val phi = deltaphi * fNedges * it + startphi
- (baseRadius * cos(phi) to baseRadius * sin(phi))
+ (0..
@@ -223,7 +227,7 @@ private fun SolidGroup.addShape(
"TGeoShapeAssembly" -> {
val fVolume by shape.dObject(::DGeoVolume)
fVolume?.let { volume ->
- addRootVolume(volume, context, block = block)
+ addRootVolume(volume, context, name = volume.fName.ifEmpty { null }, block = block)
}
}
@@ -248,14 +252,14 @@ private fun SolidGroup.addShape(
val fDz by shape.meta.double(0.0)
//TODO check proper node order
- val node1 = Point3D(-fBl1, -fH1, -fDz)
- val node2 = Point3D(fBl1, -fH1, -fDz)
- val node3 = Point3D(fTl1, fH1, -fDz)
- val node4 = Point3D(-fTl1, fH1, -fDz)
- val node5 = Point3D(-fBl2, -fH2, fDz)
- val node6 = Point3D(fBl2, -fH2, fDz)
- val node7 = Point3D(fTl2, fH2, fDz)
- val node8 = Point3D(-fTl2, fH2, fDz)
+ val node1 = Float32Vector3D(-fBl1, -fH1, -fDz)
+ val node2 = Float32Vector3D(fBl1, -fH1, -fDz)
+ val node3 = Float32Vector3D(fTl1, fH1, -fDz)
+ val node4 = Float32Vector3D(-fTl1, fH1, -fDz)
+ val node5 = Float32Vector3D(-fBl2, -fH2, fDz)
+ val node6 = Float32Vector3D(fBl2, -fH2, fDz)
+ val node7 = Float32Vector3D(fTl2, fH2, fDz)
+ val node8 = Float32Vector3D(-fTl2, fH2, fDz)
hexagon(node1, node2, node3, node4, node5, node6, node7, node8, name)
}
@@ -264,7 +268,7 @@ private fun SolidGroup.addShape(
val fScale by shape.dObject(::DGeoScale)
fShape?.let { scaledShape ->
solidGroup(name?.let { Name.parse(it) }) {
- scale = Point3D(fScale?.x ?: 1.0, fScale?.y ?: 1.0, fScale?.z ?: 1.0)
+ scale = Float32Vector3D(fScale?.x ?: 1.0, fScale?.y ?: 1.0, fScale?.z ?: 1.0)
addShape(scaledShape, context)
apply(block)
}
@@ -328,7 +332,7 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
group
}.apply {
volume.fMedium?.let { medium ->
- color.set(context.colorCache.getOrPut(medium.meta) { RootColors[11 + context.colorCache.size] })
+ color(context.colorCache.getOrPut(medium.meta) { RootColors[11 + context.colorCache.size] })
}
if (!context.ignoreRootColors) {
@@ -348,29 +352,29 @@ private fun SolidGroup.addRootVolume(
cache: Boolean = true,
block: Solid.() -> Unit = {},
) {
-
- val combinedName = if (volume.fName.isEmpty()) {
- name
- } else if (name == null) {
- volume.fName
- } else {
- "${name}_${volume.fName}"
+ val combinedName = name?.parseAsName()?.let {
+ // this fix is required to work around malformed root files with duplicated node names
+ if (get(it) != null) {
+ it.withIndex(volume.hashCode().toString(16))
+ } else {
+ it
+ }
}
if (!cache) {
- val group = buildVolume(volume, context)?.apply(block)
- setChild(combinedName?.let { Name.parse(it) }, group)
+ val group = buildVolume(volume, context)?.apply(block) ?: return
+ setChild(combinedName, group)
} else {
val templateName = volumesName + volume.name
- val existing = getPrototype(templateName)
+ val existing = context.prototypeHolder.getPrototype(templateName)
if (existing == null) {
context.prototypeHolder.prototypes {
- val group = buildVolume(volume, context)
+ val group = buildVolume(volume, context) ?: return@prototypes
setChild(templateName, group)
}
}
- ref(templateName, name).apply(block)
+ ref(templateName, combinedName).apply(block)
}
}
diff --git a/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/serialization/rootToSolid.kt b/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/serialization/rootToSolid.kt
index 50a4002a..eb39b8e7 100644
--- a/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/serialization/rootToSolid.kt
+++ b/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/serialization/rootToSolid.kt
@@ -25,12 +25,12 @@ private fun Solid.rotate(rot: DoubleArray) {
val xAngle = atan2(-rot[5], rot[8])
val yAngle = atan2(rot[2], sqrt(1.0 - rot[2].pow(2)))
val zAngle = atan2(-rot[1], rot[0])
- rotation = Point3D(xAngle, yAngle, zAngle)
+ rotation = Float32Vector3D(xAngle, yAngle, zAngle)
}
private fun Solid.translate(trans: DoubleArray) {
val (x, y, z) = trans
- position = Point3D(x, y, z)
+ position = Float32Vector3D(x, y, z)
}
private fun Solid.useMatrix(matrix: TGeoMatrix?) {
@@ -52,7 +52,7 @@ private fun Solid.useMatrix(matrix: TGeoMatrix?) {
translate(matrix.fTranslation)
rotate(matrix.fRotationMatrix)
val (xScale, yScale, zScale) = matrix.fScale
- scale = Point3D(xScale, yScale, zScale)
+ scale = Float32Vector3D(xScale, yScale, zScale)
}
}
}
diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt
index 4301966a..37c178f4 100644
--- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt
+++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt
@@ -23,7 +23,7 @@ import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
-import space.kscience.visionforge.solid.set
+import space.kscience.visionforge.solid.invoke
import styled.css
import styled.styledDiv
@@ -53,7 +53,7 @@ val GDMLApp = fc("GDMLApp") { props ->
console.info("Marking layers for file $name")
markLayers()
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
}
}
diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt
index cdca1957..7c6514bf 100644
--- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt
+++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt
@@ -12,7 +12,7 @@ import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
-import space.kscience.visionforge.solid.set
+import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication
import styled.injectGlobal
@@ -49,7 +49,7 @@ private class GDMLDemoApp : Application {
child(GDMLApp) {
val vision = GdmlShowCase.cubes().toVision().apply {
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
}
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
diff --git a/demo/js-playground/build.gradle.kts b/demo/js-playground/build.gradle.kts
index 86935c51..94835588 100644
--- a/demo/js-playground/build.gradle.kts
+++ b/demo/js-playground/build.gradle.kts
@@ -7,7 +7,8 @@ kscience{
}
kotlin{
- js(IR){
+ explicitApi = null
+ js{
useCommonJs()
browser {
binaries.executable()
diff --git a/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt b/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt
index cb6eb3e6..d77d8f52 100644
--- a/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt
+++ b/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt
@@ -76,7 +76,7 @@ private class JsPlaygroundApp : Application {
solids = playgroundContext.request(Solids)
solid {
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
repeat(100) {
sphere(5, name = "sphere[$it]") {
@@ -84,7 +84,7 @@ private class JsPlaygroundApp : Application {
y = random.nextDouble(-300.0, 300.0)
z = random.nextDouble(-300.0, 300.0)
material {
- color.set(random.nextInt())
+ color(random.nextInt())
}
detail = 16
}
diff --git a/demo/js-playground/src/main/kotlin/gravityDemo.kt b/demo/js-playground/src/main/kotlin/gravityDemo.kt
index c04baf98..a4bc9057 100644
--- a/demo/js-playground/src/main/kotlin/gravityDemo.kt
+++ b/demo/js-playground/src/main/kotlin/gravityDemo.kt
@@ -42,13 +42,13 @@ val GravityDemo = fc { props ->
solids = props.solids
solid {
pointLight(200, 200, 200, name = "light"){
- color.set(Colors.white)
+ color(Colors.white)
}
ambientLight()
sphere(5.0, "ball") {
detail = 16
- color.set("red")
+ color("red")
val h = 100.0
y = h
solids.context.launch {
diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts
index 154d4b0a..c8f26b2c 100644
--- a/demo/muon-monitor/build.gradle.kts
+++ b/demo/muon-monitor/build.gradle.kts
@@ -40,6 +40,8 @@ kscience {
}
}
+kotlin.explicitApi = null
+
application {
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
}
diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt
index b47c2b66..22a9d2e1 100644
--- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt
+++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt
@@ -1,9 +1,9 @@
package ru.mipt.npm.muon.monitor
import kotlinx.serialization.Serializable
-import space.kscience.visionforge.solid.Point3D
+import space.kscience.visionforge.solid.Float32Vector3D
-typealias Track = List
+typealias Track = List
/**
*
diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt
index 1b8eb566..f11c9e01 100644
--- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt
+++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt
@@ -16,7 +16,7 @@ class Model(val manager: VisionManager) {
private fun MutableVisionContainer.pixel(pixel: SC1) {
val group = solidGroup(pixel.name) {
- position = Point3D(pixel.center.x, pixel.center.y, pixel.center.z)
+ position = Float32Vector3D(pixel.center.x, pixel.center.y, pixel.center.z)
box(pixel.xSize, pixel.ySize, pixel.zSize)
label(pixel.name) {
z = -Monitor.PIXEL_Z_SIZE / 2 - 5
@@ -39,7 +39,7 @@ class Model(val manager: VisionManager) {
val root: SolidGroup = SolidGroup().apply {
setAsRoot(this@Model.manager)
material {
- color.set("darkgreen")
+ color("darkgreen")
}
rotationX = PI / 2
solidGroup("bottom") {
@@ -64,7 +64,7 @@ class Model(val manager: VisionManager) {
private fun highlight(pixel: String) {
println("highlight $pixel")
- map[pixel]?.color.set("blue")
+ map[pixel]?.color("blue")
}
fun reset() {
@@ -82,7 +82,7 @@ class Model(val manager: VisionManager) {
}
event.track?.let {
tracks.polyline(*it.toTypedArray(), name = "track[${event.id}]") {
- color.set("red")
+ color("red")
}
}
}
diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt
index 1a8c8aa9..48fe83d1 100644
--- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt
+++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt
@@ -2,21 +2,21 @@ package ru.mipt.npm.muon.monitor
import ru.mipt.npm.muon.monitor.Monitor.PIXEL_XY_SIZE
import ru.mipt.npm.muon.monitor.Monitor.PIXEL_Z_SIZE
-import space.kscience.visionforge.solid.Point3D
-import space.kscience.visionforge.solid.plus
+import space.kscience.visionforge.solid.Float32Euclidean3DSpace
+import space.kscience.visionforge.solid.Float32Vector3D
/**
* A single pixel
*/
class SC1(
val name: String,
- val center: Point3D,
+ val center: Float32Vector3D,
val xSize: Float = PIXEL_XY_SIZE, val ySize: Float = PIXEL_XY_SIZE, val zSize: Float = PIXEL_Z_SIZE,
)
class SC16(
val name: String,
- val center: Point3D,
+ val center: Float32Vector3D,
) {
/**
@@ -109,9 +109,9 @@ class SC16(
else -> throw Error()
}
- val offset = Point3D(-y, x, 0)//rotateDetector(Point3D(x, y, 0.0));
+ val offset = Float32Vector3D(-y, x, 0)//rotateDetector(Point3D(x, y, 0.0));
val pixelName = "${name}_${index}"
- SC1(pixelName, offset + center)
+ SC1(pixelName, with(Float32Euclidean3DSpace) { offset + center })
}
}
}
@@ -154,7 +154,7 @@ object Monitor {
val x = split[4].toDouble() - 500
val y = split[5].toDouble() - 500
val z = 180 - split[6].toDouble()
- SC16(detectorName, Point3D(x, y, z))
+ SC16(detectorName, Float32Vector3D(x, y, z))
} else {
null
}
diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt
index 4c9649c6..07dc7c7c 100644
--- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt
+++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt
@@ -26,7 +26,7 @@ import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.edges
-import space.kscience.visionforge.solid.set
+import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css
import styled.styledDiv
@@ -58,7 +58,7 @@ val MMApp = fc("Muon monitor") { props ->
props.model.root.apply {
edges()
ambientLight{
- color.set(Colors.white)
+ color(Colors.white)
}
}
}
diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/MMServer.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/MMServer.kt
index b9b8ce4c..d3d50c5b 100644
--- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/MMServer.kt
+++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/MMServer.kt
@@ -10,8 +10,7 @@ import io.ktor.server.application.install
import io.ktor.server.application.log
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
-import io.ktor.server.http.content.resources
-import io.ktor.server.http.content.static
+import io.ktor.server.http.content.staticResources
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.response.respond
import io.ktor.server.response.respondText
@@ -53,9 +52,7 @@ fun Application.module(context: Context = Global) {
status = HttpStatusCode.OK
)
}
- static("/") {
- resources()
- }
+ staticResources("/", null)
}
try {
Desktop.getDesktop().browse(URI("http://localhost:8080/index.html"))
diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt
index c2578783..d9492a74 100644
--- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt
+++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt
@@ -5,7 +5,7 @@ import org.apache.commons.math3.geometry.euclidean.threed.Plane
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D
import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z
import ru.mipt.npm.muon.monitor.Monitor.GEOMETRY_TOLERANCE
-import space.kscience.visionforge.solid.Point3D
+import space.kscience.visionforge.solid.Float32Vector3D
/**
* Created by darksnake on 11-May-16.
@@ -50,12 +50,12 @@ fun makeTrack(x: Double, y: Double, theta: Double, phi: Double): Line {
)
}
-fun Vector3D.toPoint() = Point3D(x, y, z)
+fun Vector3D.toKMathVector() = Float32Vector3D(x, y, z)
-fun Line.toPoints(): List {
+fun Line.toKMathVectors(): List {
val basePoint = basePlane.intersection(this)
val bottom = basePoint.subtract(2000.0, direction)
val top = basePoint.add(2000.0, direction)
- return listOf(bottom.toPoint(), top.toPoint())
+ return listOf(bottom.toKMathVector(), top.toKMathVector())
}
diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt
index d2ec7235..e55b74db 100644
--- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt
+++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt
@@ -43,7 +43,7 @@ fun readEffs(): Map {
fun buildEventByTrack(index: Int, track: Line, hitResolver: (Line) -> Collection = defaultHitResolver): Event {
- return Event(index, track.toPoints(), hitResolver(track).map { it.name })
+ return Event(index, track.toKMathVectors(), hitResolver(track).map { it.name })
}
val defaultHitResolver: (Line) -> Collection = { track: Line ->
diff --git a/demo/playground/build.gradle.kts b/demo/playground/build.gradle.kts
index ddc1d6a8..36bd6b7b 100644
--- a/demo/playground/build.gradle.kts
+++ b/demo/playground/build.gradle.kts
@@ -47,12 +47,11 @@ kotlin {
val commonMain by getting {
dependencies {
implementation(projects.visionforgeSolid)
- implementation(projects.visionforgeGdml)
implementation(projects.visionforgePlotly)
implementation(projects.visionforgeMarkdown)
implementation(projects.visionforgeTables)
implementation(projects.cernRootLoader)
- implementation(projects.jupyter)
+ api(projects.visionforgeJupyter.visionforgeJupyterCommon)
}
}
@@ -66,6 +65,8 @@ kotlin {
val jvmMain by getting {
dependencies {
+ implementation("io.ktor:ktor-server-cio:${spclibs.versions.ktor.get()}")
+ implementation(projects.visionforgeGdml)
implementation(projects.visionforgeServer)
implementation(spclibs.logback.classic)
implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6")
diff --git a/demo/playground/notebooks/common-demo.ipynb b/demo/playground/notebooks/common-demo.ipynb
new file mode 100644
index 00000000..78797545
--- /dev/null
+++ b/demo/playground/notebooks/common-demo.ipynb
@@ -0,0 +1,101 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "@file:Repository(\"*mavenLocal\")\n",
+ "@file:Repository(\"https://repo.kotlin.link\")\n",
+ "@file:Repository(\"https://maven.pkg.jetbrains.space/spc/p/sci/dev\")\n",
+ "@file:DependsOn(\"space.kscience:visionforge-jupyter-common-jvm:0.3.0-dev-12\")\n",
+ "//import space.kscience.visionforge.jupyter.JupyterCommonIntegration\n",
+ "//\n",
+ "//val integration = JupyterCommonIntegration()\n",
+ "//USE(integration.getDefinitions(notebook).first())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "vf.fragment {\n",
+ " h1 { +\"AAA\" }\n",
+ " vision {\n",
+ " solid {\n",
+ " ambientLight()\n",
+ " box(100, 100, 200)\n",
+ "\n",
+ " sphere(100) {\n",
+ " x = 300\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " vision {\n",
+ " plotly {\n",
+ " scatter {\n",
+ " x(1, 2, 3, 1)\n",
+ " y(1, 2, 3, 4)\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "jupyter": {
+ "outputs_hidden": false
+ },
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "Plotly.plot { \n",
+ " scatter{\n",
+ " x(1,2,3)\n",
+ " y(1,2,3)\n",
+ " }\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Kotlin",
+ "language": "kotlin",
+ "name": "kotlin"
+ },
+ "ktnbPluginMetadata": {
+ "isAddProjectLibrariesToClasspath": false
+ },
+ "language_info": {
+ "codemirror_mode": "text/x-kotlin",
+ "file_extension": ".kt",
+ "mimetype": "text/x-kotlin",
+ "name": "kotlin",
+ "nbconvert_exporter": "",
+ "pygments_lexer": "kotlin",
+ "version": "1.8.20"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/demo/playground/notebooks/dynamic-demo.ipynb b/demo/playground/notebooks/dynamic-demo.ipynb
index 41289185..ac70b4c2 100644
--- a/demo/playground/notebooks/dynamic-demo.ipynb
+++ b/demo/playground/notebooks/dynamic-demo.ipynb
@@ -2,15 +2,11 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {
"tags": [],
"pycharm": {
"is_executing": true
- },
- "ExecuteTime": {
- "end_time": "2023-05-29T15:22:37.933397300Z",
- "start_time": "2023-05-29T15:22:37.913872100Z"
}
},
"outputs": [],
@@ -18,57 +14,23 @@
},
{
"cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "ExecuteTime": {
- "end_time": "2023-05-29T15:22:50.486483300Z",
- "start_time": "2023-05-29T15:22:50.457485500Z"
- }
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Line_2.jupyter.kts (1:1 - 3) Unresolved reference: vf"
- ]
- }
- ],
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
"source": [
"vf.startServer()"
]
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
- },
- "ExecuteTime": {
- "end_time": "2023-05-29T15:22:51.410680600Z",
- "start_time": "2023-05-29T15:22:51.250779400Z"
}
},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Line_3.jupyter.kts (1:16 - 26) Unresolved reference: coroutines\n",
- "Line_3.jupyter.kts (4:1 - 7) Unresolved reference: Plotly\n",
- "Line_3.jupyter.kts (5:5 - 12) Unresolved reference: scatter\n",
- "Line_3.jupyter.kts (6:9 - 10) Unresolved reference: x\n",
- "Line_3.jupyter.kts (7:9 - 10) Unresolved reference: y\n",
- "Line_3.jupyter.kts (8:12 - 14) Unresolved reference: vf\n",
- "Line_3.jupyter.kts (9:13 - 15) Unresolved reference: vf\n",
- "Line_3.jupyter.kts (10:23 - 31) Unresolved reference: isActive\n",
- "Line_3.jupyter.kts (11:21 - 26) Unresolved reference: delay\n",
- "Line_3.jupyter.kts (12:21 - 22) Unresolved reference: y"
- ]
- }
- ],
+ "outputs": [],
"source": [
"import kotlinx.coroutines.*\n",
"import kotlin.random.Random\n",
diff --git a/demo/playground/src/jsMain/kotlin/playgroundMain.kt b/demo/playground/src/jsMain/kotlin/playgroundMain.kt
index 8e259d48..feff4de1 100644
--- a/demo/playground/src/jsMain/kotlin/playgroundMain.kt
+++ b/demo/playground/src/jsMain/kotlin/playgroundMain.kt
@@ -1,5 +1,5 @@
import space.kscience.dataforge.misc.DFExperimental
-import space.kscience.visionforge.jupyter.VFNotebookPlugin
+import space.kscience.visionforge.jupyter.VFNotebookClient
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
@@ -12,5 +12,5 @@ fun main() = runVisionClient {
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
plugin(TableVisionJsPlugin)
- plugin(VFNotebookPlugin)
+ plugin(VFNotebookClient)
}
\ No newline at end of file
diff --git a/demo/playground/src/jvmMain/kotlin/VisionForgePlayGroundForJupyter.kt b/demo/playground/src/jvmMain/kotlin/VisionForgePlayGroundForJupyter.kt
deleted file mode 100644
index 0b87e06d..00000000
--- a/demo/playground/src/jvmMain/kotlin/VisionForgePlayGroundForJupyter.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package space.kscience.visionforge.examples
-
-import org.jetbrains.kotlinx.jupyter.api.libraries.resources
-import space.kscience.dataforge.context.Context
-import space.kscience.dataforge.misc.DFExperimental
-import space.kscience.gdml.Gdml
-import space.kscience.plotly.Plot
-import space.kscience.visionforge.gdml.toVision
-import space.kscience.visionforge.jupyter.VFIntegrationBase
-import space.kscience.visionforge.plotly.PlotlyPlugin
-import space.kscience.visionforge.plotly.asVision
-import space.kscience.visionforge.solid.Solids
-import space.kscience.visionforge.visionManager
-
-@DFExperimental
-internal class VisionForgePlayGroundForJupyter : VFIntegrationBase(
- Context("VisionForge") {
- plugin(Solids)
- plugin(PlotlyPlugin)
- }.visionManager
-) {
-
- override fun Builder.afterLoaded() {
- resources {
- js("VisionForge") {
- classPath("js/visionforge-playground.js")
- }
- }
-
- import(
- "space.kscience.gdml.*",
- "space.kscience.plotly.*",
- "space.kscience.plotly.models.*",
- "space.kscience.visionforge.solid.*",
- )
-
-
- render { gdmlModel ->
- handler.produceHtml {
- vision { gdmlModel.toVision() }
- }
- }
-
- render { plot ->
- handler.produceHtml {
- vision { plot.asVision() }
- }
- }
- }
-
-}
diff --git a/demo/playground/src/jvmMain/kotlin/antenna.kt b/demo/playground/src/jvmMain/kotlin/antenna.kt
new file mode 100644
index 00000000..5ec997f7
--- /dev/null
+++ b/demo/playground/src/jvmMain/kotlin/antenna.kt
@@ -0,0 +1,102 @@
+package space.kscience.visionforge.examples
+
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+import space.kscience.dataforge.meta.configure
+import space.kscience.kmath.complex.Quaternion
+import space.kscience.kmath.complex.QuaternionField
+import space.kscience.kmath.complex.conjugate
+import space.kscience.kmath.geometry.*
+import space.kscience.visionforge.solid.*
+import kotlin.math.PI
+import kotlin.math.cos
+import kotlin.math.sin
+
+fun main() = serve {
+
+// val azimuth = 60.degrees
+// val inclination = 15.degrees
+
+// val direction = with(QuaternionField) {
+// Quaternion.fromRotation(-azimuth, Euclidean3DSpace.zAxis) *
+// Quaternion.fromRotation(Angle.piDiv2 - inclination, Euclidean3DSpace.yAxis)
+// }
+
+ //val direction2 = Quaternion.fromEuler(Angle.zero, Angle.piDiv2 - inclination, -azimuth, RotationOrder.ZYX)
+
+ val target = Quaternion.fromEuler((-45).degrees, 45.degrees, Angle.zero, RotationOrder.XYZ)
+
+
+ vision("canvas") {
+ requirePlugin(Solids)
+
+ solid(options = {
+ configure { "controls.enabled" put false }
+ }) {
+ rotationX = -PI / 2
+ rotationZ = PI
+ //axes(200)
+ ambientLight()
+ val platform = solidGroup("platform") {
+ cylinder(50, 5, name = "base")
+ solidGroup("frame") {
+ z = 60
+
+ solidGroup("antenna") {
+ axes(200)
+ tube(40, 10, 30)
+ sphereLayer(100, 95, theta = PI / 6) {
+ z = 100
+ rotationX = -PI / 2
+ }
+ cylinder(5, 30) {
+ z = 15
+ }
+
+ sphereLayer(101, 94, phi = PI / 32, theta = PI / 6) {
+ z = 100
+ rotationX = -PI / 2
+ color("red")
+ }
+
+ quaternion = target
+ }
+ }
+ }
+
+ val frame = platform["frame"] as SolidGroup
+
+ val antenna = frame["antenna"] as SolidGroup
+
+ val xPeriod = 5000 //ms
+ val yPeriod = 7000 //ms
+
+ val incRot = Quaternion.fromRotation(30.degrees, Euclidean3DSpace.zAxis)
+
+
+ val rotationJob = context.launch {
+ var time: Long = 0L
+ while (isActive) {
+ with(QuaternionField) {
+ delay(200)
+ platform.quaternion = Quaternion.fromRotation(
+ 15.degrees * sin(time.toDouble() * 2 * PI / xPeriod),
+ Euclidean3DSpace.xAxis
+ ) * Quaternion.fromRotation(
+ 15.degrees * cos(time * 2 * PI / yPeriod),
+ Euclidean3DSpace.yAxis
+ )
+
+ val qi = platform.quaternion * incRot
+
+ antenna.quaternion = qi.conjugate * incRot.conjugate * target
+
+ time += 200
+ //antenna.quaternion = Quaternion.fromRotation(5.degrees, Euclidean3DSpace.zAxis) * antenna.quaternion
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/demo/playground/src/jvmMain/kotlin/axes.kt b/demo/playground/src/jvmMain/kotlin/axes.kt
new file mode 100644
index 00000000..b8178887
--- /dev/null
+++ b/demo/playground/src/jvmMain/kotlin/axes.kt
@@ -0,0 +1,22 @@
+package space.kscience.visionforge.examples
+
+import space.kscience.kmath.geometry.Euclidean3DSpace
+import space.kscience.kmath.geometry.radians
+import space.kscience.visionforge.html.ResourceLocation
+import space.kscience.visionforge.solid.*
+import kotlin.math.PI
+
+fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
+ vision("canvas") {
+ requirePlugin(Solids)
+ solid {
+ axes(100, "root-axes")
+ solidGroup("group") {
+ z = 100
+ rotate((PI / 4).radians, Euclidean3DSpace.vector(1, 1, 1))
+ axes(100, "local-axes")
+ box(50, 50, 50, "box")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/demo/playground/src/jvmMain/kotlin/extruded.kt b/demo/playground/src/jvmMain/kotlin/extruded.kt
new file mode 100644
index 00000000..8a25549f
--- /dev/null
+++ b/demo/playground/src/jvmMain/kotlin/extruded.kt
@@ -0,0 +1,21 @@
+package space.kscience.visionforge.examples
+
+import space.kscience.visionforge.solid.ambientLight
+import space.kscience.visionforge.solid.extruded
+import space.kscience.visionforge.solid.polygon
+import space.kscience.visionforge.solid.solid
+
+fun main() = makeVisionFile {
+ vision("canvas") {
+ solid {
+ ambientLight()
+ extruded("extruded") {
+ shape{
+ polygon(8, 100)
+ layer(-30)
+ layer(30)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/demo/playground/src/jvmMain/kotlin/gdmlCurve.kt b/demo/playground/src/jvmMain/kotlin/gdmlCurve.kt
index c2af2a8f..4cac02b1 100644
--- a/demo/playground/src/jvmMain/kotlin/gdmlCurve.kt
+++ b/demo/playground/src/jvmMain/kotlin/gdmlCurve.kt
@@ -7,7 +7,7 @@ import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.color
-import space.kscience.visionforge.solid.set
+import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.visible
import java.nio.file.Path
@@ -229,7 +229,7 @@ fun main() = makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceL
visible = false
}
if(solid.name.startsWith("gas")){
- color.set("green")
+ color("green")
} else {
//make all solids semi-transparent
transparent()
diff --git a/demo/playground/src/jvmMain/kotlin/randomSpheres.kt b/demo/playground/src/jvmMain/kotlin/randomSpheres.kt
index 47201ff8..fd1b9865 100644
--- a/demo/playground/src/jvmMain/kotlin/randomSpheres.kt
+++ b/demo/playground/src/jvmMain/kotlin/randomSpheres.kt
@@ -19,7 +19,7 @@ fun main() = makeVisionFile(
vision {
solid {
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
repeat(100) {
sphere(5, name = "sphere[$it]") {
@@ -27,7 +27,7 @@ fun main() = makeVisionFile(
y = random.nextDouble(-300.0, 300.0)
z = random.nextDouble(-300.0, 300.0)
material {
- color.set(random.nextInt())
+ color(random.nextInt())
}
detail = 16
}
diff --git a/demo/playground/src/jvmMain/kotlin/rootParser.kt b/demo/playground/src/jvmMain/kotlin/rootParser.kt
index be70faf8..1faa8d0b 100644
--- a/demo/playground/src/jvmMain/kotlin/rootParser.kt
+++ b/demo/playground/src/jvmMain/kotlin/rootParser.kt
@@ -11,7 +11,7 @@ import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
-import space.kscience.visionforge.solid.set
+import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.solid
import java.util.zip.ZipInputStream
import kotlin.io.path.Path
@@ -26,7 +26,7 @@ private fun Meta.countTypes(): Sequence = sequence {
}
fun main() {
- val string = ZipInputStream(TGeoManager::class.java.getResourceAsStream("/root/BM@N_geometry.zip")!!).use {
+ val string = ZipInputStream(TGeoManager::class.java.getResourceAsStream("/root/geometry_run_7-2076.zip")!!).use {
it.nextEntry
it.readAllBytes().decodeToString()
}
@@ -44,9 +44,9 @@ fun main() {
requirePlugin(Solids)
solid {
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
- rootGeo(geo,"BM@N", maxLayer = 3, ignoreRootColors = true).also {
+ rootGeo(geo,"BM@N", ignoreRootColors = true).also {
Path("data/BM@N.vf.json").writeText(Solids.encodeToString(it))
}
}
diff --git a/demo/playground/src/jvmMain/kotlin/serverExtensions.kt b/demo/playground/src/jvmMain/kotlin/serverExtensions.kt
index 9eb87730..c20f27c7 100644
--- a/demo/playground/src/jvmMain/kotlin/serverExtensions.kt
+++ b/demo/playground/src/jvmMain/kotlin/serverExtensions.kt
@@ -1,11 +1,24 @@
package space.kscience.visionforge.examples
+import io.ktor.server.cio.CIO
+import io.ktor.server.engine.embeddedServer
+import io.ktor.server.http.content.staticResources
+import io.ktor.server.routing.routing
+import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global
import space.kscience.visionforge.html.*
+import space.kscience.visionforge.markup.MarkupPlugin
+import space.kscience.visionforge.plotly.PlotlyPlugin
+import space.kscience.visionforge.server.close
+import space.kscience.visionforge.server.openInBrowser
+import space.kscience.visionforge.server.visionPage
+import space.kscience.visionforge.solid.Solids
+import space.kscience.visionforge.tables.TableVisionPlugin
import space.kscience.visionforge.visionManager
import java.awt.Desktop
import java.nio.file.Path
+
public fun makeVisionFile(
path: Path? = null,
title: String = "VisionForge page",
@@ -26,6 +39,45 @@ public fun makeVisionFile(
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
}
+public fun serve(
+ title: String = "VisionForge page",
+ show: Boolean = true,
+ content: HtmlVisionFragment,
+) {
+ val context = Context("playground") {
+ plugin(Solids)
+ plugin(PlotlyPlugin)
+ plugin(MarkupPlugin)
+ plugin(TableVisionPlugin)
+ }
+
+ val server = embeddedServer(CIO, port = 7779) {
+ routing {
+ staticResources("", null, null)
+ }
+
+ visionPage(
+ context.visionManager,
+ VisionPage.scriptHeader("js/visionforge-playground.js") {
+ defer = true
+ },
+ VisionPage.title(title),
+ visionFragment = content
+ )
+ }.start(false)
+
+ if (show) {
+ server.openInBrowser()
+ }
+
+ println("Enter 'exit' to close server")
+ while (readlnOrNull() != "exit") {
+ //
+ }
+
+ server.close()
+}
+
//@DFExperimental
//public fun Context.makeVisionFile(
// vision: Vision,
diff --git a/demo/playground/src/jvmMain/kotlin/shapes.kt b/demo/playground/src/jvmMain/kotlin/shapes.kt
index a338d123..55ce28d5 100644
--- a/demo/playground/src/jvmMain/kotlin/shapes.kt
+++ b/demo/playground/src/jvmMain/kotlin/shapes.kt
@@ -10,23 +10,23 @@ fun main() = makeVisionFile {
ambientLight()
box(100.0, 100.0, 100.0) {
z = -110.0
- color.set("teal")
+ color("teal")
}
sphere(50.0) {
x = 110
detail = 16
- color.set("red")
+ color("red")
}
tube(50, height = 10, innerRadius = 25, angle = PI) {
y = 110
detail = 16
rotationX = PI / 4
- color.set("blue")
+ color("blue")
}
sphereLayer(50, 40, theta = PI / 2) {
rotationX = -PI * 3 / 4
z = 110
- color.set(Colors.pink)
+ color(Colors.pink)
}
diff --git a/demo/playground/src/jvmMain/kotlin/simpleCube.kt b/demo/playground/src/jvmMain/kotlin/simpleCube.kt
index 5dae515c..e1fc91eb 100644
--- a/demo/playground/src/jvmMain/kotlin/simpleCube.kt
+++ b/demo/playground/src/jvmMain/kotlin/simpleCube.kt
@@ -2,8 +2,8 @@ package space.kscience.visionforge.examples
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.box
+import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.material
-import space.kscience.visionforge.solid.set
import space.kscience.visionforge.solid.solid
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
@@ -11,7 +11,7 @@ fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
solid {
box(100, 100, 100)
material {
- emissiveColor.set("red")
+ emissiveColor("red")
}
}
}
diff --git a/demo/playground/src/jvmMain/resources/root/geometry_run_7-2076.zip b/demo/playground/src/jvmMain/resources/root/geometry_run_7-2076.zip
new file mode 100644
index 00000000..1680404c
Binary files /dev/null and b/demo/playground/src/jvmMain/resources/root/geometry_run_7-2076.zip differ
diff --git a/demo/sat-demo/build.gradle.kts b/demo/sat-demo/build.gradle.kts
index 6afadf27..5e881b63 100644
--- a/demo/sat-demo/build.gradle.kts
+++ b/demo/sat-demo/build.gradle.kts
@@ -8,13 +8,15 @@ kscience {
// useSerialization {
// json()
// }
+ useKtor()
dependencies{
+ implementation("io.ktor:ktor-server-cio")
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
- implementation("ch.qos.logback:logback-classic:1.4.5")
+ implementation(spclibs.logback.classic)
}
}
-group = "ru.mipt.npm"
+group = "center.sciprog"
application {
mainClass.set("ru.mipt.npm.sat.SatServerKt")
diff --git a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/geometry.kt b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/geometry.kt
index 052fb6e0..d2c30422 100644
--- a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/geometry.kt
+++ b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/geometry.kt
@@ -15,7 +15,7 @@ internal fun Solids.visionOfSatellite(
ySegmentSize: Number = xSegmentSize,
fiberDiameter: Number = 1.0,
): SolidGroup = solidGroup {
- color.set("darkgreen")
+ color("darkgreen")
val transparent by style {
this[SolidMaterial.MATERIAL_OPACITY_KEY] = 0.3
}
diff --git a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt
index 9e0c8282..9f2f7e59 100644
--- a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt
+++ b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt
@@ -33,7 +33,7 @@ fun main() {
//Create a geometry
val sat = solids.visionOfSatellite(ySegments = 3).apply {
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
}
val server = embeddedServer(CIO, port = 7777) {
@@ -63,7 +63,7 @@ fun main() {
val randomJ = Random.nextInt(1, 4)
val target = Name.parse("layer[$randomLayer].segment[$randomI,$randomJ]")
val targetVision = sat[target] as Solid
- targetVision.color.set("red")
+ targetVision.color("red")
delay(1000)
//use to ensure that color is cleared
targetVision.color.value = Null
diff --git a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/static.kt b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/static.kt
index 2a1fd240..89dc3a09 100644
--- a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/static.kt
+++ b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/static.kt
@@ -3,8 +3,8 @@ package ru.mipt.npm.sat
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.box
+import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.material
-import space.kscience.visionforge.solid.set
import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.three.makeThreeJsFile
@@ -14,7 +14,7 @@ fun main() = makeThreeJsFile(resourceLocation = ResourceLocation.SYSTEM) {
solid {
box(100, 100, 100)
material {
- emissiveColor.set("red")
+ emissiveColor("red")
}
}
}
diff --git a/demo/solid-showcase/build.gradle.kts b/demo/solid-showcase/build.gradle.kts
index 78e7d163..05a02260 100644
--- a/demo/solid-showcase/build.gradle.kts
+++ b/demo/solid-showcase/build.gradle.kts
@@ -1,14 +1,14 @@
plugins {
id("space.kscience.gradle.mpp")
- application
+// application
}
kscience {
useCoroutines()
- jvm {
- withJava()
+ jvm()
+ js{
+ binaries.executable()
}
- js()
dependencies {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeGdml)
@@ -19,6 +19,8 @@ kscience {
}
}
-application {
- mainClass.set("space.kscience.visionforge.solid.demo.FXDemoAppKt")
-}
\ No newline at end of file
+kotlin.explicitApi = null
+
+//application {
+// mainClass.set("space.kscience.visionforge.solid.demo.FXDemoAppKt")
+//}
\ No newline at end of file
diff --git a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt
index ef009b82..9e2ecedb 100644
--- a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt
+++ b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt
@@ -4,6 +4,8 @@ import kotlinx.coroutines.*
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.invoke
import space.kscience.dataforge.names.Name
+import space.kscience.kmath.geometry.Euclidean3DSpace
+import space.kscience.kmath.geometry.radians
import space.kscience.visionforge.Colors
import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@@ -21,7 +23,7 @@ fun VisionLayout.demo(name: String, title: String = name, block: SolidGro
val vision = solids.solidGroup {
block()
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
}
}
render(Name.parse(name), vision, meta)
@@ -47,23 +49,23 @@ fun VisionLayout.showcase() {
ambientLight()
box(100.0, 100.0, 100.0) {
z = -110.0
- color.set("teal")
+ color("teal")
}
sphere(50.0) {
x = 110
detail = 16
- color.set("red")
+ color("red")
}
tube(50, height = 10, innerRadius = 25, angle = PI) {
y = 110
detail = 16
rotationX = PI / 4
- color.set("blue")
+ color("blue")
}
sphereLayer(50, 40, theta = PI / 2) {
rotationX = -PI * 3 / 4
z = 110
- color.set(Colors.pink)
+ color(Colors.pink)
}
}
@@ -78,7 +80,7 @@ fun VisionLayout.showcase() {
visible = false
x = 110.0
//override color for this cube
- color.set(1530)
+ color(1530)
GlobalScope.launch(Dispatchers.Main) {
while (isActive) {
@@ -93,7 +95,7 @@ fun VisionLayout.showcase() {
val random = Random(111)
while (isActive) {
delay(1000)
- group.color.set(random.nextInt(0, Int.MAX_VALUE))
+ group.color(random.nextInt(0, Int.MAX_VALUE))
}
}
}
@@ -103,9 +105,16 @@ fun VisionLayout.showcase() {
solidGroup {
x = 200
rotationY = PI / 4
+ axes(200)
box(100, 100, 100) {
- rotationZ = PI / 4
- color.set(Colors.red)
+ rotate((PI / 4).radians, Euclidean3DSpace.zAxis)
+ GlobalScope.launch(Dispatchers.Main) {
+ while (isActive) {
+ delay(100)
+ rotate((PI/20).radians,Euclidean3DSpace.yAxis)
+ }
+ }
+ color(Colors.red)
}
}
}
@@ -118,7 +127,7 @@ fun VisionLayout.showcase() {
for (i in 0..100) {
layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i))
}
- color.set(Colors.teal)
+ color(Colors.teal)
rotationX = -PI / 2
}
}
@@ -127,13 +136,16 @@ fun VisionLayout.showcase() {
sphere(100) {
detail = 32
opacity = 0.4
- color.set(Colors.blue)
+ color(Colors.blue)
}
repeat(20) {
- polyline(Point3D(100, 100, 100), Point3D(-100, -100, -100)) {
+ polyline(
+ Float32Vector3D(100, 100, 100),
+ Float32Vector3D(-100, -100, -100)
+ ) {
thickness = 3.0
rotationX = it * PI2 / 20
- color.set(Colors.green)
+ color(Colors.green)
//rotationY = it * PI2 / 20
}
}
@@ -147,6 +159,10 @@ fun VisionLayout.showcase() {
z = 26
}
}
+
+ demo("STL", "STL loaded from URL") {
+ stl("https://ozeki.hu/attachments/116/Menger_sponge_sample.stl")
+ }
}
fun VisionLayout.showcaseCSG() {
@@ -160,7 +176,7 @@ fun VisionLayout.showcaseCSG() {
detail = 32
}
material {
- color.set(Colors.pink)
+ color(Colors.pink)
}
}
composite(CompositeType.UNION) {
@@ -170,7 +186,7 @@ fun VisionLayout.showcaseCSG() {
sphere(50) {
detail = 32
}
- color.set("lightgreen")
+ color("lightgreen")
opacity = 0.7
}
composite(CompositeType.SUBTRACT) {
@@ -181,7 +197,7 @@ fun VisionLayout.showcaseCSG() {
sphere(50) {
detail = 32
}
- color.set("teal")
+ color("teal")
opacity = 0.7
}
}
@@ -192,7 +208,7 @@ fun VisionLayout.showcaseCSG() {
detail = 32
}
box(100, 100, 100)
- color.set("red")
+ color("red")
opacity = 0.5
}
}
diff --git a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt
index 15e53129..701df81b 100644
--- a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt
+++ b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt
@@ -25,7 +25,7 @@ internal fun SolidGroup.varBox(
internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() {
- override fun render(three: ThreePlugin): Object3D {
+ override suspend fun render(three: ThreePlugin): Object3D {
val geometry = BoxGeometry(xSize, ySize, 1)
val material = ThreeMaterials.DEFAULT.clone()
diff --git a/jupyter/src/jvmMain/kotlin/VFForNotebook.kt b/jupyter/src/jvmMain/kotlin/VFForNotebook.kt
deleted file mode 100644
index 50619e44..00000000
--- a/jupyter/src/jvmMain/kotlin/VFForNotebook.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-package space.kscience.visionforge.jupyter
-
-import io.ktor.http.URLProtocol
-import io.ktor.server.application.install
-import io.ktor.server.cio.CIO
-import io.ktor.server.engine.ApplicationEngine
-import io.ktor.server.engine.embeddedServer
-import io.ktor.server.util.url
-import io.ktor.server.websocket.WebSockets
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.html.*
-import kotlinx.html.stream.createHTML
-import org.jetbrains.kotlinx.jupyter.api.HTML
-import org.jetbrains.kotlinx.jupyter.api.MimeTypedResult
-import space.kscience.dataforge.context.Context
-import space.kscience.dataforge.context.ContextAware
-import space.kscience.dataforge.context.info
-import space.kscience.dataforge.context.logger
-import space.kscience.dataforge.meta.get
-import space.kscience.dataforge.meta.int
-import space.kscience.dataforge.meta.string
-import space.kscience.dataforge.names.Name
-import space.kscience.visionforge.Vision
-import space.kscience.visionforge.VisionManager
-import space.kscience.visionforge.html.HtmlVisionFragment
-import space.kscience.visionforge.html.visionFragment
-import space.kscience.visionforge.server.VisionRoute
-import space.kscience.visionforge.server.serveVisionData
-import space.kscience.visionforge.visionManager
-import kotlin.coroutines.CoroutineContext
-import kotlin.random.Random
-import kotlin.random.nextUInt
-
-internal fun TagConsumer<*>.renderScriptForId(id: String) {
- script {
- type = "text/javascript"
- unsafe { +"VisionForge.renderAllVisionsById(\"$id\");" }
- }
-}
-
-/**
- * A handler class that includes a server and common utilities
- */
-public class VFForNotebook(override val context: Context) : ContextAware, CoroutineScope {
-
- public val visionManager: VisionManager = context.visionManager
-
- private var counter = 0
-
- private var engine: ApplicationEngine? = null
-
- public var isolateFragments: Boolean = false
-
- override val coroutineContext: CoroutineContext get() = context.coroutineContext
-
- public fun legacyMode() {
- isolateFragments = true
- }
-
- public fun isServerRunning(): Boolean = engine != null
-
- public fun html(block: TagConsumer<*>.() -> Unit): MimeTypedResult = HTML(createHTML().apply(block).finalize())
-
- public fun startServer(
- host: String = context.properties["visionforge.host"].string ?: "localhost",
- port: Int = context.properties["visionforge.port"].int ?: VisionRoute.DEFAULT_PORT,
- ): MimeTypedResult = html {
- if (engine != null) {
- p {
- style = "color: red;"
- +"Stopping current VisionForge server"
- }
- }
-
- //val connector: EngineConnectorConfig = EngineConnectorConfig(host, port)
-
- engine?.stop(1000, 2000)
- engine = context.embeddedServer(CIO, port, host) {
- install(WebSockets)
- }.start(false)
-
- p {
- style = "color: blue;"
- +"Starting VisionForge server on http://$host:$port"
- }
- }
-
- public fun stopServer() {
- engine?.apply {
- logger.info { "Stopping VisionForge server" }
- stop(1000, 2000)
- engine = null
- }
- }
-
- private fun produceHtmlString(
- fragment: HtmlVisionFragment,
- ): String = createHTML().apply {
- val id = "fragment[${fragment.hashCode()}/${Random.nextUInt()}]"
- div {
- this.id = id
- val engine = engine
- if (engine != null) {
- //if server exist, serve dynamically
- //server.serveVisionsFromFragment(consumer, "content-${counter++}", fragment)
- val cellRoute = "content-${counter++}"
-
- val collector: MutableMap = mutableMapOf()
-
- val url = engine.environment.connectors.first().let {
- url {
- protocol = URLProtocol.WS
- host = it.host
- port = it.port
- pathSegments = listOf(cellRoute, "ws")
- }
- }
-
- engine.application.serveVisionData(VisionRoute(cellRoute, visionManager), collector)
-
- visionFragment(
- visionManager,
- embedData = true,
- updatesUrl = url,
- onVisionRendered = { name, vision -> collector[name] = vision },
- fragment = fragment
- )
- } else {
- //if not, use static rendering
- visionFragment(visionManager, fragment = fragment)
- }
- }
- renderScriptForId(id)
- }.finalize()
-
- public fun produceHtml(isolated: Boolean? = null, fragment: HtmlVisionFragment): MimeTypedResult =
- HTML(produceHtmlString(fragment), isolated ?: isolateFragments)
-
- public fun fragment(body: HtmlVisionFragment): MimeTypedResult = produceHtml(fragment = body)
- public fun page(body: HtmlVisionFragment): MimeTypedResult = produceHtml(true, body)
-
- public fun form(builder: FORM.() -> Unit): HtmlFormFragment =
- HtmlFormFragment("form[${counter++}]", builder = builder)
-}
\ No newline at end of file
diff --git a/jupyter/src/jvmMain/kotlin/VFIntegrationBase.kt b/jupyter/src/jvmMain/kotlin/VFIntegrationBase.kt
deleted file mode 100644
index bf6322e9..00000000
--- a/jupyter/src/jvmMain/kotlin/VFIntegrationBase.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-package space.kscience.visionforge.jupyter
-
-import kotlinx.html.*
-import kotlinx.html.stream.createHTML
-import org.jetbrains.kotlinx.jupyter.api.HTML
-import org.jetbrains.kotlinx.jupyter.api.declare
-import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
-import space.kscience.dataforge.context.Context
-import space.kscience.dataforge.context.ContextAware
-import space.kscience.dataforge.misc.DFExperimental
-import space.kscience.visionforge.Vision
-import space.kscience.visionforge.VisionManager
-import space.kscience.visionforge.html.*
-import kotlin.random.Random
-import kotlin.random.nextUInt
-
-/**
- * A base class for different Jupyter VF integrations
- */
-@DFExperimental
-public abstract class VFIntegrationBase(
- public val visionManager: VisionManager,
-) : JupyterIntegration(), ContextAware {
-
- override val context: Context get() = visionManager.context
- protected val handler: VFForNotebook = VFForNotebook(visionManager.context)
-
- protected abstract fun Builder.afterLoaded()
-
- final override fun Builder.onLoaded() {
-
- onLoaded {
- declare("VisionForge" to handler, "vf" to handler)
- }
-
- onShutdown {
- handler.stopServer()
- }
-
- import(
- "kotlinx.html.*",
- "space.kscience.visionforge.html.*"
- )
-
- render { fragment ->
- handler.produceHtml(fragment = fragment)
- }
-
- render { fragment ->
- handler.produceHtml(fragment = fragment)
- }
-
- render { vision ->
- handler.produceHtml {
- vision(vision)
- }
-
- }
-
- render { page ->
- HTML(createHTML().apply {
- head {
- meta {
- charset = "utf-8"
- }
- page.pageHeaders.values.forEach {
- fragment(it)
- }
- }
- body {
- val id = "fragment[${page.hashCode()}/${Random.nextUInt()}]"
- div {
- this.id = id
- visionFragment(visionManager, fragment = page.content)
- }
- renderScriptForId(id)
- }
- }.finalize(), true)
- }
-
- render { fragment ->
- handler.produceHtml {
- if (!handler.isServerRunning()) {
- p {
- style = "color: red;"
- +"The server is not running. Forms are not interactive. Start server with `VisionForge.startServer()."
- }
- }
- fragment(fragment.formBody)
- vision(fragment.vision)
- }
- }
-
- afterLoaded()
- }
-}
\ No newline at end of file
diff --git a/jupyter/visionforge-jupyter-gdml/README.md b/jupyter/visionforge-jupyter-gdml/README.md
deleted file mode 100644
index cae8af86..00000000
--- a/jupyter/visionforge-jupyter-gdml/README.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Module visionforge-jupyter-gdml
-
-Jupyter api artifact for GDML rendering
-
-## Usage
-
-## Artifact:
-
-The Maven coordinates of this project are `space.kscience:visionforge-jupyter-gdml:0.2.0`.
-
-**Gradle Groovy:**
-```groovy
-repositories {
- maven { url 'https://repo.kotlin.link' }
- mavenCentral()
-}
-
-dependencies {
- implementation 'space.kscience:visionforge-jupyter-gdml:0.2.0'
-}
-```
-**Gradle Kotlin DSL:**
-```kotlin
-repositories {
- maven("https://repo.kotlin.link")
- mavenCentral()
-}
-
-dependencies {
- implementation("space.kscience:visionforge-jupyter-gdml:0.2.0")
-}
-```
diff --git a/jupyter/visionforge-jupyter-gdml/build.gradle.kts b/jupyter/visionforge-jupyter-gdml/build.gradle.kts
deleted file mode 100644
index 65df0c80..00000000
--- a/jupyter/visionforge-jupyter-gdml/build.gradle.kts
+++ /dev/null
@@ -1,38 +0,0 @@
-plugins {
- id("space.kscience.gradle.mpp")
-}
-
-description = "Jupyter api artifact for GDML rendering"
-
-kscience {
- fullStack("js/gdml-jupyter.js",
- jsConfig = { useCommonJs() }
- ) {
- commonWebpackConfig {
- sourceMaps = false
- cssSupport {
- enabled.set(false)
- }
- }
- }
-
- commonMain{
- implementation(projects.visionforgeSolid)
- implementation(projects.jupyter)
- }
-
- jvmMain{
- implementation(projects.visionforgeGdml)
- }
-
- jsMain{
- implementation(projects.visionforgeThreejs)
- implementation(projects.ui.ring)
- }
-
- jupyterLibrary("space.kscience.visionforge.gdml.jupyter.GdmlForJupyter")
-}
-
-readme {
- maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
-}
\ No newline at end of file
diff --git a/jupyter/visionforge-jupyter-gdml/src/jsMain/kotlin/gdmlJupyter.kt b/jupyter/visionforge-jupyter-gdml/src/jsMain/kotlin/gdmlJupyter.kt
deleted file mode 100644
index d4ee507e..00000000
--- a/jupyter/visionforge-jupyter-gdml/src/jsMain/kotlin/gdmlJupyter.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package space.kscience.visionforge.gdml.jupyter
-
-import space.kscience.dataforge.misc.DFExperimental
-import space.kscience.visionforge.ring.ThreeWithControlsPlugin
-import space.kscience.visionforge.runVisionClient
-
-@DFExperimental
-@JsExport
-public fun main(): Unit = runVisionClient {
- plugin(ThreeWithControlsPlugin)
-}
-
diff --git a/jupyter/visionforge-jupyter-gdml/src/jvmMain/kotlin/GdmlForJupyter.kt b/jupyter/visionforge-jupyter-gdml/src/jvmMain/kotlin/GdmlForJupyter.kt
deleted file mode 100644
index 0d55be2e..00000000
--- a/jupyter/visionforge-jupyter-gdml/src/jvmMain/kotlin/GdmlForJupyter.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package space.kscience.visionforge.gdml.jupyter
-
-import org.jetbrains.kotlinx.jupyter.api.libraries.resources
-import space.kscience.dataforge.context.Context
-import space.kscience.dataforge.misc.DFExperimental
-import space.kscience.gdml.Gdml
-import space.kscience.visionforge.gdml.toVision
-import space.kscience.visionforge.jupyter.VFIntegrationBase
-import space.kscience.visionforge.solid.Solids
-import space.kscience.visionforge.visionManager
-
-@DFExperimental
-internal class GdmlForJupyter : VFIntegrationBase(
- Context("GDML") {
- plugin(Solids)
- }.visionManager
-) {
-
- override fun Builder.afterLoaded() {
-
- resources {
- js("three") {
- classPath("js/gdml-jupyter.js")
- }
- }
-
- import(
- "space.kscience.gdml.*",
- "space.kscience.visionforge.gdml.jupyter.*"
- )
-
- render { gdmlModel ->
- handler.produceHtml {
- vision { gdmlModel.toVision() }
- }
- }
- }
-}
diff --git a/jupyter/visionforge-jupyter-gdml/webpack.config.d/01.ring.js b/jupyter/visionforge-jupyter-gdml/webpack.config.d/01.ring.js
deleted file mode 100644
index 41da041c..00000000
--- a/jupyter/visionforge-jupyter-gdml/webpack.config.d/01.ring.js
+++ /dev/null
@@ -1,3 +0,0 @@
-const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
-
-config.module.rules.push(...ringConfig.module.rules)
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e9e3deba..31119a06 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -64,6 +64,6 @@ include(
":demo:playground",
// ":demo:plotly-fx",
":demo:js-playground",
- ":jupyter",
- ":jupyter:visionforge-jupyter-gdml"
+ ":visionforge-jupyter",
+ ":visionforge-jupyter:visionforge-jupyter-common"
)
diff --git a/ui/react/src/jsMain/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt b/ui/react/src/jsMain/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt
index 50c8a60a..8cfa515d 100644
--- a/ui/react/src/jsMain/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt
+++ b/ui/react/src/jsMain/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt
@@ -2,7 +2,6 @@ package space.kscience.visionforge.react
import kotlinx.css.*
import org.w3c.dom.Element
-import org.w3c.dom.HTMLElement
import react.*
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
@@ -29,7 +28,7 @@ public val ThreeCanvasComponent: FC = fc("ThreeCanvasComponent
useEffect(props.solid, props.options, elementRef) {
if (canvas == null) {
- val element = elementRef.current as? HTMLElement ?: error("Canvas element not found")
+ val element = elementRef.current ?: error("Canvas element not found")
canvas = ThreeCanvas(three, element, props.options ?: Canvas3DOptions())
}
}
diff --git a/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt b/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt
index dd7f8e0d..94259b2f 100644
--- a/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt
+++ b/ui/ring/src/jsMain/kotlin/space.kscience.visionforge.ring/ThreeWithControlsPlugin.kt
@@ -7,12 +7,15 @@ import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.PluginFactory
import space.kscience.dataforge.context.PluginTag
import space.kscience.dataforge.meta.Meta
+import space.kscience.dataforge.meta.boolean
+import space.kscience.dataforge.meta.get
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solid
+import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreePlugin
public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
@@ -24,11 +27,16 @@ public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING * 2 else ElementVisionRenderer.ZERO_RATING
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
- space.kscience.visionforge.react.createRoot(element).render {
- child(ThreeCanvasWithControls) {
- attrs {
- this.solids = three.solids
- this.builderOfSolid = context.async { vision as Solid}
+ if(meta["controls.enabled"].boolean == false){
+ three.render(element, name, vision, meta)
+ } else {
+ space.kscience.visionforge.react.createRoot(element).render {
+ child(ThreeCanvasWithControls) {
+ attrs {
+ this.solids = three.solids
+ this.options = Canvas3DOptions.read(meta)
+ this.builderOfSolid = context.async { vision as Solid }
+ }
}
}
}
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt
index aa698409..ce5f588f 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt
@@ -67,7 +67,7 @@ public var Vision.visible: Boolean?
*/
public fun Vision.onPropertyChange(
scope: CoroutineScope? = manager?.context,
- callback: (Name) -> Unit
+ callback: suspend (Name) -> Unit
): Job = properties.changes.onEach {
callback(it)
}.launchIn(scope ?: error("Orphan Vision can't observe properties"))
\ No newline at end of file
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt
index 2be8a6b3..e4ca1cdb 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt
@@ -35,7 +35,6 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta), MutableVisionCont
public val jsonFormat: Json
get() = Json(defaultJson) {
- encodeDefaults = false
serializersModule = this@VisionManager.serializersModule
}
@@ -85,7 +84,6 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta), MutableVisionCont
serializersModule = defaultSerialModule
prettyPrint = true
useArrayPolymorphism = false
- encodeDefaults = false
ignoreUnknownKeys = true
explicitNulls = false
}
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlFragment.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlFragment.kt
index b733e6a4..ec3f3605 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlFragment.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlFragment.kt
@@ -4,19 +4,28 @@ import kotlinx.html.FlowContent
import kotlinx.html.TagConsumer
import kotlinx.html.stream.createHTML
-public typealias HtmlFragment = TagConsumer<*>.() -> Unit
-
-public fun HtmlFragment.renderToString(): String = createHTML().apply(this).finalize()
-
-public fun TagConsumer<*>.fragment(fragment: HtmlFragment) {
- fragment()
+/**
+ * A standalone HTML fragment
+ */
+public fun interface HtmlFragment {
+ public fun TagConsumer<*>.append()
}
-public fun FlowContent.fragment(fragment: HtmlFragment) {
- fragment(consumer)
-}
+/**
+ * Convenience method to append fragment to the given [consumer]
+ */
+public fun HtmlFragment.appendTo(consumer: TagConsumer<*>): Unit = consumer.append()
-public operator fun HtmlFragment.plus(other: HtmlFragment): HtmlFragment = {
- this@plus()
- other()
+/**
+ * Create a string from this [HtmlFragment]
+ */
+public fun HtmlFragment.renderToString(): String = createHTML().apply { append() }.finalize()
+
+public fun TagConsumer<*>.appendFragment(fragment: HtmlFragment): Unit = fragment.appendTo(this)
+
+public fun FlowContent.appendFragment(fragment: HtmlFragment): Unit = fragment.appendTo(consumer)
+
+public operator fun HtmlFragment.plus(other: HtmlFragment): HtmlFragment = HtmlFragment {
+ this@plus.appendTo(this)
+ other.appendTo(this)
}
\ No newline at end of file
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt
index d3c2427f..c02b6e64 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt
@@ -2,18 +2,17 @@ package space.kscience.visionforge.html
import kotlinx.html.*
import space.kscience.dataforge.meta.Meta
-import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionManager
-public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit
-
-@DFExperimental
-public fun HtmlVisionFragment(content: VisionTagConsumer<*>.() -> Unit): HtmlVisionFragment = content
+public fun interface HtmlVisionFragment{
+ public fun VisionTagConsumer<*>.append()
+}
+public fun HtmlVisionFragment.appendTo(consumer: VisionTagConsumer<*>): Unit = consumer.append()
/**
* Render a fragment in the given consumer and return a map of extracted visions
@@ -84,7 +83,7 @@ public fun TagConsumer<*>.visionFragment(
}
}
- fragment(consumer)
+ fragment.appendTo(consumer)
}
public fun FlowContent.visionFragment(
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionPage.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionPage.kt
index de18ced5..1ea216c5 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionPage.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionPage.kt
@@ -17,7 +17,7 @@ public data class VisionPage(
/**
* Use a script with given [src] as a global header for all pages.
*/
- public fun scriptHeader(src: String, block: SCRIPT.() -> Unit = {}): HtmlFragment = {
+ public fun scriptHeader(src: String, block: SCRIPT.() -> Unit = {}): HtmlFragment = HtmlFragment{
script {
type = "text/javascript"
this.src = src
@@ -26,9 +26,9 @@ public data class VisionPage(
}
/**
- * Use css with given stylesheet link as a global header for all pages.
+ * Use css with the given stylesheet link as a global header for all pages.
*/
- public fun styleSheetHeader(href: String, block: LINK.() -> Unit = {}): HtmlFragment = {
+ public fun styleSheetHeader(href: String, block: LINK.() -> Unit = {}): HtmlFragment = HtmlFragment{
link {
rel = "stylesheet"
this.href = href
@@ -36,7 +36,7 @@ public data class VisionPage(
}
}
- public fun title(title:String): HtmlFragment = {
+ public fun title(title:String): HtmlFragment = HtmlFragment{
title(title)
}
}
diff --git a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt
index efc7cfd0..eaea0a4e 100644
--- a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt
+++ b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt
@@ -24,7 +24,7 @@ fun FlowContent.renderVisionFragment(
renderer(name, vision, outputMeta)
}
}
- fragment(consumer)
+ fragment.appendTo(consumer)
return visionMap
}
@@ -35,7 +35,7 @@ private fun VisionOutput.base(block: VisionGroup.() -> Unit) = context.visionMan
@DFExperimental
class HtmlTagTest {
- val fragment: HtmlVisionFragment = {
+ val fragment = HtmlVisionFragment{
div {
h1 { +"Head" }
vision("ddd") {
diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt
index 7d61ce24..c9146efd 100644
--- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt
+++ b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt
@@ -286,8 +286,8 @@ public fun VisionClient.renderAllVisionsIn(element: Element) {
/**
* Render all visions in an element with a given [id]
*/
-public fun VisionClient.renderAllVisionsById(id: String): Unit = whenDocumentLoaded {
- val element = getElementById(id)
+public fun VisionClient.renderAllVisionsById(document: Document, id: String): Unit {
+ val element = document.getElementById(id)
if (element != null) {
renderAllVisionsIn(element)
} else {
diff --git a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/HtmlVisionContext.kt b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/HtmlVisionContext.kt
index 7d82da49..3796d436 100644
--- a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/HtmlVisionContext.kt
+++ b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/HtmlVisionContext.kt
@@ -34,10 +34,10 @@ public interface HtmlVisionContext : ContextAware {
public typealias HtmlVisionContextFragment = context(HtmlVisionContext) TagConsumer<*>.() -> Unit
-context(HtmlVisionContext)
-public fun HtmlVisionFragment(
- content: TagConsumer<*>.() -> Unit,
-): HtmlVisionFragment = content
+//context(HtmlVisionContext)
+//public fun HtmlVisionFragment(
+// content: TagConsumer<*>.() -> Unit,
+//): HtmlVisionFragment = HtmlVisionFragment { }
context(HtmlVisionContext)
private fun TagConsumer.vision(
diff --git a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/headers.kt b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/headers.kt
index 4c4ab90a..bf880e84 100644
--- a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/headers.kt
+++ b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/headers.kt
@@ -91,14 +91,14 @@ internal fun checkOrStoreFile(htmlPath: Path, filePath: Path, resource: String,
*/
internal fun fileScriptHeader(
path: Path,
-): HtmlFragment = {
+): HtmlFragment = HtmlFragment{
script {
type = "text/javascript"
src = path.toString()
}
}
-internal fun embedScriptHeader(resource: String, classLoader: ClassLoader): HtmlFragment = {
+internal fun embedScriptHeader(resource: String, classLoader: ClassLoader): HtmlFragment = HtmlFragment{
script {
type = "text/javascript"
unsafe {
@@ -113,7 +113,7 @@ internal fun fileCssHeader(
cssPath: Path,
resource: String,
classLoader: ClassLoader,
-): HtmlFragment = {
+): HtmlFragment = HtmlFragment{
val relativePath = checkOrStoreFile(basePath, cssPath, resource, classLoader)
link {
rel = "stylesheet"
diff --git a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/htmlExport.kt b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/htmlExport.kt
index ec31b7b4..e45dd9b5 100644
--- a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/htmlExport.kt
+++ b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/html/htmlExport.kt
@@ -78,7 +78,7 @@ public fun VisionPage.makeFile(
charset = "utf-8"
}
actualHeaders.values.forEach {
- fragment(it)
+ appendFragment(it)
}
}
body {
diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlLoaderOptions.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlLoaderOptions.kt
index 56158c55..2d3c18c9 100644
--- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlLoaderOptions.kt
+++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlLoaderOptions.kt
@@ -42,7 +42,7 @@ public class GdmlLoaderOptions {
* Configure paint for given solid with given [GdmlMaterial]
*/
public var configurePaint: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit =
- { material, _ -> color.set(randomColor(material)) }
+ { material, _ -> color(randomColor(material)) }
private set
public fun paint(block: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit) {
diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/gdmlLoader.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/gdmlLoader.kt
index 58213437..0c81d258 100644
--- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/gdmlLoader.kt
+++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/gdmlLoader.kt
@@ -6,6 +6,7 @@ import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus
import space.kscience.gdml.*
+import space.kscience.kmath.geometry.RotationOrder
import space.kscience.visionforge.*
import space.kscience.visionforge.html.VisionOutput
import space.kscience.visionforge.solid.*
@@ -206,9 +207,9 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" }
val baseRadius = solid.planes.first().rmax * lScale
shape {
- (0..solid.numsides).forEach {
+ (0..
@@ -248,14 +249,14 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
val dyBottom = solid.y1.toDouble() / 2
val dyTop = solid.y2.toDouble() / 2
val dz = solid.z.toDouble() / 2
- val node1 = Point3D(-dxBottom, -dyBottom, -dz)
- val node2 = Point3D(dxBottom, -dyBottom, -dz)
- val node3 = Point3D(dxBottom, dyBottom, -dz)
- val node4 = Point3D(-dxBottom, dyBottom, -dz)
- val node5 = Point3D(-dxTop, -dyTop, dz)
- val node6 = Point3D(dxTop, -dyTop, dz)
- val node7 = Point3D(dxTop, dyTop, dz)
- val node8 = Point3D(-dxTop, dyTop, dz)
+ val node1 = Float32Vector3D(-dxBottom, -dyBottom, -dz)
+ val node2 = Float32Vector3D(dxBottom, -dyBottom, -dz)
+ val node3 = Float32Vector3D(dxBottom, dyBottom, -dz)
+ val node4 = Float32Vector3D(-dxBottom, dyBottom, -dz)
+ val node5 = Float32Vector3D(-dxTop, -dyTop, dz)
+ val node6 = Float32Vector3D(dxTop, -dyTop, dz)
+ val node7 = Float32Vector3D(dxTop, dyTop, dz)
+ val node8 = Float32Vector3D(-dxTop, dyTop, dz)
hexagon(node1, node2, node3, node4, node5, node6, node7, node8, name)
}
diff --git a/jupyter/README.md b/visionforge-jupyter/README.md
similarity index 100%
rename from jupyter/README.md
rename to visionforge-jupyter/README.md
diff --git a/jupyter/build.gradle.kts b/visionforge-jupyter/build.gradle.kts
similarity index 64%
rename from jupyter/build.gradle.kts
rename to visionforge-jupyter/build.gradle.kts
index 1c32732b..49943631 100644
--- a/jupyter/build.gradle.kts
+++ b/visionforge-jupyter/build.gradle.kts
@@ -5,13 +5,17 @@ plugins {
description = "Common visionforge jupyter module"
kscience {
+ useKtor()
jvm()
js()
jupyterLibrary()
dependencies {
api(projects.visionforgeCore)
}
- jvmMain {
+ dependencies(jvmMain){
+ api("io.ktor:ktor-server-cio-jvm")
+ api("io.ktor:ktor-server-websockets-jvm")
+ api("io.ktor:ktor-server-cors-jvm")
api(projects.visionforgeServer)
}
}
diff --git a/jupyter/src/jsMain/kotlin/VFNotebookPlugin.kt b/visionforge-jupyter/src/jsMain/kotlin/VFNotebookClient.kt
similarity index 72%
rename from jupyter/src/jsMain/kotlin/VFNotebookPlugin.kt
rename to visionforge-jupyter/src/jsMain/kotlin/VFNotebookClient.kt
index f6a37f23..7f06c6ac 100644
--- a/jupyter/src/jsMain/kotlin/VFNotebookPlugin.kt
+++ b/visionforge-jupyter/src/jsMain/kotlin/VFNotebookClient.kt
@@ -1,6 +1,7 @@
package space.kscience.visionforge.jupyter
import kotlinx.browser.window
+import org.w3c.dom.Document
import org.w3c.dom.Element
import space.kscience.dataforge.context.AbstractPlugin
import space.kscience.dataforge.context.Context
@@ -13,15 +14,15 @@ import space.kscience.visionforge.renderAllVisionsById
import space.kscience.visionforge.renderAllVisionsIn
@JsExport
-public class VFNotebookPlugin : AbstractPlugin() {
+public class VFNotebookClient : AbstractPlugin() {
private val client by require(VisionClient)
public fun renderAllVisionsIn(element: Element) {
client.renderAllVisionsIn(element)
}
- public fun renderAllVisionsById(id: String) {
- client.renderAllVisionsById(id)
+ public fun renderAllVisionsById(document: Document, id: String) {
+ client.renderAllVisionsById(document, id)
}
public fun renderAllVisions() {
@@ -30,17 +31,18 @@ public class VFNotebookPlugin : AbstractPlugin() {
init {
+ console.info("Loading VisionForge global hooks")
//register VisionForge in the browser window
- window.asDynamic().vf = this
- window.asDynamic().VisionForge = this
+ window.parent.asDynamic().vf = this
+ window.parent.asDynamic().VisionForge = this
}
@Suppress("NON_EXPORTABLE_TYPE")
override val tag: PluginTag get() = Companion.tag
@Suppress("NON_EXPORTABLE_TYPE")
- public companion object : PluginFactory {
- override fun build(context: Context, meta: Meta): VFNotebookPlugin = VFNotebookPlugin()
+ public companion object : PluginFactory {
+ override fun build(context: Context, meta: Meta): VFNotebookClient = VFNotebookClient()
override val tag: PluginTag = PluginTag(name = "vision.notebook", group = PluginTag.DATAFORGE_GROUP)
}
diff --git a/visionforge-jupyter/src/jvmMain/kotlin/VisionForge.kt b/visionforge-jupyter/src/jvmMain/kotlin/VisionForge.kt
new file mode 100644
index 00000000..49d5fe23
--- /dev/null
+++ b/visionforge-jupyter/src/jvmMain/kotlin/VisionForge.kt
@@ -0,0 +1,177 @@
+package space.kscience.visionforge.jupyter
+
+import io.ktor.http.URLProtocol
+import io.ktor.server.application.install
+import io.ktor.server.cio.CIO
+import io.ktor.server.engine.ApplicationEngine
+import io.ktor.server.engine.embeddedServer
+import io.ktor.server.util.url
+import io.ktor.server.websocket.WebSockets
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.html.*
+import kotlinx.html.stream.createHTML
+import org.jetbrains.kotlinx.jupyter.api.*
+import space.kscience.dataforge.context.Context
+import space.kscience.dataforge.context.ContextAware
+import space.kscience.dataforge.context.info
+import space.kscience.dataforge.context.logger
+import space.kscience.dataforge.meta.*
+import space.kscience.dataforge.names.Name
+import space.kscience.visionforge.Vision
+import space.kscience.visionforge.VisionManager
+import space.kscience.visionforge.html.HtmlVisionFragment
+import space.kscience.visionforge.html.visionFragment
+import space.kscience.visionforge.server.VisionRoute
+import space.kscience.visionforge.server.serveVisionData
+import kotlin.coroutines.CoroutineContext
+import kotlin.random.Random
+import kotlin.random.nextUInt
+
+
+@Suppress("FunctionName")
+internal inline fun HTML(isolated: Boolean = false, block: TagConsumer<*>.() -> Unit): MimeTypedResult =
+ HTML(createHTML().apply(block).finalize(), isolated)
+
+internal fun KotlinKernelHost.displayHtml(block: TagConsumer<*>.() -> Unit) {
+ display(HTML(false, block), null)
+}
+
+public enum class VisionForgeCompatibility {
+ JUPYTER,
+ JUPYTER_LAB,
+ DATALORE,
+ IDEA
+}
+
+/**
+ * A handler class that includes a server and common utilities
+ */
+@Suppress("ExtractKtorModule")
+public class VisionForge(
+ public val visionManager: VisionManager,
+ public val notebook: Notebook,
+ meta: Meta = Meta.EMPTY,
+) : ContextAware, CoroutineScope {
+
+ override val context: Context get() = visionManager.context
+
+ public val configuration: ObservableMutableMeta = meta.toMutableMeta()
+
+ private var counter = 0
+
+ private var engine: ApplicationEngine? = null
+
+ override val coroutineContext: CoroutineContext get() = context.coroutineContext
+
+
+ public fun isServerRunning(): Boolean = engine != null
+
+ public fun getProperty(name: String): TypedMeta<*>? = configuration[name] ?: context.properties[name]
+
+ internal fun startServer(
+ kernel: KotlinKernelHost,
+ host: String = getProperty("visionforge.host").string ?: "localhost",
+ port: Int = getProperty("visionforge.port").int ?: VisionRoute.DEFAULT_PORT,
+ ) {
+ engine?.let {
+ kernel.displayHtml {
+ p {
+ style = "color: red;"
+ +"Stopping current VisionForge server"
+ }
+ }
+ it.stop(1000, 2000)
+ }
+
+ //val connector: EngineConnectorConfig = EngineConnectorConfig(host, port)
+
+
+ engine = context.embeddedServer(CIO, port, host) {
+ install(WebSockets)
+ }.start(false)
+
+ kernel.displayHtml {
+ p {
+ style = "color: blue;"
+ +"Starting VisionForge server on port $port"
+ }
+ }
+ }
+
+ internal fun stopServer(kernel: KotlinKernelHost) {
+ engine?.apply {
+ logger.info { "Stopping VisionForge server" }
+ stop(1000, 2000)
+ engine = null
+ }
+
+ kernel.displayHtml {
+ p {
+ style = "color: red;"
+ +"VisionForge server stopped"
+ }
+ }
+ }
+
+ internal fun TagConsumer<*>.renderScriptForId(id: String) {
+ script {
+ type = "text/javascript"
+ //language=JavaScript
+ unsafe { +"parent.VisionForge.renderAllVisionsById(document, \"$id\");" }
+ }
+ }
+
+
+ public fun produceHtml(
+ isolated: Boolean? = null,
+ fragment: HtmlVisionFragment,
+ ): MimeTypedResult {
+ val iframeIsolation = isolated ?: when (notebook.jupyterClientType) {
+ JupyterClientType.DATALORE, JupyterClientType.JUPYTER_NOTEBOOK -> true
+ else -> false
+ }
+ return HTML(
+ iframeIsolation
+ ) {
+ val id = "fragment[${fragment.hashCode()}/${Random.nextUInt()}]"
+ div {
+ this.id = id
+ val engine = engine
+ if (engine != null) {
+ //if server exist, serve dynamically
+ //server.serveVisionsFromFragment(consumer, "content-${counter++}", fragment)
+ val cellRoute = "content-${counter++}"
+
+ val collector: MutableMap = mutableMapOf()
+
+ val url = engine.environment.connectors.first().let {
+ url {
+ protocol = URLProtocol.WS
+ host = it.host
+ port = it.port
+ pathSegments = listOf(cellRoute, "ws")
+ }
+ }
+
+ engine.application.serveVisionData(VisionRoute(cellRoute, visionManager), collector)
+
+ visionFragment(
+ visionManager,
+ embedData = true,
+ updatesUrl = url,
+ onVisionRendered = { name, vision -> collector[name] = vision },
+ fragment = fragment
+ )
+ } else {
+ //if not, use static rendering
+ visionFragment(visionManager, fragment = fragment)
+ }
+ }
+ renderScriptForId(id)
+ }
+ }
+
+ public fun form(builder: FORM.() -> Unit): HtmlFormFragment =
+ HtmlFormFragment("form[${counter++}]", builder = builder)
+}
+
diff --git a/visionforge-jupyter/src/jvmMain/kotlin/VisionForgeIntegration.kt b/visionforge-jupyter/src/jvmMain/kotlin/VisionForgeIntegration.kt
new file mode 100644
index 00000000..afc2ecc2
--- /dev/null
+++ b/visionforge-jupyter/src/jvmMain/kotlin/VisionForgeIntegration.kt
@@ -0,0 +1,133 @@
+package space.kscience.visionforge.jupyter
+
+import kotlinx.html.*
+import org.jetbrains.kotlinx.jupyter.api.KotlinKernelHost
+import org.jetbrains.kotlinx.jupyter.api.MimeTypedResult
+import org.jetbrains.kotlinx.jupyter.api.declare
+import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
+import space.kscience.dataforge.context.Context
+import space.kscience.dataforge.context.ContextAware
+import space.kscience.dataforge.misc.DFExperimental
+import space.kscience.visionforge.Vision
+import space.kscience.visionforge.VisionManager
+import space.kscience.visionforge.html.*
+import kotlin.random.Random
+import kotlin.random.nextUInt
+
+/**
+ * A base class for different Jupyter VF integrations
+ */
+@DFExperimental
+public abstract class VisionForgeIntegration(
+ public val visionManager: VisionManager,
+) : JupyterIntegration(), ContextAware {
+
+ override val context: Context get() = visionManager.context
+
+ protected abstract fun Builder.afterLoaded(vf: VisionForge)
+
+ final override fun Builder.onLoaded() {
+
+ val vf: VisionForge = VisionForge(visionManager, notebook)
+
+ onLoaded {
+ val kernel: KotlinKernelHost = this
+ declare("VisionForge" to vf, "vf" to vf)
+ vf.startServer(kernel)
+ vf.configuration.onChange(this) { name ->
+ if (name.toString() == "visionforge.port") {
+ kernel.displayHtml {
+ p { +"Property 'visionforge.port' changed. Restarting server" }
+ }
+ vf.startServer(kernel)
+ }
+ }
+ }
+
+
+ onShutdown {
+ vf.stopServer(this)
+ }
+
+ import(
+ "kotlinx.html.*",
+ "space.kscience.visionforge.html.*",
+ "space.kscience.visionforge.jupyter.*"
+ )
+//
+// render { fragment ->
+// HTML(fragment.renderToString())
+// }
+//
+// render { fragment ->
+// handler.produceHtml(fragment = fragment)
+// }
+
+ render { vision ->
+ vf.produceHtml {
+ vision(vision)
+ }
+ }
+
+ render { page ->
+ HTML(true) {
+ head {
+ meta {
+ charset = "utf-8"
+ }
+ page.pageHeaders.values.forEach {
+ appendFragment(it)
+ }
+ }
+ body {
+ val id = "fragment[${page.hashCode()}/${Random.nextUInt()}]"
+ div {
+ this.id = id
+ visionFragment(visionManager, fragment = page.content)
+ }
+ with(vf) {
+ renderScriptForId(id)
+ }
+ }
+ }
+ }
+
+ render { fragment ->
+ vf.produceHtml {
+ if (!vf.isServerRunning()) {
+ p {
+ style = "color: red;"
+ +"The server is not running. Forms are not interactive. Start server with `VisionForge.startServer()."
+ }
+ }
+ appendFragment(fragment.formBody)
+ vision(fragment.vision)
+ }
+ }
+
+ afterLoaded(vf)
+ }
+}
+
+
+/**
+ * Create a fragment without a head to be embedded in the page
+ */
+@Suppress("UnusedReceiverParameter")
+public fun VisionForge.html(body: TagConsumer<*>.() -> Unit): MimeTypedResult = HTML(false, body)
+
+
+/**
+ * Create a fragment without a head to be embedded in the page
+ */
+public fun VisionForge.fragment(body: VisionTagConsumer<*>.() -> Unit): MimeTypedResult = produceHtml(false, body)
+
+
+/**
+ * Create a standalone page in the notebook
+ */
+public fun VisionForge.page(
+ pageHeaders: Map = emptyMap(),
+ body: VisionTagConsumer<*>.() -> Unit,
+): VisionPage = VisionPage(visionManager, pageHeaders, body)
+
diff --git a/jupyter/src/jvmMain/kotlin/forms.kt b/visionforge-jupyter/src/jvmMain/kotlin/forms.kt
similarity index 82%
rename from jupyter/src/jvmMain/kotlin/forms.kt
rename to visionforge-jupyter/src/jvmMain/kotlin/forms.kt
index bccce2e7..fe072887 100644
--- a/jupyter/src/jvmMain/kotlin/forms.kt
+++ b/visionforge-jupyter/src/jvmMain/kotlin/forms.kt
@@ -11,11 +11,14 @@ import space.kscience.visionforge.html.VisionOfHtmlForm
public class HtmlFormFragment internal constructor(
public val vision: VisionOfHtmlForm,
public val formBody: HtmlFragment,
-){
+) {
public val values: Meta? get() = vision.values
public operator fun get(valueName: String): Meta? = values?.get(valueName)
}
+/**
+ * Top level function to create a form
+ */
public fun HtmlFormFragment(id: String? = null, builder: FORM.() -> Unit): HtmlFormFragment {
val realId = id ?: "form[${builder.hashCode().toUInt()}]"
return HtmlFormFragment(VisionOfHtmlForm(realId)) {
@@ -24,4 +27,8 @@ public fun HtmlFormFragment(id: String? = null, builder: FORM.() -> Unit): HtmlF
builder()
}
}
-}
\ No newline at end of file
+}
+
+
+public fun VisionForge.form(id: String? = null, builder: FORM.() -> Unit): HtmlFormFragment =
+ HtmlFormFragment(id, builder)
\ No newline at end of file
diff --git a/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts b/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts
new file mode 100644
index 00000000..e6fd162b
--- /dev/null
+++ b/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts
@@ -0,0 +1,42 @@
+plugins {
+ id("space.kscience.gradle.mpp")
+}
+
+description = "Jupyter api artifact including all common modules"
+
+kscience {
+ fullStack(
+ "js/visionforge-jupyter-common.js",
+ jsConfig = { useCommonJs() }
+ ) {
+ commonWebpackConfig {
+ sourceMaps = false
+ cssSupport {
+ enabled.set(false)
+ }
+ }
+ }
+
+ dependencies {
+ api(projects.visionforgeSolid)
+ api(projects.visionforgePlotly)
+ api(projects.visionforgeTables)
+ api(projects.visionforgeMarkdown)
+ api(projects.visionforgeJupyter)
+ }
+
+ jvmMain {
+ api(projects.visionforgeGdml)
+ }
+
+ jsMain {
+ implementation(projects.ui.ring)
+ implementation(projects.visionforgeThreejs)
+ }
+
+ jupyterLibrary("space.kscience.visionforge.jupyter.JupyterCommonIntegration")
+}
+
+readme {
+ maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
+}
\ No newline at end of file
diff --git a/visionforge-jupyter/visionforge-jupyter-common/src/jsMain/kotlin/commonJupyter.kt b/visionforge-jupyter/visionforge-jupyter-common/src/jsMain/kotlin/commonJupyter.kt
new file mode 100644
index 00000000..e5fb4edd
--- /dev/null
+++ b/visionforge-jupyter/visionforge-jupyter-common/src/jsMain/kotlin/commonJupyter.kt
@@ -0,0 +1,17 @@
+package space.kscience.visionforge.gdml.jupyter
+
+import space.kscience.visionforge.jupyter.VFNotebookClient
+import space.kscience.visionforge.markup.MarkupPlugin
+import space.kscience.visionforge.plotly.PlotlyPlugin
+import space.kscience.visionforge.ring.ThreeWithControlsPlugin
+import space.kscience.visionforge.runVisionClient
+import space.kscience.visionforge.tables.TableVisionJsPlugin
+
+public fun main(): Unit = runVisionClient {
+ plugin(ThreeWithControlsPlugin)
+ plugin(PlotlyPlugin)
+ plugin(MarkupPlugin)
+ plugin(TableVisionJsPlugin)
+ plugin(VFNotebookClient)
+}
+
diff --git a/visionforge-jupyter/visionforge-jupyter-common/src/jvmMain/kotlin/JupyterCommonIntegration.kt b/visionforge-jupyter/visionforge-jupyter-common/src/jvmMain/kotlin/JupyterCommonIntegration.kt
new file mode 100644
index 00000000..6200bd5d
--- /dev/null
+++ b/visionforge-jupyter/visionforge-jupyter-common/src/jvmMain/kotlin/JupyterCommonIntegration.kt
@@ -0,0 +1,90 @@
+package space.kscience.visionforge.jupyter
+
+import kotlinx.html.*
+import org.jetbrains.kotlinx.jupyter.api.libraries.resources
+import space.kscience.dataforge.context.Context
+import space.kscience.dataforge.misc.DFExperimental
+import space.kscience.gdml.Gdml
+import space.kscience.plotly.Plot
+import space.kscience.plotly.PlotlyPage
+import space.kscience.plotly.StaticPlotlyRenderer
+import space.kscience.tables.*
+import space.kscience.visionforge.gdml.toVision
+import space.kscience.visionforge.html.HtmlFragment
+import space.kscience.visionforge.html.VisionPage
+import space.kscience.visionforge.markup.MarkupPlugin
+import space.kscience.visionforge.plotly.PlotlyPlugin
+import space.kscience.visionforge.plotly.asVision
+import space.kscience.visionforge.solid.Solids
+import space.kscience.visionforge.tables.TableVisionPlugin
+import space.kscience.visionforge.tables.toVision
+import space.kscience.visionforge.visionManager
+
+
+@DFExperimental
+public class JupyterCommonIntegration : VisionForgeIntegration(CONTEXT.visionManager) {
+
+ override fun Builder.afterLoaded(vf: VisionForge) {
+
+ resources {
+ js("visionforge-common") {
+ classPath("js/visionforge-jupyter-common.js")
+ }
+ }
+
+ import(
+ "space.kscience.gdml.*",
+ "space.kscience.visionforge.solid.*",
+ "space.kscience.tables.*",
+ "space.kscience.dataforge.meta.*",
+ "space.kscience.plotly.*",
+ "space.kscience.plotly.models.*",
+ "space.kscience.visionforge.plotly.plotly"
+ )
+
+ render { gdmlModel ->
+ vf.produceHtml {
+ vision { gdmlModel.toVision() }
+ }
+ }
+
+ render> { table ->
+ vf.produceHtml {
+ vision { table.toVision() }
+ }
+ }
+
+ render { plot ->
+ vf.produceHtml {
+ vision { plot.asVision() }
+ }
+ }
+
+
+ render { plotlyPage ->
+ val headers = plotlyPage.headers.associate { plotlyFragment ->
+ plotlyFragment.hashCode().toString(16) to HtmlFragment {
+ plotlyFragment.visit(this)
+ }
+
+ }
+ VisionPage(visionManager, headers) {
+ div{
+ p { +"Plotly page renderer is not recommended in VisionForge, use `vf.page{}`" }
+ }
+ div {
+ plotlyPage.fragment.render.invoke(this, StaticPlotlyRenderer)
+ }
+ }
+ }
+ }
+
+ public companion object {
+ private val CONTEXT: Context = Context("Jupyter-common") {
+ plugin(Solids)
+ plugin(PlotlyPlugin)
+ plugin(TableVisionPlugin)
+ plugin(MarkupPlugin)
+ }
+ }
+}
diff --git a/visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js b/visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js
new file mode 100644
index 00000000..cfb15cb8
--- /dev/null
+++ b/visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js
@@ -0,0 +1,24 @@
+const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
+
+const path = require('path');
+
+config.module.rules.push(...ringConfig.module.rules)
+
+config.module.rules.push(
+ {
+ test: /\.css$/,
+ exclude: [
+ path.resolve(__dirname, "../../node_modules/@jetbrains/ring-ui")
+ ],
+ use: [
+ {
+ loader: 'style-loader',
+ options: {}
+ },
+ {
+ loader: 'css-loader',
+ options: {}
+ }
+ ]
+ }
+)
\ No newline at end of file
diff --git a/visionforge-server/build.gradle.kts b/visionforge-server/build.gradle.kts
index a4a7d848..59034dd1 100644
--- a/visionforge-server/build.gradle.kts
+++ b/visionforge-server/build.gradle.kts
@@ -6,10 +6,10 @@ kscience{
useKtor()
dependencies {
api(projects.visionforgeCore)
- api("io.ktor:ktor-server-cio")
+ api("io.ktor:ktor-server-host-common")
api("io.ktor:ktor-server-html-builder")
api("io.ktor:ktor-server-websockets")
- implementation("io.ktor:ktor-server-cors")
+ api("io.ktor:ktor-server-cors")
}
}
diff --git a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt
index 84a87a65..61952497 100644
--- a/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt
+++ b/visionforge-server/src/main/kotlin/space/kscience/visionforge/server/VisionServer.kt
@@ -2,7 +2,6 @@ package space.kscience.visionforge.server
import io.ktor.http.*
import io.ktor.server.application.*
-import io.ktor.server.cio.*
import io.ktor.server.engine.*
import io.ktor.server.html.*
import io.ktor.server.http.content.*
@@ -58,7 +57,7 @@ public class VisionRoute(
override val context: Context get() = visionManager.context
/**
- * Update minimal interval between updates in milliseconds (if there are no updates, push will not happen
+ * Update the minimal interval between updates in milliseconds (if there are no updates, push will not happen
*/
public var updateInterval: Long by meta.long(300, key = UPDATE_INTERVAL_KEY)
@@ -171,8 +170,8 @@ public fun Application.visionPage(
meta {
charset = "utf-8"
}
- headers.forEach { header ->
- consumer.header()
+ headers.forEach { headerContent ->
+ headerContent.appendTo(consumer)
}
}
body {
diff --git a/visionforge-solid/build.gradle.kts b/visionforge-solid/build.gradle.kts
index a1d4fbc4..f87cef77 100644
--- a/visionforge-solid/build.gradle.kts
+++ b/visionforge-solid/build.gradle.kts
@@ -2,6 +2,8 @@ plugins {
id("space.kscience.gradle.mpp")
}
+val kmathVersion = "0.3.1"
+
kscience {
jvm()
js()
@@ -11,6 +13,7 @@ kscience {
}
useCoroutines()
dependencies {
+ api("space.kscience:kmath-geometry:0.3.1")
api(projects.visionforgeCore)
}
dependencies(jvmTest) {
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ColorAccessor.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ColorAccessor.kt
index 01abf310..60789027 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ColorAccessor.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ColorAccessor.kt
@@ -28,7 +28,7 @@ public class ColorAccessor(
}
}
-public fun Vision.color(
+public fun Vision.colorProperty(
propertyName: Name? = null,
): ReadOnlyProperty = ReadOnlyProperty { _, property ->
ColorAccessor(properties.root(true), propertyName ?: property.name.asName())
@@ -43,21 +43,21 @@ public var ColorAccessor?.string: String?
/**
* Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string
*/
-public fun ColorAccessor?.set(webColor: String) {
+public operator fun ColorAccessor?.invoke(webColor: String) {
this?.value = webColor.asValue()
}
/**
* Set color as RGB integer
*/
-public fun ColorAccessor?.set(rgb: Int) {
+public operator fun ColorAccessor?.invoke(rgb: Int) {
this?.value = Colors.rgbToString(rgb).asValue()
}
/**
* Set color as RGB
*/
-public fun ColorAccessor?.set(r: UByte, g: UByte, b: UByte) {
+public operator fun ColorAccessor?.invoke(r: UByte, g: UByte, b: UByte) {
this?.value = Colors.rgbToString(r, g, b).asValue()
}
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 94ea5eaf..7b2679cd 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
@@ -36,8 +36,8 @@ public class ConeSegment(
require(segments >= 4) { "The number of segments in cone is too small" }
val angleStep = phi / (segments - 1)
- fun shape(r: Float, z: Float): List = (0 until segments).map { i ->
- Point3D(r * cos(phiStart + angleStep * i), r * sin(phiStart + angleStep * i), z)
+ fun shape(r: Float, z: Float): List = (0 until segments).map { i ->
+ Float32Vector3D(r * cos(phiStart + angleStep * i), r * sin(phiStart + angleStep * i), z)
}
geometryBuilder.apply {
@@ -53,8 +53,8 @@ public class ConeSegment(
if (phi == PI2) {
face4(bottomPoints.last(), bottomPoints[0], topPoints[0], topPoints.last())
}
- val zeroBottom = Point3D(0f, 0f, -height / 2)
- val zeroTop = Point3D(0f, 0f, +height / 2)
+ val zeroBottom = Float32Vector3D(0f, 0f, -height / 2)
+ val zeroTop = Float32Vector3D(0f, 0f, +height / 2)
for (it in 1 until segments) {
face(bottomPoints[it - 1], zeroBottom, bottomPoints[it])
face(topPoints[it - 1], topPoints[it], zeroTop)
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt
index 75ff2161..8ce9ba8c 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt
@@ -38,8 +38,8 @@ public class ConeSurface(
require(segments >= 4) { "The number of segments in tube is too small" }
val angleStep = phi / (segments - 1)
- fun shape(r: Float, z: Float): List = (0 until segments).map { i ->
- Point3D(r * cos(phiStart + angleStep * i), r * sin(phiStart + angleStep * i), z)
+ fun shape(r: Float, z: Float): List = (0 until segments).map { i ->
+ Float32Vector3D(r * cos(phiStart + angleStep * i), r * sin(phiStart + angleStep * i), z)
}
geometryBuilder.apply {
@@ -56,8 +56,8 @@ public class ConeSurface(
face4(bottomOuterPoints.last(), bottomOuterPoints[0], topOuterPoints[0], topOuterPoints.last())
}
if (bottomInnerRadius == 0f) {
- val zeroBottom = Point3D(0f, 0f, -height / 2)
- val zeroTop = Point3D(0f, 0f, height / 2)
+ val zeroBottom = Float32Vector3D(0f, 0f, -height / 2)
+ val zeroTop = Float32Vector3D(0f, 0f, height / 2)
(1 until segments).forEach {
face(bottomOuterPoints[it - 1], zeroBottom, bottomOuterPoints[it])
face(topOuterPoints[it - 1], topOuterPoints[it], zeroTop)
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt
index 4d50c2c4..4fa174ac 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt
@@ -7,7 +7,7 @@ import space.kscience.visionforge.setChild
@Serializable
@SerialName("solid.convex")
-public class Convex(public val points: List) : SolidBase()
+public class Convex(public val points: List) : SolidBase()
public inline fun MutableVisionContainer.convex(
name: String? = null,
@@ -15,10 +15,10 @@ public inline fun MutableVisionContainer.convex(
): Convex = ConvexBuilder().apply(action).build().also { setChild(name, it) }
public class ConvexBuilder {
- private val points = ArrayList()
+ private val points = ArrayList()
public fun point(x: Number, y: Number, z: Number) {
- points.add(Point3D(x, y, z))
+ points.add(Float32Vector3D(x, y, z))
}
public fun build(): Convex {
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt
index faec109b..014db562 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt
@@ -4,23 +4,25 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.names.Name
-import space.kscience.visionforge.*
+import space.kscience.kmath.geometry.component1
+import space.kscience.kmath.geometry.component2
+import space.kscience.visionforge.MutableVisionContainer
+import space.kscience.visionforge.VisionBuilder
+import space.kscience.visionforge.setChild
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
-public typealias Shape2D = List
+public typealias Shape2D = List
@Serializable
-public class Shape2DBuilder(private val points: ArrayList = ArrayList()) {
+public class Shape2DBuilder(private val points: ArrayList = ArrayList()) {
public fun point(x: Number, y: Number) {
- points.add(Point2D(x, y))
+ points.add(Float32Vector2D(x, y))
}
- public infix fun Number.to(y: Number): Unit = point(this, y)
-
public fun build(): Shape2D = points
}
@@ -38,7 +40,7 @@ public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Flo
@Serializable
@SerialName("solid.extrude")
public class Extruded(
- public val shape: List,
+ public val shape: List,
public val layers: List,
) : SolidBase(), GeometrySolid {
@@ -50,18 +52,18 @@ public class Extruded(
/**
* Expand the shape for specific layers
*/
- val layers: List> = layers.map { layer ->
+ val layers: List> = layers.map { layer ->
shape.map { (x, y) ->
val newX = layer.x + x * layer.scale
val newY = layer.y + y * layer.scale
- Point3D(newX, newY, layer.z)
+ Float32Vector3D(newX, newY, layer.z)
}
}
if (layers.size < 2) error("Extruded shape requires more than one layer")
var lowerLayer = layers.first()
- var upperLayer: List
+ var upperLayer: List
for (i in (1 until layers.size)) {
upperLayer = layers[i]
@@ -94,7 +96,7 @@ public class Extruded(
}
public class ExtrudeBuilder(
- public var shape: List = emptyList(),
+ public var shape: List = emptyList(),
public var layers: MutableList = ArrayList(),
public val properties: MutableMeta = MutableMeta(),
) {
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Float32Euclidean2DSpace.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Float32Euclidean2DSpace.kt
new file mode 100644
index 00000000..b9a2fdba
--- /dev/null
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Float32Euclidean2DSpace.kt
@@ -0,0 +1,71 @@
+package space.kscience.visionforge.solid
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import space.kscience.kmath.geometry.GeometrySpace
+import space.kscience.kmath.geometry.Vector2D
+import space.kscience.kmath.operations.ScaleOperations
+import kotlin.math.pow
+import kotlin.math.sqrt
+
+@Serializable(Float32Euclidean2DSpace.VectorSerializer::class)
+public interface Float32Vector2D: Vector2D
+
+
+public object Float32Euclidean2DSpace :
+ GeometrySpace,
+ ScaleOperations {
+
+ @Serializable
+ @SerialName("Float32Vector2D")
+ private data class Vector2DImpl(
+ override val x: Float,
+ override val y: Float,
+ ) : Float32Vector2D
+
+ public object VectorSerializer : KSerializer {
+ private val proxySerializer = Vector2DImpl.serializer()
+ override val descriptor: SerialDescriptor get() = proxySerializer.descriptor
+
+ override fun deserialize(decoder: Decoder): Float32Vector2D = decoder.decodeSerializableValue(proxySerializer)
+
+ override fun serialize(encoder: Encoder, value: Float32Vector2D) {
+ val vector = value as? Vector2DImpl ?: Vector2DImpl(value.x, value.y)
+ encoder.encodeSerializableValue(proxySerializer, vector)
+ }
+ }
+
+ public fun vector(x: Float, y: Float): Float32Vector2D =
+ Vector2DImpl(x, y)
+
+ public fun vector(x: Number, y: Number): Float32Vector2D =
+ vector(x.toFloat(), y.toFloat())
+
+ override val zero: Float32Vector2D by lazy { vector(0f, 0f) }
+
+ override fun norm(arg: Float32Vector2D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2)).toDouble()
+
+ public fun Float32Vector2D.norm(): Double = norm(this)
+
+ override fun Float32Vector2D.unaryMinus(): Float32Vector2D = vector(-x, -y)
+
+ override fun Float32Vector2D.distanceTo(other: Float32Vector2D): Double = (this - other).norm()
+
+ override fun add(left: Float32Vector2D, right: Float32Vector2D): Float32Vector2D =
+ vector(left.x + right.x, left.y + right.y)
+
+ override fun scale(a: Float32Vector2D, value: Double): Float32Vector2D =
+ vector(a.x * value, a.y * value)
+
+ override fun Float32Vector2D.dot(other: Float32Vector2D): Double =
+ (x * other.x + y * other.y).toDouble()
+
+ public val xAxis: Float32Vector2D = vector(1.0, 0.0)
+ public val yAxis: Float32Vector2D = vector(0.0, 1.0)
+}
+
+public fun Float32Vector2D(x: Number, y: Number): Float32Vector2D = Float32Euclidean2DSpace.vector(x, y)
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Float32Euclidean3DSpace.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Float32Euclidean3DSpace.kt
new file mode 100644
index 00000000..04b3df35
--- /dev/null
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Float32Euclidean3DSpace.kt
@@ -0,0 +1,113 @@
+package space.kscience.visionforge.solid
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import space.kscience.kmath.geometry.GeometrySpace
+import space.kscience.kmath.geometry.Vector3D
+import space.kscience.kmath.operations.ScaleOperations
+import kotlin.math.pow
+import kotlin.math.sqrt
+
+@Serializable(Float32Euclidean3DSpace.VectorSerializer::class)
+public interface Float32Vector3D: Vector3D
+
+
+public object Float32Euclidean3DSpace :
+ GeometrySpace,
+ ScaleOperations{
+
+ @Serializable
+ @SerialName("Float32Vector3D")
+ private data class Vector3DImpl(
+ override val x: Float,
+ override val y: Float,
+ override val z: Float,
+ ) : Float32Vector3D
+
+ public object VectorSerializer : KSerializer {
+ private val proxySerializer = Vector3DImpl.serializer()
+ override val descriptor: SerialDescriptor get() = proxySerializer.descriptor
+
+ override fun deserialize(decoder: Decoder): Float32Vector3D = decoder.decodeSerializableValue(proxySerializer)
+
+ override fun serialize(encoder: Encoder, value: Float32Vector3D) {
+ val vector = value as? Vector3DImpl ?: Vector3DImpl(value.x, value.y, value.z)
+ encoder.encodeSerializableValue(proxySerializer, vector)
+ }
+ }
+
+ public fun vector(x: Float, y: Float, z: Float): Float32Vector3D =
+ Vector3DImpl(x, y, z)
+
+ public fun vector(x: Number, y: Number, z: Number): Float32Vector3D =
+ vector(x.toFloat(), y.toFloat(), z.toFloat())
+
+ override val zero: Float32Vector3D by lazy { vector(0.0, 0.0, 0.0) }
+
+ override fun norm(arg: Float32Vector3D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2) + arg.z.pow(2)).toDouble()
+
+ public fun Float32Vector3D.norm(): Double = norm(this)
+
+ override fun Float32Vector3D.unaryMinus(): Float32Vector3D = vector(-x, -y, -z)
+
+ override fun Float32Vector3D.distanceTo(other: Float32Vector3D): Double = (this - other).norm()
+
+ override fun add(left: Float32Vector3D, right: Float32Vector3D): Float32Vector3D =
+ vector(left.x + right.x, left.y + right.y, left.z + right.z)
+
+ override fun scale(a: Float32Vector3D, value: Double): Float32Vector3D =
+ vector(a.x * value, a.y * value, a.z * value)
+
+ override fun Float32Vector3D.dot(other: Float32Vector3D): Double =
+ (x * other.x + y * other.y + z * other.z).toDouble()
+
+ private fun leviCivita(i: Int, j: Int, k: Int): Int = when {
+ // even permutation
+ i == 0 && j == 1 && k == 2 -> 1
+ i == 1 && j == 2 && k == 0 -> 1
+ i == 2 && j == 0 && k == 1 -> 1
+ // odd permutations
+ i == 2 && j == 1 && k == 0 -> -1
+ i == 0 && j == 2 && k == 1 -> -1
+ i == 1 && j == 0 && k == 2 -> -1
+
+ else -> 0
+ }
+
+ /**
+ * Compute vector product of [first] and [second]. The basis is assumed to be right-handed.
+ */
+ public fun vectorProduct(
+ first: Float32Vector3D,
+ second: Float32Vector3D,
+ ): Float32Vector3D {
+ var x = 0.0
+ var y = 0.0
+ var z = 0.0
+
+ for (j in (0..2)) {
+ for (k in (0..2)) {
+ x += leviCivita(0, j, k) * first[j] * second[k]
+ y += leviCivita(1, j, k) * first[j] * second[k]
+ z += leviCivita(2, j, k) * first[j] * second[k]
+ }
+ }
+
+ return vector(x, y, z)
+ }
+
+ /**
+ * Vector product in a right-handed basis
+ */
+ public infix fun Float32Vector3D.cross(other: Float32Vector3D): Float32Vector3D = vectorProduct(this, other)
+
+ public val xAxis: Float32Vector3D = vector(1.0, 0.0, 0.0)
+ public val yAxis: Float32Vector3D = vector(0.0, 1.0, 0.0)
+ public val zAxis: Float32Vector3D = vector(0.0, 0.0, 1.0)
+}
+
+public fun Float32Vector3D(x: Number, y: Number, z: Number): Float32Vector3D = Float32Euclidean3DSpace.vector(x,y,z)
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/GeometryBuilder.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/GeometryBuilder.kt
index 3cfc5da9..ab24f8ce 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/GeometryBuilder.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/GeometryBuilder.kt
@@ -13,17 +13,17 @@ public interface GeometryBuilder {
* @param normal optional external normal to the face
* @param meta optional additional platform-specific parameters like color or texture index
*/
- public fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = Meta.EMPTY)
+ public fun face(vertex1: Float32Vector3D, vertex2: Float32Vector3D, vertex3: Float32Vector3D, normal: Float32Vector3D? = null, meta: Meta = Meta.EMPTY)
public fun build(): T
}
public fun GeometryBuilder<*>.face4(
- vertex1: Point3D,
- vertex2: Point3D,
- vertex3: Point3D,
- vertex4: Point3D,
- normal: Point3D? = null,
+ vertex1: Float32Vector3D,
+ vertex2: Float32Vector3D,
+ vertex3: Float32Vector3D,
+ vertex4: Float32Vector3D,
+ normal: Float32Vector3D? = null,
meta: Meta = Meta.EMPTY
) {
face(vertex1, vertex2, vertex3, normal, meta)
@@ -37,9 +37,9 @@ public interface GeometrySolid : Solid {
public fun toGeometry(geometryBuilder: GeometryBuilder)
}
-public fun GeometryBuilder.cap(shape: List, normal: Point3D? = null) {
+public fun GeometryBuilder.cap(shape: List, normal: Float32Vector3D? = null) {
//FIXME won't work for non-convex shapes
- val center = Point3D(
+ val center = Float32Vector3D(
shape.map { it.x }.average(),
shape.map { it.y }.average(),
shape.map { it.z }.average()
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt
index 92f11e1b..12e661eb 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt
@@ -7,14 +7,14 @@ import space.kscience.visionforge.VisionBuilder
import space.kscience.visionforge.setChild
public interface Hexagon : GeometrySolid {
- public val node1: Point3D
- public val node2: Point3D
- public val node3: Point3D
- public val node4: Point3D
- public val node5: Point3D
- public val node6: Point3D
- public val node7: Point3D
- public val node8: Point3D
+ public val node1: Float32Vector3D
+ public val node2: Float32Vector3D
+ public val node3: Float32Vector3D
+ public val node4: Float32Vector3D
+ public val node5: Float32Vector3D
+ public val node6: Float32Vector3D
+ public val node7: Float32Vector3D
+ public val node8: Float32Vector3D
override fun toGeometry(geometryBuilder: GeometryBuilder) {
geometryBuilder.face4(node1, node4, node3, node2)
@@ -41,14 +41,14 @@ public class Box(
private inline val dy get() = ySize / 2
private inline val dz get() = zSize / 2
- override val node1: Point3D get() = Point3D(-dx, -dy, -dz)
- override val node2: Point3D get() = Point3D(dx, -dy, -dz)
- override val node3: Point3D get() = Point3D(dx, dy, -dz)
- override val node4: Point3D get() = Point3D(-dx, dy, -dz)
- override val node5: Point3D get() = Point3D(-dx, -dy, dz)
- override val node6: Point3D get() = Point3D(dx, -dy, dz)
- override val node7: Point3D get() = Point3D(dx, dy, dz)
- override val node8: Point3D get() = Point3D(-dx, dy, dz)
+ override val node1: Float32Vector3D get() = Float32Vector3D(-dx, -dy, -dz)
+ override val node2: Float32Vector3D get() = Float32Vector3D(dx, -dy, -dz)
+ override val node3: Float32Vector3D get() = Float32Vector3D(dx, dy, -dz)
+ override val node4: Float32Vector3D get() = Float32Vector3D(-dx, dy, -dz)
+ override val node5: Float32Vector3D get() = Float32Vector3D(-dx, -dy, dz)
+ override val node6: Float32Vector3D get() = Float32Vector3D(dx, -dy, dz)
+ override val node7: Float32Vector3D get() = Float32Vector3D(dx, dy, dz)
+ override val node8: Float32Vector3D get() = Float32Vector3D(-dx, dy, dz)
}
@VisionBuilder
@@ -63,26 +63,26 @@ public inline fun MutableVisionContainer.box(
@Serializable
@SerialName("solid.hexagon")
public class GenericHexagon(
- override val node1: Point3D,
- override val node2: Point3D,
- override val node3: Point3D,
- override val node4: Point3D,
- override val node5: Point3D,
- override val node6: Point3D,
- override val node7: Point3D,
- override val node8: Point3D,
+ override val node1: Float32Vector3D,
+ override val node2: Float32Vector3D,
+ override val node3: Float32Vector3D,
+ override val node4: Float32Vector3D,
+ override val node5: Float32Vector3D,
+ override val node6: Float32Vector3D,
+ override val node7: Float32Vector3D,
+ override val node8: Float32Vector3D,
) : SolidBase(), Hexagon
@VisionBuilder
public inline fun MutableVisionContainer.hexagon(
- node1: Point3D,
- node2: Point3D,
- node3: Point3D,
- node4: Point3D,
- node5: Point3D,
- node6: Point3D,
- node7: Point3D,
- node8: Point3D,
+ node1: Float32Vector3D,
+ node2: Float32Vector3D,
+ node3: Float32Vector3D,
+ node4: Float32Vector3D,
+ node5: Float32Vector3D,
+ node6: Float32Vector3D,
+ node7: Float32Vector3D,
+ node8: Float32Vector3D,
name: String? = null,
action: Hexagon.() -> Unit = {},
): Hexagon = GenericHexagon(node1, node2, node3, node4, node5, node6, node7, node8).apply(action).also { setChild(name, it) }
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt
index 95aca618..6064e6ed 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt
@@ -15,7 +15,7 @@ import space.kscience.visionforge.*
public abstract class LightSource : SolidBase() {
override val descriptor: MetaDescriptor get() = LightSource.descriptor
- public val color: ColorAccessor by color(SolidMaterial.COLOR_KEY)
+ public val color: ColorAccessor by colorProperty(SolidMaterial.COLOR_KEY)
public var intensity: Number by properties.root(includeStyles = false).number(INTENSITY_KEY) { 1.0 }
public companion object {
@@ -70,6 +70,6 @@ public fun MutableVisionContainer.pointLight(
name: String? = null,
block: PointLightSource.() -> Unit = {},
): PointLightSource = PointLightSource().apply(block).also {
- it.position = Point3D(x, y, z)
+ it.position = Float32Vector3D(x, y, z)
setChild(name, it)
}
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/MiscSolid.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/MiscSolid.kt
new file mode 100644
index 00000000..f83f6cb9
--- /dev/null
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/MiscSolid.kt
@@ -0,0 +1,26 @@
+package space.kscience.visionforge.solid
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import space.kscience.visionforge.MutableVisionContainer
+import space.kscience.visionforge.VisionBuilder
+import space.kscience.visionforge.setChild
+
+public abstract class MiscSolid: SolidBase()
+
+@Serializable
+@SerialName("solid.axes")
+public class AxesSolid(public val size: Double): MiscSolid(){
+ public companion object{
+ public const val AXES_NAME: String = "@xes"
+ }
+}
+
+@VisionBuilder
+public fun MutableVisionContainer.axes(
+ size: Number,
+ name: String = "@axes",
+ block: AxesSolid.() -> Unit = {},
+): AxesSolid = AxesSolid(size.toDouble()).apply(block).also {
+ setChild(name, it)
+}
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt
index 0f366dbe..1681f44a 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt
@@ -3,11 +3,14 @@ package space.kscience.visionforge.solid
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.number
-import space.kscience.visionforge.*
+import space.kscience.visionforge.MutableVisionContainer
+import space.kscience.visionforge.VisionBuilder
+import space.kscience.visionforge.root
+import space.kscience.visionforge.setChild
@Serializable
@SerialName("solid.line")
-public class PolyLine(public val points: List) : SolidBase() {
+public class PolyLine(public val points: List) : SolidBase() {
//var lineType by string()
public var thickness: Number by properties.root(inherit = false, includeStyles = true).number { DEFAULT_THICKNESS }
@@ -19,7 +22,7 @@ public class PolyLine(public val points: List) : SolidBase()
@VisionBuilder
public fun MutableVisionContainer.polyline(
- vararg points: Point3D,
+ vararg points: Float32Vector3D,
name: String? = null,
action: PolyLine.() -> Unit = {},
): PolyLine = PolyLine(points.toList()).apply(action).also { setChild(name, it) }
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt
index f99e4bbf..f33573d7 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt
@@ -8,6 +8,9 @@ import space.kscience.dataforge.meta.descriptors.value
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus
+import space.kscience.kmath.complex.Quaternion
+import space.kscience.kmath.complex.QuaternionField
+import space.kscience.kmath.geometry.*
import space.kscience.visionforge.*
import space.kscience.visionforge.Vision.Companion.VISIBLE_KEY
import space.kscience.visionforge.solid.Solid.Companion.DETAIL_KEY
@@ -58,8 +61,6 @@ public interface Solid : Vision {
public val ROTATION_KEY: Name = "rotation".asName()
- public val QUATERNION_KEY: Name = "quaternion".asName()
-
public val X_ROTATION_KEY: Name = ROTATION_KEY + X_KEY
public val Y_ROTATION_KEY: Name = ROTATION_KEY + Y_KEY
public val Z_ROTATION_KEY: Name = ROTATION_KEY + Z_KEY
@@ -122,15 +123,6 @@ public var Solid.layer: Int
// Common properties
-public enum class RotationOrder {
- XYZ,
- YZX,
- ZXY,
- XZY,
- YXZ,
- ZYX
-}
-
/**
* Rotation order
*/
@@ -174,18 +166,21 @@ internal fun point(
defaultX: Float,
defaultY: Float = defaultX,
defaultZ: Float = defaultX,
-): ReadWriteProperty =
- object : ReadWriteProperty {
- override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? {
+): ReadWriteProperty =
+ object : ReadWriteProperty {
+ override fun getValue(thisRef: Solid, property: KProperty<*>): Float32Vector3D? {
val item = thisRef.properties.own?.get(name) ?: return null
- return object : Point3D {
+ //using dynamic property accessor because values could change
+ return object : Float32Vector3D {
override val x: Float get() = item[X_KEY]?.float ?: defaultX
override val y: Float get() = item[Y_KEY]?.float ?: defaultY
override val z: Float get() = item[Z_KEY]?.float ?: defaultZ
+
+ override fun toString(): String = item.toString()
}
}
- override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D?) {
+ override fun setValue(thisRef: Solid, property: KProperty<*>, value: Float32Vector3D?) {
if (value == null) {
thisRef.properties.setProperty(name, null)
} else {
@@ -196,9 +191,9 @@ internal fun point(
}
}
-public var Solid.position: Point3D? by point(POSITION_KEY, 0f)
-public var Solid.rotation: Point3D? by point(ROTATION_KEY, 0f)
-public var Solid.scale: Point3D? by point(SCALE_KEY, 1f)
+public var Solid.position: Float32Vector3D? by point(POSITION_KEY, 0f)
+public var Solid.rotation: Float32Vector3D? by point(ROTATION_KEY, 0f)
+public var Solid.scale: Float32Vector3D? by point(SCALE_KEY, 1f)
public var Solid.x: Number by float(X_POSITION_KEY, 0f)
public var Solid.y: Number by float(Y_POSITION_KEY, 0f)
@@ -208,33 +203,49 @@ public var Solid.rotationX: Number by float(X_ROTATION_KEY, 0f)
public var Solid.rotationY: Number by float(Y_ROTATION_KEY, 0f)
public var Solid.rotationZ: Number by float(Z_ROTATION_KEY, 0f)
-public var Solid.quaternion: Pair?
- get() = properties.getValue(Solid.QUATERNION_KEY)?.list?.let {
+/**
+ * Raw quaternion value defined in properties
+ */
+public var Solid.quaternionOrNull: Quaternion?
+ get() = properties.getValue(ROTATION_KEY)?.list?.let {
require(it.size == 4) { "Quaternion must be a number array of 4 elements" }
- it[0].float to Point3D(it[1].float, it[2].float, it[3].float)
+ Quaternion(it[0].float, it[1].float, it[2].float, it[3].float)
}
set(value) {
properties.setValue(
- Solid.QUATERNION_KEY,
+ ROTATION_KEY,
value?.let {
ListValue(
- value.first,
- value.second.x,
- value.second.y,
- value.second.z
+ value.w,
+ value.x,
+ value.y,
+ value.z
)
}
)
}
-
-//public var Solid.quaternion: Quaternion?
-// get() = meta[Solid::quaternion.name]?.value?.doubleArray?.let { Quaternion(it) }
-// set(value) {
-// meta[Solid::quaternion.name] = value?.values?.asValue()
-// }
-
+/**
+ * Quaternion value including information from euler angles
+ */
+public var Solid.quaternion: Quaternion
+ get() = quaternionOrNull ?: Quaternion.fromEuler(
+ rotationX.radians,
+ rotationY.radians,
+ rotationZ.radians,
+ rotationOrder
+ )
+ set(value) {
+ quaternionOrNull = value
+ }
public var Solid.scaleX: Number by float(X_SCALE_KEY, 1f)
public var Solid.scaleY: Number by float(Y_SCALE_KEY, 1f)
-public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
\ No newline at end of file
+public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
+
+/**
+ * Add rotation with given [angle] relative to given [axis]
+ */
+public fun Solid.rotate(angle: Angle, axis: DoubleVector3D): Unit = with(QuaternionField) {
+ quaternion = Quaternion.fromRotation(angle, axis)*quaternion
+}
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt
index f601a30e..d36057d3 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt
@@ -17,7 +17,7 @@ import space.kscience.visionforge.VisionBuilder
*/
public interface PrototypeHolder {
/**
- * Build or update prototype tree
+ * Build or update the prototype tree
*/
@VisionBuilder
public fun prototypes(builder: MutableVisionContainer.() -> Unit)
@@ -43,6 +43,9 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable
it to value
}.toMap()
+ /**
+ * Get a child solid with given relative [name] if it exists
+ */
public operator fun get(name: Name): Solid? = children.getChild(name) as? Solid
private var prototypes: SolidGroup?
@@ -84,6 +87,8 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable
}
}
+public operator fun SolidGroup.get(name:String): Solid? = get(name.parseAsName())
+
@VisionBuilder
public inline fun MutableVisionContainer.solidGroup(
name: Name? = null,
@@ -99,3 +104,8 @@ public inline fun MutableVisionContainer.solidGroup(
name: String,
action: SolidGroup.() -> Unit = {},
): SolidGroup = solidGroup(name.parseAsName(), action)
+
+/**
+ * Create a [SolidGroup] using given configuration [block]
+ */
+public inline fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt
index 80db0b3e..2770a7aa 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt
@@ -2,7 +2,9 @@ package space.kscience.visionforge.solid
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -61,7 +63,7 @@ public class SolidReference(
}
override fun getValue(name: Name, inherit: Boolean?, includeStyles: Boolean?): Value? {
- if(name == Vision.STYLE_KEY){
+ if (name == Vision.STYLE_KEY) {
return buildList {
properties?.getValue(Vision.STYLE_KEY)?.list?.forEach {
add(it)
@@ -90,7 +92,7 @@ public class SolidReference(
prototype.getStyleProperty(name)?.value?.let { return it }
}
- if(inheritFlag){
+ if (inheritFlag) {
//5. own inheritance
parent?.properties?.getValue(name, inheritFlag, includeStyles)?.let { return it }
//6. prototype inheritance
@@ -226,13 +228,13 @@ internal class SolidReferenceChild(
*/
public fun MutableVisionContainer.ref(
templateName: Name,
- name: String? = null,
+ name: Name? = null,
): SolidReference = SolidReference(templateName).also { setChild(name, it) }
public fun MutableVisionContainer.ref(
- templateName: String,
- name: String? = null,
-): SolidReference = ref(Name.parse(templateName), name)
+ templateName: Name,
+ name: String,
+): SolidReference = ref(templateName, name.parseAsName())
/**
* Add new [SolidReference] wrapping given object and automatically adding it to the prototypes.
@@ -251,7 +253,7 @@ public fun SolidGroup.newRef(
} else if (existing != obj) {
error("Can't add different prototype on top of existing one")
}
- return children.ref(prototypeName, name)
+ return children.ref(prototypeName, name?.parseAsName())
}
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 4900fc1f..1477c2a0 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
@@ -48,9 +48,12 @@ public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer Unit, block: SolidGroup.() -> Unit): SolidGroup =
+ solid(Canvas3DOptions(options), block)
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt
index ed43f663..224e8bba 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt
@@ -20,12 +20,12 @@ public class Sphere(
) : SolidBase(), GeometrySolid {
override fun toGeometry(geometryBuilder: GeometryBuilder) {
- fun point3dFromSphCoord(r: Float, theta: Float, phi: Float): Point3D {
+ fun point3dFromSphCoord(r: Float, theta: Float, phi: Float): Float32Vector3D {
// 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)
+ return Float32Vector3D(x, y, z)
}
val segments = this.detail ?: 32
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt
index bb630772..fa025df2 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt
@@ -27,12 +27,12 @@ public class SphereLayer(
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 {
+ fun point3dFromSphCoord(r: Float, theta: Float, phi: Float): Float32Vector3D {
// 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)
+ return Float32Vector3D(x, y, z)
}
val segments = detail ?: 32
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/StlSolid.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/StlSolid.kt
new file mode 100644
index 00000000..b9d9d835
--- /dev/null
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/StlSolid.kt
@@ -0,0 +1,25 @@
+package space.kscience.visionforge.solid
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import space.kscience.visionforge.MutableVisionContainer
+import space.kscience.visionforge.VisionBuilder
+import space.kscience.visionforge.setChild
+
+
+public sealed class StlSolid: SolidBase()
+
+@Serializable
+@SerialName("solid.stl.url")
+public class StlUrlSolid(public val url: String) : StlSolid()
+
+@Serializable
+@SerialName("solid.stl.binary")
+public class StlBinarySolid(public val data: ByteArray) : StlSolid()
+
+@VisionBuilder
+public inline fun MutableVisionContainer.stl(
+ url: String,
+ name: String? = null,
+ action: StlSolid.() -> Unit = {},
+): StlSolid = StlUrlSolid(url).apply(action).also { setChild(name, it) }
\ No newline at end of file
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt
index e9c9c146..58c3021d 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt
@@ -1,10 +1,5 @@
package space.kscience.visionforge.solid
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaProvider
import space.kscience.dataforge.meta.float
@@ -13,105 +8,48 @@ import space.kscience.visionforge.solid.Solid.Companion.X_KEY
import space.kscience.visionforge.solid.Solid.Companion.Y_KEY
import space.kscience.visionforge.solid.Solid.Companion.Z_KEY
import kotlin.math.PI
-import kotlin.math.pow
-import kotlin.math.sqrt
public const val PI2: Float = 2 * PI.toFloat()
-@Serializable
-public data class Point2D(public var x: Float, public var y: Float)
-
-public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toFloat(), y.toFloat())
-
-public fun Point2D.toMeta(): Meta = Meta {
+public fun Float32Vector2D.toMeta(): Meta = Meta {
X_KEY put x
Y_KEY put y
}
-internal fun Meta.point2D(): Point2D = Point2D(this["x"].float ?: 0f, this["y"].float ?: 0f)
+internal fun Meta.toVector2D(): Float32Vector2D =
+ Float32Vector2D(this["x"].float ?: 0f, this["y"].float ?: 0f)
-@Serializable(Point3DSerializer::class)
-public interface Point3D {
- public val x: Float
- public val y: Float
- public val z: Float
+//@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
+//@Serializable(Point3DSerializer::class)
+//public interface MutablePoint3D : Float32Vector3D {
+// override var x: Float
+// override var y: Float
+// override var z: Float
+//}
+//
+//
+//public fun MutablePoint3D.normalizeInPlace() {
+// val norm = sqrt(x.pow(2) + y.pow(2) + z.pow(2))
+// x /= norm
+// y /= norm
+// z /= norm
+//}
- public companion object {
- public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
- public val ONE: Point3D = Point3D(1.0, 1.0, 1.0)
- }
-}
-
-@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
-@Serializable(Point3DSerializer::class)
-public interface MutablePoint3D : Point3D {
- override var x: Float
- override var y: Float
- override var z: Float
-}
-
-@Serializable
-private class Point3DImpl(override var x: Float, override var y: Float, override var z: Float) : MutablePoint3D
-
-internal object Point3DSerializer : KSerializer {
-
- override val descriptor: SerialDescriptor = Point3DImpl.serializer().descriptor
-
- override fun deserialize(decoder: Decoder): MutablePoint3D = decoder.decodeSerializableValue(Point3DImpl.serializer())
-
- override fun serialize(encoder: Encoder, value: Point3D) {
- val impl: Point3DImpl = (value as? Point3DImpl) ?: Point3DImpl(value.x, value.y, value.z)
- encoder.encodeSerializableValue(Point3DImpl.serializer(), impl)
- }
-}
-
-public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3DImpl(x.toFloat(), y.toFloat(), z.toFloat())
-
-public operator fun Point3D.plus(other: Point3D): Point3D = Point3D(
- this.x + other.x,
- this.y + other.y,
- this.z + other.z
+internal fun MetaProvider.point3D(default: Float = 0f) = Float32Euclidean3DSpace.vector(
+ getMeta(X_KEY).float ?: default,
+ getMeta(Y_KEY).float ?: default,
+ getMeta(Z_KEY).float ?: default
)
-public operator fun Point3D.minus(other: Point3D): Point3D = Point3D(
- this.x - other.x,
- this.y - other.y,
- this.z - other.z
-)
-public operator fun Point3D.unaryMinus(): Point3D = Point3D(
- -x,
- -y,
- -z
-)
-
-public infix fun Point3D.cross(other: Point3D): Point3D = Point3D(
- y * other.z - z * other.y,
- z * other.x - x * other.z,
- x * other.y - y * other.x
-)
-
-public fun MutablePoint3D.normalizeInPlace() {
- val norm = sqrt(x.pow(2) + y.pow(2) + z.pow(2))
- x /= norm
- y /= norm
- z /= norm
-}
-
-internal fun MetaProvider.point3D(default: Float = 0f) = object : Point3D {
- override val x: Float by float(default)
- override val y: Float by float(default)
- override val z: Float by float(default)
-}
-
-public fun Point3D.toMeta(): Meta = Meta {
+public fun Float32Vector3D.toMeta(): Meta = Meta {
X_KEY put x
Y_KEY put y
Z_KEY put z
}
-internal fun Meta.toVector(default: Float = 0f) = Point3D(
+internal fun Meta.toVector3D(default: Float = 0f) = Float32Vector3D(
this[X_KEY].float ?: default,
this[Y_KEY].float ?: default,
this[Z_KEY].float ?: default
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/AxesScheme.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/AxesScheme.kt
index d4eb8e2b..0ed9126e 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/AxesScheme.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/AxesScheme.kt
@@ -7,11 +7,13 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.value
import space.kscience.dataforge.meta.double
+@Deprecated("Use separate axes object instead")
public class AxesScheme : Scheme() {
public var visible: Boolean by boolean(false)
public var size: Double by double(AXIS_SIZE)
public var width: Double by double(AXIS_WIDTH)
+ @Suppress("DEPRECATION")
public companion object : SchemeSpec(::AxesScheme) {
public const val AXIS_SIZE: Double = 1000.0
public const val AXIS_WIDTH: Double = 3.0
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt
index 78e35dfa..b24c9b75 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt
@@ -59,6 +59,7 @@ public class CanvasSize : Scheme() {
}
public class Canvas3DOptions : Scheme() {
+ @Suppress("DEPRECATION")
public var axes: AxesScheme by spec(AxesScheme)
public var camera: CameraScheme by spec(CameraScheme)
public var controls: ControlsScheme by spec(ControlsScheme)
@@ -75,6 +76,7 @@ public class Canvas3DOptions : Scheme() {
public companion object : SchemeSpec(::Canvas3DOptions) {
override val descriptor: MetaDescriptor by lazy {
MetaDescriptor {
+ @Suppress("DEPRECATION")
scheme(Canvas3DOptions::axes, AxesScheme)
value(Canvas3DOptions::layers) {
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt
index 6a309d94..d2667e76 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt
@@ -3,6 +3,7 @@ package space.kscience.visionforge.solid.transform
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
+import space.kscience.kmath.complex.QuaternionField
import space.kscience.visionforge.root
import space.kscience.visionforge.solid.*
@@ -14,10 +15,7 @@ internal fun Solid.updateFrom(other: Solid): Solid {
x += other.x
y += other.y
z += other.y
- if(quaternion != null || other.quaternion != null) TODO("Quaternion support not implemented")
- rotationX += other.rotationX
- rotationY += other.rotationY
- rotationZ += other.rotationZ
+ quaternion = with(QuaternionField) { other.quaternion * quaternion }
scaleX *= other.scaleX
scaleY *= other.scaleY
scaleZ *= other.scaleZ
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/CompositeTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/CompositeTest.kt
index e426aee2..a7c1c688 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/CompositeTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/CompositeTest.kt
@@ -18,7 +18,7 @@ class CompositeTest {
detail = 32
}
material {
- color.set("pink")
+ color("pink")
}
}
}
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/ConvexTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/ConvexTest.kt
index 79274e62..8d838f6b 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/ConvexTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/ConvexTest.kt
@@ -2,13 +2,10 @@ package space.kscience.visionforge.solid
import space.kscience.dataforge.meta.getIndexed
import space.kscience.dataforge.meta.toMeta
-import space.kscience.dataforge.misc.DFExperimental
import kotlin.test.Test
import kotlin.test.assertEquals
class ConvexTest {
- @OptIn(DFExperimental::class)
- @Suppress("UNUSED_VARIABLE")
@Test
fun testConvexBuilder() {
val group = testSolids.solidGroup {
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt
index 7f5138b1..78e2f03c 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt
@@ -18,7 +18,7 @@ class GroupTest {
}
box(100, 100, 100)
material {
- color.set(Colors.lightgreen)
+ color(Colors.lightgreen)
opacity = 0.3f
}
}
@@ -30,7 +30,7 @@ class GroupTest {
}
box(100, 100, 100)
y = 300
- color.set(Colors.red)
+ color(Colors.red)
}
subtract("subtract") {
box(100, 100, 100) {
@@ -40,7 +40,7 @@ class GroupTest {
}
box(100, 100, 100)
y = -300
- color.set(Colors.blue)
+ color(Colors.blue)
}
}
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt
index 2497b5b3..e3069647 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt
@@ -24,7 +24,7 @@ class SerializationTest {
@Test
fun testCubeSerialization() {
val cube = Box(100f, 100f, 100f).apply {
- color.set(222)
+ color(222)
x = 100
z = -100
}
@@ -37,7 +37,7 @@ class SerializationTest {
@Test
fun testProxySerialization() {
val cube = Box(100f, 100f, 100f).apply {
- color.set(222)
+ color(222)
x = 100
z = -100
}
@@ -59,7 +59,7 @@ class SerializationTest {
fun lightSerialization(){
val group = testSolids.solidGroup {
ambientLight {
- color.set(Colors.white)
+ color(Colors.white)
intensity = 100.0
}
}
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPropertyTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPropertyTest.kt
index 5fa22b86..87ba368c 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPropertyTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPropertyTest.kt
@@ -20,7 +20,7 @@ class SolidPropertyTest {
val box = Box(10.0f, 10.0f, 10.0f)
box.material {
//meta["color"] = "pink"
- color.set("pink")
+ color("pink")
}
assertEquals("pink", box.properties.getValue("material.color")?.string)
assertEquals("pink", box.color.string)
@@ -41,7 +41,7 @@ class SolidPropertyTest {
delay(5)
box.material {
- color.set("pink")
+ color("pink")
}
assertEquals("pink", c.await())
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt
index 8e851cb5..d8d971bb 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt
@@ -16,7 +16,7 @@ class SolidReferenceTest {
SolidMaterial.MATERIAL_COLOR_KEY put "red"
}
newRef("test", Box(100f,100f,100f).apply {
- color.set("blue")
+ color("blue")
useStyle(theStyle)
})
}
diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt
index 50e9362d..0e495aaa 100644
--- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt
+++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt
@@ -22,7 +22,7 @@ internal class VisionUpdateTest {
}
val dif = visionManager.VisionChange {
solidGroup("top") {
- color.set(123)
+ color(123)
box(100, 100, 100)
}
propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue()))
@@ -41,7 +41,7 @@ internal class VisionUpdateTest {
fun testVisionChangeSerialization() {
val change = visionManager.VisionChange {
solidGroup("top") {
- color.set(123)
+ color(123)
box(100, 100, 100)
}
propertyChanged("top".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue()))
diff --git a/visionforge-tables/build.gradle.kts b/visionforge-tables/build.gradle.kts
index 23d77912..cf813e6e 100644
--- a/visionforge-tables/build.gradle.kts
+++ b/visionforge-tables/build.gradle.kts
@@ -9,9 +9,9 @@ kscience {
js {
useCommonJs()
binaries.library()
- browser{
- commonWebpackConfig{
- cssSupport{
+ browser {
+ commonWebpackConfig {
+ cssSupport {
enabled.set(true)
}
}
@@ -21,13 +21,13 @@ kscience {
api(projects.visionforgeCore)
api("space.kscience:tables-kt:${tablesVersion}")
}
- dependencies(jsMain){
- implementation(npm("tabulator-tables", "5.0.1"))
- implementation(npm("@types/tabulator-tables", "5.0.1"))
+ dependencies(jsMain) {
+ implementation(npm("tabulator-tables", "5.4.4"))
+ implementation(npm("@types/tabulator-tables", "5.4.8"))
}
useSerialization()
}
-readme{
+readme {
maturity = space.kscience.gradle.Maturity.PROTOTYPE
}
\ No newline at end of file
diff --git a/visionforge-tables/src/commonMain/kotlin/space/kscience/visionforge/tables/VisionOfTable.kt b/visionforge-tables/src/commonMain/kotlin/space/kscience/visionforge/tables/VisionOfTable.kt
index 20332974..3e4f9da8 100644
--- a/visionforge-tables/src/commonMain/kotlin/space/kscience/visionforge/tables/VisionOfTable.kt
+++ b/visionforge-tables/src/commonMain/kotlin/space/kscience/visionforge/tables/VisionOfTable.kt
@@ -86,6 +86,11 @@ public fun Table.toVision(): VisionOfTable = toVision { (it ?: "").asVal
@JvmName("numberTableToVision")
public fun Table.toVision(): VisionOfTable = toVision { (it ?: Double.NaN).asValue() }
+@JvmName("anyTableToVision")
+public fun Table.toVision(): VisionOfTable = toVision {
+ (it as? Number)?.asValue() ?: it?.toString()?.asValue() ?: Null
+}
+
@DFExperimental
public inline fun VisionOutput.table(
vararg headers: ColumnHeader,
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAmbientLightFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAmbientLightFactory.kt
index 3f8e251c..f15f2c78 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAmbientLightFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAmbientLightFactory.kt
@@ -14,7 +14,7 @@ import kotlin.reflect.KClass
public object ThreeAmbientLightFactory : ThreeFactory {
override val type: KClass get() = AmbientLightSource::class
- override fun build(three: ThreePlugin, vision: AmbientLightSource, observe: Boolean): AmbientLight {
+ override suspend fun build(three: ThreePlugin, vision: AmbientLightSource, observe: Boolean): AmbientLight {
val res = AmbientLight().apply {
color = vision.color.threeColor() ?: Color(0x404040)
intensity = vision.intensity.toDouble()
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAxesFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAxesFactory.kt
new file mode 100644
index 00000000..8af445b9
--- /dev/null
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeAxesFactory.kt
@@ -0,0 +1,22 @@
+package space.kscience.visionforge.solid.three
+
+import space.kscience.visionforge.onPropertyChange
+import space.kscience.visionforge.solid.AxesSolid
+import three.helpers.AxesHelper
+import kotlin.reflect.KClass
+
+public object ThreeAxesFactory : ThreeFactory {
+ override val type: KClass get() = AxesSolid::class
+
+ override suspend fun build(three: ThreePlugin, vision: AxesSolid, observe: Boolean): AxesHelper {
+ val res = AxesHelper(vision.size.toInt())
+
+ if (observe) {
+ vision.onPropertyChange(three.context) { propertyName ->
+ res.updateProperty(vision, propertyName)
+ }
+ }
+
+ return res
+ }
+}
\ No newline at end of file
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt
index 21c52198..d6840f75 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt
@@ -5,7 +5,7 @@ import space.kscience.visionforge.solid.detail
import three.geometries.BoxGeometry
public object ThreeBoxFactory : ThreeMeshFactory(Box::class) {
- override fun buildGeometry(obj: Box): BoxGeometry =
+ override suspend fun buildGeometry(obj: Box): BoxGeometry =
obj.detail?.let { detail ->
BoxGeometry(obj.xSize, obj.ySize, obj.zSize, detail, detail, detail)
} ?: BoxGeometry(obj.xSize, obj.ySize, obj.zSize)
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt
index 4e6935a8..c692b88d 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt
@@ -1,6 +1,7 @@
package space.kscience.visionforge.solid.three
import kotlinx.browser.window
+import kotlinx.coroutines.launch
import org.w3c.dom.Element
import org.w3c.dom.HTMLCanvasElement
import org.w3c.dom.Node
@@ -56,16 +57,6 @@ public class ThreeCanvas(
axesObject.name = AXES_NAME
add(axesObject)
}
-
-// //Set up light
-// options.useProperty(Canvas3DOptions::light, this) { lightConfig ->
-// //remove old light if present
-// getObjectByName(LIGHT_NAME)?.let { remove(it) }
-// //add new light
-// val lightObject = buildLight(lightConfig)
-// lightObject.name = LIGHT_NAME
-// add(lightObject)
-// }
}
@@ -109,7 +100,7 @@ public class ThreeCanvas(
}
/**
- * Force camera aspect ration and renderer size recalculation
+ * Force camera aspect ratio and renderer size recalculation
*/
private fun updateSize() {
val width = element.clientWidth
@@ -201,7 +192,7 @@ public class ThreeCanvas(
}
/**
- * Resolve full name of the object relative to the global root
+ * Resolve the full name of the object relative to the global root
*/
private fun Object3D.fullName(): Name {
if (root == null) error("Can't resolve element name without the root")
@@ -212,7 +203,7 @@ public class ThreeCanvas(
}
}
- //find first non-static parent in this object ancestry
+ //find the first non-static parent in this object ancestry
private tailrec fun Object3D.upTrace(): Object3D? = if (!name.startsWith("@")) this else parent?.upTrace()
private fun pick(): Object3D? {
@@ -264,11 +255,13 @@ public class ThreeCanvas(
scene.findChild("@root".asName())?.let { scene.remove(it) }
root?.dispose()
}
+ three.context.launch {
+ val object3D = three.buildObject3D(vision)
- val object3D = three.buildObject3D(vision)
- object3D.name = "@root"
- scene.add(object3D)
- root = object3D
+ object3D.name = "@root"
+ scene.add(object3D)
+ root = object3D
+ }
}
private var selected: Object3D? = null
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvasLabelFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvasLabelFactory.kt
index b9f2a7d2..93bf170b 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvasLabelFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCanvasLabelFactory.kt
@@ -22,7 +22,7 @@ import kotlin.reflect.KClass
public object ThreeCanvasLabelFactory : ThreeFactory {
override val type: KClass get() = SolidLabel::class
- override fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D {
+ override suspend fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D {
val canvas = document.createElement("canvas") as HTMLCanvasElement
canvas.width = 200
canvas.height = 200
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt
index fe40022d..e6e9641c 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt
@@ -38,7 +38,7 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory
override val type: KClass get() = Composite::class
- override fun build(three: ThreePlugin, vision: Composite, observe: Boolean): Mesh {
+ override suspend fun build(three: ThreePlugin, vision: Composite, observe: Boolean): Mesh {
val first = three.buildObject3D(vision.first, observe).takeIfMesh()
?: error("First part of composite is not a mesh")
val second = three.buildObject3D(vision.second, observe).takeIfMesh()
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt
index 6b2db845..bcc147c7 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt
@@ -8,7 +8,7 @@ import kotlin.math.PI
import kotlin.math.pow
public object ThreeConeFactory : ThreeMeshFactory(ConeSegment::class) {
- override fun buildGeometry(obj: ConeSegment): BufferGeometry {
+ override suspend fun buildGeometry(obj: ConeSegment): BufferGeometry {
val cylinder = obj.detail?.let {
val segments = it.toDouble().pow(0.5).toInt()
CylinderGeometry(
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt
index 83115b13..b772c1bf 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt
@@ -4,7 +4,7 @@ import space.kscience.visionforge.solid.Convex
import three.external.geometries.ConvexBufferGeometry
public object ThreeConvexFactory : ThreeMeshFactory(Convex::class) {
- override fun buildGeometry(obj: Convex): ConvexBufferGeometry {
+ override suspend fun buildGeometry(obj: Convex): ConvexBufferGeometry {
val vectors = obj.points.map { it.toVector() }.toTypedArray()
return ConvexBufferGeometry(vectors)
}
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt
index a0852c72..122a2c30 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt
@@ -26,7 +26,7 @@ public interface ThreeFactory {
* Build an [Object3D] from [vision].
* @param observe if false, does not observe the changes in [vision] after render (useful for statics).
*/
- public fun build(three: ThreePlugin, vision: T, observe: Boolean = true): Object3D
+ public suspend fun build(three: ThreePlugin, vision: T, observe: Boolean = true): Object3D
public companion object {
public const val TYPE: String = "threeFactory"
@@ -37,27 +37,19 @@ public interface ThreeFactory {
* Update position, rotation and visibility
*/
public fun Object3D.updatePosition(vision: Vision) {
- visible = vision.visible ?: true
+// visible = vision.visible ?: true
if (vision is Solid) {
position.set(vision.x, vision.y, vision.z)
-// val quaternion = obj.quaternion
-//
-// if (quaternion != null) {
-// val (x, y, z, w) = quaternion
-// setRotationFromQuaternion(Quaternion(x, y, z, w))
-// } else {
-// setRotationFromEuler( Euler(obj.rotationX, obj.rotationY, obj.rotationZ, obj.rotationOrder.name))
-// }
- val quaternion = vision.quaternion
+ val quaternion = vision.quaternionOrNull
if (quaternion != null) {
setRotationFromQuaternion(
Quaternion(
- quaternion.second.x,
- quaternion.second.y,
- quaternion.second.z,
- quaternion.first
+ quaternion.x,
+ quaternion.y,
+ quaternion.z,
+ quaternion.w
)
)
} else {
@@ -92,7 +84,7 @@ public fun Object3D.updateProperty(source: Vision, propertyName: Name) {
* Generic factory for elements which provide inside geometry builder
*/
public object ThreeShapeFactory : ThreeMeshFactory(GeometrySolid::class) {
- override fun buildGeometry(obj: GeometrySolid): BufferGeometry = ThreeGeometryBuilder().apply {
+ override suspend fun buildGeometry(obj: GeometrySolid): BufferGeometry = ThreeGeometryBuilder().apply {
obj.toGeometry(this)
}.build()
}
\ No newline at end of file
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeGeometryBuilder.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeGeometryBuilder.kt
index d97c354a..7a5f3c49 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeGeometryBuilder.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeGeometryBuilder.kt
@@ -1,15 +1,14 @@
package space.kscience.visionforge.solid.three
import space.kscience.dataforge.meta.Meta
+import space.kscience.visionforge.solid.Float32Euclidean3DSpace
+import space.kscience.visionforge.solid.Float32Vector3D
import space.kscience.visionforge.solid.GeometryBuilder
-import space.kscience.visionforge.solid.Point3D
-import space.kscience.visionforge.solid.cross
-import space.kscience.visionforge.solid.minus
import three.core.BufferGeometry
import three.core.Float32BufferAttribute
import three.math.Vector3
-internal fun Point3D.toVector() = Vector3(x, y, z)
+internal fun Float32Vector3D.toVector() = Vector3(x, y, z)
internal fun MutableList.add(vararg values: T) {
values.forEach {
@@ -27,10 +26,10 @@ public class ThreeGeometryBuilder : GeometryBuilder {
private val normals = ArrayList()
// private val colors = ArrayList()
- private val vertexCache = HashMap()
+ private val vertexCache = HashMap()
private var counter: Short = -1
- private fun vertex(vertex: Point3D, normal: Point3D): Short = vertexCache.getOrPut(vertex) {
+ private fun vertex(vertex: Float32Vector3D, normal: Float32Vector3D): Short = vertexCache.getOrPut(vertex) {
//add vertex and update cache if needed
positions.add(vertex.x, vertex.y, vertex.z)
normals.add(normal.x, vertex.y, vertex.z)
@@ -39,8 +38,14 @@ public class ThreeGeometryBuilder : GeometryBuilder {
counter
}
- override fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D?, meta: Meta) {
- val actualNormal: Point3D = normal ?: ((vertex3 - vertex2) cross (vertex1 - vertex2))
+ override fun face(
+ vertex1: Float32Vector3D,
+ vertex2: Float32Vector3D,
+ vertex3: Float32Vector3D,
+ normal: Float32Vector3D?,
+ meta: Meta,
+ ) = with(Float32Euclidean3DSpace) {
+ val actualNormal: Float32Vector3D = normal ?: ((vertex3 - vertex2) cross (vertex1 - vertex2))
indices.add(
vertex(vertex1, actualNormal),
vertex(vertex2, actualNormal),
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt
index 9d4b8e86..6f6e166a 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt
@@ -7,5 +7,5 @@ import three.core.Object3D
* A custom visual object that has its own Three.js renderer
*/
public abstract class ThreeJsVision : SolidBase() {
- public abstract fun render(three: ThreePlugin): Object3D
+ public abstract suspend fun render(three: ThreePlugin): Object3D
}
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLabelFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLabelFactory.kt
index e168c1d2..45068a3a 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLabelFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLabelFactory.kt
@@ -17,7 +17,7 @@ import kotlin.reflect.KClass
public object ThreeLabelFactory : ThreeFactory {
override val type: KClass get() = SolidLabel::class
- override fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D {
+ override suspend fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D {
val textGeo = TextBufferGeometry(vision.text, jso {
font = vision.fontFamily
size = 20
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLineFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLineFactory.kt
index edfd6b65..45325430 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLineFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeLineFactory.kt
@@ -16,7 +16,7 @@ import kotlin.reflect.KClass
public object ThreeLineFactory : ThreeFactory {
override val type: KClass get() = PolyLine::class
- override fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
+ override suspend fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
val geometry = BufferGeometry().apply {
setFromPoints(Array((vision.points.size - 1) * 2) {
vision.points[ceil(it / 2.0).toInt()].toVector()
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt
index 30f3034b..06224bbb 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt
@@ -21,12 +21,13 @@ import kotlin.reflect.KClass
public abstract class ThreeMeshFactory(
override val type: KClass,
) : ThreeFactory {
+
/**
* Build a geometry for an object
*/
- public abstract fun buildGeometry(obj: T): BufferGeometry
+ public abstract suspend fun buildGeometry(obj: T): BufferGeometry
- override fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh {
+ override suspend fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh {
val geometry = buildGeometry(vision)
val mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply {
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshLineFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshLineFactory.kt
index 3d9b4c3b..4a94823b 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshLineFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeMeshLineFactory.kt
@@ -15,7 +15,7 @@ import kotlin.reflect.KClass
public object ThreeMeshLineFactory : ThreeFactory {
override val type: KClass get() = PolyLine::class
- override fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
+ override suspend fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
val geometry = MeshLine(
Array((vision.points.size - 1) * 2) {
vision.points[ceil(it / 2.0).toInt()].toVector()
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt
index 8f577baa..c1c2cf4d 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt
@@ -37,6 +37,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
objectFactories[PointLightSource::class] = ThreePointLightFactory
+ objectFactories[StlSolid::class] = ThreeStlFactory
+ objectFactories[AxesSolid::class] = ThreeAxesFactory
}
@Suppress("UNCHECKED_CAST")
@@ -46,7 +48,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
as ThreeFactory?
}
- public fun buildObject3D(vision: Solid, observe: Boolean = true): Object3D = when (vision) {
+ public suspend fun buildObject3D(vision: Solid, observe: Boolean = true): Object3D = when (vision) {
is ThreeJsVision -> vision.render(this)
is SolidReference -> ThreeReferenceFactory.build(this, vision, observe)
is SolidGroup -> {
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePointLightFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePointLightFactory.kt
index fdd2e019..b0a0bfeb 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePointLightFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePointLightFactory.kt
@@ -13,7 +13,7 @@ public object ThreePointLightFactory : ThreeFactory {
private val DEFAULT_COLOR = Color(0x404040)
- override fun build(three: ThreePlugin, vision: PointLightSource, observe: Boolean): PointLight {
+ override suspend fun build(three: ThreePlugin, vision: PointLightSource, observe: Boolean): PointLight {
val res = PointLight().apply {
matrixAutoUpdate = false
color = vision.color.threeColor() ?: DEFAULT_COLOR
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt
index 405956f8..beb59df8 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt
@@ -31,7 +31,7 @@ public object ThreeReferenceFactory : ThreeFactory {
}
}
- override fun build(three: ThreePlugin, vision: SolidReference, observe: Boolean): Object3D {
+ override suspend fun build(three: ThreePlugin, vision: SolidReference, observe: Boolean): Object3D {
val template = vision.prototype
val cachedObject = cache.getOrPut(template) {
three.buildObject3D(template)
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSmartLineFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSmartLineFactory.kt
index 2e7329da..b3609b66 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSmartLineFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSmartLineFactory.kt
@@ -7,11 +7,13 @@ import kotlin.reflect.KClass
public object ThreeSmartLineFactory : ThreeFactory {
override val type: KClass get() = PolyLine::class
- override fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
- return if (vision.thickness == 1.0) {
- ThreeLineFactory.build(three, vision, observe)
- } else {
- ThreeMeshLineFactory.build(three, vision, observe)
- }
+ override suspend fun build(
+ three: ThreePlugin,
+ vision: PolyLine,
+ observe: Boolean,
+ ): Object3D = if (vision.thickness == 1.0) {
+ ThreeLineFactory.build(three, vision, observe)
+ } else {
+ ThreeMeshLineFactory.build(three, vision, observe)
}
}
\ No newline at end of file
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt
index d738c073..9753f9ad 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt
@@ -6,7 +6,7 @@ import three.core.BufferGeometry
import three.geometries.SphereGeometry
public object ThreeSphereFactory : ThreeMeshFactory(Sphere::class) {
- override fun buildGeometry(obj: Sphere): BufferGeometry {
+ override suspend fun buildGeometry(obj: Sphere): BufferGeometry {
return obj.detail?.let { detail ->
SphereGeometry(
radius = obj.radius,
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeStlFactory.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeStlFactory.kt
new file mode 100644
index 00000000..e3fb676f
--- /dev/null
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreeStlFactory.kt
@@ -0,0 +1,38 @@
+package space.kscience.visionforge.solid.three
+
+import org.khronos.webgl.ArrayBuffer
+import org.khronos.webgl.Int8Array
+import space.kscience.visionforge.solid.StlBinarySolid
+import space.kscience.visionforge.solid.StlSolid
+import space.kscience.visionforge.solid.StlUrlSolid
+import three.core.BufferGeometry
+import three.external.loaders.STLLoader
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
+import kotlin.coroutines.suspendCoroutine
+
+fun ArrayBuffer.toByteArray(): ByteArray = Int8Array(this).unsafeCast()
+
+public object ThreeStlFactory : ThreeMeshFactory(StlSolid::class) {
+
+ private val loader = STLLoader().apply {
+ requestHeader = listOf("Access-Control-Allow-Origin: *")
+ }
+
+ override suspend fun buildGeometry(obj: StlSolid): BufferGeometry = when (obj) {
+ is StlBinarySolid -> loader.parse(obj.data)
+ is StlUrlSolid -> suspendCoroutine { continuation ->
+ loader.load(
+ url = obj.url,
+ onLoad = {
+ continuation.resume(it)
+ },
+ onError = {
+ continuation.resumeWithException(RuntimeException("Failed to load STL object from ${obj.url}"))
+ }
+ )
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/three.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/three.kt
index 9c9d5b2b..f3fc0594 100644
--- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/three.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/three.kt
@@ -12,14 +12,10 @@ import three.math.Vector3
import three.objects.Mesh
import three.textures.Texture
import kotlin.contracts.contract
-import kotlin.math.PI
public val Meta.vector: Vector3 get() = Vector3(this["x"].float ?: 0f, this["y"].float ?: 0f, this["z"].float ?: 0f)
-internal fun Double.toRadians() = this * PI / 180
-
-
internal fun Any.dispose() {
when (this) {
is BufferGeometry -> dispose()
diff --git a/visionforge-threejs/src/jsMain/kotlin/three/external/loaders/STLLoader.kt b/visionforge-threejs/src/jsMain/kotlin/three/external/loaders/STLLoader.kt
index 5fa253ab..e3e6133f 100644
--- a/visionforge-threejs/src/jsMain/kotlin/three/external/loaders/STLLoader.kt
+++ b/visionforge-threejs/src/jsMain/kotlin/three/external/loaders/STLLoader.kt
@@ -22,17 +22,19 @@
* THE SOFTWARE.
*/
-@file:JsModule("three")
+@file:JsModule("three/examples/jsm/loaders/STLLoader.js")
@file:JsNonModule
package three.external.loaders
+import org.khronos.webgl.ArrayBuffer
import org.w3c.xhr.XMLHttpRequest
import three.core.BufferGeometry
-import three.core.Object3D
external class STLLoader {
+ var requestHeader: List
+
fun load(
url: String,
onLoad: (BufferGeometry) -> Unit,
@@ -40,7 +42,10 @@ external class STLLoader {
onError: () -> Unit = definedExternally
)
- fun parse(data: String): Object3D
- fun parse(data: ByteArray): Object3D
+ fun parse(data: String): BufferGeometry
+
+ fun parse(data: ByteArray): BufferGeometry
+
+ fun parse(data: ArrayBuffer): BufferGeometry
}
\ No newline at end of file
diff --git a/visionforge-threejs/visionforge-threejs-server/src/jvmTest/kotlin/space/kscience/visionforge/three/TestServerExtensions.kt b/visionforge-threejs/visionforge-threejs-server/src/jvmTest/kotlin/space/kscience/visionforge/three/TestServerExtensions.kt
index 99e7fba6..95d9e6f7 100644
--- a/visionforge-threejs/visionforge-threejs-server/src/jvmTest/kotlin/space/kscience/visionforge/three/TestServerExtensions.kt
+++ b/visionforge-threejs/visionforge-threejs-server/src/jvmTest/kotlin/space/kscience/visionforge/three/TestServerExtensions.kt
@@ -3,18 +3,20 @@ package space.kscience.visionforge.three
import kotlinx.html.stream.createHTML
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.html.VisionPage
+import space.kscience.visionforge.html.appendTo
import space.kscience.visionforge.html.importScriptHeader
import kotlin.test.Test
class TestServerExtensions {
+ @Suppress("UNUSED_VARIABLE")
@Test
fun testServerHeader(){
val string = createHTML().apply {
VisionPage.importScriptHeader(
"js/visionforge-three.js",
ResourceLocation.SYSTEM
- ).invoke(this)
+ ).appendTo(this)
}.finalize()