forked from kscience/visionforge
Serialization complete. Fixed tube geometry
This commit is contained in:
parent
71c016d2fd
commit
b50a9c590f
@ -1,4 +1,4 @@
|
|||||||
val dataforgeVersion by extra("0.1.3-dev-10")
|
val dataforgeVersion by extra("0.1.3")
|
||||||
|
|
||||||
plugins{
|
plugins{
|
||||||
val kotlinVersion = "1.3.50-eap-5"
|
val kotlinVersion = "1.3.50-eap-5"
|
||||||
|
@ -18,6 +18,7 @@ kotlin {
|
|||||||
val jsMain by getting {
|
val jsMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
||||||
|
api(npm("text-encoding"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
package hep.dataforge.vis.common
|
package hep.dataforge.vis.common
|
||||||
|
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import hep.dataforge.meta.MetaItem
|
import hep.dataforge.meta.MetaItem
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.get
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.provider.Provider
|
import hep.dataforge.provider.Provider
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>, Provider {
|
open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>, Provider {
|
||||||
|
|
||||||
protected val namedChildren = HashMap<Name, T>()
|
protected open val namedChildren: MutableMap<Name, T> = HashMap()
|
||||||
protected val unnamedChildren = ArrayList<T>()
|
protected open val unnamedChildren: MutableList<T> = ArrayList()
|
||||||
|
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
override val defaultTarget: String get() = VisualObject.TYPE
|
override val defaultTarget: String get() = VisualObject.TYPE
|
||||||
|
|
||||||
@ -51,7 +54,13 @@ open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>,
|
|||||||
listeners.removeAll { it.owner === owner }
|
listeners.removeAll { it.owner === owner }
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun set(name: Name, child: T?) {
|
/**
|
||||||
|
* Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not
|
||||||
|
* allowed to be null in the same time. If name is present and [child] is null, the appropriate element is removed.
|
||||||
|
*/
|
||||||
|
operator fun set(name: Name?, child: T?) {
|
||||||
|
when {
|
||||||
|
name != null -> {
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
namedChildren.remove(name)
|
namedChildren.remove(name)
|
||||||
} else {
|
} else {
|
||||||
@ -64,14 +73,6 @@ open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>,
|
|||||||
}
|
}
|
||||||
listeners.forEach { it.callback(name, child) }
|
listeners.forEach { it.callback(name, child) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not
|
|
||||||
* allowed to be null in the same time. If name is present and [child] is null, the appropriate element is removed.
|
|
||||||
*/
|
|
||||||
operator fun set(name: Name?, child: T?) {
|
|
||||||
when {
|
|
||||||
name != null -> set(name, child)
|
|
||||||
child != null -> add(child)
|
child != null -> add(child)
|
||||||
else -> error("Both key and child element are empty")
|
else -> error("Both key and child element are empty")
|
||||||
}
|
}
|
||||||
@ -87,7 +88,7 @@ open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>,
|
|||||||
/**
|
/**
|
||||||
* Get named child by string
|
* Get named child by string
|
||||||
*/
|
*/
|
||||||
operator fun get(key: String): T? = namedChildren.get(key)
|
operator fun get(key: String): T? = namedChildren[key.toName()]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an unnamed child
|
* Get an unnamed child
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package hep.dataforge.vis.common
|
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic [VisualObject] leaf element
|
|
||||||
*/
|
|
||||||
open class VisualLeaf(meta: Meta = EmptyMeta) : AbstractVisualObject(), Configurable {
|
|
||||||
|
|
||||||
val properties = Styled(meta)
|
|
||||||
|
|
||||||
override val config: Config = properties.style
|
|
||||||
|
|
||||||
override fun setProperty(name: Name, value: Any?) {
|
|
||||||
config[name] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
|
||||||
return if (inherit) {
|
|
||||||
properties[name] ?: parent?.getProperty(name, inherit)
|
|
||||||
} else {
|
|
||||||
properties[name]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,9 @@
|
|||||||
package hep.dataforge.vis.common
|
package hep.dataforge.vis.common
|
||||||
|
|
||||||
import hep.dataforge.io.ConfigSerializer
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.provider.Type
|
import hep.dataforge.provider.Type
|
||||||
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
|
|
||||||
private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||||
@ -18,8 +15,6 @@ private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
|||||||
@Type(TYPE)
|
@Type(TYPE)
|
||||||
interface VisualObject : MetaRepr, Configurable {
|
interface VisualObject : MetaRepr, Configurable {
|
||||||
|
|
||||||
val type: String get() = this::class.simpleName ?: TYPE
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent object of this one. If null, this one is a root.
|
* The parent object of this one. If null, this one is a root.
|
||||||
*/
|
*/
|
||||||
@ -64,7 +59,9 @@ internal data class MetaListener(
|
|||||||
val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
|
val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
|
||||||
)
|
)
|
||||||
|
|
||||||
abstract class AbstractVisualObject : VisualObject {
|
abstract class AbstractVisualObject: VisualObject {
|
||||||
|
|
||||||
|
@Transient
|
||||||
override var parent: VisualObject? = null
|
override var parent: VisualObject? = null
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@ -84,12 +81,10 @@ abstract class AbstractVisualObject : VisualObject {
|
|||||||
listeners.removeAll { it.owner == owner }
|
listeners.removeAll { it.owner == owner }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable(ConfigSerializer::class)
|
abstract var properties: Config?
|
||||||
@SerialName("properties")
|
|
||||||
private var _config: Config? = null
|
|
||||||
override val config: Config
|
override val config: Config
|
||||||
get() = _config ?: Config().also { config ->
|
get() = properties ?: Config().also { config ->
|
||||||
_config = config
|
properties = config
|
||||||
config.onChange(this, ::propertyChanged)
|
config.onChange(this, ::propertyChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,19 +94,17 @@ abstract class AbstractVisualObject : VisualObject {
|
|||||||
|
|
||||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||||
return if (inherit) {
|
return if (inherit) {
|
||||||
_config?.get(name) ?: parent?.getProperty(name, inherit)
|
properties?.get(name) ?: parent?.getProperty(name, inherit)
|
||||||
} else {
|
} else {
|
||||||
_config?.get(name)
|
properties?.get(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun MetaBuilder.updateMeta() {}
|
protected open fun MetaBuilder.updateMeta() {}
|
||||||
|
|
||||||
override fun toMeta(): Meta = buildMeta {
|
override fun toMeta(): Meta = buildMeta {
|
||||||
"type" to type
|
"type" to this::class.simpleName
|
||||||
"properties" to config
|
"properties" to properties
|
||||||
updateMeta()
|
updateMeta()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
|
import hep.dataforge.vis.spatial.Visual3DPlugin
|
||||||
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
|
import nl.adaptivity.xmlutil.StAXReader
|
||||||
|
import scientifik.gdml.GDML
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N_coil.gdml")
|
||||||
|
|
||||||
|
val xmlReader = StAXReader(file.inputStream(), "UTF-8")
|
||||||
|
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||||
|
val visual = xml.toVisual {
|
||||||
|
lUnit = LUnit.CM
|
||||||
|
}
|
||||||
|
|
||||||
|
//val meta = visual.toMeta()
|
||||||
|
|
||||||
|
val str = Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)
|
||||||
|
|
||||||
|
println(str)
|
||||||
|
|
||||||
|
//println(Json.indented.stringify(meta.toJson()))
|
||||||
|
}
|
@ -29,7 +29,7 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api("info.laht.threekt:threejs-wrapper:0.106-npm-3")
|
api("info.laht.threekt:threejs-wrapper:0.106-npm-3")
|
||||||
implementation(npm("three", "0.106.2"))
|
implementation(npm("three", "0.106.2"))
|
||||||
implementation(npm("@hi-level/three-csg"))
|
implementation(npm("@hi-level/three-csg", "1.0.6"))
|
||||||
implementation(npm("style-loader"))
|
implementation(npm("style-loader"))
|
||||||
implementation(npm("element-resize-event"))
|
implementation(npm("element-resize-event"))
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class)
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.io.ConfigSerializer
|
||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.meta.float
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import hep.dataforge.meta.get
|
|
||||||
import hep.dataforge.vis.common.VisualFactory
|
import hep.dataforge.vis.common.VisualFactory
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Box(
|
data class Box(
|
||||||
val xSize: Float,
|
val xSize: Float,
|
||||||
val ySize: Float,
|
val ySize: Float,
|
||||||
val zSize: Float
|
val zSize: Float
|
||||||
) : VisualLeaf3D(), Shape {
|
) : AbstractVisualObject(), VisualObject3D, Shape {
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
//TODO add helper for color configuration
|
//TODO add helper for color configuration
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
@ -40,8 +50,13 @@ data class Box(
|
|||||||
"xSize" to xSize
|
"xSize" to xSize
|
||||||
"ySize" to ySize
|
"ySize" to ySize
|
||||||
"zSize" to ySize
|
"zSize" to ySize
|
||||||
|
updatePosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override fun toMeta(): Meta {
|
||||||
|
// return (Visual3DPlugin.json.toJson(Box.serializer(), this) as JsonObject).toMeta()
|
||||||
|
// }
|
||||||
|
|
||||||
companion object : VisualFactory<Box> {
|
companion object : VisualFactory<Box> {
|
||||||
const val TYPE = "geometry.3d.box"
|
const val TYPE = "geometry.3d.box"
|
||||||
|
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class)
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.isEmpty
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import hep.dataforge.meta.update
|
import hep.dataforge.meta.update
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
|
||||||
enum class CompositeType {
|
enum class CompositeType {
|
||||||
UNION,
|
UNION,
|
||||||
@ -9,11 +15,27 @@ enum class CompositeType {
|
|||||||
SUBTRACT
|
SUBTRACT
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Composite(
|
@Serializable
|
||||||
|
class Composite(
|
||||||
|
val compositeType: CompositeType,
|
||||||
val first: VisualObject3D,
|
val first: VisualObject3D,
|
||||||
val second: VisualObject3D,
|
val second: VisualObject3D
|
||||||
val compositeType: CompositeType = CompositeType.UNION
|
) : AbstractVisualObject(), VisualObject3D {
|
||||||
) : VisualLeaf3D()
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
|
override fun MetaBuilder.updateMeta() {
|
||||||
|
"compositeType" to compositeType
|
||||||
|
"first" to first.toMeta()
|
||||||
|
"second" to second.toMeta()
|
||||||
|
updatePosition()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline fun VisualGroup3D.composite(
|
inline fun VisualGroup3D.composite(
|
||||||
type: CompositeType,
|
type: CompositeType,
|
||||||
@ -23,14 +45,14 @@ inline fun VisualGroup3D.composite(
|
|||||||
val group = VisualGroup3D().apply(builder)
|
val group = VisualGroup3D().apply(builder)
|
||||||
val children = group.filterIsInstance<VisualObject3D>()
|
val children = group.filterIsInstance<VisualObject3D>()
|
||||||
if (children.size != 2) error("Composite requires exactly two children")
|
if (children.size != 2) error("Composite requires exactly two children")
|
||||||
return Composite(children[0], children[1], type).also {
|
return Composite(type, children[0], children[1]).also {
|
||||||
if (!group.config.isEmpty()) {
|
if (group.properties != null) {
|
||||||
it.config.update(group.config)
|
it.config.update(group.config)
|
||||||
|
it.material = group.material
|
||||||
}
|
}
|
||||||
it.position = group.position
|
it.position = group.position
|
||||||
it.rotation = group.rotation
|
it.rotation = group.rotation
|
||||||
it.scale = group.scale
|
it.scale = group.scale
|
||||||
it.material = group.material
|
|
||||||
set(name, it)
|
set(name, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class)
|
||||||
|
|
||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cylinder or cut cone segment
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
class ConeSegment(
|
||||||
|
var radius: Float,
|
||||||
|
var height: Float,
|
||||||
|
var upperRadius: Float,
|
||||||
|
var startAngle: Float = 0f,
|
||||||
|
var angle: Float = PI2
|
||||||
|
) : AbstractVisualObject(), VisualObject3D {
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun VisualGroup3D.cylinder(
|
||||||
|
r: Number,
|
||||||
|
height: Number,
|
||||||
|
name: String? = null,
|
||||||
|
block: ConeSegment.() -> Unit = {}
|
||||||
|
): ConeSegment = ConeSegment(
|
||||||
|
r.toFloat(),
|
||||||
|
height.toFloat(),
|
||||||
|
r.toFloat()
|
||||||
|
).apply(block).also { set(name, it) }
|
@ -1,15 +1,29 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class)
|
||||||
|
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
|
||||||
class Convex(
|
@Serializable
|
||||||
val points: List<Point3D>
|
class Convex(val points: List<Point3D>) : AbstractVisualObject(), VisualObject3D {
|
||||||
) : VisualLeaf3D() {
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
override fun MetaBuilder.updateMeta() {
|
override fun MetaBuilder.updateMeta() {
|
||||||
"points" to {
|
"points" to {
|
||||||
"point" to points.map{it.toMeta()}
|
"point" to points.map { it.toMeta() }
|
||||||
}
|
}
|
||||||
|
updatePosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package hep.dataforge.vis.spatial
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A cylinder or cut cone segment
|
|
||||||
*/
|
|
||||||
class Cylinder(
|
|
||||||
var radius: Float,
|
|
||||||
var height: Float,
|
|
||||||
var upperRadius: Float = radius,
|
|
||||||
var startAngle: Float = 0f,
|
|
||||||
var angle: Float = PI2
|
|
||||||
) : VisualLeaf3D()
|
|
||||||
|
|
||||||
inline fun VisualGroup3D.cylinder(
|
|
||||||
r: Number,
|
|
||||||
height: Number,
|
|
||||||
name: String? = null,
|
|
||||||
block: Cylinder.() -> Unit = {}
|
|
||||||
): Cylinder = Cylinder(
|
|
||||||
r.toFloat(),
|
|
||||||
height.toFloat()
|
|
||||||
).apply(block).also { set(name, it) }
|
|
@ -1,5 +1,11 @@
|
|||||||
|
@file:UseSerializers(Point2DSerializer::class, Point3DSerializer::class)
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@ -7,16 +13,16 @@ import kotlin.math.sin
|
|||||||
|
|
||||||
typealias Shape2D = List<Point2D>
|
typealias Shape2D = List<Point2D>
|
||||||
|
|
||||||
class Shape2DBuilder {
|
@Serializable
|
||||||
private val list = ArrayList<Point2D>()
|
class Shape2DBuilder(private val points: MutableList<Point2D> = ArrayList()) {
|
||||||
|
|
||||||
fun point(x: Number, y: Number) {
|
fun point(x: Number, y: Number) {
|
||||||
list.add(Point2D(x, y))
|
points.add(Point2D(x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Number.to(y: Number) = point(this, y)
|
infix fun Number.to(y: Number) = point(this, y)
|
||||||
|
|
||||||
fun build(): Shape2D = list
|
fun build(): Shape2D = points
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
|
fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
|
||||||
@ -27,19 +33,27 @@ fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Layer(var x: Float, var y: Float, var z: Float, var scale: Float)
|
data class Layer(var x: Float, var y: Float, var z: Float, var scale: Float)
|
||||||
|
|
||||||
class Extruded : VisualLeaf3D(), Shape {
|
@Serializable
|
||||||
|
class Extruded(
|
||||||
|
var shape: List<Point2D> = ArrayList(),
|
||||||
|
var layers: MutableList<Layer> = ArrayList()
|
||||||
|
) : AbstractVisualObject(), VisualObject3D, Shape {
|
||||||
|
|
||||||
var shape: List<Point2D> = ArrayList()
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
fun shape(block: Shape2DBuilder.() -> Unit) {
|
fun shape(block: Shape2DBuilder.() -> Unit) {
|
||||||
this.shape = Shape2DBuilder().apply(block).build()
|
this.shape = Shape2DBuilder().apply(block).build()
|
||||||
//TODO send invalidation signal
|
//TODO send invalidation signal
|
||||||
}
|
}
|
||||||
|
|
||||||
val layers: MutableList<Layer> = ArrayList()
|
|
||||||
|
|
||||||
fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) {
|
fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) {
|
||||||
layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat()))
|
layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat()))
|
||||||
//TODO send invalidation signal
|
//TODO send invalidation signal
|
||||||
|
@ -1,25 +1,37 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class, NameSerializer::class)
|
||||||
|
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.io.NameSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import hep.dataforge.meta.MetaItem
|
import hep.dataforge.meta.MetaItem
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A proxy [VisualObject3D] to reuse a template object
|
* A proxy [VisualObject3D] to reuse a template object
|
||||||
*/
|
*/
|
||||||
|
@Serializable
|
||||||
class Proxy(val templateName: Name) : AbstractVisualObject(), VisualObject3D {
|
class Proxy(val templateName: Name) : AbstractVisualObject(), VisualObject3D {
|
||||||
|
|
||||||
override var position: Point3D? = null
|
override var position: Point3D? = null
|
||||||
override var rotation: Point3D? = null
|
override var rotation: Point3D? = null
|
||||||
override var scale: Point3D? = null
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively search for defined template in the parent
|
* Recursively search for defined template in the parent
|
||||||
*/
|
*/
|
||||||
val template by lazy {
|
val template: VisualObject3D
|
||||||
(parent as? VisualGroup3D)?.getTemplate(templateName)
|
get() = (parent as? VisualGroup3D)?.getTemplate(templateName)
|
||||||
?: error("Template with name $templateName not found in $parent")
|
?: error("Template with name $templateName not found in $parent")
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||||
return if (inherit) {
|
return if (inherit) {
|
||||||
|
@ -1,14 +1,30 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class)
|
||||||
|
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
|
@Serializable
|
||||||
class Sphere(
|
class Sphere(
|
||||||
var radius: Float,
|
var radius: Float,
|
||||||
var phiStart: Float = 0f,
|
var phiStart: Float = 0f,
|
||||||
var phi: Float = PI2,
|
var phi: Float = PI2,
|
||||||
var thetaStart: Float = 0f,
|
var thetaStart: Float = 0f,
|
||||||
var theta: Float = PI.toFloat()
|
var theta: Float = PI.toFloat()
|
||||||
) : VisualLeaf3D()
|
) : AbstractVisualObject(), VisualObject3D {
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
}
|
||||||
|
|
||||||
inline fun VisualGroup3D.sphere(
|
inline fun VisualGroup3D.sphere(
|
||||||
radius: Number,
|
radius: Number,
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class)
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@ -7,13 +13,21 @@ import kotlin.math.sin
|
|||||||
/**
|
/**
|
||||||
* Straight tube segment
|
* Straight tube segment
|
||||||
*/
|
*/
|
||||||
|
@Serializable
|
||||||
class Tube(
|
class Tube(
|
||||||
var radius: Float,
|
var radius: Float,
|
||||||
var height: Float,
|
var height: Float,
|
||||||
var innerRadius: Float = 0f,
|
var innerRadius: Float = 0f,
|
||||||
var startAngle: Float = 0f,
|
var startAngle: Float = 0f,
|
||||||
var angle: Float = PI2
|
var angle: Float = PI2
|
||||||
) : VisualLeaf3D(), Shape {
|
) : AbstractVisualObject(), VisualObject3D, Shape {
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(radius > 0)
|
require(radius > 0)
|
||||||
@ -37,8 +51,8 @@ class Tube(
|
|||||||
geometryBuilder.apply {
|
geometryBuilder.apply {
|
||||||
|
|
||||||
//creating shape in x-y plane with z = 0
|
//creating shape in x-y plane with z = 0
|
||||||
val bottomOuterPoints = shape(radius, 0f)
|
val bottomOuterPoints = shape(radius, -height/2)
|
||||||
val upperOuterPoints = shape(radius, height)
|
val upperOuterPoints = shape(radius, height/2)
|
||||||
//outer face
|
//outer face
|
||||||
(1 until segments).forEach {
|
(1 until segments).forEach {
|
||||||
face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1])
|
face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1])
|
||||||
@ -62,8 +76,8 @@ class Tube(
|
|||||||
face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last())
|
face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val bottomInnerPoints = shape(innerRadius, 0f)
|
val bottomInnerPoints = shape(innerRadius, -height/2)
|
||||||
val upperInnerPoints = shape(innerRadius, height)
|
val upperInnerPoints = shape(innerRadius, height/2)
|
||||||
//outer face
|
//outer face
|
||||||
(1 until segments).forEach {
|
(1 until segments).forEach {
|
||||||
// inner surface
|
// inner surface
|
||||||
@ -97,9 +111,14 @@ class Tube(
|
|||||||
bottomOuterPoints.last()
|
bottomOuterPoints.last()
|
||||||
)
|
)
|
||||||
face4(upperInnerPoints[0], upperInnerPoints.last(), upperOuterPoints.last(), upperOuterPoints[0])
|
face4(upperInnerPoints[0], upperInnerPoints.last(), upperOuterPoints.last(), upperOuterPoints[0])
|
||||||
} else{
|
} else {
|
||||||
face4(bottomInnerPoints[0],bottomOuterPoints[0],upperOuterPoints[0],upperInnerPoints[0])
|
face4(bottomInnerPoints[0], bottomOuterPoints[0], upperOuterPoints[0], upperInnerPoints[0])
|
||||||
face4(bottomOuterPoints.last(),bottomInnerPoints.last(),upperInnerPoints.last(),upperOuterPoints.last())
|
face4(
|
||||||
|
bottomOuterPoints.last(),
|
||||||
|
bottomInnerPoints.last(),
|
||||||
|
upperInnerPoints.last(),
|
||||||
|
upperOuterPoints.last()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import hep.dataforge.context.PluginTag
|
|||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.vis.common.VisualPlugin
|
import hep.dataforge.vis.common.VisualPlugin
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||||
@ -23,6 +26,26 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP)
|
override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP)
|
||||||
override val type: KClass<out Visual3DPlugin> = Visual3DPlugin::class
|
override val type: KClass<out Visual3DPlugin> = Visual3DPlugin::class
|
||||||
override fun invoke(meta: Meta): Visual3DPlugin = Visual3DPlugin(meta)
|
override fun invoke(meta: Meta): Visual3DPlugin = Visual3DPlugin(meta)
|
||||||
|
|
||||||
|
val serialModule = SerializersModule {
|
||||||
|
polymorphic(VisualObject3D::class) {
|
||||||
|
VisualGroup3D::class with VisualGroup3D.serializer()
|
||||||
|
Proxy::class with Proxy.serializer()
|
||||||
|
Composite::class with Composite.serializer()
|
||||||
|
Tube::class with Tube.serializer()
|
||||||
|
Box::class with Box.serializer()
|
||||||
|
Convex::class with Convex.serializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val json = Json(
|
||||||
|
JsonConfiguration(
|
||||||
|
prettyPrint = true,
|
||||||
|
useArrayPolymorphism = false,
|
||||||
|
encodeDefaults = false
|
||||||
|
),
|
||||||
|
context = serialModule
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
|
@file:UseSerializers(Point3DSerializer::class, NameSerializer::class)
|
||||||
|
|
||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.io.ConfigSerializer
|
||||||
|
import hep.dataforge.io.NameSerializer
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.output.Output
|
import hep.dataforge.output.Output
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.asName
|
import hep.dataforge.vis.common.asName
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.MATERIAL_KEY
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.MATERIAL_KEY
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
|
||||||
interface VisualObject3D : VisualObject {
|
interface VisualObject3D : VisualObject {
|
||||||
var position: Point3D?
|
var position: Point3D?
|
||||||
@ -60,18 +65,8 @@ interface VisualObject3D : VisualObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class VisualLeaf3D : AbstractVisualObject(), VisualObject3D, Configurable {
|
@Serializable
|
||||||
override var position: Point3D? = null
|
|
||||||
override var rotation: Point3D? = null
|
|
||||||
override var scale: Point3D? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
class VisualGroup3D : VisualGroup<VisualObject3D>(), VisualObject3D, Configurable {
|
class VisualGroup3D : VisualGroup<VisualObject3D>(), VisualObject3D, Configurable {
|
||||||
|
|
||||||
override var position: Point3D? = null
|
|
||||||
override var rotation: Point3D? = null
|
|
||||||
override var scale: Point3D? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container for templates visible inside this group
|
* A container for templates visible inside this group
|
||||||
*/
|
*/
|
||||||
@ -81,12 +76,27 @@ class VisualGroup3D : VisualGroup<VisualObject3D>(), VisualObject3D, Configurabl
|
|||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable(ConfigSerializer::class)
|
||||||
|
override var properties: Config? = null
|
||||||
|
|
||||||
|
override var position: Point3D? = null
|
||||||
|
override var rotation: Point3D? = null
|
||||||
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
|
override val namedChildren: MutableMap<Name, VisualObject3D> = HashMap()
|
||||||
|
override val unnamedChildren: MutableList<VisualObject3D> = ArrayList()
|
||||||
|
|
||||||
fun getTemplate(name: Name): VisualObject3D? = templates?.get(name) ?: (parent as? VisualGroup3D)?.getTemplate(name)
|
fun getTemplate(name: Name): VisualObject3D? = templates?.get(name) ?: (parent as? VisualGroup3D)?.getTemplate(name)
|
||||||
|
|
||||||
override fun MetaBuilder.updateMeta() {
|
override fun MetaBuilder.updateMeta() {
|
||||||
|
set(TEMPLATES_KEY, templates?.toMeta())
|
||||||
updatePosition()
|
updatePosition()
|
||||||
updateChildren()
|
updateChildren()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TEMPLATES_KEY = "templates"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup3D.group(key: String? = null, action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
|
fun VisualGroup3D.group(key: String? = null, action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
|
||||||
@ -214,4 +224,3 @@ var VisualObject3D.scaleZ: Number
|
|||||||
scale().z = value.toDouble()
|
scale().z = value.toDouble()
|
||||||
propertyChanged(VisualObject3D.zScale)
|
propertyChanged(VisualObject3D.zScale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class Point2DSerial(val x: Double, val y: Double)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class Point3DSerial(val x: Double, val y: Double, val z: Double)
|
||||||
|
|
||||||
|
@Serializer(Point3D::class)
|
||||||
|
object Point3DSerializer : KSerializer<Point3D> {
|
||||||
|
private val serializer = Point3DSerial.serializer()
|
||||||
|
override val descriptor: SerialDescriptor get() = serializer.descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Point3D {
|
||||||
|
return serializer.deserialize(decoder).let {
|
||||||
|
Point3D(it.x, it.y, it.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: Point3D) {
|
||||||
|
serializer.serialize(encoder, Point3DSerial(obj.x, obj.y, obj.z) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializer(Point2D::class)
|
||||||
|
object Point2DSerializer : KSerializer<Point2D> {
|
||||||
|
private val serializer = Point2DSerial.serializer()
|
||||||
|
override val descriptor: SerialDescriptor get() = serializer.descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Point2D {
|
||||||
|
return serializer.deserialize(decoder).let {
|
||||||
|
Point2D(it.x, it.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: Point2D) {
|
||||||
|
serializer.serialize(encoder, Point2DSerial(obj.x, obj.y))
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@ class ConvexTest {
|
|||||||
|
|
||||||
val convex = group.first() as Convex
|
val convex = group.first() as Convex
|
||||||
|
|
||||||
|
val meta = convex.toMeta()
|
||||||
|
|
||||||
val pointsNode = convex.toMeta()["points"].node
|
val pointsNode = convex.toMeta()["points"].node
|
||||||
|
|
||||||
assertEquals(8, pointsNode?.items?.count())
|
assertEquals(8, pointsNode?.items?.count())
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class SerializationTest {
|
class SerializationTest {
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
@Test
|
@Test
|
||||||
fun testCubeSerialization(){
|
fun testCubeSerialization(){
|
||||||
val cube = Box(null,100f,100f,100f).apply{
|
val cube = Box(100f,100f,100f).apply{
|
||||||
color(222)
|
color(222)
|
||||||
}
|
}
|
||||||
val meta = cube.toMeta()
|
val meta = cube.toMeta()
|
||||||
|
@ -3,7 +3,6 @@ package hep.dataforge.vis.spatial.three
|
|||||||
import hep.dataforge.vis.spatial.Composite
|
import hep.dataforge.vis.spatial.Composite
|
||||||
import hep.dataforge.vis.spatial.CompositeType
|
import hep.dataforge.vis.spatial.CompositeType
|
||||||
import info.laht.threekt.core.BufferGeometry
|
import info.laht.threekt.core.BufferGeometry
|
||||||
import info.laht.threekt.core.Geometry
|
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,9 +22,7 @@ class ThreeCompositeFactory(val three: ThreePlugin) : MeshThreeFactory<Composite
|
|||||||
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
|
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
|
||||||
CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG)
|
CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG)
|
||||||
}
|
}
|
||||||
|
return resultCSG.toGeometry().toBufferGeometry()
|
||||||
val mesh = CSG.toMesh(resultCSG, second.matrix)
|
|
||||||
return (mesh.geometry as Geometry).toBufferGeometry()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
import hep.dataforge.vis.spatial.Cylinder
|
import hep.dataforge.vis.spatial.ConeSegment
|
||||||
import hep.dataforge.vis.spatial.detail
|
import hep.dataforge.vis.spatial.detail
|
||||||
import info.laht.threekt.core.BufferGeometry
|
import info.laht.threekt.core.BufferGeometry
|
||||||
import info.laht.threekt.geometries.CylinderBufferGeometry
|
import info.laht.threekt.geometries.CylinderBufferGeometry
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
object ThreeCylinderFactory : MeshThreeFactory<Cylinder>(Cylinder::class) {
|
object ThreeCylinderFactory : MeshThreeFactory<ConeSegment>(ConeSegment::class) {
|
||||||
override fun buildGeometry(obj: Cylinder): BufferGeometry {
|
override fun buildGeometry(obj: ConeSegment): BufferGeometry {
|
||||||
val cylinder = obj.detail?.let {
|
val cylinder = obj.detail?.let {
|
||||||
val segments = it.toDouble().pow(0.5).toInt()
|
val segments = it.toDouble().pow(0.5).toInt()
|
||||||
CylinderBufferGeometry(
|
CylinderBufferGeometry(
|
||||||
|
@ -37,6 +37,12 @@ interface ThreeFactory<T : VisualObject3D> {
|
|||||||
*/
|
*/
|
||||||
internal fun Object3D.updatePosition(obj: VisualObject3D) {
|
internal fun Object3D.updatePosition(obj: VisualObject3D) {
|
||||||
visible = obj.visible ?: true
|
visible = obj.visible ?: true
|
||||||
|
// Matrix4().apply {
|
||||||
|
// makeRotationFromEuler(obj.euler)
|
||||||
|
// applyMatrix(this)
|
||||||
|
// makeTranslation(obj.x.toDouble(), obj.y.toDouble(), obj.z.toDouble())
|
||||||
|
// applyMatrix(this)
|
||||||
|
// }
|
||||||
position.set(obj.x, obj.y, obj.z)
|
position.set(obj.x, obj.y, obj.z)
|
||||||
setRotationFromEuler(obj.euler)
|
setRotationFromEuler(obj.euler)
|
||||||
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
||||||
|
@ -27,7 +27,7 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
objectFactories[Box::class] = ThreeBoxFactory
|
objectFactories[Box::class] = ThreeBoxFactory
|
||||||
objectFactories[Convex::class] = ThreeConvexFactory
|
objectFactories[Convex::class] = ThreeConvexFactory
|
||||||
objectFactories[Sphere::class] = ThreeSphereFactory
|
objectFactories[Sphere::class] = ThreeSphereFactory
|
||||||
objectFactories[Cylinder::class] = ThreeCylinderFactory
|
objectFactories[ConeSegment::class] = ThreeCylinderFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findObjectFactory(type: KClass<out VisualObject3D>): ThreeFactory<*>? {
|
private fun findObjectFactory(type: KClass<out VisualObject3D>): ThreeFactory<*>? {
|
||||||
|
@ -13,10 +13,11 @@ package hep.dataforge.vis.spatial.three
|
|||||||
|
|
||||||
|
|
||||||
import info.laht.threekt.math.Matrix4
|
import info.laht.threekt.math.Matrix4
|
||||||
|
import info.laht.threekt.math.Vector3
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
|
|
||||||
open external class CSG {
|
open external class CSG {
|
||||||
open var polygons: Any
|
open var polygons: Array<Polygon>
|
||||||
open fun clone(): CSG
|
open fun clone(): CSG
|
||||||
open fun toPolygons(): Array<Polygon>
|
open fun toPolygons(): Array<Polygon>
|
||||||
open fun union(csg: CSG): CSG
|
open fun union(csg: CSG): CSG
|
||||||
@ -40,8 +41,7 @@ open external class CSG {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open external class Vector(x: Number, y: Number, z: Number) {
|
open external class Vector(x: Number, y: Number, z: Number): Vector3 {
|
||||||
open fun clone(): Any
|
|
||||||
open fun negated(): Vector
|
open fun negated(): Vector
|
||||||
open fun plus(a: Vector): Vector
|
open fun plus(a: Vector): Vector
|
||||||
open fun minus(a: Vector): Vector
|
open fun minus(a: Vector): Vector
|
||||||
|
@ -6,6 +6,7 @@ import hep.dataforge.meta.get
|
|||||||
import hep.dataforge.meta.node
|
import hep.dataforge.meta.node
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
import info.laht.threekt.core.BufferGeometry
|
import info.laht.threekt.core.BufferGeometry
|
||||||
|
import info.laht.threekt.core.Face3
|
||||||
import info.laht.threekt.core.Geometry
|
import info.laht.threekt.core.Geometry
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.math.Euler
|
import info.laht.threekt.math.Euler
|
||||||
@ -26,3 +27,41 @@ val VisualObject3D.euler get() = Euler(rotationX, rotationY, rotationZ, rotation
|
|||||||
val MetaItem<*>.vector get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f)
|
val MetaItem<*>.vector get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f)
|
||||||
|
|
||||||
fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) }
|
fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) }
|
||||||
|
|
||||||
|
fun CSG.toGeometry(): Geometry {
|
||||||
|
val geom = Geometry()
|
||||||
|
|
||||||
|
val vertices = ArrayList<Vector3>()
|
||||||
|
val faces = ArrayList<Face3>()
|
||||||
|
|
||||||
|
for (polygon in polygons) {
|
||||||
|
val v0 = vertices.size
|
||||||
|
val pvs = polygon.vertices
|
||||||
|
|
||||||
|
for (pv in pvs) {
|
||||||
|
vertices.add(Vector3().copy(pv.pos))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j in 3..polygon.vertices.size) {
|
||||||
|
val fc = Face3(v0, v0 + j - 2, v0 + j - 1, zero)
|
||||||
|
fc.vertexNormals = arrayOf(
|
||||||
|
Vector3().copy(pvs[0].normal),
|
||||||
|
Vector3().copy(pvs[j - 2].normal),
|
||||||
|
Vector3().copy(pvs[j - 1].normal)
|
||||||
|
)
|
||||||
|
|
||||||
|
fc.normal = Vector3().copy(polygon.plane.normal)
|
||||||
|
faces.add(fc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
geom.vertices = vertices.toTypedArray()
|
||||||
|
geom.faces = faces.toTypedArray()
|
||||||
|
// val inv: Matrix4 = Matrix4().apply { getInverse(toMatrix) }
|
||||||
|
// geom.applyMatrix(toMatrix)
|
||||||
|
geom.verticesNeedUpdate = true
|
||||||
|
geom.elementsNeedUpdate = true
|
||||||
|
geom.normalsNeedUpdate = true
|
||||||
|
geom.computeBoundingSphere()
|
||||||
|
geom.computeBoundingBox()
|
||||||
|
return geom
|
||||||
|
}
|
@ -45,6 +45,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
|
|||||||
element.append(gridRoot)
|
element.append(gridRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Output<T> {
|
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Output<T> {
|
||||||
val three = context.plugins.get<ThreePlugin>()!!
|
val three = context.plugins.get<ThreePlugin>()!!
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user