initial commit

This commit is contained in:
Alexander Nozik 2019-03-08 11:55:01 +03:00
commit 4db090c240
32 changed files with 1918 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.idea/
*.iws
out/
.gradle
build/
!gradle-wrapper.jar
gradle.properties

145
build.gradle.kts Normal file
View File

@ -0,0 +1,145 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
val kotlinVersion: String by rootProject.extra("1.3.21")
val ioVersion: String by rootProject.extra("0.1.5")
val coroutinesVersion: String by rootProject.extra("1.1.1")
val atomicfuVersion: String by rootProject.extra("0.12.1")
val dokkaVersion: String by rootProject.extra("0.9.17")
val serializationVersion: String by rootProject.extra("0.10.0")
val dataforgeVersion: String by rootProject.extra("0.1.1-dev-5")
repositories {
jcenter()
maven("https://dl.bintray.com/kotlin/kotlin-eap")
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("org.jfrog.buildinfo:build-info-extractor-gradle:4+")
classpath("com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4")
classpath("org.jetbrains.dokka:dokka-gradle-plugin:$dokkaVersion")
classpath("org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.45")
classpath("org.openjfx:javafx-plugin:0.0.7")
}
}
plugins {
id("com.jfrog.artifactory") version "4.8.1" apply false
// id("org.jetbrains.kotlin.multiplatform") apply false
}
allprojects {
apply(plugin = "maven")
apply(plugin = "maven-publish")
apply(plugin = "com.jfrog.artifactory")
repositories {
jcenter()
maven("https://kotlin.bintray.com/kotlinx")
maven("http://npm.mipt.ru:8081/artifactory/gradle-dev")
}
group = "hep.dataforge"
version = "0.0.1-dev-1"
// apply bintray configuration
apply(from = "${rootProject.rootDir}/gradle/bintray.gradle")
//apply artifactory configuration
apply(from = "${rootProject.rootDir}/gradle/artifactory.gradle")
}
subprojects {
// dokka {
// outputFormat = "html"
// outputDirectory = javadoc.destinationDir
// }
//
// task dokkaJar (type: Jar, dependsOn: dokka) {
// from javadoc . destinationDir
// classifier = "javadoc"
// }
// Create empty jar for sources classifier to satisfy maven requirements
val stubSources by tasks.registering(Jar::class) {
archiveClassifier.set("sources")
//from(sourceSets.main.get().allSource)
}
// Create empty jar for javadoc classifier to satisfy maven requirements
val stubJavadoc by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}
afterEvaluate {
extensions.findByType<KotlinMultiplatformExtension>()?.apply {
jvm {
compilations.all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
js {
compilations.all {
tasks.getByName(compileKotlinTaskName) {
kotlinOptions {
metaInfo = true
sourceMap = true
sourceMapEmbedSources = "always"
moduleKind = "umd"
}
}
}
configure(listOf(compilations["main"])) {
tasks.getByName(compileKotlinTaskName) {
kotlinOptions {
main = "call"
}
}
}
}
targets.all {
sourceSets.all {
languageSettings.progressiveMode = true
}
}
configure<PublishingExtension> {
publications.filterIsInstance<MavenPublication>().forEach { publication ->
if (publication.name == "kotlinMultiplatform") {
// for our root metadata publication, set artifactId with a package and project name
publication.artifactId = project.name
} else {
// for targets, set artifactId with a package, project name and target name (e.g. iosX64)
publication.artifactId = "${project.name}-${publication.name}"
}
}
targets.all {
val publication = publications.findByName(name) as MavenPublication
// Patch publications with fake javadoc
publication.artifact(stubJavadoc.get())
}
}
}
}
}

View File

@ -0,0 +1,30 @@
plugins {
kotlin("multiplatform")
}
val dataforgeVersion: String by rootProject.extra
kotlin {
jvm()
js()
sourceSets {
val commonMain by getting {
dependencies {
api("hep.dataforge:dataforge-io:$dataforgeVersion")
api("hep.dataforge:dataforge-io-metadata:$dataforgeVersion")
}
}
val jvmMain by getting {
dependencies {
api("hep.dataforge:dataforge-io-jvm:$dataforgeVersion")
//api("no.tornado:tornadofx:1.7.18")
}
}
val jsMain by getting {
dependencies {
api("hep.dataforge:dataforge-io-js:$dataforgeVersion")
}
}
}
}

View File

