Fix cone segmenta and cone surface representation

This commit is contained in:
Alexander Nozik 2023-05-30 13:56:14 +03:00
parent 33778801b6
commit f6f74b54f6
4 changed files with 40 additions and 47 deletions

View File

@ -1,10 +1,10 @@
package space.kscience.visionforge.examples
import kotlin.math.PI
import space.kscience.visionforge.Colors
import space.kscience.visionforge.solid.*
import kotlin.math.PI
fun main() = makeVisionFile{
fun main() = makeVisionFile {
vision("canvas") {
solid {
ambientLight()
@ -30,9 +30,9 @@ fun main() = makeVisionFile{
}
tube(30,20, 20){
cylinder(30,20, name = "cylinder"){
detail = 31
y = - 220
y = -220
}
}
}

View File

@ -22,60 +22,53 @@ public class ConeSegment(
public val phi: Float = PI2,
) : SolidBase<ConeSegment>(), GeometrySolid {
init {
require(bottomRadius > 0) { "Bottom radius must be positive" }
require(topRadius > 0) { "Top radius must be positive" }
require(bottomRadius > 0) { "Cone segment bottom radius must be positive" }
require(height > 0) { "Cone segment height must be positive" }
require(topRadius >= 0) { "Cone segment top radius must be non-negative" }
//require(startAngle >= 0)
require(phi in (0f..(PI2)))
}
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
val segments: Int = detail ?: 32
require(segments >= 4) { "The number of segments in cone segment is too small" }
val segments = detail ?: 32
require(segments >= 4) { "The number of segments in cone is too small" }
val angleStep = phi / (segments - 1)
/**
* Top and bottom shape
*/
fun shape(r: Float, z: Float): List<Point3D> = (0 until segments).map { i ->
Point3D(r * cos(phiStart + angleStep * i), r * sin(phiStart + angleStep * i), z)
}
with(geometryBuilder) {
// top and bottom faces
val bottomOuterPoints: List<Point3D> = shape(topRadius, -height / 2)
val upperOuterPoints: List<Point3D> = shape(bottomRadius, height / 2)
geometryBuilder.apply {
//creating shape in x-y plane with z = 0
val bottomPoints = shape(bottomRadius, -height / 2)
val topPoints = shape(topRadius, height / 2)
//outer face
for (it in 1 until segments) {
face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1])
face4(bottomPoints[it - 1], bottomPoints[it], topPoints[it], topPoints[it - 1])
}
//if the cone is closed
if (phi == PI2) {
face4(bottomOuterPoints.last(), bottomOuterPoints[0], upperOuterPoints[0], upperOuterPoints.last())
face4(bottomPoints.last(), bottomPoints[0], topPoints[0], topPoints.last())
}
//top and bottom cups
val zeroBottom = Point3D(0f, 0f, -height / 2)
val zeroTop = Point3D(0f, 0f, height / 2)
val zeroTop = Point3D(0f, 0f, +height / 2)
for (it in 1 until segments) {
face(bottomOuterPoints[it - 1], zeroBottom, bottomOuterPoints[it])
face(upperOuterPoints[it - 1], upperOuterPoints[it], zeroTop)
face(bottomPoints[it - 1], zeroBottom, bottomPoints[it])
face(topPoints[it - 1], topPoints[it], zeroTop)
}
// closed surface
if (phi == PI2) {
face(bottomOuterPoints.last(), zeroBottom, bottomOuterPoints[0])
face(upperOuterPoints.last(), upperOuterPoints[0], zeroTop)
face(bottomPoints.last(), zeroBottom, bottomPoints[0])
face(topPoints.last(), topPoints[0], zeroTop)
} else {
face4(zeroTop, zeroBottom, bottomOuterPoints[0], upperOuterPoints[0])
face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last())
face4(zeroTop, zeroBottom, bottomPoints[0], topPoints[0])
face4(zeroTop, zeroBottom, bottomPoints.last(), topPoints.last())
}
}
}
}
@VisionBuilder

