Merge pull request #76 from SciProgCentre/dev

0.3.0-dev-17
This commit is contained in:
SPC-code 2023-12-05 16:47:35 +03:00 committed by GitHub
commit 8e5503f0d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
478 changed files with 24605 additions and 5357 deletions

View File

@ -8,15 +8,15 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 40 timeout-minutes: 30
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3.5.3
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v2.5.0 uses: actions/setup-java@v3.12.0
with: with:
java-version: 11 java-version: 11
distribution: liberica distribution: liberica
- name: execute build - name: execute build
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v2.7.1
with: with:
arguments: build arguments: build

2
.gitignore vendored
View File

@ -7,3 +7,5 @@ build/
data/ data/
!gradle-wrapper.jar !gradle-wrapper.jar
/kotlin-js-store/yarn.lock

View File

@ -2,14 +2,27 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- Context receivers flag
- MeshLine for thick lines
- Custom client-side events and thier processing in VisionServer
### Changed ### Changed
- Color accessor property is now `colorProperty`. Color uses non-nullable `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.
- Visions use flows instead of direct subscriptions.
- Radical change of inner workings of vision children and properties.
- Three package changed to `three`.
- Naming of Canvas3D options.
- Lights are added to the scene instead of 3D options.
### Deprecated ### Deprecated
### Removed ### Removed
### Fixed ### Fixed
- Jupyter integration for IDEA and Jupyter lab.
### Security ### Security

View File

@ -1,29 +1,50 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
import space.kscience.gradle.useApache2Licence
import space.kscience.gradle.useSPCTeam
plugins { plugins {
id("ru.mipt.npm.gradle.project") id("space.kscience.gradle.project")
id("org.jetbrains.kotlinx.kover") version "0.5.0-RC" // id("org.jetbrains.kotlinx.kover") version "0.5.0"
} }
val dataforgeVersion by extra("0.5.2") val dataforgeVersion by extra("0.7.1")
val fxVersion by extra("11") val fxVersion by extra("11")
allprojects{ allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.2.0" version = "0.3.0-dev-17"
} }
subprojects { subprojects {
if (name.startsWith("visionforge")) apply<MavenPublishPlugin>() if (name.startsWith("visionforge")) apply<MavenPublishPlugin>()
repositories { repositories {
mavenLocal()
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
mavenCentral() mavenCentral()
maven("https://maven.jzy3d.org/releases") maven("https://maven.jzy3d.org/releases")
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers"
}
}
tasks.withType<KotlinJsCompile>{
kotlinOptions{
useEsClasses = true
}
} }
} }
ksciencePublish { ksciencePublish {
github("visionforge") pom("https://github.com/SciProgCentre/visionforge") {
space() useApache2Licence()
useSPCTeam()
}
repository("spc","https://maven.sciprog.center/kscience")
sonatype() sonatype()
} }

View File

@ -1,19 +1,14 @@
plugins { plugins {
id("ru.mipt.npm.gradle.mpp") id("space.kscience.gradle.mpp")
} }
kscience{ kscience{
jvm()
js()
dependencies {
api(projects.visionforgeSolid)
}
useSerialization { useSerialization {
json() json()
} }
} }
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api(project(":visionforge-solid"))
}
}
}
}

View File

@ -0,0 +1,53 @@
package ru.mipt.npm.root
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import space.kscience.visionforge.solid.Float32Vector3D
@Serializable
public data class FairTrackParam(
val fX: Double,
val fY: Double,
val fZ: Double,
val fTx: Double,
val fTy: Double,
val fQp: Double,
)
public fun FairTrackParam.toVector(): Float32Vector3D = Float32Vector3D(fX,fY,fZ)
@Serializable
public data class CbmStsTrack(
val fParamFirst: FairTrackParam,
val fParamLast: FairTrackParam,
)
@Serializable
public data class BmnGlobalTrack(
val fParamFirst: FairTrackParam,
val fParamLast: FairTrackParam,
)
public class BmnEventContainer(
public val cbmTracks: List<CbmStsTrack>,
public val bmnGlobalTracks: List<BmnGlobalTrack>,
)
public object BMN {
public val json: Json = Json {
ignoreUnknownKeys = true
classDiscriminator = "_typename"
}
public fun readEventJson(string: String): BmnEventContainer {
val jsonArray = json.parseToJsonElement(string) as JsonArray
val cbmTracks: List<CbmStsTrack> =
json.decodeFromJsonElement(ListSerializer(CbmStsTrack.serializer()), jsonArray[0])
val bmnGlobalTracks: List<BmnGlobalTrack> =
json.decodeFromJsonElement(ListSerializer(BmnGlobalTrack.serializer()), jsonArray[1])
return BmnEventContainer(cbmTracks, bmnGlobalTracks)
}
}

View File

@ -5,7 +5,6 @@ import space.kscience.dataforge.meta.*
import space.kscience.dataforge.misc.Named import space.kscience.dataforge.misc.Named
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.values.doubleArray
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
public fun MetaProvider.doubleArray( public fun MetaProvider.doubleArray(
@ -43,7 +42,7 @@ public open class DObject(public val meta: Meta, public val refCache: DObjectCac
} }
internal fun <T : DObject> tObjectArray( internal fun <T : DObject> tObjectArray(
builder: (Meta, DObjectCache) -> T builder: (Meta, DObjectCache) -> T,
): ReadOnlyProperty<Any?, List<T>> = ReadOnlyProperty { _, property -> ): ReadOnlyProperty<Any?, List<T>> = ReadOnlyProperty { _, property ->
meta.getIndexed(Name.of(property.name, "arr")).values.mapNotNull { meta.getIndexed(Name.of(property.name, "arr")).values.mapNotNull {
resolve(builder, it) resolve(builder, it)
@ -52,9 +51,9 @@ public open class DObject(public val meta: Meta, public val refCache: DObjectCac
internal fun <T : DObject> dObject( internal fun <T : DObject> dObject(
builder: (Meta, DObjectCache) -> T, builder: (Meta, DObjectCache) -> T,
key: Name? = null key: Name? = null,
): ReadOnlyProperty<Any?, T?> = ReadOnlyProperty { _, property -> ): ReadOnlyProperty<Any?, T?> = ReadOnlyProperty { _, property ->
meta[key ?: property.name.asName()]?.let { resolve(builder, it) } meta[key ?: property.name.asName()]?.takeIf { it.value != Null }?.let { resolve(builder, it) }
} }
} }
@ -63,8 +62,7 @@ public open class DNamed(meta: Meta, refCache: DObjectCache) : DObject(meta, ref
public val fTitle: String by meta.string("") public val fTitle: String by meta.string("")
} }
public class DGeoMaterial(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache) { public class DGeoMaterial(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache)
}
public class DGeoMedium(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache) { public class DGeoMedium(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache) {
public val fMaterial: DGeoMaterial? by dObject(::DGeoMaterial) public val fMaterial: DGeoMaterial? by dObject(::DGeoMaterial)
@ -91,27 +89,69 @@ public class DGeoNode(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCach
public val fVolume: DGeoVolume? by dObject(::DGeoVolume) public val fVolume: DGeoVolume? by dObject(::DGeoVolume)
} }
public open class DGeoMatrix(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache) public sealed class DGeoMatrix(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache)
public open class DGeoScale(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache) { public class DGeoIdentity(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache)
public class DGeoScale(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache) {
public val fScale: DoubleArray by meta.doubleArray(1.0, 1.0, 1.0) public val fScale: DoubleArray by meta.doubleArray(1.0, 1.0, 1.0)
public val x: Double get() = fScale[0] public val x: Double get() = fScale[0]
public val y: Double get() = fScale[1] public val y: Double get() = fScale[1]
public val z: Double get() = fScale[2] public val z: Double get() = fScale[2]
} }
public class DGeoRotation(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache) {
public val fRotationMatrix: DoubleArray by meta.doubleArray()
}
public class DGeoTranslation(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache) {
public val fTranslation: DoubleArray by meta.doubleArray()
}
public open class DGeoCombiTrans(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache) {
public val fRotation: DGeoRotation? by dObject(::DGeoRotation)
public val fTranslation: DoubleArray by meta.doubleArray()
}
public class DGeoGenTrans(meta: Meta, refCache: DObjectCache) : DGeoCombiTrans(meta, refCache) {
public val fScale: DoubleArray by meta.doubleArray()
}
public class DGeoHMatrix(meta: Meta, refCache: DObjectCache) : DGeoMatrix(meta, refCache) {
public val fRotation: DGeoRotation? by dObject(::DGeoRotation)
public val fTranslation: DoubleArray by meta.doubleArray()
public val fScale: DoubleArray by meta.doubleArray()
}
/**
* Create a specialized version of [DGeoMatrix]
*/
internal fun dGeoMatrix(
meta: Meta,
refCache: DObjectCache,
): DGeoMatrix = when (val typename = meta["_typename"].string) {
null -> error("Type name is undefined")
"TGeoIdentity" -> DGeoIdentity(meta, refCache)
"TGeoScale" -> DGeoScale(meta, refCache)
"TGeoRotation" -> DGeoRotation(meta, refCache)
"TGeoTranslation" -> DGeoTranslation(meta, refCache)
"TGeoCombiTrans" -> DGeoCombiTrans(meta, refCache)
"TGeoGenTrans" -> DGeoGenTrans(meta, refCache)
"TGeoHMatrix" -> DGeoHMatrix(meta, refCache)
else -> error("$typename is not a member of TGeoMatrix")
}
public class DGeoBoolNode(meta: Meta, refCache: DObjectCache) : DObject(meta, refCache) { public class DGeoBoolNode(meta: Meta, refCache: DObjectCache) : DObject(meta, refCache) {
public val fLeft: DGeoShape? by dObject(::DGeoShape) public val fLeft: DGeoShape? by dObject(::DGeoShape)
public val fLeftMat: DGeoMatrix? by dObject(::DGeoMatrix) public val fLeftMat: DGeoMatrix? by dObject(::dGeoMatrix)
public val fRight: DGeoShape? by dObject(::DGeoShape) public val fRight: DGeoShape? by dObject(::DGeoShape)
public val fRightMat: DGeoMatrix? by dObject(::DGeoMatrix) public val fRightMat: DGeoMatrix? by dObject(::dGeoMatrix)
} }
public class DGeoManager(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache) { public class DGeoManager(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCache) {
public val fMatrices: List<DGeoMatrix> by tObjectArray(::DGeoMatrix) public val fMatrices: List<DGeoMatrix> by tObjectArray(::dGeoMatrix)
public val fShapes: List<DGeoShape> by tObjectArray(::DGeoShape) public val fShapes: List<DGeoShape> by tObjectArray(::DGeoShape)

View File

@ -1,13 +1,23 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.double
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.set
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.parseAsName
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import space.kscience.dataforge.values.doubleArray 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.isEmpty
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY 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() private val volumesName = Name.EMPTY //"volumes".asName()
@ -20,51 +30,48 @@ private fun degToRad(d: Double) = d * PI / 180.0
private data class RootToSolidContext( private data class RootToSolidContext(
val prototypeHolder: PrototypeHolder, val prototypeHolder: PrototypeHolder,
val currentLayer: Int = 0, val currentLayer: Int = 0,
val maxLayer: Int = 5 val maxLayer: Int = 5,
val ignoreRootColors: Boolean = false,
val colorCache: MutableMap<Meta, String> = mutableMapOf(),
) )
// converting to XYZ to TaitBryan angles according to https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // apply rotation from a matrix
private fun Solid.rotate(rot: DoubleArray) { private fun Solid.rotate(rot: DoubleArray) {
val xAngle = atan2(-rot[5], rot[8]) val matrix = VirtualMatrix(3, 3) { i, j -> rot[i * 3 + j] }
val yAngle = atan2(rot[2], sqrt(1.0 - rot[2].pow(2))) quaternion = Quaternion.fromRotationMatrix(matrix)
val zAngle = atan2(-rot[1], rot[0])
rotation = Point3D(xAngle, yAngle, zAngle)
} }
private fun Solid.translate(trans: DoubleArray) { private fun Solid.translate(trans: DoubleArray) {
val (x, y, z) = trans val (x, y, z) = trans
position = Point3D(x, y, z) position = Float32Vector3D(x, y, z)
} }
private fun Solid.useMatrix(matrix: DGeoMatrix?) { private fun Solid.scale(s: DoubleArray) {
if (matrix == null) return scale = Float32Vector3D(s[0], s[1], s[2])
when (matrix.typename) { }
"TGeoIdentity" -> {
//do nothing
}
"TGeoTranslation" -> {
val fTranslation by matrix.meta.doubleArray()
translate(fTranslation)
}
"TGeoRotation" -> {
val fRotationMatrix by matrix.meta.doubleArray()
rotate(fRotationMatrix)
}
"TGeoCombiTrans" -> {
val fTranslation by matrix.meta.doubleArray()
translate(fTranslation) private fun Solid.useMatrix(matrix: DGeoMatrix?): Unit {
matrix.meta["fRotation.fRotationMatrix"]?.value?.let { when (matrix) {
rotate(it.doubleArray) null -> {}
is DGeoIdentity -> {}
is DGeoTranslation -> translate(matrix.fTranslation)
is DGeoRotation -> rotate(matrix.fRotationMatrix)
is DGeoScale -> scale(matrix.fScale)
is DGeoGenTrans -> {
translate(matrix.fTranslation)
matrix.fRotation?.fRotationMatrix?.let { rotate(it) }
scale(matrix.fScale)
} }
is DGeoCombiTrans -> {
translate(matrix.fTranslation)
matrix.fRotation?.fRotationMatrix?.let { rotate(it) }
} }
"TGeoHMatrix" -> {
val fTranslation by matrix.meta.doubleArray() is DGeoHMatrix -> {
val fRotationMatrix by matrix.meta.doubleArray() translate(matrix.fTranslation)
val fScale by matrix.meta.doubleArray() matrix.fRotation?.fRotationMatrix?.let { rotate(it) }
translate(fTranslation) scale(matrix.fScale)
rotate(fRotationMatrix)
scale = Point3D(fScale[0], fScale[1], fScale[2])
} }
} }
} }
@ -73,7 +80,7 @@ private fun SolidGroup.addShape(
shape: DGeoShape, shape: DGeoShape,
context: RootToSolidContext, context: RootToSolidContext,
name: String? = shape.fName.ifEmpty { null }, name: String? = shape.fName.ifEmpty { null },
block: Solid.() -> Unit = {} block: Solid.() -> Unit = {},
) { ) {
when (shape.typename) { when (shape.typename) {
"TGeoCompositeShape" -> { "TGeoCompositeShape" -> {
@ -87,13 +94,14 @@ private fun SolidGroup.addShape(
} }
smartComposite(compositeType, name = name) { smartComposite(compositeType, name = name) {
addShape(node.fLeft!!, context, null) { addShape(node.fLeft!!, context, null) {
this.useMatrix(node.fLeftMat) useMatrix(node.fLeftMat)
} }
addShape(node.fRight!!, context, null) { addShape(node.fRight!!, context, null) {
this.useMatrix(node.fRightMat) useMatrix(node.fRightMat)
} }
}.apply(block) }.apply(block)
} }
"TGeoXtru" -> { "TGeoXtru" -> {
val fNvert by shape.meta.int(0) val fNvert by shape.meta.int(0)
val fX by shape.meta.doubleArray() val fX by shape.meta.doubleArray()
@ -105,8 +113,8 @@ private fun SolidGroup.addShape(
val fScale by shape.meta.doubleArray() val fScale by shape.meta.doubleArray()
extruded(name = name) { extruded(name = name) {
(0 until fNvert).forEach { index ->
shape { shape {
(0 until fNvert).forEach { index ->
point(fX[index], fY[index]) point(fX[index], fY[index])
} }
} }
@ -121,6 +129,7 @@ private fun SolidGroup.addShape(
} }
}.apply(block) }.apply(block)
} }
"TGeoTube" -> { "TGeoTube" -> {
val fRmax by shape.meta.double(0.0) val fRmax by shape.meta.double(0.0)
val fDz by shape.meta.double(0.0) val fDz by shape.meta.double(0.0)
@ -134,6 +143,7 @@ private fun SolidGroup.addShape(
block = block block = block
) )
} }
"TGeoTubeSeg" -> { "TGeoTubeSeg" -> {
val fRmax by shape.meta.double(0.0) val fRmax by shape.meta.double(0.0)
val fDz by shape.meta.double(0.0) val fDz by shape.meta.double(0.0)
@ -151,6 +161,7 @@ private fun SolidGroup.addShape(
block = block block = block
) )
} }
"TGeoPcon" -> { "TGeoPcon" -> {
val fDphi by shape.meta.double(0.0) val fDphi by shape.meta.double(0.0)
val fNz by shape.meta.int(2) val fNz by shape.meta.int(2)
@ -170,14 +181,14 @@ private fun SolidGroup.addShape(
name = name, name = name,
) { ) {
z = (fZ[1] + fZ[0]) / 2 z = (fZ[1] + fZ[0]) / 2
}.apply(block) }.apply(block)
} else { } else {
TODO() TODO("Polycone is not implemented")
} }
} }
"TGeoPgon" -> { "TGeoPgon" -> {
//TODO add a inner polygone layer
val fDphi by shape.meta.double(0.0) val fDphi by shape.meta.double(0.0)
val fNz by shape.meta.int(2) val fNz by shape.meta.int(2)
val fPhi1 by shape.meta.double(360.0) val fPhi1 by shape.meta.double(360.0)
@ -190,31 +201,41 @@ private fun SolidGroup.addShape(
val startphi = degToRad(fPhi1) val startphi = degToRad(fPhi1)
val deltaphi = degToRad(fDphi) val deltaphi = degToRad(fDphi)
extruded(name) { fun Shape2DBuilder.pGon(radius: Double){
(0..<fNedges).forEach {
val phi = deltaphi / fNedges * it + startphi
point(radius * cos(phi), radius * sin(phi))
}
}
surface(name) {
//getting the radius of first //getting the radius of first
require(fNz > 1) { "The polyhedron geometry requires at least two planes" } require(fNz > 1) { "The polyhedron geometry requires at least two planes" }
val baseRadius = fRmax[0] for (index in 0 until fNz){
shape { layer(
(0..fNedges).forEach { fZ[index],
val phi = deltaphi * fNedges * it + startphi innerBuilder = {
(baseRadius * cos(phi) to baseRadius * sin(phi)) pGon(fRmin[index])
},
outerBuilder = {
pGon(fRmax[index])
} }
} )
(0 until fNz).forEach { index ->
//scaling all radii relative to first layer radius
layer(fZ[index], scale = fRmax[index] / baseRadius)
} }
}.apply(block) }.apply(block)
} }
"TGeoShapeAssembly" -> { "TGeoShapeAssembly" -> {
val fVolume by shape.dObject(::DGeoVolume) val fVolume by shape.dObject(::DGeoVolume)
fVolume?.let { volume -> fVolume?.let { volume ->
addRootVolume(volume, context, block = block) addRootVolume(volume, context, name = volume.fName.ifEmpty { null }, block = block)
} }
} }
"TGeoBBox" -> { "TGeoBBox" -> {
box(shape.fDX * 2, shape.fDY * 2, shape.fDZ * 2, name = name, block = block) box(shape.fDX * 2, shape.fDY * 2, shape.fDZ * 2, name = name, block = block)
} }
"TGeoTrap" -> { "TGeoTrap" -> {
val fTheta by shape.meta.double(0.0) val fTheta by shape.meta.double(0.0)
val fPhi by shape.meta.double(0.0) val fPhi by shape.meta.double(0.0)
@ -232,27 +253,67 @@ private fun SolidGroup.addShape(
val fDz by shape.meta.double(0.0) val fDz by shape.meta.double(0.0)
//TODO check proper node order //TODO check proper node order
val node1 = Point3D(-fBl1, -fH1, -fDz) val node1 = Float32Vector3D(-fBl1, -fH1, -fDz)
val node2 = Point3D(fBl1, -fH1, -fDz) val node2 = Float32Vector3D(fBl1, -fH1, -fDz)
val node3 = Point3D(fTl1, fH1, -fDz) val node3 = Float32Vector3D(fTl1, fH1, -fDz)
val node4 = Point3D(-fTl1, fH1, -fDz) val node4 = Float32Vector3D(-fTl1, fH1, -fDz)
val node5 = Point3D(-fBl2, -fH2, fDz) val node5 = Float32Vector3D(-fBl2, -fH2, fDz)
val node6 = Point3D(fBl2, -fH2, fDz) val node6 = Float32Vector3D(fBl2, -fH2, fDz)
val node7 = Point3D(fTl2, fH2, fDz) val node7 = Float32Vector3D(fTl2, fH2, fDz)
val node8 = Point3D(-fTl2, fH2, fDz) val node8 = Float32Vector3D(-fTl2, fH2, fDz)
hexagon(node1, node2, node3, node4, node5, node6, node7, node8, name) hexagon(node1, node2, node3, node4, node5, node6, node7, node8, name)
} }
"TGeoScaledShape" -> { "TGeoScaledShape" -> {
val fShape by shape.dObject(::DGeoShape) val fShape by shape.dObject(::DGeoShape)
val fScale by shape.dObject(::DGeoScale) val fScale by shape.dObject(::DGeoScale)
fShape?.let { scaledShape -> fShape?.let { scaledShape ->
group(name?.let { Name.parse(it) }) { 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) addShape(scaledShape, context)
apply(block) apply(block)
} }
} }
} }
"TGeoCone" -> {
val fDz by shape.meta.double(0.0)
val fRmin1 by shape.meta.double(0.0)
val fRmax1 by shape.meta.double(0.0)
val fRmin2 by shape.meta.double(0.0)
val fRmax2 by shape.meta.double(0.0)
coneSurface(
bottomOuterRadius = fRmax1,
bottomInnerRadius = fRmin1,
height = fDz * 2.0,
topOuterRadius = fRmax2,
topInnerRadius = fRmin2,
name = name,
)
}
"TGeoCtub" -> {
val fRmin by shape.meta.double(0.0)
val fRmax by shape.meta.double(0.0)
val fDz by shape.meta.double(0.0)
val fPhi1 by shape.meta.double(0.0)
val fPhi2 by shape.meta.double(PI2.toDouble())
val fNlow by shape.meta.doubleArray()
val fNhigh by shape.meta.doubleArray()
cutTube(
outerRadius = fRmax,
innerRadius = fRmin,
height = fDz * 2.0,
startAngle = degToRad(fPhi1),
angle = degToRad(fPhi2 - fPhi1),
topNormal = Float32Vector3D(fNhigh[0], fNhigh[1], fNhigh[2]),
bottomNormal = Float32Vector3D(fNlow[0], fNlow[1], fNlow[2]),
name = name,
)
}
else -> { else -> {
TODO("A shape with type ${shape.typename} not implemented") TODO("A shape with type ${shape.typename} not implemented")
} }
@ -264,9 +325,10 @@ private fun SolidGroup.addRootNode(obj: DGeoNode, context: RootToSolidContext) {
addRootVolume(volume, context, obj.fName) { addRootVolume(volume, context, obj.fName) {
when (obj.typename) { when (obj.typename) {
"TGeoNodeMatrix" -> { "TGeoNodeMatrix" -> {
val fMatrix by obj.dObject(::DGeoMatrix) val fMatrix by obj.dObject(::dGeoMatrix)
this.useMatrix(fMatrix) this.useMatrix(fMatrix)
} }
"TGeoNodeOffset" -> { "TGeoNodeOffset" -> {
val fOffset by obj.meta.double(0.0) val fOffset by obj.meta.double(0.0)
x = fOffset x = fOffset
@ -276,12 +338,12 @@ private fun SolidGroup.addRootNode(obj: DGeoNode, context: RootToSolidContext) {
} }
private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid? { private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid? {
val group = SolidGroup { val group = SolidGroup().apply {
//set current layer //set current layer
layer = context.currentLayer layer = context.currentLayer
val nodes = volume.fNodes val nodes = volume.fNodes
if (nodes.isEmpty() || context.currentLayer >= context.maxLayer) { if (volume.typename != "TGeoVolumeAssembly" && (nodes.isEmpty() || context.currentLayer >= context.maxLayer)) {
//TODO add smart filter //TODO add smart filter
volume.fShape?.let { shape -> volume.fShape?.let { shape ->
addShape(shape, context) addShape(shape, context)
@ -301,12 +363,22 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
} }
} }
} }
return if (group.isEmpty()) { return if (group.children.isEmpty()) {
null null
} else if (group.children.size == 1 && group.meta.isEmpty()) { } else if (group.items.size == 1 && group.properties.own == null) {
(group.children.values.first() as Solid).apply { parent = null } group.items.values.first().apply { parent = null }
} else { } else {
group group
}.apply {
volume.fMedium?.let { medium ->
color(context.colorCache.getOrPut(medium.meta) { RootColors[11 + context.colorCache.size] })
}
if (!context.ignoreRootColors) {
volume.fFillColor?.let {
properties[MATERIAL_COLOR_KEY] = RootColors[it]
}
}
} }
} }
@ -317,46 +389,42 @@ private fun SolidGroup.addRootVolume(
context: RootToSolidContext, context: RootToSolidContext,
name: String? = null, name: String? = null,
cache: Boolean = true, cache: Boolean = true,
block: Solid.() -> Unit = {} block: Solid.() -> Unit = {},
) { ) {
val combinedName = if (volume.fName.isEmpty()) { val combinedName = name?.parseAsName()?.let {
name // this fix is required to work around malformed root files with duplicated node names
} else if (name == null) { if (get(it) != null) {
volume.fName it.withIndex(volume.hashCode().toString(16))
} else { } else {
"${name}_${volume.fName}" it
}
} }
if (!cache) { if (!cache) {
val group = buildVolume(volume, context)?.apply { val group = buildVolume(volume, context)?.apply(block) ?: return
volume.fFillColor?.let { setChild(combinedName, group)
meta[MATERIAL_COLOR_KEY] = RootColors[it]
}
block()
}
set(combinedName?.let { Name.parse(it) }, group)
} else { } else {
val templateName = volumesName + volume.name val templateName = volumesName + volume.name
val existing = getPrototype(templateName) val existing = context.prototypeHolder.getPrototype(templateName)
if (existing == null) { if (existing == null) {
context.prototypeHolder.prototypes { context.prototypeHolder.prototypes {
val group = buildVolume(volume, context) val group = buildVolume(volume, context) ?: return@prototypes
set(templateName, group) setChild(templateName, group)
} }
} }
ref(templateName, name).apply { ref(templateName, combinedName).apply(block)
volume.fFillColor?.let {
meta[MATERIAL_COLOR_KEY] = RootColors[it]
}
block()
}
} }
} }
public fun DGeoManager.toSolid(): SolidGroup = SolidGroup { public fun MutableVisionContainer<Solid>.rootGeo(
val context = RootToSolidContext(this) dGeoManager: DGeoManager,
fNodes.forEach { node -> name: String? = null,
maxLayer: Int = 5,
ignoreRootColors: Boolean = false,
): SolidGroup = solidGroup(name = name?.parseAsName()) {
val context = RootToSolidContext(this, maxLayer = maxLayer, ignoreRootColors = ignoreRootColors)
dGeoManager.fNodes.forEach { node ->
addRootNode(node, context) addRootNode(node, context)
} }
} }

View File

@ -1,7 +1,7 @@
package ru.mipt.npm.root package ru.mipt.npm.root
public object RootColors { public object RootColors {
private val colorMap = Array<String>(924) { "white" } private val colorMap = MutableList(924) { "white" }
//colorMap[110] = "white" //colorMap[110] = "white"

View File

@ -12,9 +12,10 @@ import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass import kotlinx.serialization.modules.subclass
@Suppress("UNUSED_PARAMETER")
private fun <T> jsonRootDeserializer( private fun <T> jsonRootDeserializer(
tSerializer: KSerializer<T>, tSerializer: KSerializer<T>,
builder: (JsonElement) -> T builder: (JsonElement) -> T,
): DeserializationStrategy<T> = object : ): DeserializationStrategy<T> = object :
DeserializationStrategy<T> { DeserializationStrategy<T> {
private val jsonElementSerializer = JsonElement.serializer() private val jsonElementSerializer = JsonElement.serializer()
@ -46,6 +47,7 @@ private object RootDecoder {
private val refCache: List<RefEntry>, private val refCache: List<RefEntry>,
) : KSerializer<T> by tSerializer { ) : KSerializer<T> by tSerializer {
@OptIn(ExperimentalSerializationApi::class)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun deserialize(decoder: Decoder): T { override fun deserialize(decoder: Decoder): T {
val input = decoder as JsonDecoder val input = decoder as JsonDecoder
@ -82,7 +84,7 @@ private object RootDecoder {
return ref.getOrPutValue { return ref.getOrPutValue {
// println("Decoding $it") // println("Decoding $it")
val actualTypeName = it.jsonObject["_typename"]?.jsonPrimitive?.content // val actualTypeName = it.jsonObject["_typename"]?.jsonPrimitive?.content
input.json.decodeFromJsonElement(tSerializer, it) input.json.decodeFromJsonElement(tSerializer, it)
} }
} }
@ -90,9 +92,8 @@ private object RootDecoder {
private fun <T> KSerializer<T>.unref(refCache: List<RefEntry>): KSerializer<T> = RootUnrefSerializer(this, refCache) private fun <T> KSerializer<T>.unref(refCache: List<RefEntry>): KSerializer<T> = RootUnrefSerializer(this, refCache)
@OptIn(ExperimentalSerializationApi::class)
fun unrefSerializersModule( fun unrefSerializersModule(
refCache: List<RefEntry> refCache: List<RefEntry>,
): SerializersModule = SerializersModule { ): SerializersModule = SerializersModule {
contextual(TObjArray::class) { contextual(TObjArray::class) {
@ -118,7 +119,7 @@ private object RootDecoder {
subclass(TGeoCompositeShape.serializer().unref(refCache)) subclass(TGeoCompositeShape.serializer().unref(refCache))
subclass(TGeoShapeAssembly.serializer().unref(refCache)) subclass(TGeoShapeAssembly.serializer().unref(refCache))
default { defaultDeserializer {
if (it == null) { if (it == null) {
TGeoShape.serializer().unref(refCache) TGeoShape.serializer().unref(refCache)
} else { } else {
@ -136,7 +137,7 @@ private object RootDecoder {
val unrefed = TGeoMatrix.serializer().unref(refCache) val unrefed = TGeoMatrix.serializer().unref(refCache)
default { defaultDeserializer {
if (it == null) { if (it == null) {
unrefed unrefed
} else { } else {
@ -149,7 +150,7 @@ private object RootDecoder {
subclass(TGeoVolumeAssembly.serializer().unref(refCache)) subclass(TGeoVolumeAssembly.serializer().unref(refCache))
val unrefed = TGeoVolume.serializer().unref(refCache) val unrefed = TGeoVolume.serializer().unref(refCache)
default { defaultDeserializer {
if (it == null) { if (it == null) {
unrefed unrefed
} else { } else {
@ -163,7 +164,7 @@ private object RootDecoder {
subclass(TGeoNodeOffset.serializer().unref(refCache)) subclass(TGeoNodeOffset.serializer().unref(refCache))
val unrefed = TGeoNode.serializer().unref(refCache) val unrefed = TGeoNode.serializer().unref(refCache)
default { defaultDeserializer {
if (it == null) { if (it == null) {
unrefed unrefed
} else { } else {
@ -197,11 +198,13 @@ private object RootDecoder {
fillCache(it) fillCache(it)
} }
} }
is JsonArray -> { is JsonArray -> {
element.forEach { element.forEach {
fillCache(it) fillCache(it)
} }
} }
else -> { else -> {
//ignore primitives //ignore primitives
} }
@ -216,6 +219,7 @@ private object RootDecoder {
var value: Any? = null var value: Any? = null
@Suppress("UNCHECKED_CAST")
fun <T> getOrPutValue(builder: (JsonElement) -> T): T { fun <T> getOrPutValue(builder: (JsonElement) -> T): T {
if (value == null) { if (value == null) {
value = builder(element) value = builder(element)

View File

@ -3,6 +3,7 @@ package ru.mipt.npm.root.serialization
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import space.kscience.visionforge.MutableVisionContainer
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.atan2 import kotlin.math.atan2
@ -24,12 +25,12 @@ private fun Solid.rotate(rot: DoubleArray) {
val xAngle = atan2(-rot[5], rot[8]) val xAngle = atan2(-rot[5], rot[8])
val yAngle = atan2(rot[2], sqrt(1.0 - rot[2].pow(2))) val yAngle = atan2(rot[2], sqrt(1.0 - rot[2].pow(2)))
val zAngle = atan2(-rot[1], rot[0]) val zAngle = atan2(-rot[1], rot[0])
rotation = Point3D(xAngle, yAngle, zAngle) rotation = Float32Vector3D(xAngle, yAngle, zAngle)
} }
private fun Solid.translate(trans: DoubleArray) { private fun Solid.translate(trans: DoubleArray) {
val (x, y, z) = trans val (x, y, z) = trans
position = Point3D(x, y, z) position = Float32Vector3D(x, y, z)
} }
private fun Solid.useMatrix(matrix: TGeoMatrix?) { private fun Solid.useMatrix(matrix: TGeoMatrix?) {
@ -51,7 +52,7 @@ private fun Solid.useMatrix(matrix: TGeoMatrix?) {
translate(matrix.fTranslation) translate(matrix.fTranslation)
rotate(matrix.fRotationMatrix) rotate(matrix.fRotationMatrix)
val (xScale, yScale, zScale) = matrix.fScale val (xScale, yScale, zScale) = matrix.fScale
scale = Point3D(xScale, yScale, zScale) scale = Float32Vector3D(xScale, yScale, zScale)
} }
} }
} }
@ -132,7 +133,7 @@ private fun buildGroup(volume: TGeoVolume): SolidGroup {
return if (volume is TGeoVolumeAssemblyRef) { return if (volume is TGeoVolumeAssemblyRef) {
buildGroup(volume.value) buildGroup(volume.value)
} else { } else {
SolidGroup { SolidGroup().apply {
volume.fShape?.let { addShape(it) } volume.fShape?.let { addShape(it) }
volume.fNodes?.let { volume.fNodes?.let {
it.arr.forEach { obj -> it.arr.forEach { obj ->
@ -160,7 +161,7 @@ private fun SolidGroup.volume(volume: TGeoVolume, name: String? = null, cache: B
name = combinedName, name = combinedName,
obj = group, obj = group,
prototypeHolder = rootPrototypes, prototypeHolder = rootPrototypes,
templateName = volumesName + Name.parse(combinedName ?: "volume[${group.hashCode()}]") prototypeName = volumesName + Name.parse(combinedName ?: "volume[${group.hashCode()}]")
) )
} }
@ -180,8 +181,8 @@ private fun SolidGroup.volume(volume: TGeoVolume, name: String? = null, cache: B
// } // }
public fun TGeoManager.toSolid(): SolidGroup = SolidGroup { public fun MutableVisionContainer<Solid>.rootGeo(tGeoManager: TGeoManager): SolidGroup = solidGroup {
fNodes.arr.forEach { tGeoManager.fNodes.arr.forEach {
node(it) node(it)
} }
} }

11
demo/build.gradle.kts Normal file
View File

@ -0,0 +1,11 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
subprojects {
plugins.withType<KotlinPluginWrapper> {
configure<KotlinProjectExtension> {
explicitApi = ExplicitApiMode.Disabled
}
}
}

View File

@ -1,60 +1,68 @@
import ru.mipt.npm.gradle.DependencyConfiguration
import ru.mipt.npm.gradle.FXModule
plugins { plugins {
id("ru.mipt.npm.gradle.mpp") id("space.kscience.gradle.mpp")
application
} }
group = "demo"
kscience { kscience {
val fxVersion: String by rootProject.extra jvm()
useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION)
application()
}
kotlin {
jvm {
withJava()
}
js { js {
useCommonJs() useCommonJs()
browser { browser {
binaries.executable()
commonWebpackConfig { commonWebpackConfig {
cssSupport.enabled = false cssSupport {
enabled.set(false)
}
} }
} }
} }
sourceSets {
commonMain {
dependencies { dependencies {
implementation(project(":visionforge-solid")) implementation(projects.visionforgeSolid)
implementation(project(":visionforge-gdml")) implementation(projects.visionforgeGdml)
}
} }
jvmMain { jvmMain {
dependencies { // implementation(project(":visionforge-fx"))
implementation(project(":visionforge-fx")) implementation(spclibs.logback.classic)
implementation("ch.qos.logback:logback-classic:1.2.5")
}
} }
jsMain { jsMain {
dependencies { implementation(projects.ui.ring)
implementation(project(":ui:ring")) implementation(projects.visionforgeThreejs)
implementation(project(":visionforge-threejs"))
implementation(npm("react-file-drop", "3.0.6")) implementation(npm("react-file-drop", "3.0.6"))
} }
}
}
} }
application { kotlin {
mainClass.set("space.kscience.visionforge.gdml.demo.GdmlFxDemoAppKt") explicitApi = null
} }
val convertGdmlToJson by tasks.creating(JavaExec::class) { //kotlin {
group = "application" //
classpath = sourceSets["main"].runtimeClasspath // sourceSets {
mainClass.set("space.kscience.dataforge.vis.spatial.gdml.demo.SaveToJsonKt") // commonMain {
} // dependencies {
// implementation(project(":visionforge-solid"))
// implementation(project(":visionforge-gdml"))
// }
// }
// jvmMain {
// dependencies {
//// implementation(project(":visionforge-fx"))
// implementation("ch.qos.logback:logback-classic:1.2.11")
// }
// }
// jsMain {
// dependencies {
// implementation(project(":ui:ring"))
// implementation(project(":visionforge-threejs"))
// implementation(npm("react-file-drop", "3.0.6"))
// }
// }
// }
//}
//val convertGdmlToJson by tasks.creating(JavaExec::class) {
// group = "application"
// classpath = sourceSets["main"].runtimeClasspath
// mainClass.set("space.kscience.dataforge.vis.spatial.gdml.demo.SaveToJsonKt")
//}

View File

@ -1,13 +1,11 @@
package space.kscience.visionforge.gdml package space.kscience.visionforge.gdml
import space.kscience.dataforge.meta.asValue
import space.kscience.dataforge.meta.string
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.values.asValue
import space.kscience.dataforge.values.string
import space.kscience.gdml.GdmlShowCase import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.computeProperties import space.kscience.visionforge.getChild
import space.kscience.visionforge.get
import space.kscience.visionforge.setProperty
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.SolidMaterial import space.kscience.visionforge.solid.SolidMaterial
import space.kscience.visionforge.solid.material import space.kscience.visionforge.solid.material
@ -20,8 +18,8 @@ class GDMLVisionTest {
@Test @Test
fun testCubesStyles(){ fun testCubesStyles(){
val segment = cubes["composite-000.segment-0"] as Solid val segment = cubes.children.getChild("composite-000.segment-0") as Solid
println(segment.computeProperties().getValue(Vision.STYLE_KEY)) println(segment.properties.getValue(Vision.STYLE_KEY))
// println(segment.computePropertyNode(SolidMaterial.MATERIAL_KEY)) // println(segment.computePropertyNode(SolidMaterial.MATERIAL_KEY))
// println(segment.computeProperty(SolidMaterial.MATERIAL_COLOR_KEY)) // println(segment.computeProperty(SolidMaterial.MATERIAL_COLOR_KEY))
@ -35,7 +33,7 @@ class GDMLVisionTest {
fun testPrototypeProperty() { fun testPrototypeProperty() {
val child = cubes[Name.of("composite-000","segment-0")] val child = cubes[Name.of("composite-000","segment-0")]
assertNotNull(child) assertNotNull(child)
child.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) child.properties.setValue(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
assertEquals("red", child.getPropertyValue(SolidMaterial.MATERIAL_COLOR_KEY)?.string) assertEquals("red", child.properties[SolidMaterial.MATERIAL_COLOR_KEY].string)
} }
} }

View File

@ -9,30 +9,38 @@ import react.Component
import react.Props import react.Props
import react.State import react.State
external enum class DropEffects { sealed external class DropEffects {
copy, @JsName("copy")
move, object Copy : DropEffects
link,
none @JsName("move")
object Move : DropEffects
@JsName("link")
object Link : DropEffects
@JsName("none")
object None : DropEffects
} }
external interface FileDropProps: Props { external interface FileDropProps : Props {
var className: String? var className: String?
var targetClassName: String? var targetClassName: String?
var draggingOverFrameClassName: String? var draggingOverFrameClassName: String?
var draggingOverTargetClassName: String? var draggingOverTargetClassName: String?
// var frame?: Exclude<HTMLElementTagNameMap[keyof HTMLElementTagNameMap], HTMLElement> | HTMLDocument; // var frame?: Exclude<HTMLElementTagNameMap[keyof HTMLElementTagNameMap], HTMLElement> | HTMLDocument;
var onFrameDragEnter: ((event: DragEvent) -> Unit)? var onFrameDragEnter: ((event: DragEvent) -> Unit)?
var onFrameDragLeave: ((event: DragEvent) -> Unit)? var onFrameDragLeave: ((event: DragEvent) -> Unit)?
var onFrameDrop: ((event: DragEvent) -> Unit)? var onFrameDrop: ((event: DragEvent) -> Unit)?
// var onDragOver: ReactDragEventHandler<HTMLDivElement>?
// var onDragOver: ReactDragEventHandler<HTMLDivElement>?
// var onDragLeave: ReactDragEventHandler<HTMLDivElement>? // var onDragLeave: ReactDragEventHandler<HTMLDivElement>?
var onDrop: ((files: FileList?, event: dynamic) -> Unit)?//event:DragEvent<HTMLDivElement>) var onDrop: ((files: FileList?, event: dynamic) -> Unit)?//event:DragEvent<HTMLDivElement>)
var dropEffect: DropEffects? var dropEffect: DropEffects?
} }
external interface FileDropState: State { external interface FileDropState : State {
var draggingOverFrame: Boolean var draggingOverFrame: Boolean
var draggingOverTarget: Boolean var draggingOverTarget: Boolean
} }

View File

@ -10,13 +10,11 @@ import org.w3c.files.get
import react.Props import react.Props
import react.dom.h2 import react.dom.h2
import react.fc import react.fc
import react.useMemo
import react.useState import react.useState
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.fetch
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.gdml.Gdml import space.kscience.gdml.Gdml
import space.kscience.gdml.decodeFromString import space.kscience.gdml.decodeFromString
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.markLayers import space.kscience.visionforge.gdml.markLayers
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.ThreeCanvasWithControls
@ -24,18 +22,19 @@ import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.setAsRoot import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.invoke
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
external interface GDMLAppProps : Props { external interface GDMLAppProps : Props {
var context: Context var solids: Solids
var vision: Solid? var vision: Solid?
var selected: Name? var selected: Name?
} }
@JsExport @JsExport
val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props -> val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
var deferredVision: Deferred<Solid?> by useState { var deferredVision: Deferred<Solid?> by useState {
CompletableDeferred(props.vision) CompletableDeferred(props.vision)
} }
@ -50,12 +49,15 @@ val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
name.endsWith(".gdml") || name.endsWith(".xml") -> { name.endsWith(".gdml") || name.endsWith(".xml") -> {
val gdml = Gdml.decodeFromString(data) val gdml = Gdml.decodeFromString(data)
gdml.toVision().apply { gdml.toVision().apply {
setAsRoot(visionManager) setAsRoot(props.solids.visionManager)
console.info("Marking layers for file $name") console.info("Marking layers for file $name")
markLayers() markLayers()
ambientLight {
color(Colors.white)
} }
} }
name.endsWith(".json") -> visionManager.decodeFromString(data) }
name.endsWith(".json") -> props.solids.visionManager.decodeFromString(data)
else -> { else -> {
window.alert("File extension is not recognized: $name") window.alert("File extension is not recognized: $name")
error("File extension is not recognized: $name") error("File extension is not recognized: $name")
@ -76,7 +78,7 @@ val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
} }
child(ThreeCanvasWithControls) { child(ThreeCanvasWithControls) {
attrs { attrs {
this.context = props.context this.solids = props.solids
this.builderOfSolid = deferredVision this.builderOfSolid = deferredVision
this.selected = props.selected this.selected = props.selected
tab("Load") { tab("Load") {

View File

@ -1,12 +1,18 @@
package space.kscience.visionforge.gdml.demo package space.kscience.visionforge.gdml.demo
import kotlinx.browser.document
import kotlinx.css.* import kotlinx.css.*
import react.dom.render import org.w3c.dom.Document
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.gdml.GdmlShowCase import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
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.invoke
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication import space.kscience.visionforge.startApplication
import styled.injectGlobal import styled.injectGlobal
@ -14,7 +20,7 @@ import styled.injectGlobal
private class GDMLDemoApp : Application { private class GDMLDemoApp : Application {
override fun start(state: Map<String, Any>) { override fun start(document: Document, state: Map<String, Any>) {
val context = Context("gdml-demo"){ val context = Context("gdml-demo"){
plugin(ThreePlugin) plugin(ThreePlugin)
} }
@ -39,12 +45,16 @@ private class GDMLDemoApp : Application {
val element = document.getElementById("application") ?: error("Element with id 'application' not found on page") val element = document.getElementById("application") ?: error("Element with id 'application' not found on page")
render(element) { createRoot(element).render {
child(GDMLApp) { child(GDMLApp) {
val vision = GdmlShowCase.cubes().toVision() val vision = GdmlShowCase.cubes().toVision().apply {
ambientLight {
color(Colors.white)
}
}
//println(context.plugins.fetch(VisionManager).encodeToString(vision)) //println(context.plugins.fetch(VisionManager).encodeToString(vision))
attrs { attrs {
this.context = context this.solids = context.request(Solids)
this.vision = vision this.vision = vision
} }
} }

View File

@ -2,7 +2,6 @@ package space.kscience.visionforge.gdml.demo
import drop.FileDrop import drop.FileDrop
import kotlinx.css.* import kotlinx.css.*
import kotlinx.css.properties.border
import org.w3c.files.FileList import org.w3c.files.FileList
import react.RBuilder import react.RBuilder
import styled.css import styled.css
@ -13,7 +12,7 @@ import styled.styledDiv
fun RBuilder.fileDrop(title: String, action: (files: FileList?) -> Unit) { fun RBuilder.fileDrop(title: String, action: (files: FileList?) -> Unit) {
styledDiv { styledDiv {
css { css {
border(style = BorderStyle.dashed, width = 1.px, color = Color.orange) border = Border(style = BorderStyle.dashed, width = 1.px, color = Color.orange)
flexGrow = 0.0 flexGrow = 0.0
alignContent = Align.center alignContent = Align.center
} }

View File

@ -1,83 +1,83 @@
package space.kscience.visionforge.gdml.demo //package space.kscience.visionforge.gdml.demo
//
import javafx.geometry.Orientation //import javafx.geometry.Orientation
import javafx.scene.Parent //import javafx.scene.Parent
import javafx.stage.FileChooser //import javafx.stage.FileChooser
import space.kscience.dataforge.context.Context //import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.fetch //import space.kscience.dataforge.context.fetch
import space.kscience.gdml.GdmlShowCase //import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.VisionManager //import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.editor.VisionEditorFragment //import space.kscience.visionforge.editor.VisionEditorFragment
import space.kscience.visionforge.editor.VisionTreeFragment //import space.kscience.visionforge.editor.VisionTreeFragment
import space.kscience.visionforge.gdml.toVision //import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.solid.FX3DPlugin //import space.kscience.visionforge.solid.FX3DPlugin
import space.kscience.visionforge.solid.FXCanvas3D //import space.kscience.visionforge.solid.FXCanvas3D
import space.kscience.visionforge.solid.Solid //import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.SolidMaterial //import space.kscience.visionforge.solid.SolidMaterial
import tornadofx.* //import tornadofx.*
//
class GDMLDemoApp : App(GDMLView::class) //class GDMLDemoApp : App(GDMLView::class)
//
class GDMLView : View() { //class GDMLView : View() {
private val context = Context { // private val context = Context {
plugin(FX3DPlugin) // plugin(FX3DPlugin)
} // }
//
private val fx3d = context.fetch(FX3DPlugin) // private val fx3d = context.fetch(FX3DPlugin)
private val visionManager = context.fetch(VisionManager) // private val visionManager = context.fetch(VisionManager)
private val canvas = FXCanvas3D(fx3d) // private val canvas = FXCanvas3D(fx3d)
//
private val treeFragment = VisionTreeFragment().apply { // private val treeFragment = VisionTreeFragment().apply {
this.itemProperty.bind(canvas.rootObjectProperty) // this.itemProperty.bind(canvas.rootObjectProperty)
} // }
//
private val propertyEditor = VisionEditorFragment().apply { // private val propertyEditor = VisionEditorFragment().apply {
descriptorProperty.set(SolidMaterial.descriptor) // descriptorProperty.set(SolidMaterial.descriptor)
visionProperty.bind(treeFragment.selectedProperty) // visionProperty.bind(treeFragment.selectedProperty)
} // }
//
override val root: Parent = borderpane { // override val root: Parent = borderpane {
top { // top {
buttonbar { // buttonbar {
button("Load GDML/json") { // button("Load GDML/json") {
action { // action {
val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull() // val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull()
if (file != null) { // if (file != null) {
runAsync { // runAsync {
visionManager.readFile(file) as Solid // visionManager.readFile(file) as Solid
} ui { // } ui {
canvas.render(it) // canvas.render(it)
} // }
} // }
} // }
} // }
} // }
} // }
center { // center {
splitpane(Orientation.HORIZONTAL, treeFragment.root, canvas.root, propertyEditor.root) { // splitpane(Orientation.HORIZONTAL, treeFragment.root, canvas.root, propertyEditor.root) {
setDividerPositions(0.2, 0.6, 0.2) // setDividerPositions(0.2, 0.6, 0.2)
} // }
} // }
} // }
//
init { // init {
runAsync { // runAsync {
GdmlShowCase.cubes().toVision() // GdmlShowCase.cubes().toVision()
} ui { // } ui {
canvas.render(it) // canvas.render(it)
} // }
} // }
//
companion object { // companion object {
private val fileNameFilter = arrayOf( // private val fileNameFilter = arrayOf(
FileChooser.ExtensionFilter("GDML", "*.gdml", "*.xml"), // FileChooser.ExtensionFilter("GDML", "*.gdml", "*.xml"),
FileChooser.ExtensionFilter("JSON", "*.json"), // FileChooser.ExtensionFilter("JSON", "*.json"),
FileChooser.ExtensionFilter("JSON.ZIP", "*.json.zip"), // FileChooser.ExtensionFilter("JSON.ZIP", "*.json.zip"),
FileChooser.ExtensionFilter("JSON.GZ", "*.json.gz") // FileChooser.ExtensionFilter("JSON.GZ", "*.json.gz")
) // )
} // }
} //}
//
fun main() { //fun main() {
launch<GDMLDemoApp>() // launch<GDMLDemoApp>()
} //}

View File

@ -1,28 +1,35 @@
plugins { plugins {
id("ru.mipt.npm.gradle.js") id("space.kscience.gradle.mpp")
} }
kscience{ kscience {
useCoroutines() useCoroutines()
application()
} }
kotlin{ kotlin {
js(IR){ explicitApi = null
js {
useCommonJs() useCommonJs()
browser { browser {
binaries.executable()
commonWebpackConfig { commonWebpackConfig {
cssSupport.enabled = false cssSupport {
enabled.set(false)
}
} }
} }
} }
} }
kscience {
dependencies{ dependencies {
implementation(projects.visionforge.visionforgeGdml) implementation(projects.visionforge.visionforgeGdml)
implementation(projects.visionforge.visionforgePlotly) implementation(projects.visionforge.visionforgePlotly)
implementation(projects.visionforge.visionforgeMarkdown) implementation(projects.visionforge.visionforgeMarkdown)
implementation(projects.visionforge.visionforgeThreejs) implementation(projects.visionforge.visionforgeThreejs)
}
jsMain {
implementation(projects.ui.ring) implementation(projects.ui.ring)
}
} }

View File

@ -1,15 +1,17 @@
import kotlinx.browser.document
import kotlinx.css.* import kotlinx.css.*
import react.child import org.w3c.dom.Document
import react.dom.render
import ringui.SmartTabs import ringui.SmartTabs
import ringui.Tab import ringui.Tab
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.plotly.models.Trace import space.kscience.plotly.models.Trace
import space.kscience.plotly.scatter import space.kscience.plotly.scatter
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.VisionClient import space.kscience.visionforge.Colors
import space.kscience.visionforge.JsVisionClient
import space.kscience.visionforge.plotly.PlotlyPlugin import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.ThreeWithControlsPlugin import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.ring.solid import space.kscience.visionforge.ring.solid
@ -28,29 +30,29 @@ fun Trace.appendXYLatest(x: Number, y: Number, history: Int = 400, xErr: Number?
private class JsPlaygroundApp : Application { private class JsPlaygroundApp : Application {
override fun start(state: Map<String, Any>) { override fun start(document: Document, state: Map<String, Any>) {
val playgroundContext = Context { val playgroundContext = Context {
plugin(ThreeWithControlsPlugin) plugin(ThreeWithControlsPlugin)
plugin(VisionClient) plugin(JsVisionClient)
plugin(PlotlyPlugin) plugin(PlotlyPlugin)
} }
val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page") val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page")
render(element) { createRoot(element).render {
styledDiv { styledDiv {
css { css {
padding(0.pt) padding = Padding(0.pt)
margin(0.pt) margin = Margin(0.pt)
height = 100.vh height = 100.vh
width = 100.vw width = 100.vw
} }
SmartTabs("gravity") { SmartTabs("gravity") {
Tab("gravity") { Tab("gravity") {
GravityDemo{ GravityDemo {
attrs { attrs {
this.context = playgroundContext this.solids = playgroundContext.request(Solids)
} }
} }
} }
@ -71,8 +73,11 @@ private class JsPlaygroundApp : Application {
child(ThreeCanvasWithControls) { child(ThreeCanvasWithControls) {
val random = Random(112233) val random = Random(112233)
attrs { attrs {
context = playgroundContext solids = playgroundContext.request(Solids)
solid { solid {
ambientLight {
color(Colors.white)
}
repeat(100) { repeat(100) {
sphere(5, name = "sphere[$it]") { sphere(5, name = "sphere[$it]") {
x = random.nextDouble(-300.0, 300.0) x = random.nextDouble(-300.0, 300.0)

View File

@ -4,9 +4,9 @@ import kotlinx.coroutines.launch
import kotlinx.css.* import kotlinx.css.*
import react.Props import react.Props
import react.fc import react.fc
import space.kscience.dataforge.context.Context
import space.kscience.plotly.layout import space.kscience.plotly.layout
import space.kscience.plotly.models.Trace import space.kscience.plotly.models.Trace
import space.kscience.visionforge.Colors
import space.kscience.visionforge.markup.VisionOfMarkup import space.kscience.visionforge.markup.VisionOfMarkup
import space.kscience.visionforge.react.flexRow import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.ThreeCanvasWithControls
@ -17,14 +17,14 @@ import styled.styledDiv
import kotlin.math.sqrt import kotlin.math.sqrt
external interface DemoProps : Props { external interface DemoProps : Props {
var context: Context var solids: Solids
} }
val GravityDemo = fc<DemoProps> { props -> val GravityDemo = fc<DemoProps> { props ->
val velocityTrace = Trace{ val velocityTrace = Trace {
name = "velocity" name = "velocity"
} }
val energyTrace = Trace{ val energyTrace = Trace {
name = "energy" name = "energy"
} }
val markup = VisionOfMarkup() val markup = VisionOfMarkup()
@ -39,14 +39,19 @@ val GravityDemo = fc<DemoProps> { props ->
} }
child(ThreeCanvasWithControls) { child(ThreeCanvasWithControls) {
attrs { attrs {
context = props.context solids = props.solids
solid { solid {
pointLight(200, 200, 200, name = "light"){
color(Colors.white)
}
ambientLight()
sphere(5.0, "ball") { sphere(5.0, "ball") {
detail = 16 detail = 16
color("red") color("red")
val h = 100.0 val h = 100.0
y = h y = h
context.launch { solids.context.launch {
val g = 10.0 val g = 10.0
val dt = 0.1 val dt = 0.1
var time = 0.0 var time = 0.0
@ -91,7 +96,7 @@ val GravityDemo = fc<DemoProps> { props ->
height = 50.vh - 50.pt height = 50.vh - 50.pt
} }
plotly { plotly {
traces(velocityTrace,energyTrace) traces(velocityTrace, energyTrace)
layout { layout {
xaxis.title = "time" xaxis.title = "time"
} }

View File

@ -1,5 +1,4 @@
import kotlinx.css.* import kotlinx.css.*
import kotlinx.css.properties.border
import kotlinx.dom.clear import kotlinx.dom.clear
import kotlinx.html.dom.append import kotlinx.html.dom.append
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
@ -45,10 +44,10 @@ val Markup = fc<MarkupProps>("Markup") { props ->
css { css {
width = 100.pct width = 100.pct
height = 100.pct height = 100.pct
border(2.pt, BorderStyle.solid, Color.blue) border= Border(2.pt, BorderStyle.solid, Color.blue)
padding(left = 8.pt) padding = Padding(left = 8.pt)
backgroundColor = Color.white backgroundColor = Color.white
flex(1.0) flex = Flex(1.0)
zIndex = 10000 zIndex = 10000
} }
ref = elementRef ref = elementRef

View File

@ -1,5 +1,4 @@
import kotlinx.css.* import kotlinx.css.*
import kotlinx.css.properties.border
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import react.* import react.*
@ -20,9 +19,9 @@ val Plotly = fc<PlotlyProps>("Plotly") { props ->
useEffect(props.plot, elementRef) { useEffect(props.plot, elementRef) {
val element = elementRef.current as? HTMLElement ?: error("Plotly element not found") val element = elementRef.current as? HTMLElement ?: error("Plotly element not found")
props.plot?.let { props.plot?.let {
element.plot(it, PlotlyConfig { element.plot(PlotlyConfig {
responsive = true responsive = true
}) }, it)
} }
} }
@ -30,8 +29,8 @@ val Plotly = fc<PlotlyProps>("Plotly") { props ->
css { css {
width = 100.pct width = 100.pct
height = 100.pct height = 100.pct
border(2.pt, BorderStyle.solid, Color.blue) border = Border(2.pt, BorderStyle.solid, Color.blue)
flex(1.0) flex = Flex(1.0)
} }
ref = elementRef ref = elementRef
} }

View File

@ -1,64 +1,47 @@
plugins { plugins {
id("ru.mipt.npm.gradle.mpp") id("space.kscience.gradle.mpp")
application application
} }
group = "ru.mipt.npm" group = "ru.mipt.npm"
val ktorVersion: String = npmlibs.versions.ktor.get() val ktorVersion: String = spclibs.versions.ktor.get()
kscience { kscience {
useCoroutines() useCoroutines()
useSerialization() useSerialization()
application() useKtor()
} fullStack(
"muon-monitor.js",
kotlin { jvmConfig = { withJava() },
jvm { jsConfig = { useCommonJs() }
withJava() ) {
}
js {
useCommonJs()
browser {
commonWebpackConfig { commonWebpackConfig {
cssSupport.enabled = false cssSupport {
enabled.set(false)
} }
} }
} }
afterEvaluate {
val jsBrowserDistribution by tasks.getting
tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from(jsBrowserDistribution)
}
}
sourceSets {
commonMain { commonMain {
dependencies { implementation(projects.visionforgeSolid)
implementation(project(":visionforge-solid"))
}
} }
jvmMain { jvmMain {
dependencies {
implementation("org.apache.commons:commons-math3:3.6.1") implementation("org.apache.commons:commons-math3:3.6.1")
implementation(npmlibs.ktor.server.cio) implementation("io.ktor:ktor-server-cio:${ktorVersion}")
implementation(npmlibs.ktor.serialization) implementation("io.ktor:ktor-server-content-negotiation:${ktorVersion}")
} implementation("io.ktor:ktor-serialization-kotlinx-json:${ktorVersion}")
implementation("ch.qos.logback:logback-classic:1.2.11")
} }
jsMain { jsMain {
dependencies { implementation(projects.ui.ring)
implementation(project(":ui:ring")) implementation(projects.visionforgeThreejs)
implementation(project(":visionforge-threejs"))
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0")) //implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
} }
}
}
} }
kotlin.explicitApi = null
application { application {
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt") mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
} }

View File

@ -1,9 +1,9 @@
package ru.mipt.npm.muon.monitor package ru.mipt.npm.muon.monitor
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.visionforge.solid.Point3D import space.kscience.visionforge.solid.Float32Vector3D
typealias Track = List<Point3D> typealias Track = List<Float32Vector3D>
/** /**
* *

View File

@ -3,20 +3,21 @@ package ru.mipt.npm.muon.monitor
import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z
import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z
import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.MutableVisionContainer
import space.kscience.visionforge.VisionManager import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.removeAll
import space.kscience.visionforge.setAsRoot import space.kscience.visionforge.setAsRoot
import space.kscience.visionforge.setProperty
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import kotlin.collections.set
import kotlin.math.PI import kotlin.math.PI
class Model(val manager: VisionManager) { class Model(val manager: VisionManager) {
private val map = HashMap<String, SolidGroup>() private val map = HashMap<String, SolidGroup>()
private val events = HashSet<Event>() private val events = HashSet<Event>()
private fun SolidGroup.pixel(pixel: SC1) { private fun MutableVisionContainer<Solid>.pixel(pixel: SC1) {
val group = group(pixel.name) { 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) box(pixel.xSize, pixel.ySize, pixel.zSize)
label(pixel.name) { label(pixel.name) {
z = -Monitor.PIXEL_Z_SIZE / 2 - 5 z = -Monitor.PIXEL_Z_SIZE / 2 - 5
@ -27,52 +28,52 @@ class Model(val manager: VisionManager) {
} }
private fun SolidGroup.detector(detector: SC16) { private fun SolidGroup.detector(detector: SC16) {
group(detector.name) { solidGroup(detector.name) {
detector.pixels.forEach { detector.pixels.forEach {
pixel(it) pixel(it)
} }
} }
} }
var tracks: SolidGroup val tracks: SolidGroup = SolidGroup()
val root: SolidGroup = SolidGroup().apply { val root: SolidGroup = SolidGroup().apply {
setAsRoot(this@Model.manager) setAsRoot(this@Model.manager)
material { material {
wireframe
color("darkgreen") color("darkgreen")
} }
rotationX = PI / 2 rotationX = PI / 2
group("bottom") { solidGroup("bottom") {
Monitor.detectors.filter { it.center.z == LOWER_LAYER_Z }.forEach { Monitor.detectors.filter { it.center.z == LOWER_LAYER_Z }.forEach {
detector(it) detector(it)
} }
} }
group("middle") { solidGroup("middle") {
Monitor.detectors.filter { it.center.z == CENTRAL_LAYER_Z }.forEach { Monitor.detectors.filter { it.center.z == CENTRAL_LAYER_Z }.forEach {
detector(it) detector(it)
} }
} }
group("top") { solidGroup("top") {
Monitor.detectors.filter { it.center.z == UPPER_LAYER_Z }.forEach { Monitor.detectors.filter { it.center.z == UPPER_LAYER_Z }.forEach {
detector(it) detector(it)
} }
} }
tracks = group("tracks")
setChild("tracks".asName(), tracks)
} }
private fun highlight(pixel: String) { private fun highlight(pixel: String) {
println("highlight $pixel") println("highlight $pixel")
map[pixel]?.color?.invoke("blue") map[pixel]?.color("blue")
} }
fun reset() { fun reset() {
map.values.forEach { map.values.forEach {
it.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, null) it.properties[SolidMaterial.MATERIAL_COLOR_KEY] = null
} }
tracks.removeAll() tracks.children.clear()
} }
fun displayEvent(event: Event) { fun displayEvent(event: Event) {
@ -83,7 +84,6 @@ class Model(val manager: VisionManager) {
} }
event.track?.let { event.track?.let {
tracks.polyline(*it.toTypedArray(), name = "track[${event.id}]") { tracks.polyline(*it.toTypedArray(), name = "track[${event.id}]") {
thickness = 4
color("red") color("red")
} }
} }

View File

@ -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_XY_SIZE
import ru.mipt.npm.muon.monitor.Monitor.PIXEL_Z_SIZE import ru.mipt.npm.muon.monitor.Monitor.PIXEL_Z_SIZE
import space.kscience.visionforge.solid.Point3D import space.kscience.visionforge.solid.Float32Euclidean3DSpace
import space.kscience.visionforge.solid.plus import space.kscience.visionforge.solid.Float32Vector3D
/** /**
* A single pixel * A single pixel
*/ */
class SC1( class SC1(
val name: String, 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 val xSize: Float = PIXEL_XY_SIZE, val ySize: Float = PIXEL_XY_SIZE, val zSize: Float = PIXEL_Z_SIZE,
) )
class SC16( class SC16(
val name: String, val name: String,
val center: Point3D val center: Float32Vector3D,
) { ) {
/** /**
@ -28,77 +28,90 @@ class SC16(
val y: Double val y: Double
when (index) { when (index) {
7 -> { 7 -> {
x = 1.5 * Monitor.PIXEL_XY_SPACING; x = 1.5 * Monitor.PIXEL_XY_SPACING
y = 1.5 * Monitor.PIXEL_XY_SPACING; y = 1.5 * Monitor.PIXEL_XY_SPACING
} }
4 -> { 4 -> {
x = 0.5 * Monitor.PIXEL_XY_SPACING; x = 0.5 * Monitor.PIXEL_XY_SPACING
y = 1.5 * Monitor.PIXEL_XY_SPACING; y = 1.5 * Monitor.PIXEL_XY_SPACING
} }
6 -> { 6 -> {
x = 1.5 * Monitor.PIXEL_XY_SPACING; x = 1.5 * Monitor.PIXEL_XY_SPACING
y = 0.5 * Monitor.PIXEL_XY_SPACING; y = 0.5 * Monitor.PIXEL_XY_SPACING
} }
5 -> { 5 -> {
x = 0.5 * Monitor.PIXEL_XY_SPACING; x = 0.5 * Monitor.PIXEL_XY_SPACING
y = 0.5 * Monitor.PIXEL_XY_SPACING; y = 0.5 * Monitor.PIXEL_XY_SPACING
} }
3 -> { 3 -> {
x = -1.5 * Monitor.PIXEL_XY_SPACING; x = -1.5 * Monitor.PIXEL_XY_SPACING
y = 1.5 * Monitor.PIXEL_XY_SPACING; y = 1.5 * Monitor.PIXEL_XY_SPACING
} }
0 -> { 0 -> {
x = -0.5 * Monitor.PIXEL_XY_SPACING; x = -0.5 * Monitor.PIXEL_XY_SPACING
y = 1.5 * Monitor.PIXEL_XY_SPACING; y = 1.5 * Monitor.PIXEL_XY_SPACING
} }
2 -> { 2 -> {
x = -1.5 * Monitor.PIXEL_XY_SPACING; x = -1.5 * Monitor.PIXEL_XY_SPACING
y = 0.5 * Monitor.PIXEL_XY_SPACING; y = 0.5 * Monitor.PIXEL_XY_SPACING
} }
1 -> { 1 -> {
x = -0.5 * Monitor.PIXEL_XY_SPACING; x = -0.5 * Monitor.PIXEL_XY_SPACING
y = 0.5 * Monitor.PIXEL_XY_SPACING; y = 0.5 * Monitor.PIXEL_XY_SPACING
} }
11 -> { 11 -> {
x = -1.5 * Monitor.PIXEL_XY_SPACING; x = -1.5 * Monitor.PIXEL_XY_SPACING
y = -1.5 * Monitor.PIXEL_XY_SPACING; y = -1.5 * Monitor.PIXEL_XY_SPACING
} }
8 -> { 8 -> {
x = -0.5 * Monitor.PIXEL_XY_SPACING; x = -0.5 * Monitor.PIXEL_XY_SPACING
y = -1.5 * Monitor.PIXEL_XY_SPACING; y = -1.5 * Monitor.PIXEL_XY_SPACING
} }
10 -> { 10 -> {
x = -1.5 * Monitor.PIXEL_XY_SPACING; x = -1.5 * Monitor.PIXEL_XY_SPACING
y = -0.5 * Monitor.PIXEL_XY_SPACING; y = -0.5 * Monitor.PIXEL_XY_SPACING
} }
9 -> { 9 -> {
x = -0.5 * Monitor.PIXEL_XY_SPACING; x = -0.5 * Monitor.PIXEL_XY_SPACING
y = -0.5 * Monitor.PIXEL_XY_SPACING; y = -0.5 * Monitor.PIXEL_XY_SPACING
} }
15 -> { 15 -> {
x = 1.5 * Monitor.PIXEL_XY_SPACING; x = 1.5 * Monitor.PIXEL_XY_SPACING
y = -1.5 * Monitor.PIXEL_XY_SPACING; y = -1.5 * Monitor.PIXEL_XY_SPACING
} }
12 -> { 12 -> {
x = 0.5 * Monitor.PIXEL_XY_SPACING; x = 0.5 * Monitor.PIXEL_XY_SPACING
y = -1.5 * Monitor.PIXEL_XY_SPACING; y = -1.5 * Monitor.PIXEL_XY_SPACING
} }
14 -> { 14 -> {
x = 1.5 * Monitor.PIXEL_XY_SPACING; x = 1.5 * Monitor.PIXEL_XY_SPACING
y = -0.5 * Monitor.PIXEL_XY_SPACING; y = -0.5 * Monitor.PIXEL_XY_SPACING
} }
13 -> { 13 -> {
x = 0.5 * Monitor.PIXEL_XY_SPACING; x = 0.5 * Monitor.PIXEL_XY_SPACING
y = -0.5 * Monitor.PIXEL_XY_SPACING; y = -0.5 * Monitor.PIXEL_XY_SPACING
} }
else -> throw Error();
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}" val pixelName = "${name}_${index}"
SC1(pixelName, offset + center) SC1(pixelName, with(Float32Euclidean3DSpace) { offset + center })
} }
} }
} }
@ -137,11 +150,11 @@ object Monitor {
.mapNotNull { line -> .mapNotNull { line ->
if (line.startsWith(" ")) { if (line.startsWith(" ")) {
val split = line.trim().split("\\s+".toRegex()) val split = line.trim().split("\\s+".toRegex())
val detectorName = split[1]; val detectorName = split[1]
val x = split[4].toDouble() - 500 val x = split[4].toDouble() - 500
val y = split[5].toDouble() - 500 val y = split[5].toDouble() - 500
val z = 180 - split[6].toDouble() val z = 180 - split[6].toDouble()
SC16(detectorName, Point3D(x, y, z)) SC16(detectorName, Float32Vector3D(x, y, z))
} else { } else {
null null
} }

View File

@ -16,15 +16,18 @@ import react.dom.p
import react.fc import react.fc
import react.useMemo import react.useMemo
import react.useState import react.useState
import space.kscience.dataforge.context.Context import space.kscience.dataforge.meta.invoke
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Colors
import space.kscience.visionforge.react.flexColumn import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.tab import space.kscience.visionforge.ring.tab
import space.kscience.visionforge.solid.specifications.Camera import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.edges
import space.kscience.visionforge.solid.invoke
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.edges
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
import styled.styledSpan import styled.styledSpan
@ -32,7 +35,7 @@ import kotlin.math.PI
external interface MMAppProps : Props { external interface MMAppProps : Props {
var model: Model var model: Model
var context: Context var solids: Solids
var selected: Name? var selected: Name?
} }
@ -42,17 +45,21 @@ val MMApp = fc<MMAppProps>("Muon monitor") { props ->
val mmOptions = useMemo { val mmOptions = useMemo {
Canvas3DOptions { Canvas3DOptions {
camera = Camera { camera {
distance = 2100.0 distance = 2100.0
latitude = PI / 6 latitude = PI / 6
azimuth = PI + PI / 6 azimuth = PI + PI / 6
} }
} }
} }
val root = useMemo(props.model) { val root = useMemo(props.model) {
props.model.root.apply { props.model.root.apply {
edges() edges()
ambientLight{
color(Colors.white)
}
} }
} }
@ -64,7 +71,7 @@ val MMApp = fc<MMAppProps>("Muon monitor") { props ->
} }
child(ThreeCanvasWithControls) { child(ThreeCanvasWithControls) {
attrs { attrs {
this.context = props.context this.solids = props.solids
this.builderOfSolid = CompletableDeferred(root) this.builderOfSolid = CompletableDeferred(root)
this.selected = props.selected this.selected = props.selected
this.options = mmOptions this.options = mmOptions
@ -75,7 +82,7 @@ val MMApp = fc<MMAppProps>("Muon monitor") { props ->
+"Next" +"Next"
attrs { attrs {
onClickFunction = { onClickFunction = {
context.launch { solids.context.launch {
val event = window.fetch( val event = window.fetch(
"http://localhost:8080/event", "http://localhost:8080/event",
RequestInit("GET") RequestInit("GET")

View File

@ -1,31 +1,34 @@
package ru.mipt.npm.muon.monitor package ru.mipt.npm.muon.monitor
import kotlinx.browser.document import org.w3c.dom.Document
import react.dom.render
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.fetch import space.kscience.dataforge.context.request
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.VisionManager import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.react.createRoot
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication import space.kscience.visionforge.startApplication
private class MMDemoApp : Application { private class MMDemoApp : Application {
override fun start(state: Map<String, Any>) { override fun start(document: Document, state: Map<String, Any>) {
val context = Context("MM-demo") { val context = Context("MM-demo") {
plugin(ThreePlugin) plugin(ThreePlugin)
} }
val visionManager = context.fetch(VisionManager)
val visionManager = context.request(VisionManager)
val model = Model(visionManager) val model = Model(visionManager)
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") val element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
render(element) { createRoot(element).render {
child(MMApp) { child(MMApp) {
attrs { attrs {
this.model = model this.model = model
this.context = context this.solids = context.request(Solids)
} }
} }
} }

View File

@ -5,7 +5,6 @@
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">--> <!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
<title>Three js demo for particle physics</title> <title>Three js demo for particle physics</title>
<script type="text/javascript" src="muon-monitor.js"></script> <script type="text/javascript" src="muon-monitor.js"></script>
<link rel="stylesheet" href="css/custom-bootstrap.css">
</head> </head>
<body class="application"> <body class="application">
<div class="container-fluid max-vh-100" id = "app"> </div> <div class="container-fluid max-vh-100" id = "app"> </div>

View File

@ -1,31 +1,28 @@
package ru.mipt.npm.muon.monitor.server package ru.mipt.npm.muon.monitor.server
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.application.log
import io.ktor.features.CallLogging
import io.ktor.features.ContentNegotiation
import io.ktor.features.DefaultHeaders
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.http.content.resources import io.ktor.serialization.kotlinx.json.json
import io.ktor.http.content.static import io.ktor.server.application.Application
import io.ktor.response.respond import io.ktor.server.application.call
import io.ktor.response.respondText import io.ktor.server.application.install
import io.ktor.routing.Routing import io.ktor.server.application.log
import io.ktor.routing.get
import io.ktor.serialization.json
import io.ktor.server.cio.CIO import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer import io.ktor.server.engine.embeddedServer
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
import io.ktor.server.routing.Routing
import io.ktor.server.routing.get
import org.apache.commons.math3.random.JDKRandomGenerator import org.apache.commons.math3.random.JDKRandomGenerator
import ru.mipt.npm.muon.monitor.Model import ru.mipt.npm.muon.monitor.Model
import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
import ru.mipt.npm.muon.monitor.sim.simulateOne import ru.mipt.npm.muon.monitor.sim.simulateOne
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.fetch import space.kscience.dataforge.context.request
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import java.awt.Desktop import java.awt.Desktop
@ -38,10 +35,8 @@ private val generator = Cos2TrackGenerator(JDKRandomGenerator(223))
fun Application.module(context: Context = Global) { fun Application.module(context: Context = Global) {
val currentDir = File(".").absoluteFile val currentDir = File(".").absoluteFile
environment.log.info("Current directory: $currentDir") environment.log.info("Current directory: $currentDir")
val solidManager = context.fetch(Solids) val solidManager = context.request(Solids)
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) { install(ContentNegotiation) {
json() json()
} }
@ -57,9 +52,7 @@ fun Application.module(context: Context = Global) {
status = HttpStatusCode.OK status = HttpStatusCode.OK
) )
} }
static("/") { staticResources("/", null)
resources()
}
} }
try { try {
Desktop.getDesktop().browse(URI("http://localhost:8080/index.html")) Desktop.getDesktop().browse(URI("http://localhost:8080/index.html"))

View File

@ -5,7 +5,7 @@ import org.apache.commons.math3.geometry.euclidean.threed.Plane
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D 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.CENTRAL_LAYER_Z
import ru.mipt.npm.muon.monitor.Monitor.GEOMETRY_TOLERANCE 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. * 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<Point3D> { fun Line.toKMathVectors(): List<Float32Vector3D> {
val basePoint = basePlane.intersection(this) val basePoint = basePlane.intersection(this)
val bottom = basePoint.subtract(2000.0, direction) val bottom = basePoint.subtract(2000.0, direction)
val top = basePoint.add(2000.0, direction) val top = basePoint.add(2000.0, direction)
return listOf(bottom.toPoint(), top.toPoint()) return listOf(bottom.toKMathVector(), top.toKMathVector())
} }

View File

@ -43,7 +43,7 @@ fun readEffs(): Map<String, Double> {
fun buildEventByTrack(index: Int, track: Line, hitResolver: (Line) -> Collection<SC1> = defaultHitResolver): Event { fun buildEventByTrack(index: Int, track: Line, hitResolver: (Line) -> Collection<SC1> = 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<SC1> = { track: Line -> val defaultHitResolver: (Line) -> Collection<SC1> = { track: Line ->

View File

@ -2,6 +2,7 @@ plugins {
kotlin("multiplatform") kotlin("multiplatform")
kotlin("jupyter.api") kotlin("jupyter.api")
id("com.github.johnrengelman.shadow") version "7.1.2" id("com.github.johnrengelman.shadow") version "7.1.2"
// application
} }
repositories { repositories {
@ -16,23 +17,25 @@ kotlin {
useCommonJs() useCommonJs()
browser { browser {
webpackTask { webpackTask {
this.outputFileName = "js/visionforge-playground.js" mainOutputFileName.set("js/visionforge-playground.js")
} }
commonWebpackConfig { commonWebpackConfig {
sourceMaps = true sourceMaps = true
cssSupport.enabled = false cssSupport{
enabled.set(false)
}
} }
} }
binaries.executable() binaries.executable()
} }
jvm { jvm {
withJava() // withJava()
compilations.all { compilations.all {
kotlinOptions { kotlinOptions {
jvmTarget = "11" jvmTarget = "11"
freeCompilerArgs = freeCompilerArgs =
freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" + "-Xcontext-receivers"
} }
} }
testRuns["test"].executionTask.configure { testRuns["test"].executionTask.configure {
@ -44,12 +47,11 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
implementation(projects.visionforgeSolid) implementation(projects.visionforgeSolid)
implementation(projects.visionforgeGdml)
implementation(projects.visionforgePlotly) implementation(projects.visionforgePlotly)
implementation(projects.visionforgeMarkdown) implementation(projects.visionforgeMarkdown)
implementation(projects.visionforgeTables) implementation(projects.visionforgeTables)
implementation(projects.cernRootLoader) implementation(projects.cernRootLoader)
implementation(projects.jupyter) api(projects.visionforgeJupyter.visionforgeJupyterCommon)
} }
} }
@ -63,8 +65,10 @@ kotlin {
val jvmMain by getting { val jvmMain by getting {
dependencies { dependencies {
implementation("io.ktor:ktor-server-cio:${spclibs.versions.ktor.get()}")
implementation(projects.visionforgeGdml)
implementation(projects.visionforgeServer) implementation(projects.visionforgeServer)
implementation("ch.qos.logback:logback-classic:1.2.3") implementation(spclibs.logback.classic)
implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6") implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6")
} }
} }
@ -88,3 +92,7 @@ val processJupyterApiResources by tasks.getting(org.jetbrains.kotlinx.jupyter.ap
} }
tasks.findByName("shadowJar")?.dependsOn(processJupyterApiResources) tasks.findByName("shadowJar")?.dependsOn(processJupyterApiResources)
//application{
// mainClass.set("space.kscience.visionforge.examples.ShapesKt")
//}

View File

@ -0,0 +1,98 @@
{
"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": {
"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"
},
"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"
},
"ktnbPluginMetadata": {
"projectLibraries": []
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,45 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"USE(JupyterCommonIntegration())"
]
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [],
"metadata": {
"collapsed": false
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.9.0",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
},
"ktnbPluginMetadata": {
"projectDependencies": true
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -0,0 +1,89 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [],
"pycharm": {
"is_executing": true
}
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vf.startServer()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import kotlinx.coroutines.*\n",
"import kotlin.random.Random\n",
"\n",
"Plotly.plot{\n",
" scatter{\n",
" x(1,2,3)\n",
" y(1,2,3)\n",
" if(vf.isServerRunning()){\n",
" vf.launch{\n",
" while(isActive){\n",
" delay(500)\n",
" y(Random.nextDouble(), Random.nextDouble(), Random.nextDouble())\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vf.stopServer()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"codemirror_mode": "text/x-kotlin",
"file_extension": ".kt",
"mimetype": "text/x-kotlin",
"name": "kotlin",
"nbconvert_exporter": "",
"pygments_lexer": "kotlin",
"version": "1.8.0-dev-3517"
},
"ktnbPluginMetadata": {
"projectLibraries": []
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -1,4 +1,5 @@
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.jupyter.VFNotebookClient
import space.kscience.visionforge.markup.MarkupPlugin import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.ring.ThreeWithControlsPlugin import space.kscience.visionforge.ring.ThreeWithControlsPlugin
@ -11,4 +12,5 @@ fun main() = runVisionClient {
plugin(PlotlyPlugin) plugin(PlotlyPlugin)
plugin(MarkupPlugin) plugin(MarkupPlugin)
plugin(TableVisionJsPlugin) plugin(TableVisionJsPlugin)
plugin(VFNotebookClient)
} }

View File

@ -0,0 +1,83 @@
package space.kscience.visionforge.examples
import ru.mipt.npm.root.BMN
import ru.mipt.npm.root.DGeoManager
import ru.mipt.npm.root.rootGeo
import ru.mipt.npm.root.serialization.TGeoManager
import ru.mipt.npm.root.toVector
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.meta.string
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.*
import java.util.zip.ZipInputStream
import kotlin.io.path.Path
import kotlin.io.path.createDirectories
import kotlin.io.path.writeText
private fun Meta.countTypes(): Sequence<String> = sequence {
if (!isLeaf) {
get("_typename")?.value?.let { yield(it.string) }
items.forEach { yieldAll(it.value.countTypes()) }
}
}
fun main() {
Path("data").createDirectories()
val string = ZipInputStream(TGeoManager::class.java.getResourceAsStream("/root/geometry_run_7-2076.zip")!!).use {
it.nextEntry
it.readAllBytes().decodeToString()
}
val geo = DGeoManager.parse(string)
val sizes = geo.meta.countTypes().groupBy { it }.mapValues { it.value.size }
sizes.forEach {
println(it)
}
val events = BMN.readEventJson(TGeoManager::class.java.getResourceAsStream("/root/event_0.json")!!.bufferedReader().readText())
makeVisionFile(path = Path("data/output.html"), resourceLocation = ResourceLocation.EMBED) {
vision("canvas") {
requirePlugin(Solids)
solid {
ambientLight {
color(Colors.white)
}
rootGeo(geo,"BM@N", ignoreRootColors = true).also {
Path("data/BM@N.vf.json").writeText(Solids.encodeToString(it))
}
solidGroup("cbmStsTracks") {
events.cbmTracks.forEach { track ->
polyline(
track.fParamFirst.toVector(),
track.fParamLast.toVector()
) {
thickness = 2.0
color(Colors.blue)
}
}
}
solidGroup("bmnGlobalTracks") {
events.bmnGlobalTracks.forEach { track ->
polyline(
track.fParamFirst.toVector(),
track.fParamLast.toVector()
) {
thickness = 2.0
color(Colors.red)
}
}
}
}
}
}
}

View File

@ -1,50 +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.JupyterPluginBase
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.plotly.asVision
import space.kscience.visionforge.solid.Solids
@DFExperimental
internal class VisionForgePlayGroundForJupyter : JupyterPluginBase(
Context("VisionForge") {
plugin(Solids)
plugin(PlotlyPlugin)
}
) {
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<Gdml> { gdmlModel ->
handler.produceHtml {
vision { gdmlModel.toVision() }
}
}
render<Plot> { plot ->
handler.produceHtml {
vision { plot.asVision() }
}
}
}
}

View File

@ -1,7 +1,8 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import kotlinx.html.h2 import kotlinx.html.h2
import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.invoke
import space.kscience.plotly.layout import space.kscience.plotly.layout
import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.ScatterMode
import space.kscience.plotly.models.TextPosition import space.kscience.plotly.models.TextPosition
@ -12,13 +13,14 @@ import space.kscience.visionforge.markup.markdown
import space.kscience.visionforge.plotly.plotly import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.solid import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.z import space.kscience.visionforge.solid.z
import space.kscience.visionforge.tables.columnTable import space.kscience.visionforge.tables.columnTable
import java.nio.file.Paths import kotlin.io.path.Path
fun main() = makeVisionFile( fun main() = makeVisionFile(
Paths.get("VisionForgeDemo.html"), Path("VisionForgeDemo.html"),
resourceLocation = ResourceLocation.EMBED resourceLocation = ResourceLocation.EMBED
) { ) {
markdown { markdown {
@ -32,8 +34,15 @@ fun main() = makeVisionFile(
h2 { +"3D visualization with Three-js" } h2 { +"3D visualization with Three-js" }
vision("3D") { vision("3D") {
solid { solid(
box(100, 100, 100, name = "aBox"){ Canvas3DOptions {
axes {
size = 200.0
visible = true
}
}
) {
box(100, 100, 100, name = "aBox") {
z = 50.0 z = 50.0
} }
} }

View File

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

View File

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

View File

@ -0,0 +1,22 @@
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(0, x = 10, y = 10)
layer(30)
}
}
}
}

View File

@ -1,22 +1,42 @@
package space.kscience.visionforge.examples 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 kotlinx.html.* import kotlinx.html.*
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.fetch import space.kscience.dataforge.context.request
import space.kscience.visionforge.VisionManager import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.html.Page import space.kscience.visionforge.html.VisionOfHtmlForm
import space.kscience.visionforge.html.formFragment import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.html.bindForm
import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.onPropertyChange
import space.kscience.visionforge.server.close import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.serve import space.kscience.visionforge.server.visionPage
@Suppress("ExtractKtorModule")
fun main() { fun main() {
val visionManager = Global.fetch(VisionManager) val visionManager = Global.request(VisionManager)
val server = visionManager.serve { val server = embeddedServer(CIO) {
page(header = Page.scriptHeader("js/visionforge-playground.js")) {
val form = formFragment("form") { routing {
staticResources("/", null)
}
val form = VisionOfHtmlForm("form").apply {
onPropertyChange(visionManager.context) {
println(values)
}
}
visionPage(
visionManager,
VisionPage.scriptHeader("js/visionforge-playground.js"),
) {
bindForm(form) {
label { label {
htmlFor = "fname" htmlFor = "fname"
+"First name:" +"First name:"
@ -47,17 +67,15 @@ fun main() {
value = "Submit" value = "Submit"
} }
} }
println(form.values)
vision(form)
}
vision("form") { form } }.start(false)
form.onPropertyChange {
println(this)
}
}
}
server.openInBrowser() server.openInBrowser()
while (readln() != "exit") { while (readlnOrNull() != "exit") {
} }

View File

@ -5,7 +5,7 @@ import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){ fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision("canvas") { vision("canvas") {
requirePlugin(Solids) requirePlugin(Solids)
GdmlShowCase.cubes().toVision() GdmlShowCase.cubes().toVision()

View File

@ -223,7 +223,7 @@ fun main() = makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceL
} }
} }
}.toVision { }.toVision {
configure { _, solid, _ -> solids { _, solid, _ ->
//disable visibility for the world box //disable visibility for the world box
if(solid.name == "world"){ if(solid.name == "world"){
visible = false visible = false

View File

@ -1,12 +1,15 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.gdml.GdmlShowCase import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.gdml
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.solid
fun main() = makeVisionFile { fun main() = makeVisionFile {
vision("canvas") { vision("canvas") {
requirePlugin(Solids) requirePlugin(Solids)
GdmlShowCase.babyIaxo().toVision() solid {
gdml(GdmlShowCase.babyIaxo(), "D0")
}
} }
} }

View File

@ -6,6 +6,7 @@ import kotlinx.serialization.json.Json
import space.kscience.visionforge.solid.SolidGroup import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
@OptIn(ExperimentalSerializationApi::class)
private val json = Json { private val json = Json {
serializersModule = Solids.serializersModuleForSolids serializersModule = Solids.serializersModuleForSolids
prettyPrintIndent = " " prettyPrintIndent = " "

View File

@ -1,15 +1,92 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.plotly.scatter import space.kscience.dataforge.meta.Value
import space.kscience.plotly.layout
import space.kscience.plotly.models.*
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.plotly.plotly import space.kscience.visionforge.plotly.plotly
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) { fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision { vision {
val trace1 = Violin {
text("sample length: 32")
marker {
line {
width = 2
color("#bebada")
}
symbol = Symbol.valueOf("line-ns")
}
orientation = Orientation.h
hoveron = ViolinHoveron.`points+kde`
meanline {
visible = true
}
legendgroup = "F"
scalegroup = "F"
points = ViolinPoints.all
pointpos = 1.2
jitter = 0
box {
visible = true
}
scalemode = ViolinScaleMode.count
showlegend = false
side = ViolinSide.positive
y0 = Value.of(0)
line {
color("#bebada")
}
name = "F"
x(10.07, 34.83, 10.65, 12.43, 24.08, 13.42, 12.48, 29.8, 14.52, 11.38,
20.27, 11.17, 12.26, 18.26, 8.51, 10.33, 14.15, 13.16, 17.47, 27.05, 16.43,
8.35, 18.64, 11.87, 19.81, 43.11, 13.0, 12.74, 13.0, 16.4, 16.47, 18.78)
}
val trace2 = Violin {
text("sample length: 32")
marker {
line {
width = 2
color("#8dd3c7")
}
symbol = Symbol.valueOf("line-ns")
}
orientation = Orientation.h
hoveron = ViolinHoveron.`points+kde`
meanline {
visible = true
}
legendgroup = "M"
scalegroup = "M"
points = ViolinPoints.all
pointpos = -1.2
jitter = 0
box {
visible = true
}
scalemode = ViolinScaleMode.count
showlegend = false
side = ViolinSide.negative
y0 = Value.of(0)
line {
color("#8dd3c7")
}
name = "M"
x(27.2, 22.76, 17.29, 19.44, 16.66, 32.68, 15.98, 13.03, 18.28, 24.71,
21.16, 11.69, 14.26, 15.95, 8.52, 22.82, 19.08, 16.0, 34.3, 41.19, 9.78,
7.51, 28.44, 15.48, 16.58, 7.56, 10.34, 13.51, 18.71, 20.53)
}
plotly { plotly {
scatter { traces(trace1, trace2)
x(1, 2, 3) layout {
y(5, 8, 7) width = 800
height = 800
title = "Advanced Violin Plot"
} }
} }
} }

View File

@ -2,6 +2,7 @@ package space.kscience.visionforge.examples
import kotlinx.html.div import kotlinx.html.div
import kotlinx.html.h1 import kotlinx.html.h1
import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import java.nio.file.Paths import java.nio.file.Paths
@ -17,6 +18,9 @@ fun main() = makeVisionFile(
div { div {
vision { vision {
solid { solid {
ambientLight {
color(Colors.white)
}
repeat(100) { repeat(100) {
sphere(5, name = "sphere[$it]") { sphere(5, name = "sphere[$it]") {
x = random.nextDouble(-300.0, 300.0) x = random.nextDouble(-300.0, 300.0)

View File

@ -1,106 +0,0 @@
package space.kscience.visionforge.examples
import ru.mipt.npm.root.DGeoManager
import ru.mipt.npm.root.serialization.TGeoManager
import ru.mipt.npm.root.toSolid
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.values.string
import space.kscience.visionforge.solid.Solids
import java.nio.file.Paths
import java.util.zip.ZipInputStream
import kotlin.io.path.writeText
private fun Meta.countTypes(): Sequence<String> = sequence {
if (!isLeaf) {
get("_typename")?.value?.let { yield(it.string) }
items.forEach { yieldAll(it.value.countTypes()) }
}
}
fun main() {
val string = ZipInputStream(TGeoManager::class.java.getResourceAsStream("/root/BM@N_geometry.zip")!!).use {
it.nextEntry
it.readAllBytes().decodeToString()
}
val geo = DGeoManager.parse(string)
val sizes = geo.meta.countTypes().groupBy { it }.mapValues { it.value.size }
sizes.forEach {
println(it)
}
val solid = geo.toSolid()
Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid))
//println(Solids.encodeToString(solid))
makeVisionFile {
vision("canvas") {
requirePlugin(Solids)
solid
}
}
}
/* SolidGroup {
set(
"Coil",
solid.getPrototype("Coil".asName())!!.apply {
parent = null
}
)
*//* group("Shade") {
y = 200
color("red")
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(79.6, 0, -122.1)
rotation = Point3D(-1.5707964, 0, 0)
}
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(-79.6, 0, -122.1)
rotation = Point3D(1.5707964, 0, -3.1415927)
}
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(79.6, 0, 122.1)
rotation = Point3D(1.5707964, 0, 0)
}
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(-79.6, 0, 122.1)
rotation = Point3D(-1.5707964, 0, -3.1415927)
}
}*//*
}*/

View File

@ -1,14 +1,24 @@
package space.kscience.visionforge.examples 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.dataforge.context.Global
import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.*
import space.kscience.visionforge.html.Page import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.html.importScriptHeader import space.kscience.visionforge.server.close
import space.kscience.visionforge.makeFile 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.awt.Desktop
import java.nio.file.Path import java.nio.file.Path
public fun makeVisionFile( public fun makeVisionFile(
path: Path? = null, path: Path? = null,
title: String = "VisionForge page", title: String = "VisionForge page",
@ -16,15 +26,58 @@ public fun makeVisionFile(
show: Boolean = true, show: Boolean = true,
content: HtmlVisionFragment, content: HtmlVisionFragment,
): Unit { ): Unit {
val actualPath = Page(Global, content = content).makeFile(path) { actualPath -> val actualPath = VisionPage(Global.visionManager, content = content).makeFile(path) { actualPath ->
mapOf( mapOf(
"title" to Page.title(title), "title" to VisionPage.title(title),
"playground" to Page.importScriptHeader("js/visionforge-playground.js", resourceLocation, actualPath), "playground" to VisionPage.importScriptHeader(
"js/visionforge-playground.js",
resourceLocation,
actualPath
),
) )
} }
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI()) 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 //@DFExperimental
//public fun Context.makeVisionFile( //public fun Context.makeVisionFile(
// vision: Vision, // vision: Vision,

View File

@ -0,0 +1,40 @@
package space.kscience.visionforge.examples
import space.kscience.visionforge.Colors
import space.kscience.visionforge.solid.*
import kotlin.math.PI
fun main() = makeVisionFile {
vision("canvas") {
solid {
ambientLight()
box(100.0, 100.0, 100.0) {
z = -110.0
color("teal")
}
sphere(50.0) {
x = 110
detail = 16
color("red")
}
tube(50, height = 10, innerRadius = 25, angle = PI) {
y = 110
detail = 16
rotationX = PI / 4
color("blue")
}
sphereLayer(50, 40, theta = PI / 2) {
rotationX = -PI * 3 / 4
z = 110
color(Colors.pink)
}
cylinder(30,20, name = "cylinder"){
detail = 31
y = -220
z = 15
}
}
}
}

View File

@ -0,0 +1,19 @@
package space.kscience.visionforge.examples
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.polygon
import space.kscience.visionforge.solid.solid
import space.kscience.visionforge.solid.surface
fun main() = makeVisionFile {
vision("canvas") {
solid {
ambientLight()
surface("surface") {
layer(0, { polygon(8, 10) }, { polygon(8, 20) })
layer(10, { polygon(8, 20) }, { polygon(8, 30) })
layer(20, { polygon(8, 10) }, { polygon(8, 20) })
}
}
}
}

View File

@ -1,6 +1,6 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.meta.ValueType
import space.kscience.tables.ColumnHeader import space.kscience.tables.ColumnHeader
import space.kscience.tables.valueRow import space.kscience.tables.valueRow
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
[
[{
"_typename" : "CbmStsTrack",
"fUniqueID" : 0,
"fBits" : 0,
"ststrk" : 2112745000,
"fStsHits" : [216, 221, 5, 50, 63, 82, 133],
"fMvdHits" : [],
"fPidHypo" : 211,
"fParamFirst" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : -4.79052305221558,
"fY" : 8.83165168762207,
"fZ" : 36.5065002441406,
"fTx" : -0.11185921728611,
"fTy" : 0.228091076016426,
"fQp" : 0.893607378005981,
"fCovMatrix" : [1.68777798535302e-4, -9.69577522482723e-4, -1.07744517663377e-5, 1.2614247680176e-5, 2.87587154161884e-5, 0.0403835587203503, 5.90448107686825e-5, -5.16064348630607e-4, -2.05383723368868e-4, 2.20405854634009e-6, -8.30146461794357e-7, -5.49759215573431e-6, 1.16227884063846e-5, 3.6013934732182e-6, 1.46196922287345e-4]
},
"fParamLast" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : 4.67626953125,
"fY" : 43.7959594726562,
"fZ" : 190.759826660156,
"fTx" : 0.240885242819786,
"fTy" : 0.230351597070694,
"fQp" : 0.896391570568085,
"fCovMatrix" : [0.00152156152762473, 0.00325645040720701, 4.73157851956785e-5, 4.51812447863631e-5, 1.32256536744535e-4, 0.0311740729957819, 1.29416745039634e-4, 3.94528120523319e-4, 3.28425812767819e-4, 3.75195077140233e-6, 1.75166894678114e-6, 9.62230569712119e-6, 9.89728778222343e-6, 4.38717188444571e-6, 1.46559861605056e-4]
},
"fFlag" : 0,
"fChi2" : 3.59655165672302,
"fNDF" : 9,
"fB" : 0,
"fnEv" : 0,
"fHitsArr" : {
"_typename" : "TClonesArray",
"name" : "CbmStsHits",
"arr" : []
}
}, {
"_typename" : "CbmStsTrack",
"fUniqueID" : 0,
"fBits" : 0,
"ststrk" : 0,
"fStsHits" : [79, 108, 136, 160],
"fMvdHits" : [],
"fPidHypo" : 211,
"fParamFirst" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : 7.56474113464355,
"fY" : -6.31765508651733,
"fZ" : 123.474571228027,
"fTx" : 0.198165953159332,
"fTy" : -0.0599287338554859,
"fQp" : 0.826108694076538,
"fCovMatrix" : [0.00192060391418636, -0.00543995574116707, -7.47249359847046e-5, 9.40304598771036e-5, 4.32362634455785e-4, 0.0452092550694942, 2.69763870164752e-4, -7.19496863894165e-4, -0.00178805936593562, 5.47440777154407e-6, -4.97666542287334e-6, -3.32396593876183e-5, 1.67156704264926e-5, 3.69572808267549e-5, 3.62657097866759e-4]
},
"fParamLast" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : 38.4175720214844,
"fY" : -12.5351896286011,
"fZ" : 222.266052246094,
"fTx" : 0.428264498710632,
"fTy" : -0.0652719661593437,
"fQp" : 0.827384233474731,
"fCovMatrix" : [0.00191446917597204, 0.00539331184700131, 7.50113686081022e-5, 9.10265880520456e-5, 4.29905543569475e-4, 0.0449054278433323, 2.68147414317355e-4, 7.0479983696714e-4, 0.00177141127642244, 5.60895068701939e-6, 4.76898094348144e-6, 3.39166836056393e-5, 1.61108710017288e-5, 3.51894050254487e-5, 3.57192009687424e-4]
},
"fFlag" : 0,
"fChi2" : 0.0889237225055695,
"fNDF" : 3,
"fB" : 0,
"fnEv" : 0,
"fHitsArr" : {
"_typename" : "TClonesArray",
"name" : "CbmStsHits",
"arr" : []
}
}]
,
[{
"_typename" : "BmnGlobalTrack",
"fUniqueID" : 0,
"fBits" : 0,
"fHits" : [],
"fParamFirst" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : 0.514997541904449,
"fY" : 0.614071667194366,
"fZ" : 0.716018855571747,
"fTx" : -0.182437181472778,
"fTy" : 0.231170654296875,
"fQp" : 0.890645802021027,
"fCovMatrix" : [0.00640107085928321, -0.00549036636948586, -2.40077963098884e-4, 5.9050194977317e-5, 4.4034980237484e-4, 0.0939982086420059, 1.37060953420587e-4, -0.0010447750100866, -3.45796346664429e-4, 1.4494138667942e-5, -1.88720639471285e-6, -1.71545361808967e-5, 2.24065261136275e-5, 4.27886925535859e-6, 1.46344274980947e-4]
},
"fParamLast" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : 4.67626953125,
"fY" : 43.7959594726562,
"fZ" : 190.759826660156,
"fTx" : 0.240885242819786,
"fTy" : 0.230351597070694,
"fQp" : 0.896391570568085,
"fCovMatrix" : [0.00152156152762473, 0.00325645040720701, 4.73157851956785e-5, 4.51812447863631e-5, 1.32256536744535e-4, 0.0311740729957819, 1.29416745039634e-4, 3.94528120523319e-4, 3.28425812767819e-4, 3.75195077140233e-6, 1.75166894678114e-6, 9.62230569712119e-6, 9.89728778222343e-6, 4.38717188444571e-6, 1.46559861605056e-4]
},
"fFlag" : -1,
"fChi2" : 3.596552,
"fNDF" : 9,
"fB" : 0,
"fLength" : 196.4224,
"fNhits" : 7,
"fUsing" : false,
"fGemTrack" : 0,
"fSsdTrack" : -1,
"fSilTrack" : -1,
"fTof1Hit" : -1,
"fTof2Hit" : -1,
"fDch1Track" : -1,
"fDch2Track" : -1,
"fDchTrack" : -1,
"fMwpc1Track" : -1,
"fMwpc2Track" : -1,
"fUpstreamTrack" : -1,
"fScWallCellId" : -1,
"fCscHit" : [-1, -1, -1, -1],
"fScWallSignal" : -1000,
"fBeta400" : -1000,
"fBeta700" : -1000,
"fdQdNUpper" : 0,
"fdQdNLower" : 0,
"fA" : -1,
"fZ" : 0,
"fPDG" : 0,
"fChi2InVertex" : 2.34478793822074e-310,
"fDCAInVertex" : 0.169359803199768,
"fPidTof400" : [],
"fPidTof700" : [],
"fIsPrimary" : true,
"fRefIndex" : 0
}, {
"_typename" : "BmnGlobalTrack",
"fUniqueID" : 0,
"fBits" : 0,
"fHits" : [],
"fParamFirst" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : -1.30332088470459,
"fY" : 0.709633886814117,
"fZ" : 0.716018855571747,
"fTx" : -0.0394387505948544,
"fTy" : -0.0554707236588001,
"fQp" : 0.794627845287323,
"fCovMatrix" : [1.0362377166748, -0.242409482598305, -0.0120293609797955, 0.00132000644225627, 0.0113498065620661, 1.10034370422363, 0.0026963478885591, -0.0100266374647617, -0.00638964772224426, 1.71858730027452e-4, -1.46718830364989e-5, -1.39145020511933e-4, 1.31993641844019e-4, 3.72123940906022e-5, 3.64089268259704e-4]
},
"fParamLast" : {
"_typename" : "FairTrackParam",
"fUniqueID" : 0,
"fBits" : 0,
"fX" : 153.443832397461,
"fY" : -27.7408638000488,
"fZ" : 422.371002197266,
"fTx" : 0.623147189617157,
"fTy" : -0.0757252722978592,
"fQp" : 0.879441320896149,
"fCovMatrix" : [0.210621446371078, 0.00677151698619127, 0.00126052019186318, -1.89192069228739e-5, 0.00233594398014247, 0.117487587034702, 1.90632126759738e-5, 5.61361608561128e-4, 3.66047053830698e-4, 5.4321233619703e-5, -1.38209452416049e-6, 1.40239317261148e-5, 3.86252722819336e-5, -2.07852266953523e-7, 1.6525064711459e-4]
},
"fFlag" : -1,
"fChi2" : 28.54445,
"fNDF" : 3,
"fB" : 0,
"fLength" : 456.7299,
"fNhits" : 5,
"fUsing" : false,
"fGemTrack" : 1,
"fSsdTrack" : -1,
"fSilTrack" : -1,
"fTof1Hit" : 0,
"fTof2Hit" : -1,
"fDch1Track" : -1,
"fDch2Track" : -1,
"fDchTrack" : -1,
"fMwpc1Track" : -1,
"fMwpc2Track" : -1,
"fUpstreamTrack" : -1,
"fScWallCellId" : -1,
"fCscHit" : [-1, -1, -1, -1],
"fScWallSignal" : -1000,
"fBeta400" : 0.813491527513362,
"fBeta700" : -1000,
"fdQdNUpper" : 0,
"fdQdNLower" : 0,
"fA" : -1,
"fZ" : 0,
"fPDG" : 0,
"fChi2InVertex" : 2.34478793822074e-310,
"fDCAInVertex" : 1.82100653648376,
"fPidTof400" : [0.698706510566553, 0.0456706934329348, 0.070160747316434, 0.044178479600919, 0.0321317585690916, 0.0203602877603981, 0.0563498151154308, 0.0324417076382387],
"fPidTof700" : [],
"fIsPrimary" : true,
"fRefIndex" : 0
}]
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("ru.mipt.npm.gradle.jvm") id("space.kscience.gradle.jvm")
application application
} }
@ -8,15 +8,15 @@ kscience {
// useSerialization { // useSerialization {
// json() // json()
// } // }
application() useKtor()
dependencies{
implementation("io.ktor:ktor-server-cio")
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
implementation(spclibs.logback.classic)
}
} }
group = "ru.mipt.npm" group = "center.sciprog"
dependencies{
implementation(project(":visionforge-threejs:visionforge-threejs-server"))
implementation("ch.qos.logback:logback-classic:1.2.3")
}
application { application {
mainClass.set("ru.mipt.npm.sat.SatServerKt") mainClass.set("ru.mipt.npm.sat.SatServerKt")

View File

@ -6,7 +6,7 @@ import space.kscience.visionforge.style
import space.kscience.visionforge.useStyle import space.kscience.visionforge.useStyle
import kotlin.math.PI import kotlin.math.PI
internal fun visionOfSatellite( internal fun Solids.visionOfSatellite(
layers: Int = 10, layers: Int = 10,
layerHeight: Number = 10, layerHeight: Number = 10,
xSegments: Int = 3, xSegments: Int = 3,
@ -14,7 +14,7 @@ internal fun visionOfSatellite(
xSegmentSize: Number = 30, xSegmentSize: Number = 30,
ySegmentSize: Number = xSegmentSize, ySegmentSize: Number = xSegmentSize,
fiberDiameter: Number = 1.0, fiberDiameter: Number = 1.0,
): SolidGroup = SolidGroup { ): SolidGroup = solidGroup {
color("darkgreen") color("darkgreen")
val transparent by style { val transparent by style {
this[SolidMaterial.MATERIAL_OPACITY_KEY] = 0.3 this[SolidMaterial.MATERIAL_OPACITY_KEY] = 0.3
@ -31,7 +31,7 @@ internal fun visionOfSatellite(
val totalXSize = xSegments * xSegmentSize.toDouble() val totalXSize = xSegments * xSegmentSize.toDouble()
val totalYSize = ySegments * ySegmentSize.toDouble() val totalYSize = ySegments * ySegmentSize.toDouble()
for (layer in 1..layers) { for (layer in 1..layers) {
group("layer[$layer]") { solidGroup("layer[$layer]") {
for (i in 1..xSegments) { for (i in 1..xSegments) {
for (j in 1..ySegments) { for (j in 1..ySegments) {
box(xSegmentSize, ySegmentSize, layerHeight, name = "segment[$i,$j]") { box(xSegmentSize, ySegmentSize, layerHeight, name = "segment[$i,$j]") {
@ -42,7 +42,7 @@ internal fun visionOfSatellite(
} }
} }
} }
group("fibers") { solidGroup("fibers") {
for (i in 1..xSegments) { for (i in 1..xSegments) {
cylinder(fiberDiameter, totalYSize) { cylinder(fiberDiameter, totalYSize) {
useStyle(red) useStyle(red)

View File

@ -1,38 +1,57 @@
package ru.mipt.npm.sat package ru.mipt.npm.sat
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 kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.html.div import kotlinx.html.div
import kotlinx.html.h1 import kotlinx.html.h1
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.dataforge.meta.Null
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.html.Page import space.kscience.visionforge.Colors
import space.kscience.visionforge.html.plus import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.server.close import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.serve import space.kscience.visionforge.server.visionPage
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.three.threeJsHeader import space.kscience.visionforge.three.threeJsHeader
import space.kscience.visionforge.visionManager
import kotlin.random.Random import kotlin.random.Random
@Suppress("ExtractKtorModule")
fun main() { fun main() {
val satContext = Context("sat") { val satContext = Context("sat") {
plugin(Solids) plugin(Solids)
} }
//Create a geometry val solids = satContext.request(Solids)
val sat = visionOfSatellite(ySegments = 3)
val server = satContext.visionManager.serve { //Create a geometry
page(header = Page.threeJsHeader + Page.styleSheetHeader("css/styles.css")) { val sat = solids.visionOfSatellite(ySegments = 3).apply {
ambientLight {
color(Colors.white)
}
}
val server = embeddedServer(CIO, port = 7777) {
routing {
staticResources("", null, null)
}
visionPage(
solids.visionManager, VisionPage.threeJsHeader,
VisionPage.styleSheetHeader("css/styles.css")
) {
div("flex-column") { div("flex-column") {
h1 { +"Satellite detector demo" } h1 { +"Satellite detector demo" }
vision { sat } vision { sat }
} }
} }
}
}.start(false)
server.openInBrowser() server.openInBrowser()
@ -46,7 +65,8 @@ fun main() {
val targetVision = sat[target] as Solid val targetVision = sat[target] as Solid
targetVision.color("red") targetVision.color("red")
delay(1000) delay(1000)
targetVision.color.clear() //use to ensure that color is cleared
targetVision.color.value = Null
delay(500) delay(500)
} }
} }

View File

@ -0,0 +1,21 @@
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.solid
import space.kscience.visionforge.three.makeThreeJsFile
@OptIn(DFExperimental::class)
fun main() = makeThreeJsFile(resourceLocation = ResourceLocation.SYSTEM) {
vision ("canvas") {
solid {
box(100, 100, 100)
material {
emissiveColor("red")
}
}
}
}

View File

@ -1,44 +1,26 @@
import ru.mipt.npm.gradle.DependencyConfiguration
import ru.mipt.npm.gradle.FXModule
plugins { plugins {
id("ru.mipt.npm.gradle.mpp") id("space.kscience.gradle.mpp")
application // application
} }
kscience { kscience {
useCoroutines() useCoroutines()
val fxVersion: String by rootProject.extra jvm()
useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) js{
application() binaries.executable()
}
kotlin {
jvm {
withJava()
} }
sourceSets {
commonMain {
dependencies { dependencies {
implementation(project(":visionforge-solid")) implementation(projects.visionforgeSolid)
// implementation(project(":visionforge-gdml")) implementation(projects.visionforgeGdml)
}
}
jvmMain {
dependencies {
implementation(project(":visionforge-fx"))
}
} }
jsMain { jsMain {
dependencies { implementation(projects.visionforgeThreejs)
implementation(project(":visionforge-threejs"))
}
}
} }
} }
application { kotlin.explicitApi = null
mainClassName = "space.kscience.visionforge.solid.demo.FXDemoAppKt"
} //application {
// mainClass.set("space.kscience.visionforge.solid.demo.FXDemoAppKt")
//}

View File

@ -3,7 +3,10 @@ package space.kscience.visionforge.solid.demo
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.solid.Solids
public interface VisionLayout<in V: Vision> { interface VisionLayout<in V: Vision> {
public fun render(name: Name, vision: V, meta: Meta = Meta.EMPTY) val solids: Solids
fun render(name: Name, vision: V, meta: Meta = Meta.EMPTY)
} }

View File

@ -4,6 +4,8 @@ import kotlinx.coroutines.*
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.invoke import space.kscience.dataforge.meta.invoke
import space.kscience.dataforge.names.Name 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.Colors
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@ -18,7 +20,12 @@ fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGro
val meta = Meta { val meta = Meta {
"title" put title "title" put title
} }
val vision = SolidGroup(block) val vision = solids.solidGroup {
block()
ambientLight {
color(Colors.white)
}
}
render(Name.parse(name), vision, meta) render(Name.parse(name), vision, meta)
} }
@ -39,6 +46,7 @@ val canvasOptions = Canvas3DOptions {
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
fun VisionLayout<Solid>.showcase() { fun VisionLayout<Solid>.showcase() {
demo("shapes", "Basic shapes") { demo("shapes", "Basic shapes") {
ambientLight()
box(100.0, 100.0, 100.0) { box(100.0, 100.0, 100.0) {
z = -110.0 z = -110.0
color("teal") color("teal")
@ -62,7 +70,7 @@ fun VisionLayout<Solid>.showcase() {
} }
demo("dynamic", "Dynamic properties") { demo("dynamic", "Dynamic properties") {
val group = group { val group = solidGroup {
box(100, 100, 100) { box(100, 100, 100) {
z = 110.0 z = 110.0
opacity = 0.5 opacity = 0.5
@ -94,11 +102,18 @@ fun VisionLayout<Solid>.showcase() {
demo("rotation", "Rotations") { demo("rotation", "Rotations") {
box(100, 100, 100) box(100, 100, 100)
group { solidGroup {
x = 200 x = 200
rotationY = PI / 4 rotationY = PI / 4
axes(200)
box(100, 100, 100) { box(100, 100, 100) {
rotationZ = PI / 4 rotate((PI / 4).radians, Euclidean3DSpace.zAxis)
GlobalScope.launch(Dispatchers.Main) {
while (isActive) {
delay(100)
rotate((PI/20).radians,Euclidean3DSpace.yAxis)
}
}
color(Colors.red) color(Colors.red)
} }
} }
@ -124,7 +139,10 @@ fun VisionLayout<Solid>.showcase() {
color(Colors.blue) color(Colors.blue)
} }
repeat(20) { repeat(20) {
polyline(Point3D(100, 100, 100), Point3D(-100, -100, -100)) { polyline(
Float32Vector3D(100, 100, 100),
Float32Vector3D(-100, -100, -100)
) {
thickness = 3.0 thickness = 3.0
rotationX = it * PI2 / 20 rotationX = it * PI2 / 20
color(Colors.green) color(Colors.green)
@ -141,6 +159,10 @@ fun VisionLayout<Solid>.showcase() {
z = 26 z = 26
} }
} }
demo("STL", "STL loaded from URL") {
stl("https://ozeki.hu/attachments/116/Menger_sponge_sample.stl")
}
} }
fun VisionLayout<Solid>.showcaseCSG() { fun VisionLayout<Solid>.showcaseCSG() {

View File

@ -1,9 +1,9 @@
package space.kscience.visionforge.solid.demo package space.kscience.visionforge.solid.demo
import kotlinx.browser.document
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.w3c.dom.Document
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.solid.x import space.kscience.visionforge.solid.x
import space.kscience.visionforge.solid.y import space.kscience.visionforge.solid.y
@ -12,7 +12,7 @@ import kotlin.random.Random
private class ThreeDemoApp : Application { private class ThreeDemoApp : Application {
override fun start(state: Map<String, Any>) { override fun start(document: Document, state: Map<String, Any>) {
val element = document.getElementById("demo") ?: error("Element with id 'demo' not found on page") val element = document.getElementById("demo") ?: error("Element with id 'demo' not found on page")

View File

@ -10,12 +10,13 @@ import org.w3c.dom.Element
import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.fetch import space.kscience.dataforge.context.request
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.string import space.kscience.dataforge.meta.string
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.three.ThreeCanvas import space.kscience.visionforge.solid.three.ThreeCanvas
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
@ -25,7 +26,9 @@ class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
private val outputs: MutableMap<Name, ThreeCanvas> = HashMap() private val outputs: MutableMap<Name, ThreeCanvas> = HashMap()
private val three = Global.fetch(ThreePlugin) private val three = Global.request(ThreePlugin)
override val solids: Solids get() = three.solids
init { init {
element.clear() element.clear()

View File

@ -1,20 +1,19 @@
package space.kscience.visionforge.solid.demo package space.kscience.visionforge.solid.demo
import info.laht.threekt.core.Object3D import space.kscience.dataforge.meta.asValue
import info.laht.threekt.geometries.BoxGeometry
import info.laht.threekt.objects.Mesh
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.int import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.number import space.kscience.dataforge.meta.number
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.startsWith import space.kscience.dataforge.names.startsWith
import space.kscience.dataforge.values.asValue
import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.onPropertyChange
import space.kscience.visionforge.set import space.kscience.visionforge.setChild
import space.kscience.visionforge.setProperty
import space.kscience.visionforge.solid.SolidGroup import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.SolidMaterial.Companion.EDGES_KEY
import space.kscience.visionforge.solid.layer import space.kscience.visionforge.solid.layer
import space.kscience.visionforge.solid.three.* import space.kscience.visionforge.solid.three.*
import three.core.Object3D
import three.geometries.BoxGeometry
import three.objects.Mesh
import kotlin.math.max import kotlin.math.max
internal fun SolidGroup.varBox( internal fun SolidGroup.varBox(
@ -22,11 +21,11 @@ internal fun SolidGroup.varBox(
ySize: Number, ySize: Number,
name: String = "", name: String = "",
action: VariableBox.() -> Unit = {}, action: VariableBox.() -> Unit = {},
): VariableBox = VariableBox(xSize, ySize).apply(action).also { set(name, it) } ): VariableBox = VariableBox(xSize, ySize).apply(action).also { setChild(name, it) }
internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() { 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 geometry = BoxGeometry(xSize, ySize, 1)
val material = ThreeMaterials.DEFAULT.clone() val material = ThreeMaterials.DEFAULT.clone()
@ -44,13 +43,13 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
it.layers.enable(this@VariableBox.layer) it.layers.enable(this@VariableBox.layer)
} }
} }
mesh.scale.z = meta[VALUE].number?.toDouble() ?: 1.0 mesh.scale.z = properties.getValue(VALUE)?.number?.toDouble() ?: 1.0
//add listener to object properties //add listener to object properties
onPropertyChange { name -> onPropertyChange { name ->
when { when {
name == VALUE -> { name == VALUE -> {
val value = meta.get(VALUE).int ?: 0 val value = properties.getValue(VALUE)?.int ?: 0
val size = value.toFloat() / 255f * 20f val size = value.toFloat() / 255f * 20f
mesh.scale.z = size.toDouble() mesh.scale.z = size.toDouble()
mesh.position.z = size.toDouble() / 2 mesh.position.z = size.toDouble() / 2
@ -61,7 +60,8 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
material.color.setRGB(r.toFloat() / 256, g.toFloat() / 256, b.toFloat() / 256) material.color.setRGB(r.toFloat() / 256, g.toFloat() / 256, b.toFloat() / 256)
mesh.updateMatrix() mesh.updateMatrix()
} }
name.startsWith(MeshThreeFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox)
name.startsWith(EDGES_KEY) -> mesh.applyEdges(this@VariableBox)
else -> mesh.updateProperty(this@VariableBox, name) else -> mesh.updateProperty(this@VariableBox, name)
} }
} }
@ -70,9 +70,9 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
} }
var value: Int var value: Int
get() = meta[VALUE].int ?: 0 get() = properties.getValue(VALUE)?.int ?: 0
set(value) { set(value) {
setProperty(VALUE, value.asValue()) properties.setValue(VALUE, value.asValue())
} }
companion object { companion object {

View File

@ -10,9 +10,11 @@ import space.kscience.dataforge.names.Name
import space.kscience.visionforge.solid.FX3DPlugin import space.kscience.visionforge.solid.FX3DPlugin
import space.kscience.visionforge.solid.FXCanvas3D import space.kscience.visionforge.solid.FXCanvas3D
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.Solids
import tornadofx.* import tornadofx.*
class FXDemoGrid : View(title = "DataForge-vis FX demo"), VisionLayout<Solid> { class FXDemoGrid : View(title = "DataForge-vis FX demo"), VisionLayout<Solid> {
private val outputs = FXCollections.observableHashMap<Name, FXCanvas3D>() private val outputs = FXCollections.observableHashMap<Name, FXCanvas3D>()
override val root: Parent = borderpane { override val root: Parent = borderpane {
@ -24,6 +26,9 @@ class FXDemoGrid : View(title = "DataForge-vis FX demo"), VisionLayout<Solid> {
} }
private val fx3d = Global.fetch(FX3DPlugin) private val fx3d = Global.fetch(FX3DPlugin)
override val solids: Solids get() = fx3d.solids
override fun render(name: Name, vision: Solid, meta: Meta) { override fun render(name: Name, vision: Solid, meta: Meta) {
outputs.getOrPut(name) { FXCanvas3D(fx3d, canvasOptions) }.render(vision) outputs.getOrPut(name) { FXCanvas3D(fx3d, canvasOptions) }.render(vision)

View File

@ -2,10 +2,10 @@ package space.kscience.visionforge.demo
import javafx.geometry.Orientation import javafx.geometry.Orientation
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.node import space.kscience.dataforge.meta.descriptors.node
import space.kscience.dataforge.meta.descriptors.value import space.kscience.dataforge.meta.descriptors.value
import space.kscience.dataforge.values.ValueType
import space.kscience.visionforge.editor.FXMetaModel import space.kscience.visionforge.editor.FXMetaModel
import space.kscience.visionforge.editor.MetaViewer import space.kscience.visionforge.editor.MetaViewer
import space.kscience.visionforge.editor.MutableMetaEditor import space.kscience.visionforge.editor.MutableMetaEditor

View File

@ -3,7 +3,7 @@
![](../docs/images/hierarchy.png) ![](../docs/images/hierarchy.png)
### Vision ### Vision
* function `getPropertyValue(name: Name, inherit: Boolean = false, includeStyles: Boolean = true, includeDefaults: Boolean = true)` - get property value with given layer flags. * function `getProperty(name: Name, inherit: Boolean = false, includeStyles: Boolean = true, includeDefaults: Boolean = true)` - get property value with given layer flags.
* function `setProperty(name: Name, item: Any?)` - a convenient method to set property node or value. If `item` is null, then node is removed, not a value * function `setProperty(name: Name, item: Any?)` - a convenient method to set property node or value. If `item` is null, then node is removed, not a value
Sets the `item` property to the element with the `name` identification. Sets the `item` property to the element with the `name` identification.

View File

@ -7,7 +7,7 @@ Properties, which can be inherited by objects, are `styles`, `prototypes` (if th
All values of `styles` property are contained in class `StyleSheet`, where they all are defined at `Group`s level. The `prototypes` property tree is defined in `SolidGroup` class via `PrototypeHolder` interface, and All values of `styles` property are contained in class `StyleSheet`, where they all are defined at `Group`s level. The `prototypes` property tree is defined in `SolidGroup` class via `PrototypeHolder` interface, and
`SolidReference` class helps to reuse a template object. `SolidReference` class helps to reuse a template object.
The order of inheritance of properties is set in function `getPropertyValue` in `VisionBase` class. The order of inheritance of properties is set in function `getProperty` in `VisionBase` class.
The order is this: The order is this:
* own styles * own styles
* prototypes * prototypes

View File

@ -59,7 +59,7 @@ box(10, 10, 10, name = "small box"){
rotation = Point3D(0, 0, 0) rotation = Point3D(0, 0, 0)
} }
``` ```
![](../docs/images/small-box.png) ![](../images/small-box.png)
The `big box` will have properties with custom values. The `big box` will have properties with custom values.
```kotlin ```kotlin
@ -72,7 +72,7 @@ box(40, 40, 40, name = "big box"){
rotation = Point3D(60, 80, 0) rotation = Point3D(60, 80, 0)
} }
``` ```
![](../docs/images/big-rotated-box.png) ![](../images/big-rotated-box.png)
If we compare these boxes, we will see all differences. If we compare these boxes, we will see all differences.
Here is the function `main` with both boxes. Here is the function `main` with both boxes.
@ -111,8 +111,8 @@ fun main(){
} }
} }
``` ```
![](../docs/images/two-boxes-1.png) ![](../images/two-boxes-1.png)
![](../docs/images/two-boxes-2.png) ![](../images/two-boxes-2.png)
***There is plenty of other properties, especially those, which you can create by yourself. Here we mention just a small part.*** ***There is plenty of other properties, especially those, which you can create by yourself. Here we mention just a small part.***
@ -142,8 +142,8 @@ polyline(Point3D(30, 20, 10), Point3D(30, -100, 30), Point3D(30, -100, 30), Poin
} }
``` ```
![](../docs/images/polyline-points.png) ![](../images/polyline-points.png)
![](../docs/images/polyline-points-2.png) ![](../images/polyline-points-2.png)
### 2) Box ### 2) Box
@ -165,7 +165,7 @@ Let's create just usual `box` with equal ribs.
color("pink") color("pink")
} }
``` ```
![](../docs/images/box.png) ![](../images/box.png)
Now, let's make `box` with bigger `y` value. Now, let's make `box` with bigger `y` value.
```kotlin ```kotlin
@ -175,7 +175,7 @@ Now, let's make `box` with bigger `y` value.
``` ```
As you can see, only the rib of `y-axis` differs from other ribs. As you can see, only the rib of `y-axis` differs from other ribs.
![](../docs/images/high-box.png) ![](../images/high-box.png)
For a final trial, let's create a `box` with a bigger `x` value. For a final trial, let's create a `box` with a bigger `x` value.
@ -189,7 +189,7 @@ For a final trial, let's create a `box` with a bigger `x` value.
``` ```
Predictably, only the `x-axis` rib is bigger than other ribs. Predictably, only the `x-axis` rib is bigger than other ribs.
![](../docs/images/wide-box.png) ![](../images/wide-box.png)
### 3) Sphere ### 3) Sphere
@ -206,7 +206,7 @@ As for `radius`, it has `Float` type, and, as you can guess, it sets the radius
color("blue") color("blue")
} }
``` ```
![](../docs/images/sphere.png) ![](../images/sphere.png)
### 4) Hexagon ### 4) Hexagon
@ -220,7 +220,7 @@ It is solid which has six edges. It is set by eight values: `node1`,..., `node8`
5) Edge with vertices `node1`, `node5`, `node8`, `node4` 5) Edge with vertices `node1`, `node5`, `node8`, `node4`
6) Edge with vertices `node8`, `node5`, `node6`, `node7` 6) Edge with vertices `node8`, `node5`, `node6`, `node7`
![](../docs/images/scheme.png) ![](../images/scheme.png)
As the hexagon takes in specific points, we understand that this solid cannot be moved, it is fixed in space, and it can't make pivots. As the hexagon takes in specific points, we understand that this solid cannot be moved, it is fixed in space, and it can't make pivots.
@ -239,7 +239,7 @@ Let's make classic parallelepiped.
color("green") color("green")
} }
``` ```
![](../docs/images/classic-hexagon.png) ![](../images/classic-hexagon.png)
Now, let's make a custom hexagon. Now, let's make a custom hexagon.
@ -258,7 +258,7 @@ hexagon(
color("brown") color("brown")
} }
``` ```
![](../docs/images/custom-hexagon.png) ![](../images/custom-hexagon.png)
### 3) Cone ### 3) Cone
It takes in six values: `bottomRadius`, `height`, `upperRadius`, `startAngle`, `angle`, and `name`. It takes in six values: `bottomRadius`, `height`, `upperRadius`, `startAngle`, `angle`, and `name`.
@ -274,8 +274,8 @@ Let's build a classic cone:
color("beige") color("beige")
} }
``` ```
![](../docs/images/cone-1.png) ![](../images/cone-1.png)
![](../docs/images/cone-2.png) ![](../images/cone-2.png)
First of all, we have to try to build a frustum cone: First of all, we have to try to build a frustum cone:
```kotlin ```kotlin
@ -283,7 +283,7 @@ cone(60, 80, name = "cone") {
color(0u, 40u, 0u) color(0u, 40u, 0u)
} }
``` ```
![](../docs/images/frustum-cone.png) ![](../images/frustum-cone.png)
Now, we need to make a try to build a cone segment: Now, we need to make a try to build a cone segment:
@ -292,8 +292,8 @@ cone(60, 80, angle = PI, name = "cone") {
color(0u, 0u, 200u) color(0u, 0u, 200u)
} }
``` ```
![](../docs/images/cone-segment-1.png) ![](../images/cone-segment-1.png)
![](../docs/images/cone-segment-2.png) ![](../images/cone-segment-2.png)
Finally, the segment of frustum cone is left for a try: Finally, the segment of frustum cone is left for a try:
```kotlin ```kotlin
@ -301,7 +301,7 @@ cone(60, 100, 20, PI*3/4, angle = PI/3, name = "cone") {
color(190u, 0u, 0u) color(190u, 0u, 0u)
} }
``` ```
![](../docs/images/frustum-cone-segment.png) ![](../images/frustum-cone-segment.png)
### 4) Cone Surface ### 4) Cone Surface
This solid is set by seven values:`bottomOuterRadius`, `bottomInnerRadius`, `height`, `topOuterRadius`, `topInnerRadius`, `startAngle`, and `angle`. This solid is set by seven values:`bottomOuterRadius`, `bottomInnerRadius`, `height`, `topOuterRadius`, `topInnerRadius`, `startAngle`, and `angle`.
@ -318,8 +318,8 @@ Let's build usual cone surface with almost all properties set:
rotation = Point3D(2, 50, -9) rotation = Point3D(2, 50, -9)
} }
``` ```
![](../docs/images/cone-surface-1.png) ![](../images/cone-surface-1.png)
![](../docs/images/cone-surface-2.png) ![](../images/cone-surface-2.png)
Now, let's create a cone surface and set all it's properties: Now, let's create a cone surface and set all it's properties:
@ -329,8 +329,8 @@ coneSurface(30, 25, 10, 10, 8,0f, pi*3/4, name = "cone surface") {
rotation = Point3D(2, 50, -9) rotation = Point3D(2, 50, -9)
} }
``` ```
![](../docs/images/cone-surface-fragment.png) ![](../images/cone-surface-fragment.png)
![](../docs/images/cone-surface-fragment-2.png) ![](../images/cone-surface-fragment-2.png)
### 5) Cylinder ### 5) Cylinder
@ -344,8 +344,8 @@ cylinder(40, 100, "cylinder"){
color("indigo") color("indigo")
} }
``` ```
![](../docs/images/cylinder-1.png) ![](../images/cylinder-1.png)
![](../docs/images/cylinder-2.png) ![](../images/cylinder-2.png)
### 6) Tube ### 6) Tube
`tube` takes in `radius`, `height`, `innerRadius`, `startAngle`, `angle`, and `name`. *All values are familiar from `cone`, and `coneSurface` solids.* `tube` takes in `radius`, `height`, `innerRadius`, `startAngle`, `angle`, and `name`. *All values are familiar from `cone`, and `coneSurface` solids.*
@ -356,7 +356,7 @@ tube(50, 40, 20, name = "usual tube"){
opacity = 0.4 opacity = 0.4
} }
``` ```
![](../docs/images/tube.png) ![](../images/tube.png)
This is an example of tube fragment: This is an example of tube fragment:
@ -365,7 +365,7 @@ tube(50, 40, 20, 0f, PI, name = "fragmented tube"){
color("white") color("white")
} }
``` ```
![](../docs/images/tube-fragment.png) ![](../images/tube-fragment.png)
### 7) Extruded ### 7) Extruded
`extruded` is set by two values: `shape`, and `layer`. `extruded` is set by two values: `shape`, and `layer`.

View File

@ -3,7 +3,7 @@
interface Vision{ interface Vision{
val parent: VisionGroup? val parent: VisionGroup?
fun getPropertyValue(name,inherit,includeStyles,includeDefaults): Value? fun getProperty(name,inherit,includeStyles,includeDefaults): Value?
} }
interface Solid{ interface Solid{
@ -81,7 +81,7 @@ Solid <--- Composite
interface SolidReference{ interface SolidReference{
val prototype: Solid val prototype: Solid
fun getPropertyValue(name,inherit,includeStyles,includeDefaults): Value? fun getProperty(name,inherit,includeStyles,includeDefaults): Value?
} }
VisionGroup <---- SolidReference VisionGroup <---- SolidReference
SolidReferenceGroup -- SolidReference SolidReferenceGroup -- SolidReference
@ -91,7 +91,7 @@ class SolidReferenceGroup{
var properties: MutableMeta? var properties: MutableMeta?
val prototype: Solid val prototype: Solid
val children: Map<NameToken, Vision> val children: Map<NameToken, Vision>
fun getPropertyValue(name,inherit,includeStyles,includeDefaults): Value? fun getProperty(name,inherit,includeStyles,includeDefaults): Value?
} }
VisionBase <-- SolidReferenceGroup VisionBase <-- SolidReferenceGroup
VisionGroup <-- SolidReferenceGroup VisionGroup <-- SolidReferenceGroup

View File

@ -1,12 +1,13 @@
kotlin.code.style=official kotlin.code.style=official
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
kotlin.js.compiler=ir
#kotlin.incremental.js.ir=true
kotlin.jupyter.add.scanner=false
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.jvmargs=-Xmx4G
publishing.github=false org.jetbrains.compose.experimental.jscanvas.enabled=true
publishing.sonatype=false
toolsVersion=0.11.1-kotlin-1.6.10 toolsVersion=0.15.2-kotlin-1.9.21
#kotlin.experimental.tryK2=true
#kscience.wasm.disabled=true

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,25 +0,0 @@
plugins {
id("ru.mipt.npm.gradle.mpp")
id("org.jetbrains.kotlin.jupyter.api")
}
description = "Common visionforge jupyter module"
kotlin {
sourceSets {
commonMain{
dependencies{
api(projects.visionforgeCore)
}
}
jvmMain {
dependencies {
api(projects.visionforgeServer)
}
}
}
}
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
}

View File

@ -1,71 +0,0 @@
package space.kscience.visionforge.jupyter
import kotlinx.html.p
import kotlinx.html.stream.createHTML
import kotlinx.html.style
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.html.*
@DFExperimental
public abstract class JupyterPluginBase(final override val context: Context) : JupyterIntegration(), ContextAware {
protected val handler: VisionForgeForNotebook = VisionForgeForNotebook(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<HtmlFragment> { fragment ->
handler.produceHtml(fragment = fragment)
}
render<HtmlVisionFragment> { fragment ->
handler.produceHtml(fragment = fragment)
}
render<Vision> { vision ->
handler.produceHtml {
vision { vision }
}
}
render<Page> { page ->
HTML(page.render(createHTML()), true)
}
render<HtmlFormFragment> { 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()
}
}

View File

@ -1,89 +0,0 @@
package space.kscience.visionforge.jupyter
import io.ktor.server.engine.ApplicationEngine
import kotlinx.html.FORM
import kotlinx.html.TagConsumer
import kotlinx.html.p
import kotlinx.html.stream.createHTML
import kotlinx.html.style
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.visionforge.html.HtmlFormFragment
import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.visionFragment
import space.kscience.visionforge.server.VisionServer
import space.kscience.visionforge.server.serve
import space.kscience.visionforge.visionManager
/**
* A handler class that includes a server and common utilities
*/
public class VisionForgeForNotebook(override val context: Context) : ContextAware {
private var counter = 0
private var engine: ApplicationEngine? = null
private var server: VisionServer? = null
public var isolateFragments: Boolean = false
public fun legacyMode() {
isolateFragments = true
}
public fun isServerRunning(): Boolean = server != 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 ?: VisionServer.DEFAULT_PORT,
configuration: VisionServer.() -> Unit = {},
): MimeTypedResult = html {
if (server != null) {
p {
style = "color: red;"
+"Stopping current VisionForge server"
}
}
engine?.stop(1000, 2000)
engine = context.visionManager.serve(host, port) {
configuration()
server = this
}.start()
p {
style = "color: blue;"
+"Starting VisionForge server on http://$host:$port"
}
}
public fun stopServer() {
engine?.apply {
logger.info { "Stopping VisionForge server" }
}?.stop(1000, 2000)
}
private fun produceHtmlString(
fragment: HtmlVisionFragment,
): String = server?.serveVisionsFromFragment("content[${counter++}]", fragment)
?: createHTML().apply {
visionFragment(context, fragment = fragment)
}.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)
}

View File

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

View File

@ -1,60 +0,0 @@
plugins {
id("ru.mipt.npm.gradle.mpp")
}
description = "Jupyter api artifact for GDML rendering"
kotlin {
explicitApi = null
js {
useCommonJs()
browser {
webpackTask {
this.outputFileName = "js/gdml-jupyter.js"
}
commonWebpackConfig {
sourceMaps = false
cssSupport.enabled = false
}
}
binaries.executable()
}
afterEvaluate {
val jsBrowserDistribution by tasks.getting
tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution)
from(jsBrowserDistribution)
}
}
sourceSets {
commonMain {
dependencies {
implementation(projects.visionforgeSolid)
implementation(projects.jupyter)
}
}
jvmMain {
dependencies {
implementation(projects.visionforgeGdml)
}
}
jsMain {
dependencies {
implementation(projects.visionforgeThreejs)
implementation(projects.ui.ring)
}
}
}
}
kscience {
jupyterLibrary("space.kscience.visionforge.gdml.jupyter.GdmlForJupyter")
}
readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
}

View File

@ -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
fun main(): Unit = runVisionClient {
plugin(ThreeWithControlsPlugin)
}

View File

@ -1,37 +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.JupyterPluginBase
import space.kscience.visionforge.solid.Solids
@DFExperimental
internal class GdmlForJupyter : JupyterPluginBase(
Context("GDML") {
plugin(Solids)
}
) {
override fun Builder.afterLoaded() {
resources {
js("three") {
classPath("js/gdml-jupyter.js")
}
}
import(
"space.kscience.gdml.*",
"space.kscience.visionforge.gdml.jupyter.*"
)
render<Gdml> { gdmlModel ->
handler.produceHtml {
vision { gdmlModel.toVision() }
}
}
}
}

View File

@ -1,3 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -1,7 +1,6 @@
rootProject.name = "visionforge" rootProject.name = "visionforge"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
enableFeaturePreview("VERSION_CATALOGS")
pluginManagement { pluginManagement {
@ -12,13 +11,14 @@ pluginManagement {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
} }
plugins { plugins {
id("ru.mipt.npm.gradle.project") version toolsVersion id("space.kscience.gradle.project") version toolsVersion
id("ru.mipt.npm.gradle.mpp") version toolsVersion id("space.kscience.gradle.mpp") version toolsVersion
id("ru.mipt.npm.gradle.jvm") version toolsVersion id("space.kscience.gradle.jvm") version toolsVersion
id("ru.mipt.npm.gradle.js") version toolsVersion id("space.kscience.gradle.js") version toolsVersion
} }
} }
@ -33,8 +33,8 @@ dependencyResolutionManagement {
} }
versionCatalogs { versionCatalogs {
create("npmlibs") { create("spclibs") {
from("ru.mipt.npm:version-catalog:$toolsVersion") from("space.kscience:version-catalog:$toolsVersion")
} }
} }
} }
@ -45,9 +45,10 @@ include(
":ui:ring", ":ui:ring",
// ":ui:material", // ":ui:material",
":ui:bootstrap", ":ui:bootstrap",
":ui:compose",
":visionforge-core", ":visionforge-core",
":visionforge-solid", ":visionforge-solid",
":visionforge-fx", // ":visionforge-fx",
":visionforge-threejs", ":visionforge-threejs",
":visionforge-threejs:visionforge-threejs-server", ":visionforge-threejs:visionforge-threejs-server",
":visionforge-gdml", ":visionforge-gdml",
@ -61,8 +62,8 @@ include(
":demo:muon-monitor", ":demo:muon-monitor",
":demo:sat-demo", ":demo:sat-demo",
":demo:playground", ":demo:playground",
":demo:plotly-fx", // ":demo:plotly-fx",
":demo:js-playground", ":demo:js-playground",
":jupyter", ":visionforge-jupyter",
":jupyter:visionforge-jupyter-gdml" ":visionforge-jupyter:visionforge-jupyter-common"
) )

View File

@ -1,15 +1,19 @@
plugins { plugins {
kotlin("js") id("space.kscience.gradle.mpp")
id("ru.mipt.npm.gradle.js")
} }
val dataforgeVersion: String by rootProject.extra val dataforgeVersion: String by rootProject.extra
dependencies { kscience{
js()
jsMain{
dependencies {
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
api(project(":ui:react")) api(project(":ui:react"))
implementation(npm("file-saver", "2.0.2")) implementation(npm("file-saver", "2.0.2"))
implementation(npm("bootstrap","4.6.0")) implementation(npm("bootstrap","4.6.0"))
implementation(npm("jquery","3.5.1")) implementation(npm("jquery","3.5.1"))
implementation(npm("popper.js","1.16.1")) implementation(npm("popper.js","1.16.1"))
}
}
} }

View File

@ -1,8 +1,8 @@
package space.kscience.visionforge.bootstrap package space.kscience.visionforge.bootstrap
public fun useBootstrap(){ public fun useBootstrap(){
kotlinext.js.require("bootstrap/dist/css/bootstrap.min.css") kotlinext.js.require<dynamic>("bootstrap/dist/css/bootstrap.min.css")
kotlinext.js.require("bootstrap") kotlinext.js.require<dynamic>("bootstrap")
} }
//public inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) { //public inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {

View File

@ -1,10 +1,8 @@
package space.kscience.visionforge.bootstrap package space.kscience.visionforge.bootstrap
import kotlinx.css.BorderStyle import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.css.Color import kotlinx.coroutines.GlobalScope
import kotlinx.css.padding import kotlinx.css.*
import kotlinx.css.properties.border
import kotlinx.css.px
import kotlinx.html.js.onClickFunction import kotlinx.html.js.onClickFunction
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import org.w3c.files.Blob import org.w3c.files.Blob
@ -15,7 +13,6 @@ import react.RBuilder
import react.dom.attrs import react.dom.attrs
import react.dom.button import react.dom.button
import react.fc import react.fc
import space.kscience.dataforge.meta.withDefault
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.encodeToString import space.kscience.visionforge.encodeToString
import space.kscience.visionforge.react.flexColumn import space.kscience.visionforge.react.flexColumn
@ -28,7 +25,7 @@ private fun saveData(event: Event, fileName: String, mimeType: String = "text/pl
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
val fileSaver = kotlinext.js.require("file-saver") val fileSaver = kotlinext.js.require<dynamic>("file-saver")
val blob = Blob(arrayOf(dataBuilder()), BlobPropertyBag("$mimeType;charset=utf-8")) val blob = Blob(arrayOf(dataBuilder()), BlobPropertyBag("$mimeType;charset=utf-8"))
fileSaver.saveAs(blob, fileName) fileSaver.saveAs(blob, fileName)
} }
@ -47,12 +44,13 @@ public external interface CanvasControlsProps : Props {
public var vision: Vision? public var vision: Vision?
} }
public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props -> public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props ->
flexColumn { flexColumn {
flexRow { flexRow {
css { css {
border(1.px, BorderStyle.solid, Color.blue) border = Border(1.px, BorderStyle.solid, Color.blue)
padding(4.px) padding = Padding(4.px)
} }
props.vision?.let { vision -> props.vision?.let { vision ->
button { button {
@ -68,9 +66,10 @@ public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { prop
} }
} }
} }
@OptIn(DelicateCoroutinesApi::class)
propertyEditor( propertyEditor(
ownProperties = props.canvasOptions.meta, scope = props.vision?.manager?.context ?: GlobalScope,
allProperties = props.canvasOptions.meta.withDefault(Canvas3DOptions.descriptor.defaultNode), properties = props.canvasOptions.meta,
descriptor = Canvas3DOptions.descriptor, descriptor = Canvas3DOptions.descriptor,
expanded = false expanded = false
) )

View File

@ -30,7 +30,7 @@ public external interface TabPaneProps : PropsWithChildren {
public val TabPane: FC<TabPaneProps> = fc("TabPane") { props -> public val TabPane: FC<TabPaneProps> = fc("TabPane") { props ->
var activeTab: String? by useState(props.activeTab) var activeTab: String? by useState(props.activeTab)
val children: Array<out ReactElement?> = Children.map(props.children) { val children: Array<out ReactElement<*>?> = Children.map(props.children) {
it.asElementOrNull() it.asElementOrNull()
} ?: emptyArray() } ?: emptyArray()

View File

@ -1,7 +1,6 @@
package space.kscience.visionforge.bootstrap package space.kscience.visionforge.bootstrap
import kotlinx.css.* import kotlinx.css.*
import kotlinx.css.properties.border
import react.FC import react.FC
import react.PropsWithChildren import react.PropsWithChildren
import react.RBuilder import react.RBuilder
@ -10,8 +9,8 @@ import react.fc
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.isEmpty import space.kscience.dataforge.names.isEmpty
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionGroup
import space.kscience.visionforge.react.visionTree import space.kscience.visionforge.react.visionTree
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
@ -33,13 +32,13 @@ public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
} }
tab("Tree") { tab("Tree") {
css { css {
border(1.px, BorderStyle.solid, Color.lightGray) border = Border(1.px, BorderStyle.solid, Color.lightGray)
padding(10.px) padding = Padding(10.px)
} }
h2 { +"Object tree" } h2 { +"Object tree" }
styledDiv { styledDiv {
css { css {
flex(1.0, 1.0, FlexBasis.inherit) flex = Flex(1.0, 1.0, FlexBasis.inherit)
} }
props.vision?.let { props.vision?.let {
visionTree(it, props.selected, props.onSelect) visionTree(it, props.selected, props.onSelect)
@ -51,7 +50,7 @@ public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
val selectedObject: Vision? = when { val selectedObject: Vision? = when {
selected == null -> null selected == null -> null
selected.isEmpty() -> props.vision selected.isEmpty() -> props.vision
else -> (props.vision as? VisionGroup)?.get(selected) else -> (props.vision as? SolidGroup)?.get(selected)
} }
if (selectedObject != null) { if (selectedObject != null) {
visionPropertyEditor(selectedObject, key = selected) visionPropertyEditor(selectedObject, key = selected)

Some files were not shown because too many files have changed in this diff Show More