feature/root #69

Merged
altavir merged 23 commits from feature/root into dev 2021-09-11 19:14:21 +03:00
14 changed files with 207 additions and 107 deletions
Showing only changes of commit 2e3b63c0f4 - Show all commits

View File

@ -105,6 +105,8 @@ public class DGeoVolume(meta: Meta, refCache: DObjectCache) : DNamed(meta, refCa
public val fShape: DGeoShape? by dObject(::DGeoShape) public val fShape: DGeoShape? by dObject(::DGeoShape)
public val fMedium: DGeoMedium? by dObject(::DGeoMedium) public val fMedium: DGeoMedium? by dObject(::DGeoMedium)
public val fFillColor: Int? by meta.int()
override val name: Name by lazy { Name.parse(fName.ifEmpty { "volume[${meta.hashCode().toUInt()}]" }) } override val name: Name by lazy { Name.parse(fName.ifEmpty { "volume[${meta.hashCode().toUInt()}]" }) }
} }

View File

@ -1,12 +1,11 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.isEmpty
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import space.kscience.dataforge.values.doubleArray
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
import kotlin.math.* import kotlin.math.*
private val volumesName = Name.EMPTY //"volumes".asName() private val volumesName = Name.EMPTY //"volumes".asName()
@ -50,9 +49,8 @@ private fun Solid.useMatrix(matrix: DGeoMatrix?) {
val fTranslation by matrix.meta.doubleArray() val fTranslation by matrix.meta.doubleArray()
translate(fTranslation) translate(fTranslation)
if (matrix.meta["fRotationMatrix"] != null) { matrix.meta["fRotation.fRotationMatrix"]?.value?.let {
val fRotationMatrix by matrix.meta.doubleArray() rotate(it.doubleArray)
rotate(fRotationMatrix)
} }
} }
"TGeoHMatrix" -> { "TGeoHMatrix" -> {
@ -77,15 +75,15 @@ private fun SolidGroup.addShape(
val compositeType = when (node.typename) { val compositeType = when (node.typename) {
"TGeoIntersection" -> CompositeType.INTERSECT "TGeoIntersection" -> CompositeType.INTERSECT
"TGeoSubtraction" -> CompositeType.SUBTRACT "TGeoSubtraction" -> CompositeType.SUBTRACT
"TGeoUnion" -> CompositeType.UNION "TGeoUnion" -> CompositeType.GROUP
else -> error("Unknown bool node type ${node.typename}") else -> error("Unknown bool node type ${node.typename}")
} }
composite(compositeType, name = name) { smartComposite(compositeType, name = name) {
addShape(node.fLeft!!, context, "left").also { addShape(node.fLeft!!, context, null).also {
if (it == null) TODO() if (it == null) TODO()
it.useMatrix(node.fLeftMat) it.useMatrix(node.fLeftMat)
} }
addShape(node.fRight!!, context, "right").also { addShape(node.fRight!!, context, null).also {
if (it == null) TODO() if (it == null) TODO()
it.useMatrix(node.fRightMat) it.useMatrix(node.fRightMat)
} }
@ -277,7 +275,11 @@ private fun SolidGroup.addRootVolume(
} }
} }
return ref(templateName, name) ref(templateName, name)
}.apply {
volume.fFillColor?.let {
meta[MATERIAL_COLOR_KEY] = RootColors[it]
}
} }
} }

View File

