Make solid arguments immutable

This commit is contained in:
Alexander Nozik 2021-07-12 15:22:02 +03:00
parent 5af8fe3e99
commit 0d53b6f77d
17 changed files with 128 additions and 86 deletions

View File

@ -19,6 +19,8 @@
- VisionGroup builder accepts `null` as name for statics instead of `""`
- gdml sphere is rendered as a SphereLayer instead of Sphere (#35)
- Tube is replaced by more general ConeSurface
- position, rotation and size moved to properties
- prototypes moved to children
### Deprecated

View File

@ -27,7 +27,7 @@ fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGro
}
val canvasOptions = Canvas3DOptions {
size{
size {
minSize = 400
}
axes {
@ -57,9 +57,8 @@ fun VisionLayout<Solid>.showcase() {
rotationX = PI / 4
color("blue")
}
sphereLayer(50,40){
theta = (PI/2).toFloat()
rotationX = - PI * 3 / 4
sphereLayer(50, 40, theta = PI / 2) {
rotationX = -PI * 3 / 4
z = 110
color(Colors.pink)
}

View File

@ -23,7 +23,7 @@ internal fun SolidGroup.varBox(
action: VariableBox.() -> Unit = {},
): VariableBox = VariableBox(xSize, ySize).apply(action).also { set(name, it) }
internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeVision() {
internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() {
override fun render(three: ThreePlugin): Object3D {
val geometry = BoxGeometry(xSize, ySize, 1)

View File

@ -1,12 +1,15 @@
package space.kscience.visionforge
import space.kscience.dataforge.meta.Config
import space.kscience.dataforge.meta.MetaItem
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.set
import space.kscience.dataforge.names.Name
/**
* Property containers are used to create a symmetric behaviors for vision properties and style builders
*/
public interface VisionPropertyContainer<out T> {
public interface VisionPropertyContainer<out V: Vision> {
public fun getProperty(
name: Name,
inherit: Boolean = false,
@ -15,4 +18,18 @@ public interface VisionPropertyContainer<out T> {
): MetaItem?
public fun setProperty(name: Name, item: MetaItem?, notify: Boolean = true)
}
public open class SimpleVisionPropertyContainer<out V: Vision>(protected val config: Config): VisionPropertyContainer<V>{
override fun getProperty(
name: Name,
inherit: Boolean,
includeStyles: Boolean,
includeDefaults: Boolean
): MetaItem? = config[name]
override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) {
config[name] = item
}
}

View File

@ -232,11 +232,10 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
bottomRadius = solid.rmax1 * lScale,
height = solid.z * lScale,
upperRadius = solid.rmax2 * lScale,
startAngle = solid.startphi * aScale,
angle = solid.deltaphi * aScale,
name = name
) {
startAngle = solid.startphi * aScale
angle = solid.deltaphi * aScale
}
)
} else {
coneSurface(
bottomOuterRadius = solid.rmax1 * lScale,
@ -244,11 +243,10 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
height = solid.z * lScale,
topOuterRadius = solid.rmax2 * lScale,
topInnerRadius = solid.rmin2 * lScale,
startAngle = solid.startphi * aScale,
angle = solid.deltaphi * aScale,
name = name
) {
startAngle = solid.startphi * aScale
angle = solid.deltaphi * aScale
}
)
}
is GdmlXtru -> extrude(name) {
shape {
@ -276,12 +274,15 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
scaleZ = solid.scale.z.toFloat()
}
}
is GdmlSphere -> sphereLayer(solid.rmax * lScale, solid.rmin * lScale, name) {
phi = solid.deltaphi * aScale
theta = solid.deltatheta * aScale
phiStart = solid.startphi * aScale
thetaStart = solid.starttheta * aScale
}
is GdmlSphere -> sphereLayer(
outerRadius = solid.rmax * lScale,
innerRadius = solid.rmin * lScale,
phi = solid.deltaphi * aScale,
theta = solid.deltatheta * aScale,
phiStart = solid.startphi * aScale,
thetaStart = solid.starttheta * aScale,
name = name,
)
is GdmlOrb -> sphere(solid.r * lScale, name = name)
is GdmlPolyhedra -> extrude(name) {
//getting the radius of first

View File

@ -15,11 +15,11 @@ import kotlin.math.sin
@Serializable
@SerialName("solid.cone")
public class ConeSegment(
public var bottomRadius: Float,
public var height: Float,
public var topRadius: Float,
public var startAngle: Float = 0f,
public var angle: Float = PI2
public val bottomRadius: Float,
public val height: Float,
public val topRadius: Float,
public val startAngle: Float = 0f,
public val angle: Float = PI2
) : SolidBase(), GeometrySolid {
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
@ -83,10 +83,14 @@ public inline fun VisionContainerBuilder<Solid>.cone(
bottomRadius: Number,
height: Number,
upperRadius: Number = 0.0,
startAngle: Number = 0f,
angle: Number = PI2,
name: String? = null,
block: ConeSegment.() -> Unit = {}
): ConeSegment = ConeSegment(
bottomRadius.toFloat(),
height.toFloat(),
topRadius = upperRadius.toFloat()
topRadius = upperRadius.toFloat(),
startAngle = startAngle.toFloat(),
angle = angle.toFloat()
).apply(block).also { set(name, it) }

View File

@ -16,13 +16,13 @@ import kotlin.math.sin
@Serializable
@SerialName("solid.coneSurface")
public class ConeSurface(
public var bottomRadius: Float,
public var bottomInnerRadius: Float,
public var height: Float,
public var topRadius: Float,
public var topInnerRadius: Float,
public var startAngle: Float = 0f,
public var angle: Float = PI2,
public val bottomRadius: Float,
public val bottomInnerRadius: Float,
public val height: Float,
public val topRadius: Float,
public val topInnerRadius: Float,
public val startAngle: Float = 0f,
public val angle: Float = PI2,
) : SolidBase(), GeometrySolid {
init {
@ -148,6 +148,8 @@ public inline fun VisionContainerBuilder<Solid>.coneSurface(
height: Number,
topOuterRadius: Number,
topInnerRadius: Number,
startAngle: Number = 0f,
angle: Number = PI2,
name: String? = null,
block: ConeSurface.() -> Unit = {},
): ConeSurface = ConeSurface(
@ -156,4 +158,6 @@ public inline fun VisionContainerBuilder<Solid>.coneSurface(
height = height.toFloat(),
topRadius = topOuterRadius.toFloat(),
topInnerRadius = topInnerRadius.toFloat(),
startAngle = startAngle.toFloat(),
angle = angle.toFloat()
).apply(block).also { set(name, it) }

View File

@ -2,9 +2,8 @@ package space.kscience.visionforge.solid
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import space.kscience.visionforge.VisionBuilder
import space.kscience.visionforge.VisionContainerBuilder
import space.kscience.visionforge.set
import space.kscience.dataforge.meta.Config
import space.kscience.visionforge.*
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
@ -13,7 +12,7 @@ import kotlin.math.sin
public typealias Shape2D = List<Point2D>
@Serializable
public class Shape2DBuilder(private val points: MutableList<Point2D> = ArrayList()) {
public class Shape2DBuilder(private val points: ArrayList<Point2D> = ArrayList()) {
public fun point(x: Number, y: Number) {
points.add(Point2D(x, y))
@ -38,19 +37,9 @@ public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Flo
@Serializable
@SerialName("solid.extrude")
public class Extruded(
public var shape: List<Point2D> = ArrayList(),
public var layers: MutableList<Layer> = ArrayList()
) : SolidBase(), GeometrySolid {
public fun shape(block: Shape2DBuilder.() -> Unit) {
this.shape = Shape2DBuilder().apply(block).build()
//TODO send invalidation signal
}
public 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
}
public val shape: List<Point2D>,
public val layers: List<Layer>
) : SolidBase(), GeometrySolid, VisionPropertyContainer<Extruded> {
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
val shape: Shape2D = shape
@ -103,6 +92,24 @@ public class Extruded(
}
}
public class ExtrudeBuilder(
public var shape: List<Point2D> = emptyList(),
public var layers: ArrayList<Layer> = ArrayList(),
config: Config = Config()
) : SimpleVisionPropertyContainer<Extruded>(config) {
public fun shape(block: Shape2DBuilder.() -> Unit) {
this.shape = Shape2DBuilder().apply(block).build()
}
public 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()))
}
internal fun build(): Extruded = Extruded(shape, layers).apply { configure(config) }
}
@VisionBuilder
public fun VisionContainerBuilder<Solid>.extrude(name: String? = null, action: Extruded.() -> Unit = {}): Extruded =
Extruded().apply(action).also { set(name, it) }
public fun VisionContainerBuilder<Solid>.extrude(
name: String? = null,
action: ExtrudeBuilder.() -> Unit = {}
): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) }

View File

@ -13,7 +13,7 @@ import space.kscience.visionforge.set
@Serializable
@SerialName("solid.line")
public class PolyLine(public var points: List<Point3D>) : SolidBase(), Solid {
public class PolyLine(public val points: List<Point3D>) : SolidBase(), Solid {
//var lineType by string()
public var thickness: Number by allProperties(inherit = false).number(1.0,

View File

@ -37,6 +37,8 @@ public interface Solid : Vision {
override val descriptor: NodeDescriptor get() = Companion.descriptor
public companion object {
// val SELECTED_KEY = "selected".asName()
public val DETAIL_KEY: Name = "detail".asName()

View File

@ -2,11 +2,7 @@ package space.kscience.visionforge.solid
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.meta.float
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.node
import space.kscience.visionforge.VisionBase
import space.kscience.visionforge.VisionChange
@ -20,15 +16,3 @@ public open class SolidBase : VisionBase(), Solid {
super.update(change)
}
}
internal fun Meta.toVector(default: Float = 0f) = Point3D(
this[Solid.X_KEY].float ?: default,
this[Solid.Y_KEY].float ?: default,
this[Solid.Z_KEY].float ?: default
)
internal fun Solid.updatePosition(meta: Meta?) {
meta[Solid.POSITION_KEY].node?.toVector()?.let { position = it }
meta[Solid.ROTATION_KEY].node?.toVector()?.let { rotation = it }
meta[Solid.SCALE_KEY].node?.toVector(1f)?.let { scale = it }
}

View File

@ -9,9 +9,9 @@ import space.kscience.visionforge.set
@Serializable
@SerialName("solid.label")
public class SolidLabel(
public var text: String,
public var fontSize: Double,
public var fontFamily: String,
public val text: String,
public val fontSize: Double,
public val fontFamily: String,
) : SolidBase(), Solid
@VisionBuilder

View File

@ -4,6 +4,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import space.kscience.visionforge.VisionBuilder
import space.kscience.visionforge.VisionContainerBuilder
import space.kscience.visionforge.VisionPropertyContainer
import space.kscience.visionforge.set
import kotlin.math.PI
import kotlin.math.cos
@ -12,12 +13,12 @@ import kotlin.math.sin
@Serializable
@SerialName("solid.sphere")
public class Sphere(
public var radius: Float,
public var phiStart: Float = 0f,
public var phi: Float = PI2,
public var thetaStart: Float = 0f,
public var theta: Float = PI.toFloat(),
) : SolidBase(), GeometrySolid {
public val radius: Float,
public val phiStart: Float = 0f,
public val phi: Float = PI2,
public val thetaStart: Float = 0f,
public val theta: Float = PI.toFloat(),
) : SolidBase(), GeometrySolid, VisionPropertyContainer<Sphere> {
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
fun point3DfromSphCoord(r: Float, theta: Float, phi: Float): Point3D {

View File

@ -15,12 +15,12 @@ import kotlin.math.sin
@Serializable
@SerialName("solid.sphereLayer")
public class SphereLayer(
public var outerRadius: Float,
public var innerRadius: Float,
public var phiStart: Float = 0f,
public var phi: Float = PI2,
public var thetaStart: Float = 0f,
public var theta: Float = PI.toFloat(),
public val outerRadius: Float,
public val innerRadius: Float,
public val phiStart: Float = 0f,
public val phi: Float = PI2,
public val thetaStart: Float = 0f,
public val theta: Float = PI.toFloat(),
) : SolidBase(), GeometrySolid {
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>): Unit = geometryBuilder.run {
@ -72,9 +72,17 @@ public class SphereLayer(
public inline fun VisionContainerBuilder<Solid>.sphereLayer(
outerRadius: Number,
innerRadius: Number,
phiStart: Number = 0f,
phi: Number = PI2,
thetaStart: Number = 0f,
theta: Number = PI.toFloat(),
name: String? = null,
action: SphereLayer.() -> Unit = {},
): SphereLayer = SphereLayer(
outerRadius.toFloat(),
innerRadius.toFloat(),
phiStart.toFloat(),
phi.toFloat(),
thetaStart.toFloat(),
theta.toFloat()
).apply(action).also { set(name, it) }

View File

@ -105,4 +105,17 @@ public fun Point3D.toMeta(): MetaBuilder = Meta {
X_KEY put x
Y_KEY put y
Z_KEY put z
}
internal fun Meta.toVector(default: Float = 0f) = Point3D(
this[Solid.X_KEY].float ?: default,
this[Solid.Y_KEY].float ?: default,
this[Solid.Z_KEY].float ?: default
)
internal fun Solid.updatePosition(meta: Meta?) {
meta[Solid.POSITION_KEY].node?.toVector()?.let { position = it }
meta[Solid.ROTATION_KEY].node?.toVector()?.let { rotation = it }
meta[Solid.SCALE_KEY].node?.toVector(1f)?.let { scale = it }
}

View File

@ -6,6 +6,6 @@ import space.kscience.visionforge.solid.SolidBase
/**
* A custom visual object that has its own Three.js renderer
*/
public abstract class ThreeVision : SolidBase() {
public abstract class ThreeJsVision : SolidBase() {
public abstract fun render(three: ThreePlugin): Object3D
}

View File

@ -49,7 +49,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
}
public fun buildObject3D(obj: Solid): Object3D = when (obj) {
is ThreeVision -> obj.render(this)
is ThreeJsVision -> obj.render(this)
is SolidReferenceGroup -> ThreeReferenceFactory(this, obj)
is SolidGroup -> {
val group = ThreeGroup()