@ -0,0 +1,150 @@
package hep.dataforge.vis
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vis.DisplayObject.Companion.DEFAULT_TYPE
import hep.dataforge.vis.DisplayObject.Companion.META_KEY
import hep.dataforge.vis.DisplayObject.Companion.TAGS_KEY
/**
* A root type for display hierarchy
*/
interface DisplayObject {
/**
* The parent object of this one. If null, this one is a root.
*/
val parent: DisplayObject?
/**
* The type of this object. Uses `.` notation. Empty type means untyped group
*/
val type: String
val properties: Styled
companion object {
const val DEFAULT_TYPE = ""
const val TYPE_KEY = "@type"
const val CHILDREN_KEY = "@children"
const val META_KEY = "@meta"
const val TAGS_KEY = "@tags"
}
}
interface DisplayGroup : DisplayObject {
val children: List<DisplayObject>
/**
* Add a child object and notify listeners
*/
fun addChild(obj: DisplayObject)
/**
* Remove a specific child and notify listeners
*/
fun removeChild(obj: DisplayObject)
/**
* Add listener for children change
* TODO add detailed information into change listener
*/
fun onChildrenChange(owner: Any? = null, action: () -> Unit)
/**
* Remove children change listener
*/
fun removeChildrenChangeListener(owner: Any? = null)
}
/**
* Get the property of this display object of parent's if not found
*/
tailrec operator fun DisplayObject.get(name: Name): MetaItem<*>? = properties[name] ?: parent?.get(name)
operator fun DisplayObject.get(name: String) = get(name.toName())
/**
* A change listener for [DisplayObject] configuration.
*/
fun DisplayObject.onChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
properties.style.onChange(owner, action)
parent?.onChange(owner, action)
}
/**
* Remove all meta listeners with matching owners
*/
fun DisplayObject.removeChangeListener(owner: Any?) {
properties.style.removeListener(owner)
parent?.removeChangeListener(owner)
}
/**
* Additional meta not relevant to display
*/
val DisplayObject.meta: Meta get() = properties[META_KEY]?.node ?: EmptyMeta
val DisplayObject.tags: List<String> get() = properties[TAGS_KEY].stringList
internal data class ObjectListener(
val owner: Any?,
val action: () -> Unit
)
/**
* Basic group of display objects
*/
open class DisplayNode(
override val parent: DisplayObject? = null,
override val type: String = DEFAULT_TYPE,
meta: Meta = EmptyMeta
) : DisplayGroup {
private val _children = ArrayList<DisplayObject>()
override val children: List<DisplayObject> get() = _children
override val properties = Styled(meta)
private val listeners = HashSet<ObjectListener>()
override fun addChild(obj: DisplayObject) {
// val before = _children[name]
// if (obj == null) {
// _children.remove(name)
// } else {
// _children[name] = obj
// }
// listeners.forEach { it.action(name, before, obj) }
_children.add(obj)
listeners.forEach { it.action() }
}
override fun removeChild(obj: DisplayObject) {
if (_children.remove(obj)) {
listeners.forEach { it.action }
}
}
override fun onChildrenChange(owner: Any?, action: () -> Unit) {
listeners.add(ObjectListener(owner, action))
}
override fun removeChildrenChangeListener(owner: Any?) {
listeners.removeAll { it.owner === owner }
}
}
/**
* Basic [DisplayObject] leaf element
*/
open class DisplayLeaf(
override val parent: DisplayObject?,
override val type: String,
meta: Meta = EmptyMeta
) : DisplayObject {
final override val properties = Styled(meta)
}

View File