@ -0,0 +1,42 @@
package ru.mipt.npm.root
public object RootColors {
private val colorMap = Array<String>(924) { "white" }
//colorMap[110] = "white"
private val moreCol = listOf(
11 to "c1b7ad4d4d4d6666668080809a9a9ab3b3b3cdcdcde6e6e6f3f3f3cdc8accdc8acc3c0a9bbb6a4b3a697b8a49cae9a8d9c8f83886657b1cfc885c3a48aa9a1839f8daebdc87b8f9a768a926983976e7b857d9ad280809caca6c0d4cf88dfbb88bd9f83c89a7dc08378cf5f61ac8f94a6787b946971d45a549300ff7b00ff6300ff4b00ff3300ff1b00ff0300ff0014ff002cff0044ff005cff0074ff008cff00a4ff00bcff00d4ff00ecff00fffd00ffe500ffcd00ffb500ff9d00ff8500ff6d00ff5500ff3d00ff2600ff0e0aff0022ff003aff0052ff006aff0082ff009aff00b1ff00c9ff00e1ff00f9ff00ffef00ffd700ffbf00ffa700ff8f00ff7700ff6000ff4800ff3000ff1800ff0000",
201 to "5c5c5c7b7b7bb8b8b8d7d7d78a0f0fb81414ec4848f176760f8a0f14b81448ec4876f1760f0f8a1414b84848ec7676f18a8a0fb8b814ecec48f1f1768a0f8ab814b8ec48ecf176f10f8a8a14b8b848ecec76f1f1",
390 to "ffffcdffff9acdcd9affff66cdcd669a9a66ffff33cdcd339a9a33666633ffff00cdcd009a9a00666600333300",
406 to "cdffcd9aff9a9acd9a66ff6666cd66669a6633ff3333cd33339a3333663300ff0000cd00009a00006600003300",
422 to "cdffff9affff9acdcd66ffff66cdcd669a9a33ffff33cdcd339a9a33666600ffff00cdcd009a9a006666003333",
590 to "cdcdff9a9aff9a9acd6666ff6666cd66669a3333ff3333cd33339a3333660000ff0000cd00009a000066000033",
606 to "ffcdffff9affcd9acdff66ffcd66cd9a669aff33ffcd33cd9a339a663366ff00ffcd00cd9a009a660066330033",
622 to "ffcdcdff9a9acd9a9aff6666cd66669a6666ff3333cd33339a3333663333ff0000cd00009a0000660000330000",
791 to "ffcd9acd9a669a66339a6600cd9a33ffcd66ff9a00ffcd33cd9a00ffcd00ff9a33cd66006633009a3300cd6633ff9a66ff6600ff6633cd3300ff33009aff3366cd00336600339a0066cd339aff6666ff0066ff3333cd0033ff00cdff9a9acd66669a33669a009acd33cdff669aff00cdff339acd00cdff009affcd66cd9a339a66009a6633cd9a66ffcd00ff6633ffcd00cd9a00ffcd33ff9a00cd66006633009a3333cd6666ff9a00ff9a33ff6600cd3300ff339acdff669acd33669a00339a3366cd669aff0066ff3366ff0033cd0033ff339aff0066cd00336600669a339acd66cdff009aff33cdff009acd00cdffcd9aff9a66cd66339a66009a9a33cdcd66ff9a00ffcd33ff9a00cdcd00ff9a33ff6600cd33006633009a6633cd9a66ff6600ff6633ff3300cd3300ffff339acd00666600339a0033cd3366ff669aff0066ff3366cd0033ff0033ff9acdcd669a9a33669a0066cd339aff66cdff009acd009aff33cdff009a",
920 to "cdcdcd9a9a9a666666333333"
)
init {
colorMap[0] = "white"
colorMap[1] = "black"
colorMap[2] = "red"
colorMap[3] = "green"
colorMap[4] = "blue"
colorMap[5] = "yellow"
colorMap[6] = "magenta"
colorMap[7] = "cyan"
colorMap[8] = "rgb(89,212,84)"
colorMap[9] = "rgb(89,84,217)"
colorMap[10] = "white"
moreCol.forEach { (n, s) ->
for (i in 0 until (s.length / 6)) {
colorMap[n + i] = "#" + s.substring(i * 6, (i + 1) * 6)
}
}
}
public operator fun get(index: Int): String = colorMap[index]
}

View File

