Merge remote-tracking branch 'origin/dev' into feature/df-new

# Conflicts:
#	visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt
This commit is contained in:
Alexander Nozik 2021-08-11 18:34:49 +03:00
commit 1505aa8091
42 changed files with 451 additions and 37 deletions

33
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Gradle build
on:
push:
branches: [ dev, master ]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v2
- uses: DeLaGuardo/setup-graalvm@4.0
with:
graalvm: 21.2.0
java: java11
arch: amd64
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- uses: actions/cache@v2
with:
path: ~/.konan
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- run: ./gradlew build --build-cache --no-daemon --stacktrace

View File

@ -1,19 +0,0 @@
name: Gradle build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Build with Gradle
run: ./gradlew build

28
.github/workflows/pages.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: Dokka publication
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v2
- uses: DeLaGuardo/setup-graalvm@4.0
with:
graalvm: 21.2.0
java: java11
arch: amd64
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- run: ./gradlew dokkaHtmlMultiModule --build-cache --no-daemon --no-parallel --stacktrace
- uses: JamesIves/github-pages-deploy-action@4.1.0
with:
branch: gh-pages
folder: build/dokka/htmlMultiModule

View File

@ -19,7 +19,7 @@
* [visionforge-gdml](#visionforge-gdml) * [visionforge-gdml](#visionforge-gdml)
* [Visualization for External Systems](#visualization-for-external-systems) * [Visualization for External Systems](#visualization-for-external-systems)
* [Demonstrations](#demonstrations) * [Demonstrations](#demonstrations)
* [Simple Example - Spatial Showcase](#simple-example---spatial-showcase) * [Simple Example - Solid Showcase](#simple-example---solid-showcase)
* [Full-Stack Application Example - Muon Monitor](#full-stack-application-example---muon-monitor-visualization) * [Full-Stack Application Example - Muon Monitor](#full-stack-application-example---muon-monitor-visualization)
* [GDML Example](#gdml-example) * [GDML Example](#gdml-example)
@ -118,16 +118,16 @@ The `demo` module contains several example projects (demonstrations) of using th
They are briefly described in this section, for more details please consult the corresponding per-project They are briefly described in this section, for more details please consult the corresponding per-project
README file. README file.
### Simple Example - Spatial Showcase ### Simple Example - Solid Showcase
Contains a simple demonstration with a grid including a few shapes that you can rotate, move camera, and so on. Contains a simple demonstration with a grid including a few shapes that you can rotate, move camera, and so on.
Some shapes will also periodically change their color and visibility. Some shapes will also periodically change their color and visibility.
[More details](demo/spatial-showcase/README.md) [More details](demo/solid-showcase/README.md)
**Example view:** **Example view:**
![](docs/images/spatial-showcase.png) ![](docs/images/solid-showcase.png)
### Full-Stack Application Example - Muon Monitor Visualization ### Full-Stack Application Example - Muon Monitor Visualization
@ -156,4 +156,4 @@ Visualization example for geometry defined as GDML file.
## Thanks and references ## Thanks and references
The original three.js bindings were made by [Lars Ivar Hatledal](https://github.com/markaren), but the project is discontinued right now. The original three.js bindings were made by [Lars Ivar Hatledal](https://github.com/markaren), but the project is discontinued right now.
All other libraries are explicitly shown as dependencies. We would like to express specific thanks to JetBrains Kotlin-JS team for consulting us during the work. All other libraries are explicitly shown as dependencies. We would like to express specific thanks to JetBrains Kotlin-JS team for consulting us during the work.

View File

@ -1,12 +1,10 @@
### GDML Example ### GDML Example
Visualization example for geometry defined as GDML file. Visualization example for geometry defined as GDML file.
##### Building project ##### Building project
To build the app, run `demo/gdml/Tasks/distribution/jsBrowserDistribution` Gradle task, then open To build the app, run `demo/gdml/Tasks/kotlin browser/jsBrowserDistribution` Gradle task, then
`demo/gdml/build/distribuions/gdml-js-0.1.3-dev/index.html` file in your browser, and
drag-and-drop GDML file to the window to see visualization. For an example file, you can use drag-and-drop GDML file to the window to see visualization. For an example file, you can use
`demo/gdml/src/jsMain/resources/cubes.gdml`. `demo/gdml/src/jsMain/resources/cubes.gdml`.

View File

@ -26,9 +26,8 @@ with it.
##### Building project ##### Building project
To run full-stack Muon Monitor Visualization application (both JVM server and Web browser front-end), To run full-stack Muon Monitor Visualization application (both JVM server and Web browser front-end),
run `demo/muon-monitor/application/run` task. run `demo/muon-monitor/Tasks/application/run` task.
##### Example view: ##### Example view:
![](../../docs/images/muon-monitor.png) ![](../../docs/images/muon-monitor.png)

View File

@ -5,8 +5,8 @@ Some shapes will also periodically change their color and visibility.
##### Building project ##### Building project
To see the JS demo: run `demo/spatial-showcase/Tasks/distribution/jsBrowserDistribution` Gradle task, then open To see the JS demo: run `demo/solid-showcase/Tasks/kotlin browser/jsBrowserRun` Gradle task, then open
`build/distribuions/spatial-showcase-js-0.1.3-dev/index.html` file in your browser. `build/distribuions/solid-showcase-js-0.1.3-dev/index.html` file in your browser.
To see Java FX demo, run `demo/spatial-showcase/Tasks/application/run` Gradle task, or `main()` from `FXDemoApp.kt`. To see Java FX demo, run `demo/spatial-showcase/Tasks/application/run` Gradle task, or `main()` from `FXDemoApp.kt`.

View File

@ -105,7 +105,7 @@ fun VisionLayout<Solid>.showcase() {
} }
demo("extrude", "extruded shape") { demo("extrude", "extruded shape") {
extrude { extruded {
shape { shape {
polygon(8, 50) polygon(8, 50)
} }

BIN
docs/images/all-solids.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
docs/images/box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
docs/images/cone-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
docs/images/cone-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
docs/images/cylinder-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
docs/images/cylinder-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
docs/images/cylinder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
docs/images/high-box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
docs/images/scheme.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
docs/images/small-box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
docs/images/sphere.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
docs/images/tube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
docs/images/two-boxes-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
docs/images/two-boxes-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
docs/images/wide-box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

373
docs/tutorial.md Normal file
View File

@ -0,0 +1,373 @@
# Tutorial
#### The main goal of this tutorial is to show the main capabilities of the visualization instrument.
The simple visualization can be made with function `main`. (this part will be supplemented)
```kotlin
import kotlinx.html.div
import space.kscience.dataforge.context.Context
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.*
import java.nio.file.Paths
fun main(){
val context = Context{
plugin(Solids)
}
context.makeVisionFile (
Paths.get("nameFile.html"),
resourceLocation = ResourceLocation.EMBED
){
div {
//first vision
vision {
solid {
//solids which you want to visualize
}
}
//second vision
vision {
solid {
//solids which you want to visualize
}
}
}
}
}
```
## Solids properties
**We will analyze which basic properties solids have using `box` solid.**
*Basic properties:*
1. `opacity` &mdash; It is set in `float`. It takes on values from 0 to 1, which represent percents of solid opacity. It's initial value is 1.
2. `color` &mdash; It can be specified as `Int`, `String`, or as three `Ubytes`, which represent color in `rgb`. Elementally, the solid will have `green` color.
3. `rotation` &mdash; it's the point, which sets rotations along axes. Initially, the value is `Point3D(0, 0, 0)`. Changing `x` coordinate of the point, you make pivot around `x axis`. The same for other coordinates: changing `y` &mdash; pivot around `y axis`, changing `z` &mdash; pivot around `z axis`.
4. position, which is given by values `x`, `y`, `z`. Initial values are `x = 0`, `y = 0`, `z = 0`. The coordinate system is Cartesian. It's elemental position is this &mdash; vertical `y` axis and horizontal `Oxz` plane.
Let's see how properties are set in solids.
The `small box` will have elemental values of properties. If you don't set properties, it will have the same `position`, `color`, `rotation`, and `opacity` values.
***You can see that `box` take four values. Later, we will discuss what they do in more detail. Now, it does not really matter.***
```kotlin
box(10, 10, 10, name = "small box"){
x = 0
y = 0
z = 0
opacity = 1 //100% opacity
color("red") //as string
rotation = Point3D(0, 0, 0)
}
```
![](../docs/images/small-box.png)
The `big box` will have properties with custom values.
```kotlin
box(40, 40, 40, name = "big box"){
x = 20
y = 10
z = 60
opacity = 0.5 //50% opacity
color(0u, 179u, 179u) //color in rgb
rotation = Point3D(60, 80, 0)
}
```
![](../docs/images/big-rotated-box.png)
If we compare these boxes, we will see all differences.
Here is the function `main` with both boxes.
```kotlin
fun main(){
val context = Context{
plugin(Solids)
}
context.makeVisionFile (
Paths.get("customFile.html"),
resourceLocation = ResourceLocation.EMBED
){
div {
vision {
solid {
box(10, 10, 10, name = "small box"){
x = 0
y = 0
z = 0
opacity = 1 //100% opacity
color("red") //as string
rotation = Point3D(0, 0, 0)
}
box(40, 40, 40, name = "big box"){
x = 20
y = 10
z = 60
opacity = 0.5 //50% opacity
color(0u, 179u, 179u) //rgb
rotation = Point3D(60, 80, 0)
}
}
}
}
}
}
```
![](../docs/images/two-boxes-1.png)
![](../docs/images/two-boxes-2.png)
***There is plenty of other properties, especially those, which you can create by yourself. Here we mention just a small part.***
## Basic Solids
Now, let's see which solids can be visualized:
### 1) PolyLine
It's scarcely a solid, but it can be visualized, so we mention it.
`polyline` build lines, obviously. Let's take a look at it's work.
`polyline` requires two values &mdash; `points`, and `name`:
* `points` is a `vararg` with `Point3D` type. It takes pairs of points, which you want to connect.
* `name` is an identifier of *any solid*; but in this case, it is an identifier of `polyline`.
It's type is `String`. **This value can be required by any solid;
you can set it, you can not to set it, but without you won't be able to control solid, since it won't be inherited.**
This is an example of polyline with other solid `box`:
```kotlin
box(100, 100, 100, name = "box"){
x = -10
y = -10
z = -10
opacity = 0.4
}
polyline(Point3D(30, 20, 10), Point3D(30, -100, 30), Point3D(30, -100, 30), Point3D(50, -100, 30), name = "polyline"){
color("red")
}
```
![](../docs/images/polyline-points.png)
![](../docs/images/polyline-points-2.png)
### 2) Box
First thing which has to be mentioned is that `box` takes four values: `box(x, y, z, name)`
* `x` &mdash; x-axis length of the `box`
* `y` &mdash; y-axis length of the `box`
* `z` &mdash; z-axis length of the `box`
These values have `Float` type.
*`x`, `y`, and `z` are necessary values, which cannot be ignored. You have to set them.*
* `name` &mdash; `box`'es identifier. You've already met it.
Let's create just usual `box` with equal ribs.
```kotlin
box(50, 50, 50, name = "box") {
color("pink")
}
```
![](../docs/images/box.png)
Now, let's make `box` with bigger `y` value.
```kotlin
box(10, 25, 10, name = "high box") {
color("black")
}
```
As you can see, only the rib of `y-axis` differs from other ribs.
![](../docs/images/high-box.png)
For a final trial, let's create a `box` with a bigger `x` value.
```kotlin
box(65, 40, 40, name = "wide box") {
x = 0
y = 0
z = 0
color("black")
}
```
Predictably, only the `x-axis` rib is bigger than other ribs.
![](../docs/images/wide-box.png)
### 3) Sphere
It takes in two values: `radius`, and `name`.
We bring you to mind that `name` is a general value for all solids, so do not wonder, since all solids need their own identifier.
As for `radius`, it has `Float` type, and, as you can guess, it sets the radius of the sphere which will be created.
```kotlin
sphere(50, name = "sphere") {
x = 0
y = 0
z = 0
opacity = 0.9
color("blue")
}
```
![](../docs/images/sphere.png)
### 4) Hexagon
It is solid which has six edges. It is set by eight values: `node1`,..., `node8`. They all have `Point3D` type, so they are just points, vertices.
*Six edges are these:*
1) Edge with vertices `node1`, `node4`, `node3`, `node2`
2) Edge with vertices `node1`, `node2`, `node6`, `node5`
3) Edge with vertices `node2`, `node3`, `node7`, `node6`
4) Edge with vertices `node4`, `node8`, `node7`, `node3`
5) Edge with vertices `node1`, `node5`, `node8`, `node4`
6) Edge with vertices `node8`, `node5`, `node6`, `node7`
![](../docs/images/scheme.png)
As the hexagon takes in specific points, we understand that this solid cannot be moved, it is fixed in space, and it can't make pivots.
Let's make classic parallelepiped.
```kotlin
hexagon(
Point3D(25, 30, 25),
Point3D(35, 30, 25),
Point3D(35, 30, 15),
Point3D(25, 30, 15),
Point3D(30, 18, 20),
Point3D(40, 18, 20),
Point3D(40, 18, 10),
Point3D(30, 18, 10),
name = "classic hexagon"){
color("green")
}
```
![](../docs/images/classic-hexagon.png)
Now, let's make a custom hexagon.
```kotlin
hexagon(
Point3D(5, 30, 5),
Point3D(24, 30, 8),
Point3D(20, 30, -10),
Point3D(5, 30, -7),
Point3D(8, 16, 0),
Point3D(12, 16, 0),
Point3D(10, 16, -5),
Point3D(6.5, 12, -3),
name = "custom_hexagon"
) {
color("brown")
}
```
![](../docs/images/custom-hexagon.png)
### 3) Cone
It takes in six values: `bottomRadius`, `height`, `upperRadius`, `startAngle`, `angle`, and `name`.
Obviously, `bottomRadius` is responsible for the radius of a bottom base, and `height` sets the height of a cone along the `z-axis`.
As it takes such values as `upperRadius`, `startAngle`, `angle`, `cone` can build not only usual cones, but also cone segments. Initially, `upperRadius` will have `0.0` value, `startAngle` &mdash; `0f`, `angle` &mdash; `PI2`, so if you don't set them, you'll get just a simple cone.
Setting `upperRadius`, you make a frustum cone, since it sets a radius of the upper base of a cone. Set `startAngle`, and `angle` let to cut off segments by planes perpendicular to the base. `startAngle` &mdash; an angle, starting with which segment will be left, `angle` &mdash; an angle of cone, which will be set from `startAngle`.
Let's build a classic cone:
```kotlin
cone(60, 80, name = "cone") {
color("beige")
}
```
![](../docs/images/cone-1.png)
![](../docs/images/cone-2.png)
First of all, we have to try to build a frustum cone:
```kotlin
cone(60, 80, name = "cone") {
color(0u, 40u, 0u)
}
```
![](../docs/images/frustum-cone.png)
Now, we need to make a try to build a cone segment:
```kotlin
cone(60, 80, angle = PI, name = "cone") {
color(0u, 0u, 200u)
}
```
![](../docs/images/cone-segment-1.png)
![](../docs/images/cone-segment-2.png)
Finally, the segment of frustum cone is left for a try:
```kotlin
cone(60, 100, 20, PI*3/4, angle = PI/3, name = "cone") {
color(190u, 0u, 0u)
}
```
![](../docs/images/frustum-cone-segment.png)
### 4) Cone Surface
This solid is set by seven values:`bottomOuterRadius`, `bottomInnerRadius`, `height`, `topOuterRadius`, `topInnerRadius`, `startAngle`, and `angle`.
In addition to `height`, `startAngle`, and `angle`, which work as they work in `cone`, there are some new values.
`bottomOuterRadius`, and `bottomInnerRadius` set properties of the bottom circle, `topOuterRadius`, `topInnerRadius` &mdash; of the upper circle. They have no initial value, so that means they have to be set.
Generally, `cone`, and `coneSurface` buildings work in the same way, it's possible to make `coneSurface`'s fragments as in `cone`
Let's build usual cone surface with almost all properties set:
```kotlin
coneSurface(60, 50, 30, 10, 100, name = "cone surface") {
color("red")
rotation = Point3D(2, 50, -9)
}
```
![](../docs/images/cone-surface-1.png)
![](../docs/images/cone-surface-2.png)
Now, let's create a cone surface and set all it's properties:
```kotlin
coneSurface(30, 25, 10, 10, 8,0f, pi*3/4, name = "cone surface") {
color("fuchsia")
rotation = Point3D(2, 50, -9)
}
```
![](../docs/images/cone-surface-fragment.png)
![](../docs/images/cone-surface-fragment-2.png)
### 5) Cylinder
This solid is set by `radius`, and `height`. As you can see by accepting values, there's no option of building fragments of cylinders.
Here's a demonstration of a cylinder:
```kotlin
cylinder(40, 100, "cylinder"){
rotation = Point3D(40, 0, 0)
color("indigo")
}
```
![](../docs/images/cylinder-1.png)
![](../docs/images/cylinder-2.png)
### 6) Tube
`tube` takes in `radius`, `height`, `innerRadius`, `startAngle`, `angle`, and `name`. *All values are familiar from `cone`, and `coneSurface` solids.*
Here is an example of classic tube:
```kotlin
tube(50, 40, 20, name = "usual tube"){
opacity = 0.4
}
```
![](../docs/images/tube.png)
This is an example of tube fragment:
```kotlin
tube(50, 40, 20, 0f, PI, name = "fragmented tube"){
color("white")
}
```
![](../docs/images/tube-fragment.png)
### 7) Extruded
`extruded` is set by two values: `shape`, and `layer`.
* `shape` is a value of `List<Point2D>` type. It's just a list of all points of the solid. *`shape` has to consist of not less than two points!*
* `layer` is `MutableList` types variable. (here is a sentence with a description of the work of this function). *The amount of `layer`-s has to be more than one*

Binary file not shown.

2
gradlew vendored Normal file → Executable file
View File

@ -72,7 +72,7 @@ case "`uname`" in
Darwin* ) Darwin* )
darwin=true darwin=true
;; ;;
MINGW* ) MSYS* | MINGW* )
msys=true msys=true
;; ;;
NONSTOP* ) NONSTOP* )