@ -0,0 +1,120 @@
package hep.dataforge.vis
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.values.Value
import kotlin.jvm.JvmName
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* A delegate for display object properties
*/
class DisplayObjectDelegate(
val key: Name?,
val default: MetaItem<*>?,
val inherited: Boolean
) : ReadWriteProperty<DisplayObject, MetaItem<*>?> {
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): MetaItem<*>? {
val name = key ?: property.name.toName()
return if (inherited) {
thisRef[name]
} else {
thisRef.properties[name]
} ?: default
}
override fun setValue(thisRef: DisplayObject, property: KProperty<*>, value: MetaItem<*>?) {
val name = key ?: property.name.toName()
thisRef.properties.style[name] = value
}
}
class DisplayObjectDelegateWrapper<T>(
val key: Name?,
val default: T,
val inherited: Boolean,
val write: Config.(name: Name, value: T) -> Unit = { name, value -> set(name, value) },
val read: (MetaItem<*>?) -> T?
) : ReadWriteProperty<DisplayObject, T> {
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T {
val name = key ?: property.name.toName()
return if (inherited) {
read(thisRef[name])
} else {
read(thisRef.properties[name])
} ?: default
}
override fun setValue(thisRef: DisplayObject, property: KProperty<*>, value: T) {
val name = key ?: property.name.toName()
thisRef.properties.style.write(name, value)
}
}
fun DisplayObject.value(default: Value? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.value }
fun DisplayObject.string(default: String? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.string }
fun DisplayObject.boolean(default: Boolean? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.boolean }
fun DisplayObject.number(default: Number? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.number }
fun DisplayObject.double(default: Double? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
fun DisplayObject.int(default: Int? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.int }
fun DisplayObject.node(key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it.node }
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
@JvmName("safeString")
fun DisplayObject.string(default: String, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.string }
@JvmName("safeBoolean")
fun DisplayObject.boolean(default: Boolean, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.boolean }
@JvmName("safeNumber")
fun DisplayObject.number(default: Number, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.number }
@JvmName("safeDouble")
fun DisplayObject.double(default: Double, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
inline fun <reified E : Enum<E>> DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
//merge properties
fun <T> DisplayObject.merge(
key: String? = null,
transformer: (Sequence<MetaItem<*>>) -> T
): ReadOnlyProperty<DisplayObject, T> {
return object : ReadOnlyProperty<DisplayObject, T> {
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T {
val name = key?.toName() ?: property.name.toName()
val sequence = sequence<MetaItem<*>> {
var thisObj: DisplayObject? = thisRef
while (thisObj != null) {
thisObj.properties[name]?.let { yield(it) }
thisObj = thisObj.parent
}
}
return transformer(sequence)
}
}
}

View File

@ -0,0 +1,40 @@
package hep.dataforge.vis
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
interface NamedObject : DisplayObject {
val name: String
operator fun get(nameToken: NameToken): DisplayGroup?
operator fun set(nameToken: NameToken, group: DisplayGroup)
}
/**
* Recursively get a child
*/
tailrec operator fun NamedObject.get(name: Name): DisplayObject? = when (name.length) {
0 -> this
1 -> this[name[0]]
else -> name.first()?.let { this[it] as? NamedObject }?.get(name.cutFirst())
}
/**
* Set given object creating intermediate empty groups if needed
* @param name - the full name of a child
* @param objFactory - a function that creates child object from parent (to avoid mutable parent parameter)
*/
fun NamedObject.set(name: Name, objFactory: (parent: DisplayObject) -> DisplayGroup): Unit = when (name.length) {
0 -> error("Can't set object with empty name")
1 -> set(name[0], objFactory(this))
else -> (this[name.first()!!] ?: DisplayNode(this))
.run {
if (this is NamedObject) {
this.set(name.cutFirst(), objFactory)
} else {
error("Can't assign child to a leaf element $this")
}
}
}

View File

@ -0,0 +1,16 @@
import org.openjfx.gradle.JavaFXOptions
plugins {
kotlin("jvm")
id("org.openjfx.javafxplugin")
}
dependencies {
api(project(":dataforge-vis-spatial"))
api("no.tornado:tornadofx:1.7.18")
implementation("org.fxyz3d:fxyz3d:0.4.0")
}
configure<JavaFXOptions> {
modules("javafx.controls")
}

View File

@ -0,0 +1,41 @@
package hep.dataforge.vis
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import javafx.beans.binding.ObjectBinding
import tornadofx.*
/**
* A caching binding collection for [DisplayObject] properties
*/
class DisplayObjectFXListener(val obj: DisplayObject) {
private val binndings = HashMap<Name, ObjectBinding<MetaItem<*>?>>()
init {
obj.onChange(this) { name, _, _ ->
binndings[name]?.invalidate()
}
}
operator fun get(key: Name): ObjectBinding<MetaItem<*>?> {
return binndings.getOrPut(key) {
object : ObjectBinding<MetaItem<*>?>() {
override fun computeValue(): MetaItem<*>? = obj.get(key)
}
}
}
operator fun get(key: String) = get(key.toName())
}
fun ObjectBinding<MetaItem<*>?>.value() = this.objectBinding { it.value }
fun ObjectBinding<MetaItem<*>?>.string() = this.stringBinding { it.string }
fun ObjectBinding<MetaItem<*>?>.number() = this.objectBinding { it.number }
fun ObjectBinding<MetaItem<*>?>.double() = this.objectBinding { it.double }
fun ObjectBinding<MetaItem<*>?>.float() = this.objectBinding { it.number?.toFloat() }
fun ObjectBinding<MetaItem<*>?>.int() = this.objectBinding { it.int }
fun ObjectBinding<MetaItem<*>?>.long() = this.objectBinding { it.long }
fun ObjectBinding<MetaItem<*>?>.node() = this.objectBinding { it.node }
fun <T> ObjectBinding<MetaItem<*>?>.transform(transform: (MetaItem<*>) -> T) = this.objectBinding { it?.let(transform) }

View File

@ -0,0 +1,166 @@
package hep.dataforge.vis.spatial
import hep.dataforge.vis.spatial.World.CAMERA_FAR_CLIP
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_DISTANCE
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_X_ANGLE
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_Y_ANGLE
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_Z_ANGLE
import hep.dataforge.vis.spatial.World.CAMERA_NEAR_CLIP
import javafx.event.EventHandler
import javafx.scene.*
import javafx.scene.input.KeyCode
import javafx.scene.input.KeyEvent
import javafx.scene.input.MouseEvent
import javafx.scene.input.ScrollEvent
import javafx.scene.paint.Color
import org.fxyz3d.utils.CameraTransformer
import tornadofx.*
class Canvas3D : Fragment() {
val world: Group = Group()
private val camera = PerspectiveCamera().apply {
nearClip = CAMERA_NEAR_CLIP
farClip = CAMERA_FAR_CLIP
translateZ = CAMERA_INITIAL_DISTANCE
}
private val cameraShift = CameraTransformer().apply {
val cameraFlip = CameraTransformer()
cameraFlip.children.add(camera)
cameraFlip.setRotateZ(180.0)
children.add(cameraFlip)
}
val translationXProperty get() = cameraShift.t.xProperty()
var translateX by translationXProperty
val translationYProperty get() = cameraShift.t.yProperty()
var translateY by translationYProperty
val translationZProperty get() = cameraShift.t.zProperty()
var translateZ by translationZProperty
private val cameraRotation = CameraTransformer().apply {
children.add(cameraShift)
ry.angle = CAMERA_INITIAL_Y_ANGLE
rx.angle = CAMERA_INITIAL_X_ANGLE
rz.angle = CAMERA_INITIAL_Z_ANGLE
}
val rotationXProperty get() = cameraRotation.rx.angleProperty()
var angleX by rotationXProperty
val rotationYProperty get() = cameraRotation.ry.angleProperty()
var angleY by rotationYProperty
val rotationZProperty get() = cameraRotation.rz.angleProperty()
var angleZ by rotationZProperty
override val root =borderpane {
center = SubScene(
Group(world, cameraRotation).apply { DepthTest.ENABLE },
1024.0,
768.0,
true,
SceneAntialiasing.BALANCED
).apply {
fill = Color.GREY
this.camera = this@Canvas3D.camera
id = "canvas"
handleKeyboard(this)
handleMouse(this)
}
}
private fun handleKeyboard(scene: SubScene) {
scene.onKeyPressed = EventHandler<KeyEvent> { event ->
if (event.isControlDown) {
when (event.code) {
KeyCode.Z -> {
cameraShift.t.x = 0.0
cameraShift.t.y = 0.0
camera.translateZ = CAMERA_INITIAL_DISTANCE
cameraRotation.ry.angle = CAMERA_INITIAL_Y_ANGLE
cameraRotation.rx.angle = CAMERA_INITIAL_X_ANGLE
}
// KeyCode.X -> axisGroup.isVisible = !axisGroup.isVisible
// KeyCode.S -> snapshot()
// KeyCode.DIGIT1 -> pixelMap.filterKeys { it.getLayerNumber() == 1 }.values.forEach {
// toggleTransparency(
// it
// )
// }
// KeyCode.DIGIT2 -> pixelMap.filterKeys { it.getLayerNumber() == 2 }.values.forEach {
// toggleTransparency(
// it
// )
// }
// KeyCode.DIGIT3 -> pixelMap.filterKeys { it.getLayerNumber() == 3 }.values.forEach {
// toggleTransparency(
// it
// )
// }
else -> {
}//do nothing
}
}
}
}
private fun handleMouse(scene: SubScene) {
var mousePosX: Double = 0.0
var mousePosY: Double = 0.0
var mouseOldX: Double = 0.0
var mouseOldY: Double = 0.0
var mouseDeltaX: Double = 0.0
var mouseDeltaY: Double = 0.0
scene.onMousePressed = EventHandler<MouseEvent> { me ->
mousePosX = me.sceneX
mousePosY = me.sceneY
mouseOldX = me.sceneX
mouseOldY = me.sceneY
}
scene.onMouseDragged = EventHandler<MouseEvent> { me ->
mouseOldX = mousePosX
mouseOldY = mousePosY
mousePosX = me.sceneX
mousePosY = me.sceneY
mouseDeltaX = mousePosX - mouseOldX
mouseDeltaY = mousePosY - mouseOldY
val modifier = when {
me.isControlDown -> CONTROL_MULTIPLIER
me.isShiftDown -> SHIFT_MULTIPLIER
else -> 1.0
}
if (me.isPrimaryButtonDown) {
cameraRotation.rz.angle =
cameraRotation.rz.angle + mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED
cameraRotation.rx.angle =
cameraRotation.rx.angle + mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED
} else if (me.isSecondaryButtonDown) {
cameraShift.t.x = cameraShift.t.x + mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED
cameraShift.t.y = cameraShift.t.y + mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED
}
}
scene.onScroll = EventHandler<ScrollEvent> { event ->
val z = camera.translateZ
val newZ = z + MOUSE_SPEED * event.deltaY * RESIZE_SPEED
camera.translateZ = newZ
}
}
companion object {
private const val AXIS_LENGTH = 2000.0
private const val CONTROL_MULTIPLIER = 0.1
private const val SHIFT_MULTIPLIER = 10.0
private const val MOUSE_SPEED = 0.1
private const val ROTATION_SPEED = 2.0
private const val TRACK_SPEED = 6.0
private const val RESIZE_SPEED = 50.0
private const val LINE_WIDTH = 3.0
}
}

View File

@ -0,0 +1,48 @@
package hep.dataforge.vis.spatial
import hep.dataforge.context.Context
import hep.dataforge.io.Output
import hep.dataforge.meta.Meta
import hep.dataforge.vis.*
import javafx.scene.Group
import javafx.scene.Node
import org.fxyz3d.shapes.primitives.CuboidMesh
import tornadofx.*
/**
* https://github.com/miho/JCSG for operations
*
*/
class FX3DOutput(override val context: Context) : Output<DisplayObject> {
val canvas by lazy { Canvas3D() }
private fun buildNode(obj: DisplayObject): Node? {
val listener = DisplayObjectFXListener(obj)
val x = listener["pos.x"].float()
val y = listener["pos.y"].float()
val z = listener["pos.z"].float()
val center = objectBinding(x, y, z) {
org.fxyz3d.geometry.Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f)
}
return when (obj) {
is DisplayGroup -> Group(obj.children.map { buildNode(it) }).apply {
this.translateXProperty().bind(x)
this.translateYProperty().bind(y)
this.translateZProperty().bind(z)
}
is Box -> CuboidMesh(obj.xSize, obj.ySize, obj.zSize).apply {
this.centerProperty().bind(center)
this.materialProperty().bind(listener["color"].transform { it.material() })
}
else -> {
logger.error { "No renderer defined for ${obj::class}" }
null
}
}
}
override fun render(obj: DisplayObject, meta: Meta) {
buildNode(obj)?.let { canvas.world.children.add(it) }
}
}

View File

@ -0,0 +1,69 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.double
import hep.dataforge.meta.get
import hep.dataforge.meta.int
import hep.dataforge.values.ValueType
import javafx.scene.paint.Color
import javafx.scene.paint.Material
import javafx.scene.paint.PhongMaterial
object Materials {
val RED = PhongMaterial().apply {
diffuseColor = Color.DARKRED
specularColor = Color.RED
}
val WHITE = PhongMaterial().apply {
diffuseColor = Color.WHITE
specularColor = Color.LIGHTBLUE
}
val GREY = PhongMaterial().apply {
diffuseColor = Color.DARKGREY
specularColor = Color.GREY
}
val BLUE = PhongMaterial(Color.BLUE)
}
/**
* Infer color based on meta item
*/
fun MetaItem<*>.color(): Color {
return when (this) {
is MetaItem.ValueItem -> if (this.value.type == ValueType.STRING) {
Color.web(this.value.string)
} else {
val int = value.number.toInt()
val red = int and 0x00ff0000 shr 16
val green = int and 0x0000ff00 shr 8
val blue = int and 0x000000ff
Color.rgb(red, green, blue)
}
is MetaItem.NodeItem -> {
Color.rgb(
node["red"]?.int ?: 0,
node["green"]?.int ?: 0,
node["blue"]?.int ?: 0,
node["opacity"]?.double ?: 1.0
)
}
}
}
/**
* Infer FX material based on meta item
*/
fun MetaItem<*>?.material(): Material {
return when (this) {
null -> Materials.GREY
is MetaItem.ValueItem -> PhongMaterial(color())
is MetaItem.NodeItem -> PhongMaterial().apply {
(node["color"]?: this@material).let { diffuseColor = it.color() }
node["specularColor"]?.let { specularColor = it.color() }
}
}
}

View File

@ -0,0 +1,64 @@
package hep.dataforge.vis.spatial
import hep.dataforge.context.Global
import hep.dataforge.meta.number
import hep.dataforge.vis.DisplayGroup
import javafx.scene.Parent
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import tornadofx.*
import kotlin.random.Random
class RendererDemoApp : App(RendererDemoView::class)
class RendererDemoView : View() {
val renderer = FX3DOutput(Global)
override val root: Parent = borderpane {
center = renderer.canvas.root
}
lateinit var group: DisplayGroup
init {
renderer.render {
group = group {
box {
xSize = 100.0
ySize = 100.0
zSize = 100.0
}
box {
x = 110.0
xSize = 100.0
ySize = 100.0
zSize = 100.0
}
}
}
var color by group.properties.number(1530).int
GlobalScope.launch {
val random = Random(111)
while (isActive) {
delay(1000)
color = random.nextInt(0, Int.MAX_VALUE)
}
}
renderer.canvas.apply {
angleY = -30.0
angleX = -15.0
}
}
}
fun main() {
launch<RendererDemoApp>()
}

View File

@ -0,0 +1,59 @@
import org.jetbrains.kotlin.gradle.frontend.KotlinFrontendExtension
import org.jetbrains.kotlin.gradle.frontend.npm.NpmExtension
import org.jetbrains.kotlin.gradle.frontend.webpack.WebPackExtension
plugins {
id("kotlin2js")
id("kotlin-dce-js")
id("org.jetbrains.kotlin.frontend")
}
dependencies {
api(project(":dataforge-vis-spatial"))
implementation("info.laht.threekt:threejs-wrapper:0.88-npm-1")
}
configure<KotlinFrontendExtension> {
downloadNodeJsVersion = "latest"
configure<NpmExtension> {
dependency("three")
dependency("three-orbitcontrols")
dependency("style-loader")
devDependency("karma")
}
sourceMaps = true
bundle("webpack") {
this as WebPackExtension
bundleName = "main"
proxyUrl = "http://localhost:8080"
contentPath = file("src/main/web")
sourceMapEnabled = true
//mode = "production"
mode = "development"
}
}
tasks{
compileKotlin2Js{
kotlinOptions{
metaInfo = true
outputFile = "${project.buildDir.path}/js/${project.name}.js"
sourceMap = true
moduleKind = "umd"
main = "call"
}
}
compileTestKotlin2Js{
kotlinOptions{
metaInfo = true
outputFile = "${project.buildDir.path}/js/${project.name}-test.js"
sourceMap = true
moduleKind = "umd"
}
}
}

View File

@ -0,0 +1,19 @@
package hep.dataforge.vis.hmr
external val module: Module
external interface Module {
val hot: Hot?
}
external interface Hot {
val data: dynamic
fun accept()
fun accept(dependency: String, callback: () -> Unit)
fun accept(dependencies: Array<String>, callback: (updated: Array<String>) -> Unit)
fun dispose(callback: (data: dynamic) -> Unit)
}
external fun require(name: String): dynamic

View File

@ -0,0 +1,50 @@
package hep.dataforge.vis
import hep.dataforge.vis.hmr.module
import hep.dataforge.vis.spatial.ThreeDemoApp
import kotlin.browser.document
import kotlin.dom.hasClass
abstract class ApplicationBase {
abstract val stateKeys: List<String>
abstract fun start(state: Map<String, Any>)
abstract fun dispose(): Map<String, Any>
}
fun main() {
var application: ApplicationBase? = null
val state: dynamic = module.hot?.let { hot ->
hot.accept()
hot.dispose { data ->
data.appState = application?.dispose()
application = null
}
hot.data
}
if (document.body != null) {
application = start(state)
} else {
application = null
document.addEventListener("DOMContentLoaded", { application = start(state) })
}
}
fun start(state: dynamic): ApplicationBase? {
return if (document.body?.hasClass("testApp") == true) {
val application = ThreeDemoApp()
@Suppress("UnsafeCastFromDynamic")
application.start(state?.appState ?: emptyMap())
application
} else {
null
}
}

View File

@ -0,0 +1,59 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.double
import hep.dataforge.meta.get
import hep.dataforge.meta.int
import hep.dataforge.values.ValueType
import info.laht.threekt.materials.Material
import info.laht.threekt.materials.MeshPhongMaterial
import info.laht.threekt.math.Color
import info.laht.threekt.math.ColorConstants
object Materials {
val DEFAULT = MeshPhongMaterial().apply {
this.color.set(ColorConstants.darkgreen)
}
}
/**
* Infer color based on meta item
*/
fun MetaItem<*>.color(): Color {
return when (this) {
is MetaItem.ValueItem -> if (this.value.type == ValueType.STRING) {
Color(this.value.string)
} else {
val int = value.number.toInt()
// val red = int and 0x00ff0000 shr 16
// val green = int and 0x0000ff00 shr 8
// val blue = int and 0x000000ff
Color(int)
}
is MetaItem.NodeItem -> {
Color(
node["red"]?.int ?: 0,
node["green"]?.int ?: 0,
node["blue"]?.int ?: 0
)
}
}
}
/**
* Infer FX material based on meta item
*/
fun MetaItem<*>?.material(): Material {
return when (this) {
null -> Materials.DEFAULT
is MetaItem.ValueItem -> MeshPhongMaterial().apply {
color = this@material.color()
}
is MetaItem.NodeItem -> MeshPhongMaterial().apply {
(node["color"] ?: this@material).let { color = it.color() }
opacity = node["opacity"]?.double ?: 1.0
node["specularColor"]?.let { specular = it.color() }
}
}
}

View File

@ -0,0 +1,66 @@
package hep.dataforge.vis.spatial
import hep.dataforge.context.Global
import hep.dataforge.meta.number
import hep.dataforge.meta.set
import hep.dataforge.vis.ApplicationBase
import hep.dataforge.vis.DisplayGroup
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlin.browser.document
import kotlin.random.Random
class ThreeDemoApp : ApplicationBase() {
override val stateKeys: List<String> = emptyList()
override fun start(state: Map<String, Any>) {
val renderer = ThreeOutput(Global)
renderer.start(document.getElementById("canvas")!!)
println("started")
lateinit var group: DisplayGroup
renderer.render {
group = group {
box {
xSize = 100.0
ySize = 100.0
zSize = 100.0
}
box {
x = 110.0
xSize = 100.0
ySize = 100.0
zSize = 100.0
properties.style["color"] = 1530
}
}
}
var color by group.properties.number(1530).int
GlobalScope.launch {
val random = Random(111)
while (isActive) {
delay(1000)
color = random.nextInt(0, Int.MAX_VALUE)
}
}
// view.animate()
// view = WebLinesView(document.getElementById("lines")!!, document.getElementById("addForm")!!)
// presenter = LinesPresenter(view)
//
// state["lines"]?.let { linesState ->
// @Suppress("UNCHECKED_CAST")
// presenter.restore(linesState as Array<String>)
// }
}
override fun dispose() = emptyMap<String,Any>()//mapOf("lines" to presenter.dispose())
}

View File

@ -0,0 +1,141 @@
package hep.dataforge.vis.spatial
import hep.dataforge.context.Context
import hep.dataforge.io.Output
import hep.dataforge.meta.Meta
import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.get
import hep.dataforge.vis.onChange
import info.laht.threekt.WebGLRenderer
import info.laht.threekt.cameras.PerspectiveCamera
import info.laht.threekt.core.Object3D
import info.laht.threekt.external.controls.OrbitControls
import info.laht.threekt.geometries.BoxBufferGeometry
import info.laht.threekt.lights.AmbientLight
import info.laht.threekt.math.ColorConstants
import info.laht.threekt.objects.Mesh
import info.laht.threekt.scenes.Scene
import org.w3c.dom.Element
import kotlin.browser.window
class ThreeOutput(override val context: Context) : Output<DisplayObject> {
private val renderer = WebGLRenderer { antialias = true }.apply {
setClearColor(ColorConstants.skyblue, 1)
setSize(window.innerWidth, window.innerHeight)
}
val scene: Scene = Scene().apply {
add(AmbientLight())
}
val camera = PerspectiveCamera(
75,
window.innerWidth.toDouble() / window.innerHeight,
World.CAMERA_NEAR_CLIP,
World.CAMERA_FAR_CLIP
).apply {
position.setZ(World.CAMERA_INITIAL_DISTANCE)
rotation.set(World.CAMERA_INITIAL_X_ANGLE, World.CAMERA_INITIAL_Y_ANGLE, World.CAMERA_INITIAL_Z_ANGLE)
}
val controls: OrbitControls = OrbitControls(camera, renderer.domElement)
val root get() = renderer.domElement
private fun animate() {
window.requestAnimationFrame {
animate()
}
renderer.render(scene, camera)
}
fun start(element: Element) {
window.addEventListener("resize", {
camera.aspect = window.innerWidth.toDouble() / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight)
}, false)
element.appendChild(root)
animate()
}
private fun buildNode(obj: DisplayObject): Object3D? {
// general properties updater
val updateProperties: Object3D.(DisplayObject) -> Unit = {
position.set(obj.x, obj.y, obj.z)
setRotationFromEuler(obj.euler)
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
visible = obj.visible
}
return when (obj) {
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) })
is Box -> {
val geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
val update: Mesh.(Box) -> Unit = { box ->
this.geometry = BoxBufferGeometry(box.xSize, box.ySize, box.zSize)
material = box["color"].material()
}
Mesh(geometry, obj["color"].material()).also { mesh ->
obj.onChange(this) { _, _, _ ->
mesh.updateProperties(obj)
mesh.update(obj)
}
}
}
else -> {
logger.error { "No renderer defined for ${obj::class}" }
return null
}
}.apply {
updateProperties(obj)
}
}
override fun render(obj: DisplayObject, meta: Meta) {
buildNode(obj)?.let { scene.add(it) }
}
// init {
// val cube: Mesh
//
// cube = Mesh(
// BoxBufferGeometry(1, 1, 1),
// MeshPhongMaterial().apply {
// this.color.set(ColorConstants.darkgreen)
// }
// ).also(scene::add)
//
// Mesh(cube.geometry as BufferGeometry,
// MeshBasicMaterial().apply {
// this.wireframe = true
// this.color.set(ColorConstants.black)
// }
// ).also(cube::add)
//
// val points = CatmullRomCurve3(
// arrayOf(
// Vector3(-10, 0, 10),
// Vector3(-5, 5, 5),
// Vector3(0, 0, 0),
// Vector3(5, -5, 5),
// Vector3(10, 0, 10)
// )
// ).getPoints(50)
//
// val geometry = BufferGeometry().setFromPoints(points)
//
// val material = LineBasicMaterial().apply {
// color.set(0xff0000)
// }
//
// // Create the final object to add to the scene
// Line(geometry, material).apply(scene::add)
// }
}