@ -1,72 +0,0 @@
package ru.mipt.npm.root
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive
import ru.mipt.npm.root.serialization.TGeoManager
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.values.string
import space.kscience.visionforge.solid.Solids
import java.nio.file.Paths
import java.time.Duration
import kotlin.io.path.writeText
import kotlin.system.measureTimeMillis
private fun JsonElement.countTypes(): Sequence<String> = sequence {
when (val json = this@countTypes) {
is JsonObject -> {
json["_typename"]?.let { yield(it.jsonPrimitive.content) }
json.values.forEach { yieldAll(it.countTypes()) }
}
is JsonArray -> {
json.forEach {
yieldAll(it.countTypes())
}
}
else -> {
}
}
}
private fun Meta.countTypes() :Sequence<String> = sequence {
if(!isLeaf){
get("_typename")?.value?.let { yield(it.string) }
items.forEach { yieldAll(it.value.countTypes()) }
}
}
fun main() {
val string = TGeoManager::class.java.getResourceAsStream("/BM@N.root.json")!!
.readAllBytes().decodeToString()
val time = measureTimeMillis {
val geo = DGeoManager.parse(string)
val sizes = geo.meta.countTypes().groupBy { it }.mapValues { it.value.size }
sizes.forEach {
println(it)
}
val solid = geo.toSolid()
Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid))
//println(Solids.encodeToString(solid))
}
// val json = Json.parseToJsonElement(string)
// val sizes = json.countTypes().groupBy { it }.mapValues { it.value.size }
// sizes.forEach {
// println(it)
// }
//
// val time = measureTimeMillis {
// val geo = TObject.decodeFromString(TGeoManager.serializer(), string)
// val solid = geo.toSolid()
//
// println(Solids.encodeToString(solid))
// }
//
println(Duration.ofMillis(time))
}

View File

@ -55,6 +55,7 @@ kotlin {
api(project(":visionforge-gdml")) api(project(":visionforge-gdml"))
api(project(":visionforge-plotly")) api(project(":visionforge-plotly"))
api(projects.visionforge.visionforgeMarkdown) api(projects.visionforge.visionforgeMarkdown)
api(projects.visionforge.cernRootLoader)
} }
} }

View File

@ -0,0 +1,104 @@
package space.kscience.visionforge.examples
import ru.mipt.npm.root.DGeoManager
import ru.mipt.npm.root.serialization.TGeoManager
import ru.mipt.npm.root.toSolid
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.values.string
import space.kscience.visionforge.solid.Solids
private fun Meta.countTypes(): Sequence<String> = sequence {
if (!isLeaf) {
get("_typename")?.value?.let { yield(it.string) }
items.forEach { yieldAll(it.value.countTypes()) }
}
}
fun main() {
val context = Context {
plugin(Solids)
}
val string = TGeoManager::class.java.getResourceAsStream("/root/BM@N.root.json")!!
.readAllBytes().decodeToString()
val geo = DGeoManager.parse(string)
val sizes = geo.meta.countTypes().groupBy { it }.mapValues { it.value.size }
sizes.forEach {
println(it)
}
val solid = geo.toSolid()
//Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid))
//println(Solids.encodeToString(solid))
context.makeVisionFile {
vision("canvas") {
solid
/* SolidGroup {
set(
"Coil",
solid.getPrototype("Coil".asName())!!.apply {
parent = null
}
)
*//* group("Shade") {
y = 200
color("red")
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(79.6, 0, -122.1)
rotation = Point3D(-1.5707964, 0, 0)
}
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(-79.6, 0, -122.1)
rotation = Point3D(1.5707964, 0, -3.1415927)
}
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(79.6, 0, 122.1)
rotation = Point3D(1.5707964, 0, 0)
}
coneSurface(
bottomOuterRadius = 135,
bottomInnerRadius = 25,
height = 50,
topOuterRadius = 135,
topInnerRadius = 25,
angle = 1.5707964
) {
position = Point3D(-79.6, 0, 122.1)
rotation = Point3D(-1.5707964, 0, -3.1415927)
}
}*//*
}*/
}
}
}

