Serialization complete. Fixed tube geometry

This commit is contained in:
Alexander Nozik 2019-08-17 14:22:39 +03:00
parent 71c016d2fd
commit b50a9c590f
28 changed files with 396 additions and 151 deletions

View File

@ -1,4 +1,4 @@
val dataforgeVersion by extra("0.1.3-dev-10")
val dataforgeVersion by extra("0.1.3")
plugins{
val kotlinVersion = "1.3.50-eap-5"

View File

@ -18,6 +18,7 @@ kotlin {
val jsMain by getting {
dependencies {
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
api(npm("text-encoding"))
}
}
}

View File

@ -1,17 +1,20 @@
package hep.dataforge.vis.common
import hep.dataforge.meta.Config
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.MetaItem
import hep.dataforge.names.Name
import hep.dataforge.names.get
import hep.dataforge.names.toName
import hep.dataforge.provider.Provider
import kotlinx.serialization.Transient
import kotlin.collections.set
open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>, Provider {
protected val namedChildren = HashMap<Name, T>()
protected val unnamedChildren = ArrayList<T>()
protected open val namedChildren: MutableMap<Name, T> = HashMap()
protected open val unnamedChildren: MutableList<T> = ArrayList()
override var properties: Config? = null
override val defaultTarget: String get() = VisualObject.TYPE
@ -51,7 +54,13 @@ open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>,
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) {
namedChildren.remove(name)
} else {
@ -64,14 +73,6 @@ open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>,
}
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)
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
*/
operator fun get(key: String): T? = namedChildren.get(key)
operator fun get(key: String): T? = namedChildren[key.toName()]
/**
* Get an unnamed child

View File

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

View File

@ -1,12 +1,9 @@
package hep.dataforge.vis.common
import hep.dataforge.io.ConfigSerializer
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.provider.Type
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
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)
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.
*/
@ -65,6 +60,8 @@ internal data class MetaListener(
)
abstract class AbstractVisualObject: VisualObject {
@Transient
override var parent: VisualObject? = null
@Transient
@ -84,12 +81,10 @@ abstract class AbstractVisualObject : VisualObject {
listeners.removeAll { it.owner == owner }
}
@Serializable(ConfigSerializer::class)
@SerialName("properties")
private var _config: Config? = null
abstract var properties: Config?
override val config: Config
get() = _config ?: Config().also { config ->
_config = config
get() = properties ?: Config().also { config ->
properties = config
config.onChange(this, ::propertyChanged)
}
@ -99,19 +94,17 @@ abstract class AbstractVisualObject : VisualObject {
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
_config?.get(name) ?: parent?.getProperty(name, inherit)
properties?.get(name) ?: parent?.getProperty(name, inherit)
} else {
_config?.get(name)
properties?.get(name)
}
}
protected open fun MetaBuilder.updateMeta() {}
override fun toMeta(): Meta = buildMeta {
"type" to type
"properties" to config
"type" to this::class.simpleName
"properties" to properties
updateMeta()
}
}

View File

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

View File

@ -29,7 +29,7 @@ kotlin {
dependencies {
api("info.laht.threekt:threejs-wrapper:0.106-npm-3")
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("element-resize-event"))
}

View File