View File

@ -0,0 +1,24 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.float
import hep.dataforge.meta.get
import hep.dataforge.meta.node
import hep.dataforge.vis.DisplayObject
import info.laht.threekt.core.Object3D
import info.laht.threekt.math.Euler
import info.laht.threekt.math.Vector3
/**
* Utility methods for three.kt.
* TODO move to three project
*/
@Suppress("FunctionName")
fun Group(children: Collection<Object3D>) = info.laht.threekt.objects.Group().apply {
children.forEach { this.add(it) }
}
val DisplayObject.euler get() = Euler(rotationX, rotationY, rotationZ, rotationOrder.name)
val MetaItem<*>.vector get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f)

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Three js demo for particle physics</title>
<style>
body {
margin: 0px;
overflow: hidden;
}
</style>
<!--<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>-->
<!--<script type="text/javascript" src="js/OrbitControls.js"></script>-->
<script type="text/javascript" language="JavaScript" src="main.bundle.js"></script>
</head>
<body class="testApp">
<h1>Demo canvas</h1>
<div id="canvas"></div>
</body>
</html>

View File

@ -0,0 +1,27 @@
plugins {
kotlin("multiplatform")
}
kotlin {
jvm()
js()
sourceSets {
val commonMain by getting {
dependencies {
api(project(":dataforge-vis-common"))
}
}
val jvmMain by getting {
dependencies {
}
}
val jsMain by getting {
dependencies {
}
}
}
}