View File

@ -48,7 +48,7 @@ public class FXCompositeFactory(public val plugin: FX3DPlugin) : FX3DFactory<Com
val firstCSG = first.toCSG() val firstCSG = first.toCSG()
val secondCSG = second.toCSG() val secondCSG = second.toCSG()
val resultCSG = when (obj.compositeType) { val resultCSG = when (obj.compositeType) {
CompositeType.SUM, CompositeType.UNION -> firstCSG.union(secondCSG) CompositeType.GROUP, CompositeType.UNION -> firstCSG.union(secondCSG)
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG) CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
CompositeType.SUBTRACT -> firstCSG.difference(secondCSG) CompositeType.SUBTRACT -> firstCSG.difference(secondCSG)
} }

View File

@ -215,12 +215,12 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
val first: GdmlSolid = solid.first.resolve(root) ?: error("") val first: GdmlSolid = solid.first.resolve(root) ?: error("")
val second: GdmlSolid = solid.second.resolve(root) ?: error("") val second: GdmlSolid = solid.second.resolve(root) ?: error("")
val type: CompositeType = when (solid) { val type: CompositeType = when (solid) {
is GdmlUnion -> CompositeType.SUM // dumb sum for better performance is GdmlUnion -> CompositeType.GROUP // dumb sum for better performance
is GdmlSubtraction -> CompositeType.SUBTRACT is GdmlSubtraction -> CompositeType.SUBTRACT
is GdmlIntersection -> CompositeType.INTERSECT is GdmlIntersection -> CompositeType.INTERSECT
} }
return composite(type, name) { return smartComposite(type, name) {
addSolid(root, first).withPosition( addSolid(root, first).withPosition(
solid.resolveFirstPosition(root), solid.resolveFirstPosition(root),
solid.resolveFirstRotation(root), solid.resolveFirstRotation(root),

View File

@ -2,6 +2,7 @@ package space.kscience.visionforge.solid
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.isEmpty
import space.kscience.dataforge.meta.update import space.kscience.dataforge.meta.update
import space.kscience.visionforge.VisionBuilder import space.kscience.visionforge.VisionBuilder
import space.kscience.visionforge.VisionContainerBuilder import space.kscience.visionforge.VisionContainerBuilder
@ -9,7 +10,7 @@ import space.kscience.visionforge.VisionPropertyContainer
import space.kscience.visionforge.set import space.kscience.visionforge.set
public enum class CompositeType { public enum class CompositeType {
SUM, // Dumb sum of meshes GROUP, // Dumb sum of meshes
UNION, //CSG union UNION, //CSG union
INTERSECT, INTERSECT,
SUBTRACT SUBTRACT
@ -50,6 +51,31 @@ public inline fun VisionContainerBuilder<Solid>.composite(
return res return res
} }
/**
* A smart form of [Composite] that in case of [CompositeType.GROUP] creates a static group instead
*/
@VisionBuilder
public fun SolidGroup.smartComposite(
type: CompositeType,
name: String? = null,
builder: SolidGroup.() -> Unit,
): Solid = if (type == CompositeType.GROUP) {
val group = SolidGroup(builder)
if (name == null && group.meta.isEmpty()) {
//append directly to group if no properties are defined
group.children.forEach { (key, value) ->
value.parent = null
set(null, value)
}
this
} else {
set(name, group)
group
}
} else {
composite(type, name, builder)
}
@VisionBuilder @VisionBuilder
public inline fun VisionContainerBuilder<Solid>.union( public inline fun VisionContainerBuilder<Solid>.union(
name: String? = null, name: String? = null,

View File

@ -82,8 +82,8 @@ public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
@VisionBuilder @VisionBuilder
public fun VisionContainerBuilder<Vision>.group( public fun VisionContainerBuilder<Vision>.group(
name: Name? = null, name: Name? = null,
action: SolidGroup.() -> Unit = {}, builder: SolidGroup.() -> Unit = {},
): SolidGroup = SolidGroup().apply(action).also { set(name, it) } ): SolidGroup = SolidGroup().apply(builder).also { set(name, it) }
/** /**
* Define a group with given [name], attach it to this parent and return it. * Define a group with given [name], attach it to this parent and return it.

View File

@ -5,5 +5,5 @@ plugins {
dependencies { dependencies {
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
implementation(npm("three", "0.130.1")) implementation(npm("three", "0.130.1"))
implementation(npm("three-csg-ts", "3.1.6")) implementation(npm("three-csg-ts", "3.1.9"))
} }

View File

@ -167,7 +167,7 @@ public class ThreeCanvas(
} }
//Clipping planes //Clipping planes
options.useProperty(Canvas3DOptions::clipping){clipping -> options.useProperty(Canvas3DOptions::clipping) { clipping ->
if (!clipping.meta.isEmpty()) { if (!clipping.meta.isEmpty()) {
renderer.localClippingEnabled = true renderer.localClippingEnabled = true
boundingBox?.let { boundingBox -> boundingBox?.let { boundingBox ->
@ -192,7 +192,7 @@ public class ThreeCanvas(
} }
} }
options.useProperty(Canvas3DOptions::size){ options.useProperty(Canvas3DOptions::size) {
canvas.style.apply { canvas.style.apply {
minWidth = "${options.size.minWith.toInt()}px" minWidth = "${options.size.minWith.toInt()}px"
maxWidth = "${options.size.maxWith.toInt()}px" maxWidth = "${options.size.maxWith.toInt()}px"
@ -273,18 +273,14 @@ public class ThreeCanvas(
return return
} }
if (this is Mesh) { if (this is Mesh) {
if (highlight) { val edges = getObjectByName(edgesName) ?: LineSegments(
val edges = LineSegments(
EdgesGeometry(geometry), EdgesGeometry(geometry),
material material
).apply { ).also {
name = edgesName it.name = edgesName
} add(it)
add(edges)
} else {
val highlightEdges = children.find { it.name == edgesName }
highlightEdges?.let { remove(it) }
} }
edges.visible = highlight
} else { } else {
children.filter { it.name != edgesName }.forEach { children.filter { it.name != edgesName }.forEach {
it.toggleHighlight(highlight, edgesName, material) it.toggleHighlight(highlight, edgesName, material)

View File

@ -1,7 +1,6 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import CSG import CSG
import info.laht.threekt.core.Object3D
import info.laht.threekt.objects.Mesh import info.laht.threekt.objects.Mesh
import space.kscience.dataforge.names.startsWith import space.kscience.dataforge.names.startsWith
import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.onPropertyChange
@ -38,11 +37,11 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory
override val type: KClass<in Composite> get() = Composite::class override val type: KClass<in Composite> get() = Composite::class
override fun invoke(three: ThreePlugin, obj: Composite): Object3D { override fun invoke(three: ThreePlugin, obj: Composite): Mesh {
val first = three.buildObject3D(obj.first) as? Mesh ?: error("First part of composite is not a mesh") val first = three.buildObject3D(obj.first) as? Mesh ?: error("First part of composite is not a mesh")
val second = three.buildObject3D(obj.second) as? Mesh ?: error("Second part of composite is not a mesh") val second = three.buildObject3D(obj.second) as? Mesh ?: error("Second part of composite is not a mesh")
return when (obj.compositeType) { return when (obj.compositeType) {
CompositeType.SUM, CompositeType.UNION -> CSG.union(first, second) CompositeType.GROUP, CompositeType.UNION -> CSG.union(first, second)
CompositeType.INTERSECT -> CSG.intersect(first, second) CompositeType.INTERSECT -> CSG.intersect(first, second)
CompositeType.SUBTRACT -> CSG.subtract(first, second) CompositeType.SUBTRACT -> CSG.subtract(first, second)
}.apply { }.apply {