Reimplemented coordinates as properties

This commit is contained in:
Alexander Nozik 2021-07-11 12:07:04 +03:00
parent ba637413c7
commit 2b6942b827
9 changed files with 142 additions and 157 deletions

View File

@ -1,7 +1,5 @@
import kotlinx.browser.document import kotlinx.browser.document
import kotlinx.css.height import kotlinx.css.*
import kotlinx.css.pct
import kotlinx.css.width
import react.child import react.child
import react.dom.render import react.dom.render
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
@ -31,8 +29,10 @@ private class JsPlaygroundApp : Application {
render(element) { render(element) {
styledDiv { styledDiv {
css{ css{
height = 100.pct padding(0.pt)
width = 100.pct margin(0.pt)
height = 100.vh
width = 100.vw
} }
child(ThreeCanvasWithControls) { child(ThreeCanvasWithControls) {
attrs { attrs {

View File

@ -11,22 +11,14 @@ public expect class Counter() {
public fun incrementAndGet(): Int public fun incrementAndGet(): Int
} }
private fun Point3D?.safePlus(other: Point3D?): Point3D? = if (this == null && other == null) {
null
} else {
(this ?: Point3D(0, 0, 0)) + (other ?: Point3D(0, 0, 0))
}
@DFExperimental @DFExperimental
internal fun Vision.updateFrom(other: Vision): Vision { internal fun Vision.updateFrom(other: Vision): Vision {
if (this is Solid && other is Solid) { if (this is Solid && other is Solid) {
position = position.safePlus(other.position) position += other.position
rotation = rotation.safePlus(other.rotation) rotation += other.rotation
if (this.scale != null || other.scale != null) {
scaleX = scaleX.toDouble() * other.scaleX.toDouble() scaleX = scaleX.toDouble() * other.scaleX.toDouble()
scaleY = scaleY.toDouble() * other.scaleY.toDouble() scaleY = scaleY.toDouble() * other.scaleY.toDouble()
scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble()
}
other.meta.itemSequence().forEach { (name, item) -> other.meta.itemSequence().forEach { (name, item) ->
if (getProperty(name) == null) { if (getProperty(name) == null) {
setProperty(name, item) setProperty(name, item)

View File

@ -1,9 +1,7 @@
package space.kscience.visionforge.solid package space.kscience.visionforge.solid
import space.kscience.dataforge.meta.boolean import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.NodeDescriptor import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.meta.enum
import space.kscience.dataforge.meta.int
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
@ -14,15 +12,28 @@ import space.kscience.visionforge.Vision.Companion.VISIBLE_KEY
import space.kscience.visionforge.solid.Solid.Companion.DETAIL_KEY import space.kscience.visionforge.solid.Solid.Companion.DETAIL_KEY
import space.kscience.visionforge.solid.Solid.Companion.IGNORE_KEY import space.kscience.visionforge.solid.Solid.Companion.IGNORE_KEY
import space.kscience.visionforge.solid.Solid.Companion.LAYER_KEY import space.kscience.visionforge.solid.Solid.Companion.LAYER_KEY
import space.kscience.visionforge.solid.Solid.Companion.POSITION_KEY
import space.kscience.visionforge.solid.Solid.Companion.ROTATION_KEY
import space.kscience.visionforge.solid.Solid.Companion.SCALE_KEY
import space.kscience.visionforge.solid.Solid.Companion.X_KEY
import space.kscience.visionforge.solid.Solid.Companion.X_POSITION_KEY
import space.kscience.visionforge.solid.Solid.Companion.X_ROTATION_KEY
import space.kscience.visionforge.solid.Solid.Companion.X_SCALE_KEY
import space.kscience.visionforge.solid.Solid.Companion.Y_KEY
import space.kscience.visionforge.solid.Solid.Companion.Y_POSITION_KEY
import space.kscience.visionforge.solid.Solid.Companion.Y_ROTATION_KEY
import space.kscience.visionforge.solid.Solid.Companion.Y_SCALE_KEY
import space.kscience.visionforge.solid.Solid.Companion.Z_KEY
import space.kscience.visionforge.solid.Solid.Companion.Z_POSITION_KEY
import space.kscience.visionforge.solid.Solid.Companion.Z_ROTATION_KEY
import space.kscience.visionforge.solid.Solid.Companion.Z_SCALE_KEY
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/** /**
* Interface for 3-dimensional [Vision] * Interface for 3-dimensional [Vision]
*/ */
public interface Solid : Vision { public interface Solid : Vision {
public var position: Point3D?
public var rotation: Point3D?
public var scale: Point3D?
override val descriptor: NodeDescriptor get() = Companion.descriptor override val descriptor: NodeDescriptor get() = Companion.descriptor
public companion object { public companion object {
@ -72,7 +83,7 @@ public interface Solid : Vision {
hide() hide()
} }
value(DETAIL_KEY){ value(DETAIL_KEY) {
type(ValueType.NUMBER) type(ValueType.NUMBER)
hide() hide()
} }
@ -84,22 +95,6 @@ public interface Solid : Vision {
} }
} }
} }
internal fun solidEquals(first: Solid, second: Solid): Boolean {
if (first.position != second.position) return false
if (first.rotation != second.rotation) return false
if (first.scale != second.scale) return false
if (first.meta != second.meta) return false
return true
}
internal fun solidHashCode(solid: Solid): Int {
var result = +(solid.position?.hashCode() ?: 0)
result = 31 * result + (solid.rotation?.hashCode() ?: 0)
result = 31 * result + (solid.scale?.hashCode() ?: 0)
result = 31 * result + solid.allProperties().hashCode()
return result
}
} }
} }
@ -150,74 +145,44 @@ public var Vision.ignore: Boolean?
// get() = getProperty(SELECTED_KEY).boolean // get() = getProperty(SELECTED_KEY).boolean
// set(value) = setProperty(SELECTED_KEY, value) // set(value) = setProperty(SELECTED_KEY, value)
private fun Solid.position(): Point3D = internal fun number(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
position ?: Point3D(0.0, 0.0, 0.0).also { position = it } object : ReadWriteProperty<Solid, Number> {
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
public var Solid.x: Number return thisRef.getOwnProperty(name)?.number ?: default
get() = position?.x ?: 0f
set(value) {
position().x = value.toFloat()
invalidateProperty(Solid.X_POSITION_KEY)
} }
public var Solid.y: Number override fun setValue(thisRef: Solid, property: KProperty<*>, value: Number) {
get() = position?.y ?: 0f thisRef.setProperty(name, value)
set(value) { }
position().y = value.toFloat()
invalidateProperty(Solid.Y_POSITION_KEY)
} }
public var Solid.z: Number internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D> =
get() = position?.z ?: 0f object : ReadWriteProperty<Solid, Point3D> {
set(value) { override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D = object : Point3D {
position().z = value.toFloat() override val x: Float get() = thisRef.getOwnProperty(name + X_KEY)?.float ?: default
invalidateProperty(Solid.Z_POSITION_KEY) override val y: Float get() = thisRef.getOwnProperty(name + Y_KEY)?.float ?: default
override val z: Float get() = thisRef.getOwnProperty(name + Z_KEY)?.float ?: default
} }
private fun Solid.rotation(): Point3D = override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D) {
rotation ?: Point3D(0.0, 0.0, 0.0).also { rotation = it } thisRef.setProperty(name + X_KEY, value.x)
thisRef.setProperty(name + Y_KEY, value.y)
public var Solid.rotationX: Number thisRef.setProperty(name + Z_KEY, value.z)
get() = rotation?.x ?: 0f }
set(value) {
rotation().x = value.toFloat()
invalidateProperty(Solid.X_ROTATION_KEY)
} }
public var Solid.rotationY: Number public var Solid.position: Point3D by point(POSITION_KEY, 0f)
get() = rotation?.y ?: 0f public var Solid.rotation: Point3D by point(ROTATION_KEY, 0f)
set(value) { public var Solid.scale: Point3D by point(SCALE_KEY, 1f)
rotation().y = value.toFloat()
invalidateProperty(Solid.Y_ROTATION_KEY)
}
public var Solid.rotationZ: Number public var Solid.x: Number by number(X_POSITION_KEY, 0f)
get() = rotation?.z ?: 0f public var Solid.y: Number by number(Y_POSITION_KEY, 0f)
set(value) { public var Solid.z: Number by number(Z_POSITION_KEY, 0f)
rotation().z = value.toFloat()
invalidateProperty(Solid.Z_ROTATION_KEY)
}
private fun Solid.scale(): Point3D = public var Solid.rotationX: Number by number(X_ROTATION_KEY, 0f)
scale ?: Point3D(1.0, 1.0, 1.0).also { scale = it } public var Solid.rotationY: Number by number(Y_ROTATION_KEY, 0f)
public var Solid.rotationZ: Number by number(Z_ROTATION_KEY, 0f)
public var Solid.scaleX: Number public var Solid.scaleX: Number by number(X_SCALE_KEY, 1f)
get() = scale?.x ?: 1f public var Solid.scaleY: Number by number(Y_SCALE_KEY, 1f)
set(value) { public var Solid.scaleZ: Number by number(Z_SCALE_KEY, 1f)
scale().x = value.toFloat()
invalidateProperty(Solid.X_SCALE_KEY)
}
public var Solid.scaleY: Number
get() = scale?.y ?: 1f
set(value) {
scale().y = value.toFloat()
invalidateProperty(Solid.Y_SCALE_KEY)
}
public var Solid.scaleZ: Number
get() = scale?.z ?: 1f
set(value) {
scale().z = value.toFloat()
invalidateProperty(Solid.Z_SCALE_KEY)
}

View File

@ -13,9 +13,9 @@ import space.kscience.visionforge.VisionChange
@Serializable @Serializable
@SerialName("solid") @SerialName("solid")
public open class SolidBase( public open class SolidBase(
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,
) : VisionBase(), Solid { ) : VisionBase(), Solid {
override val descriptor: NodeDescriptor get() = Solid.descriptor override val descriptor: NodeDescriptor get() = Solid.descriptor

View File

@ -29,9 +29,9 @@ public interface PrototypeHolder {
@SerialName("group.solid") @SerialName("group.solid")
public class SolidGroup( public class SolidGroup(
@Serializable(PrototypeSerializer::class) internal var prototypes: MutableVisionGroup? = null, @Serializable(PrototypeSerializer::class) internal var prototypes: MutableVisionGroup? = null,
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,
) : VisionGroupBase(), Solid, PrototypeHolder { ) : VisionGroupBase(), Solid, PrototypeHolder {
init { init {

View File

@ -96,22 +96,22 @@ public class SolidReferenceGroup(
*/ */
private inner class ReferenceChild(private val childName: Name) : SolidReference, VisionGroup { private inner class ReferenceChild(private val childName: Name) : SolidReference, VisionGroup {
//TODO replace by properties // //TODO replace by properties
override var position: Point3D? // override var position: Point3D?
get() = prototype.position // get() = prototype.position
set(_) { // set(_) {
error("Can't set position of reference") // error("Can't set position of reference")
} // }
override var rotation: Point3D? // override var rotation: Point3D?
get() = prototype.rotation // get() = prototype.rotation
set(_) { // set(_) {
error("Can't set position of reference") // error("Can't set position of reference")
} // }
override var scale: Point3D? // override var scale: Point3D?
get() = prototype.scale // get() = prototype.scale
set(_) { // set(_) {
error("Can't set position of reference") // error("Can't set position of reference")
} // }
override val prototype: Solid get() = prototypeFor(childName) override val prototype: Solid get() = prototypeFor(childName)
override val children: Map<NameToken, Vision> override val children: Map<NameToken, Vision>

View File

@ -1,10 +1,14 @@
package space.kscience.visionforge.solid package space.kscience.visionforge.solid
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.Meta import kotlinx.serialization.descriptors.SerialDescriptor
import space.kscience.dataforge.meta.MetaBuilder import kotlinx.serialization.encoding.Decoder
import space.kscience.dataforge.meta.float import kotlinx.serialization.encoding.Encoder
import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.*
import space.kscience.visionforge.solid.Solid.Companion.X_KEY
import space.kscience.visionforge.solid.Solid.Companion.Y_KEY
import space.kscience.visionforge.solid.Solid.Companion.Z_KEY
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.sqrt import kotlin.math.sqrt
@ -17,25 +21,48 @@ public data class Point2D(public var x: Float, public var y: Float)
public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toFloat(), y.toFloat()) public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toFloat(), y.toFloat())
public fun Point2D.toMeta(): Meta = Meta { public fun Point2D.toMeta(): Meta = Meta {
Solid.X_KEY put x X_KEY put x
Solid.Y_KEY put y Y_KEY put y
} }
internal fun Meta.point2D(): Point2D = Point2D(this["x"].float ?: 0f, this["y"].float ?: 0f) internal fun Meta.point2D(): Point2D = Point2D(this["x"].float ?: 0f, this["y"].float ?: 0f)
@Serializable @Serializable(Point3DSerializer::class)
public data class Point3D( public interface Point3D {
public var x: Float, public val x: Float
public var y: Float, public val y: Float
public var z: Float, public val z: Float
) {
public companion object { public companion object {
public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0) public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
public val ONE: Point3D = Point3D(1.0, 1.0, 1.0) public val ONE: Point3D = Point3D(1.0, 1.0, 1.0)
} }
} }
public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3D(x.toFloat(), y.toFloat(), z.toFloat()) @Serializable(Point3DSerializer::class)
public interface MutablePoint3D : Point3D {
override var x: Float
override var y: Float
override var z: Float
}
@Serializable
private class Point3DImpl(override var x: Float, override var y: Float, override var z: Float) : MutablePoint3D
internal object Point3DSerializer : KSerializer<Point3D> {
override val descriptor: SerialDescriptor = Point3DImpl.serializer().descriptor
override fun deserialize(decoder: Decoder): Point3D = decoder.decodeSerializableValue(Point3DImpl.serializer())
override fun serialize(encoder: Encoder, value: Point3D) {
val impl: Point3DImpl = (value as? Point3DImpl) ?: Point3DImpl(value.x, value.y, value.z)
encoder.encodeSerializableValue(Point3DImpl.serializer(), impl)
}
}
public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3DImpl(x.toFloat(), y.toFloat(), z.toFloat())
public operator fun Point3D.plus(other: Point3D): Point3D = Point3D( public operator fun Point3D.plus(other: Point3D): Point3D = Point3D(
this.x + other.x, this.x + other.x,
@ -61,17 +88,21 @@ public infix fun Point3D.cross(other: Point3D): Point3D = Point3D(
x * other.y - y * other.x x * other.y - y * other.x
) )
public fun Point3D.normalizeInPlace(){ public fun MutablePoint3D.normalizeInPlace() {
val norm = sqrt(x.pow(2) + y.pow(2) + z.pow(2)) val norm = sqrt(x.pow(2) + y.pow(2) + z.pow(2))
x /= norm x /= norm
y /= norm y /= norm
z /= norm z /= norm
} }
internal fun Meta.point3D() = Point3D(this["x"].float ?: 0.0, this["y"].float ?: 0.0, this["y"].float ?: 0.0) internal fun ItemProvider.point3D(default: Float = 0f) = object : Point3D {
override val x: Float by float(default)
override val y: Float by float(default)
override val z: Float by float(default)
}
public fun Point3D.toMeta(): MetaBuilder = Meta { public fun Point3D.toMeta(): MetaBuilder = Meta {
Solid.X_KEY put x X_KEY put x
Solid.Y_KEY put y Y_KEY put y
Solid.Z_KEY put z Z_KEY put z
} }

View File

@ -14,18 +14,14 @@ internal fun mergeChild(parent: VisionGroup, child: Vision): Vision {
//parent.properties?.let { config.update(it) } //parent.properties?.let { config.update(it) }
if (this is Solid && parent is Solid) { if (this is Solid && parent is Solid) {
position = (position ?: Point3D.ZERO) + (parent.position ?: Point3D.ZERO) position += parent.position
rotation = (parent.rotation ?: Point3D.ZERO) + (parent.rotation ?: Point3D.ZERO) rotation += parent.rotation
scale = when { scale = Point3D(
scale == null && parent.scale == null -> null scale.x * parent.scale.x,
scale == null -> parent.scale scale.y * parent.scale.y,
parent.scale == null -> scale scale.z * parent.scale.z
else -> Point3D(
scale!!.x * parent.scale!!.x,
scale!!.y * parent.scale!!.y,
scale!!.z * parent.scale!!.z
) )
}
} }
} }

View File

@ -1,3 +1,4 @@
@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "unused")
@file:JsModule("three") @file:JsModule("three")
@file:JsNonModule @file:JsNonModule