View File

@ -0,0 +1,23 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.DisplayLeaf
import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.double
class Box(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) {
var xSize by double(1.0)
var ySize by double(1.0)
var zSize by double(1.0)
//TODO add helper for color configuration
companion object {
const val TYPE = "geometry.spatial.box"
}
}
fun DisplayGroup.box(meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
Box(this, meta).apply(action).also { addChild(it) }

View File

@ -0,0 +1,18 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.DisplayLeaf
import hep.dataforge.vis.DisplayObject
class Extruded(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) {
companion object {
const val TYPE = "geometry.spatial.extruded"
}
}
fun DisplayGroup.extrude(meta: Meta = EmptyMeta, action: Extruded.() -> Unit = {}) =
Extruded(this, meta).apply(action).also { addChild(it) }

View File

@ -0,0 +1 @@
package hep.dataforge.vis.spatial

View File

@ -0,0 +1,109 @@
package hep.dataforge.vis.spatial
import hep.dataforge.io.Output
import hep.dataforge.meta.*
import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.DisplayNode
import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.DisplayObject.Companion.DEFAULT_TYPE
fun DisplayGroup.group(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit = {}) =
DisplayNode(this, DEFAULT_TYPE, meta).apply(action).also { addChild(it) }
fun Output<DisplayObject>.render(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit) =
render(DisplayNode(null, DEFAULT_TYPE, EmptyMeta).apply(action), meta)
//TODO replace properties by containers?
// Common properties
var DisplayObject.visible
get() = properties["visible"].boolean ?: true
set(value) {
properties.style["visible"] = value
}
// 3D Object position
var DisplayObject.x
get() = properties["pos.x"].number ?: 0.0
set(value) {
properties.style["pos.x"] = value
}
var DisplayObject.y
get() = properties["pos.y"].number ?: 0.0
set(value) {
properties.style["pos.y"] = value
}
var DisplayObject.z
get() = properties["pos.z"].number ?: 0.0
set(value) {
properties.style["pos.z"] = value
}
// 3D Object rotation
var DisplayObject.rotationX
get() = properties["rotation.x"].number ?: 0.0
set(value) {
properties.style["rotation.x"] = value
}
var DisplayObject.rotationY
get() = properties["rotation.y"].number ?: 0.0
set(value) {
properties.style["rotation.y"] = value
}
var DisplayObject.rotationZ
get() = properties["rotation.z"].number ?: 0.0
set(value) {
properties.style["rotation.z"] = value
}
enum class RotationOrder {
XYZ,
YZX,
ZXY,
XZY,
YXZ,
ZYX
}
var DisplayObject.rotationOrder: RotationOrder
get() = properties["rotation.order"].enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) {
properties.style["rotation.order"] = value
}
// 3D object scale
var DisplayObject.scaleX
get() = properties["scale.x"].number ?: 1.0
set(value) {
properties.style["scale.x"] = value
}
var DisplayObject.scaleY
get() = properties["scale.y"].number ?: 1.0
set(value) {
properties.style["scale.y"] = value
}
var DisplayObject.scaleZ
get() = properties["scale.z"].number ?: 1.0
set(value) {
properties.style["scale.z"] = value
}
object World {
const val CAMERA_INITIAL_DISTANCE = -500.0
const val CAMERA_INITIAL_X_ANGLE = -50.0
const val CAMERA_INITIAL_Y_ANGLE = 0.0
const val CAMERA_INITIAL_Z_ANGLE = -210.0
const val CAMERA_NEAR_CLIP = 0.1
const val CAMERA_FAR_CLIP = 10000.0
}