@ -1,19 +1,29 @@
@file:UseSerializers(Point3DSerializer::class)
package hep.dataforge.vis.spatial
import hep.dataforge.context.Context
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.float
import hep.dataforge.meta.get
import hep.dataforge.io.ConfigSerializer
import hep.dataforge.meta.*
import hep.dataforge.vis.common.AbstractVisualObject
import hep.dataforge.vis.common.VisualFactory
import hep.dataforge.vis.common.VisualObject
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import kotlin.reflect.KClass
@Serializable
data class Box(
val xSize: Float,
val ySize: 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
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
@ -40,8 +50,13 @@ data class Box(
"xSize" to xSize
"ySize" to ySize
"zSize" to ySize
updatePosition()
}
// override fun toMeta(): Meta {
// return (Visual3DPlugin.json.toJson(Box.serializer(), this) as JsonObject).toMeta()
// }
companion object : VisualFactory<Box> {
const val TYPE = "geometry.3d.box"

View File

@ -1,7 +1,13 @@
@file:UseSerializers(Point3DSerializer::class)
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.vis.common.AbstractVisualObject
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
enum class CompositeType {
UNION,
@ -9,11 +15,27 @@ enum class CompositeType {
SUBTRACT
}
open class Composite(
@Serializable
class Composite(
val compositeType: CompositeType,
val first: VisualObject3D,
val second: VisualObject3D,
val compositeType: CompositeType = CompositeType.UNION
) : VisualLeaf3D()
val second: VisualObject3D
) : AbstractVisualObject(), VisualObject3D {
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(
type: CompositeType,
@ -23,14 +45,14 @@ inline fun VisualGroup3D.composite(
val group = VisualGroup3D().apply(builder)
val children = group.filterIsInstance<VisualObject3D>()
if (children.size != 2) error("Composite requires exactly two children")
return Composite(children[0], children[1], type).also {
if (!group.config.isEmpty()) {
return Composite(type, children[0], children[1]).also {
if (group.properties != null) {
it.config.update(group.config)
it.material = group.material
}
it.position = group.position
it.rotation = group.rotation
it.scale = group.scale
it.material = group.material
set(name, it)
}
}

View File

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

View File

@ -1,15 +1,29 @@
@file:UseSerializers(Point3DSerializer::class)
package hep.dataforge.vis.spatial
import hep.dataforge.io.ConfigSerializer
import hep.dataforge.meta.Config
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.vis.common.AbstractVisualObject
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
class Convex(
val points: List<Point3D>
) : VisualLeaf3D() {
@Serializable
class Convex(val points: List<Point3D>) : 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
override fun MetaBuilder.updateMeta() {
"points" to {
"point" to points.map { it.toMeta() }
}
updatePosition()
}
companion object {

View File

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

View File

@ -1,5 +1,11 @@
@file:UseSerializers(Point2DSerializer::class, 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
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
@ -7,16 +13,16 @@ import kotlin.math.sin
typealias Shape2D = List<Point2D>
class Shape2DBuilder {
private val list = ArrayList<Point2D>()
@Serializable
class Shape2DBuilder(private val points: MutableList<Point2D> = ArrayList()) {
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)
fun build(): Shape2D = list
fun build(): Shape2D = points
}
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)
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) {
this.shape = Shape2DBuilder().apply(block).build()
//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) {
layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat()))
//TODO send invalidation signal

View File

@ -1,25 +1,37 @@
@file:UseSerializers(Point3DSerializer::class, NameSerializer::class)
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.MetaItem
import hep.dataforge.names.Name
import hep.dataforge.vis.common.AbstractVisualObject
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
/**
* A proxy [VisualObject3D] to reuse a template object
*/
@Serializable
class Proxy(val templateName: Name) : AbstractVisualObject(), VisualObject3D {
override var position: Point3D? = null
override var rotation: Point3D? = null
override var scale: Point3D? = null
@Serializable(ConfigSerializer::class)
override var properties: Config? = null
/**
* Recursively search for defined template in the parent
*/
val template by lazy {
(parent as? VisualGroup3D)?.getTemplate(templateName)
val template: VisualObject3D
get() = (parent as? VisualGroup3D)?.getTemplate(templateName)
?: error("Template with name $templateName not found in $parent")
}
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {

View File

@ -1,14 +1,30 @@
@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
import kotlin.math.PI
@Serializable
class Sphere(
var radius: Float,
var phiStart: Float = 0f,
var phi: Float = PI2,
var thetaStart: Float = 0f,
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(
radius: Number,

View File

@ -1,5 +1,11 @@
@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
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
@ -7,13 +13,21 @@ import kotlin.math.sin
/**
* Straight tube segment
*/
@Serializable
class Tube(
var radius: Float,
var height: Float,
var innerRadius: Float = 0f,
var startAngle: Float = 0f,
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 {
require(radius > 0)
@ -37,8 +51,8 @@ class Tube(
geometryBuilder.apply {
//creating shape in x-y plane with z = 0
val bottomOuterPoints = shape(radius, 0f)
val upperOuterPoints = shape(radius, height)
val bottomOuterPoints = shape(radius, -height/2)
val upperOuterPoints = shape(radius, height/2)
//outer face
(1 until segments).forEach {
face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1])
@ -62,8 +76,8 @@ class Tube(
face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last())
}
} else {
val bottomInnerPoints = shape(innerRadius, 0f)
val upperInnerPoints = shape(innerRadius, height)
val bottomInnerPoints = shape(innerRadius, -height/2)
val upperInnerPoints = shape(innerRadius, height/2)
//outer face
(1 until segments).forEach {
// inner surface
@ -99,7 +113,12 @@ class Tube(
face4(upperInnerPoints[0], upperInnerPoints.last(), upperOuterPoints.last(), upperOuterPoints[0])
} else {
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()
)
}
}
}

View File

@ -6,6 +6,9 @@ import hep.dataforge.context.PluginTag
import hep.dataforge.meta.*
import hep.dataforge.names.Name
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
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 type: KClass<out Visual3DPlugin> = Visual3DPlugin::class
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
)
}
}

View File

@ -1,16 +1,21 @@
@file:UseSerializers(Point3DSerializer::class, NameSerializer::class)
package hep.dataforge.vis.spatial
import hep.dataforge.io.ConfigSerializer
import hep.dataforge.io.NameSerializer
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.plus
import hep.dataforge.output.Output
import hep.dataforge.vis.common.AbstractVisualObject
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.asName
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.VISIBLE_KEY
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
interface VisualObject3D : VisualObject {
var position: Point3D?
@ -60,18 +65,8 @@ interface VisualObject3D : VisualObject {
}
}
abstract class VisualLeaf3D : AbstractVisualObject(), VisualObject3D, Configurable {
override var position: Point3D? = null
override var rotation: Point3D? = null
override var scale: Point3D? = null
}
@Serializable
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
*/
@ -81,12 +76,27 @@ class VisualGroup3D : VisualGroup<VisualObject3D>(), VisualObject3D, Configurabl
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)
override fun MetaBuilder.updateMeta() {
set(TEMPLATES_KEY, templates?.toMeta())
updatePosition()
updateChildren()
}
companion object {
const val TEMPLATES_KEY = "templates"
}
}
fun VisualGroup3D.group(key: String? = null, action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
@ -214,4 +224,3 @@ var VisualObject3D.scaleZ: Number
scale().z = value.toDouble()
propertyChanged(VisualObject3D.zScale)
}

View File

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

View File

@ -25,6 +25,8 @@ class ConvexTest {
val convex = group.first() as Convex
val meta = convex.toMeta()
val pointsNode = convex.toMeta()["points"].node
assertEquals(8, pointsNode?.items?.count())

View File

@ -1,13 +1,15 @@
package hep.dataforge.vis.spatial
import hep.dataforge.context.Global
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlin.test.Test
import kotlin.test.assertEquals
class SerializationTest {
@ImplicitReflectionSerializer
@Test
fun testCubeSerialization(){
val cube = Box(null,100f,100f,100f).apply{
val cube = Box(100f,100f,100f).apply{
color(222)
}
val meta = cube.toMeta()

View File

@ -3,7 +3,6 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.vis.spatial.Composite
import hep.dataforge.vis.spatial.CompositeType
import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
import info.laht.threekt.objects.Mesh
/**
@ -23,9 +22,7 @@ class ThreeCompositeFactory(val three: ThreePlugin) : MeshThreeFactory<Composite
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG)
}
val mesh = CSG.toMesh(resultCSG, second.matrix)
return (mesh.geometry as Geometry).toBufferGeometry()
return resultCSG.toGeometry().toBufferGeometry()
}
}

View File

@ -1,14 +1,14 @@
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 info.laht.threekt.core.BufferGeometry
import info.laht.threekt.geometries.CylinderBufferGeometry
import kotlin.math.PI
import kotlin.math.pow
object ThreeCylinderFactory : MeshThreeFactory<Cylinder>(Cylinder::class) {
override fun buildGeometry(obj: Cylinder): BufferGeometry {
object ThreeCylinderFactory : MeshThreeFactory<ConeSegment>(ConeSegment::class) {
override fun buildGeometry(obj: ConeSegment): BufferGeometry {
val cylinder = obj.detail?.let {
val segments = it.toDouble().pow(0.5).toInt()
CylinderBufferGeometry(

View File

@ -37,6 +37,12 @@ interface ThreeFactory<T : VisualObject3D> {
*/
internal fun Object3D.updatePosition(obj: VisualObject3D) {
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)
setRotationFromEuler(obj.euler)
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)

View File

@ -27,7 +27,7 @@ class ThreePlugin : AbstractPlugin() {
objectFactories[Box::class] = ThreeBoxFactory
objectFactories[Convex::class] = ThreeConvexFactory
objectFactories[Sphere::class] = ThreeSphereFactory
objectFactories[Cylinder::class] = ThreeCylinderFactory
objectFactories[ConeSegment::class] = ThreeCylinderFactory
}
private fun findObjectFactory(type: KClass<out VisualObject3D>): ThreeFactory<*>? {

View File

@ -13,10 +13,11 @@ package hep.dataforge.vis.spatial.three
import info.laht.threekt.math.Matrix4
import info.laht.threekt.math.Vector3
import info.laht.threekt.objects.Mesh
open external class CSG {
open var polygons: Any
open var polygons: Array<Polygon>
open fun clone(): CSG
open fun toPolygons(): Array<Polygon>
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 fun clone(): Any
open external class Vector(x: Number, y: Number, z: Number): Vector3 {
open fun negated(): Vector
open fun plus(a: Vector): Vector
open fun minus(a: Vector): Vector

View File

@ -6,6 +6,7 @@ import hep.dataforge.meta.get
import hep.dataforge.meta.node
import hep.dataforge.vis.spatial.*
import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Face3
import info.laht.threekt.core.Geometry
import info.laht.threekt.core.Object3D
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)
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
}

View File

@ -45,6 +45,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
element.append(gridRoot)
}
@Suppress("UNCHECKED_CAST")
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Output<T> {
val three = context.plugins.get<ThreePlugin>()!!