View File

@ -248,7 +248,7 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
name = name name = name
) )
} }
is GdmlXtru -> extrude(name) { is GdmlXtru -> extruded(name) {
shape { shape {
solid.vertices.forEach { solid.vertices.forEach {
point(it.x * lScale, it.y * lScale) point(it.x * lScale, it.y * lScale)
@ -284,7 +284,7 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
name = name, name = name,
) )
is GdmlOrb -> sphere(solid.r * lScale, name = name) is GdmlOrb -> sphere(solid.r * lScale, name = name)
is GdmlPolyhedra -> extrude(name) { is GdmlPolyhedra -> extruded(name) {
//getting the radius of first //getting the radius of first
require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" } require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" }
val baseRadius = solid.planes.first().rmax * lScale val baseRadius = solid.planes.first().rmax * lScale

View File

@ -96,7 +96,9 @@ public class Extruded(
public class ExtrudeBuilder( public class ExtrudeBuilder(
public var shape: List<Point2D> = emptyList(), public var shape: List<Point2D> = emptyList(),
public var layers: ArrayList<Layer> = ArrayList(),
public var layers: MutableList<Layer> = ArrayList(),
config: ObservableMutableMeta = MutableMeta() config: ObservableMutableMeta = MutableMeta()
) : SimpleVisionPropertyContainer<Extruded>(config) { ) : SimpleVisionPropertyContainer<Extruded>(config) {
public fun shape(block: Shape2DBuilder.() -> Unit) { public fun shape(block: Shape2DBuilder.() -> Unit) {
@ -113,7 +115,7 @@ public class ExtrudeBuilder(
} }
@VisionBuilder @VisionBuilder
public fun VisionContainerBuilder<Solid>.extrude( public fun VisionContainerBuilder<Solid>.extruded(
name: String? = null, name: String? = null,
action: ExtrudeBuilder.() -> Unit = {} action: ExtrudeBuilder.() -> Unit = {}
): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) } ): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) }