31
gradle/artifactory.gradle Normal file
View File

@ -0,0 +1,31 @@
apply plugin: "com.jfrog.artifactory"
artifactory {
def artifactory_user = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : ""
def artifactory_password = project.hasProperty('artifactoryPassword') ? project.property('artifactoryPassword') : ""
def artifactory_contextUrl = 'http://npm.mipt.ru:8081/artifactory'
contextUrl = artifactory_contextUrl //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'gradle-dev-local'
username = artifactory_user
password = artifactory_password
}
defaults {
publications('jvm', 'js', 'kotlinMultiplatform', 'metadata')
publishBuildInfo = false
publishArtifacts = true
publishPom = true
publishIvy = false
}
}
resolve {
repository {
repoKey = 'gradle-dev'
username = artifactory_user
password = artifactory_password
}
}
}

85
gradle/bintray.gradle Normal file
View File

@ -0,0 +1,85 @@
apply plugin: 'com.jfrog.bintray'
def vcs = "https://github.com/mipt-npm/kmath"
def pomConfig = {
licenses {
license {
name "The Apache Software License, Version 2.0"
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
distribution "repo"
}
}
developers {
developer {
id "MIPT-NPM"
name "MIPT nuclear physics methods laboratory"
organization "MIPT"
organizationUrl "http://npm.mipt.ru"
}
}
scm {
url vcs
}
}
project.ext.configureMavenCentralMetadata = { pom ->
def root = asNode()
root.appendNode('name', project.name)
root.appendNode('description', project.description)
root.appendNode('url', vcs)
root.children().last() + pomConfig
}
project.ext.configurePom = pomConfig
// Configure publishing
publishing {
repositories {
maven {
url = "https://bintray.com/mipt-npm/scientifik"
}
}
// Process each publication we have in this project
publications.all { publication ->
// apply changes to pom.xml files, see pom.gradle
pom.withXml(configureMavenCentralMetadata)
}
}
bintray {
user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
publish = true
override = true // for multi-platform Kotlin/Native publishing
pkg {
userOrg = "mipt-npm"
repo = "scientifik"
name = "scientifik.kmath"
issueTrackerUrl = "https://github.com/mipt-npm/kmath/issues"
licenses = ['Apache-2.0']
vcsUrl = vcs
version {
name = project.version
vcsTag = project.version
released = new Date()
}
}
}
bintrayUpload.dependsOn publishToMavenLocal
// This is for easier debugging of bintray uploading problems
bintrayUpload.doFirst {
publications = project.publishing.publications.findAll {
!it.name.contains('-test') && it.name != 'kotlinMultiplatform'
}.collect {
println("Uploading artifact '$it.groupId:$it.artifactId:$it.version' from publication '$it.name'")
it.name//https://github.com/bintray/gradle-bintray-plugin/issues/256
}
}

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

172
gradlew vendored Normal file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
gradlew.bat vendored Normal file
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

27
settings.gradle.kts Normal file
View File

@ -0,0 +1,27 @@
pluginManagement {
repositories {
jcenter()
gradlePluginPortal()
maven("https://dl.bintray.com/kotlin/kotlin-eap")
}
resolutionStrategy {
eachPlugin {
when (requested.id.id) {
"kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
"kotlin-multiplatform" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
"kotlin2js" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
"org.jetbrains.kotlin.frontend" -> useModule("org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.45")
}
}
}
}
enableFeaturePreview("GRADLE_METADATA")
rootProject.name = "dataforge-vis"
include(
":dataforge-vis-common",
":dataforge-vis-spatial",
":dataforge-vis-spatial-fx",
":dataforge-vis-spatial-js"
)