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

View File

@ -11,22 +11,14 @@ public expect class Counter() {
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
internal fun Vision.updateFrom(other: Vision): Vision {
if (this is Solid && other is Solid) {
position = position.safePlus(other.position)
rotation = rotation.safePlus(other.rotation)
if (this.scale != null || other.scale != null) {
scaleX = scaleX.toDouble() * other.scaleX.toDouble()
scaleY = scaleY.toDouble() * other.scaleY.toDouble()
scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble()
}
position += other.position
rotation += other.rotation
scaleX = scaleX.toDouble() * other.scaleX.toDouble()
scaleY = scaleY.toDouble() * other.scaleY.toDouble()
scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble()
other.meta.itemSequence().forEach { (name, item) ->
if (getProperty(name) == null) {
setProperty(name, item)

View File

@ -1,9 +1,7 @@
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.enum
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
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.IGNORE_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]
*/
public interface Solid : Vision {
public var position: Point3D?
public var rotation: Point3D?
public var scale: Point3D?
override val descriptor: NodeDescriptor get() = Companion.descriptor
public companion object {
@ -72,7 +83,7 @@ public interface Solid : Vision {
hide()
}
value(DETAIL_KEY){
value(DETAIL_KEY) {
type(ValueType.NUMBER)
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
// set(value) = setProperty(SELECTED_KEY, value)
private fun Solid.position(): Point3D =
position ?: Point3D(0.0, 0.0, 0.0).also { position = it }
internal fun number(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
object : ReadWriteProperty<Solid, Number> {
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
return thisRef.getOwnProperty(name)?.number ?: default
}
public var Solid.x: Number
get() = position?.x ?: 0f
set(value) {
position().x = value.toFloat()
invalidateProperty(Solid.X_POSITION_KEY)
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Number) {
thisRef.setProperty(name, value)
}
}
public var Solid.y: Number
get() = position?.y ?: 0f
set(value) {
position().y = value.toFloat()
invalidateProperty(Solid.Y_POSITION_KEY)
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D> =
object : ReadWriteProperty<Solid, Point3D> {
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D = object : Point3D {
override val x: Float get() = thisRef.getOwnProperty(name + X_KEY)?.float ?: default
override val y: Float get() = thisRef.getOwnProperty(name + Y_KEY)?.float ?: default
override val z: Float get() = thisRef.getOwnProperty(name + Z_KEY)?.float ?: default
}
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D) {
thisRef.setProperty(name + X_KEY, value.x)
thisRef.setProperty(name + Y_KEY, value.y)
thisRef.setProperty(name + Z_KEY, value.z)
}
}
public var Solid.z: Number
get() = position?.z ?: 0f
set(value) {
position().z = value.toFloat()
invalidateProperty(Solid.Z_POSITION_KEY)
}
public var Solid.position: Point3D by point(POSITION_KEY, 0f)
public var Solid.rotation: Point3D by point(ROTATION_KEY, 0f)
public var Solid.scale: Point3D by point(SCALE_KEY, 1f)
private fun Solid.rotation(): Point3D =
rotation ?: Point3D(0.0, 0.0, 0.0).also { rotation = it }
public var Solid.x: Number by number(X_POSITION_KEY, 0f)
public var Solid.y: Number by number(Y_POSITION_KEY, 0f)
public var Solid.z: Number by number(Z_POSITION_KEY, 0f)
public var Solid.rotationX: Number
get() = rotation?.x ?: 0f
set(value) {
rotation().x = value.toFloat()
invalidateProperty(Solid.X_ROTATION_KEY)
}
public var Solid.rotationX: Number by number(X_ROTATION_KEY, 0f)
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.rotationY: Number
get() = rotation?.y ?: 0f
set(value) {
rotation().y = value.toFloat()
invalidateProperty(Solid.Y_ROTATION_KEY)
}
public var Solid.rotationZ: Number
get() = rotation?.z ?: 0f
set(value) {
rotation().z = value.toFloat()
invalidateProperty(Solid.Z_ROTATION_KEY)
}
private fun Solid.scale(): Point3D =
scale ?: Point3D(1.0, 1.0, 1.0).also { scale = it }
public var Solid.scaleX: Number
get() = scale?.x ?: 1f
set(value) {
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)
}
public var Solid.scaleX: Number by number(X_SCALE_KEY, 1f)
public var Solid.scaleY: Number by number(Y_SCALE_KEY, 1f)
public var Solid.scaleZ: Number by number(Z_SCALE_KEY, 1f)

View File

@ -13,9 +13,9 @@ import space.kscience.visionforge.VisionChange
@Serializable
@SerialName("solid")
public open class SolidBase(
override var position: Point3D? = null,
override var rotation: Point3D? = null,
override var scale: Point3D? = null,
// override var position: Point3D? = null,
// override var rotation: Point3D? = null,
// override var scale: Point3D? = null,
) : VisionBase(), Solid {
override val descriptor: NodeDescriptor get() = Solid.descriptor

View File

@ -29,9 +29,9 @@ public interface PrototypeHolder {
@SerialName("group.solid")
public class SolidGroup(
@Serializable(PrototypeSerializer::class) internal var prototypes: MutableVisionGroup? = null,
override var position: Point3D? = null,
override var rotation: Point3D? = null,
override var scale: Point3D? = null,
// override var position: Point3D? = null,
// override var rotation: Point3D? = null,
// override var scale: Point3D? = null,
) : VisionGroupBase(), Solid, PrototypeHolder {
init {

View File

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

View File

@ -1,10 +1,14 @@
package space.kscience.visionforge.solid
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaBuilder
import space.kscience.dataforge.meta.float
import space.kscience.dataforge.meta.get
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
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.pow
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.toMeta(): Meta = Meta {
Solid.X_KEY put x
Solid.Y_KEY put y
X_KEY put x
Y_KEY put y
}
internal fun Meta.point2D(): Point2D = Point2D(this["x"].float ?: 0f, this["y"].float ?: 0f)
@Serializable
public data class Point3D(
public var x: Float,
public var y: Float,
public var z: Float,
) {
@Serializable(Point3DSerializer::class)
public interface Point3D {
public val x: Float
public val y: Float
public val z: Float
public companion object {
public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
public val ONE: Point3D = Point3D(1.0, 1.0, 1.0)
}
}
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(
this.x + other.x,
@ -61,17 +88,21 @@ public infix fun Point3D.cross(other: Point3D): Point3D = Point3D(
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))
x /= norm
y /= 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 {
Solid.X_KEY put x
Solid.Y_KEY put y
Solid.Z_KEY put z
X_KEY put x
Y_KEY put y
Z_KEY put z
}

View File

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