View File

@ -21,8 +21,8 @@ public class ConeSurface(
public val height: Float,
public val topRadius: Float,
public val topInnerRadius: Float,
public val startAngle: Float = 0f,
public val angle: Float = PI2,
public val phiStart: Float = 0f,
public val phi: Float = PI2,
) : SolidBase<ConeSurface>(), GeometrySolid {
init {
@ -30,16 +30,16 @@ public class ConeSurface(
require(height > 0) { "Cone surface height must be positive" }
require(bottomInnerRadius >= 0) { "Cone surface bottom inner radius must be non-negative" }
//require(startAngle >= 0)
require(angle in (0f..(PI2)))
require(phi in (0f..(PI2)))
}
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
val segments = detail ?: 32
require(segments >= 4) { "The number of segments in tube is too small" }
val angleStep = angle / (segments - 1)
val angleStep = phi / (segments - 1)
fun shape(r: Float, z: Float): List<Point3D> = (0 until segments).map { i ->
Point3D(r * cos(startAngle + angleStep * i), r * sin(startAngle + angleStep * i), z)
Point3D(r * cos(phiStart + angleStep * i), r * sin(phiStart + angleStep * i), z)
}
geometryBuilder.apply {
@ -52,17 +52,17 @@ public class ConeSurface(
face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], topOuterPoints[it], topOuterPoints[it - 1])
}
if (angle == PI2) {
if (phi == PI2) {
face4(bottomOuterPoints.last(), bottomOuterPoints[0], topOuterPoints[0], topOuterPoints.last())
}
if (bottomInnerRadius == 0f) {
val zeroBottom = Point3D(0f, 0f, 0f)
val zeroTop = Point3D(0f, 0f, height)
val zeroBottom = Point3D(0f, 0f, -height / 2)
val zeroTop = Point3D(0f, 0f, height / 2)
(1 until segments).forEach {
face(bottomOuterPoints[it - 1], zeroBottom, bottomOuterPoints[it])
face(topOuterPoints[it - 1], topOuterPoints[it], zeroTop)
}
if (angle == PI2) {
if (phi == PI2) {
face(bottomOuterPoints.last(), zeroBottom, bottomOuterPoints[0])
face(topOuterPoints.last(), topOuterPoints[0], zeroTop)
} else {
@ -96,7 +96,7 @@ public class ConeSurface(
topOuterPoints[it]
)
}
if (angle == PI2) {
if (phi == PI2) {
face4(bottomInnerPoints[0], bottomInnerPoints.last(), topInnerPoints.last(), topInnerPoints[0])
face4(
bottomInnerPoints.last(),
@ -135,8 +135,8 @@ public inline fun MutableVisionContainer<Solid>.tube(
height = height.toFloat(),
topRadius = radius.toFloat(),
topInnerRadius = innerRadius.toFloat(),
startAngle = startAngle.toFloat(),
angle = angle.toFloat()
phiStart = startAngle.toFloat(),
phi = angle.toFloat()
).apply(block).also { setChild(name, it) }
@VisionBuilder
@ -156,6 +156,6 @@ public inline fun MutableVisionContainer<Solid>.coneSurface(
height = height.toFloat(),
topRadius = topOuterRadius.toFloat(),
topInnerRadius = topInnerRadius.toFloat(),
startAngle = startAngle.toFloat(),
angle = angle.toFloat()
phiStart = startAngle.toFloat(),
phi = angle.toFloat()
).apply(block).also { setChild(name, it) }

View File

@ -34,7 +34,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
objectFactories[Box::class] = ThreeBoxFactory
objectFactories[Convex::class] = ThreeConvexFactory
objectFactories[Sphere::class] = ThreeSphereFactory
objectFactories[ConeSegment::class] = ThreeConeFactory
// objectFactories[ConeSegment::class] = ThreeConeFactory
objectFactories[PolyLine::class] = ThreeSmartLineFactory
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory