Compare commits

...

7 Commits

33 changed files with 2532 additions and 3 deletions

View File

@@ -0,0 +1,491 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:OptIn(ExperimentalUuidApi::class)
package proposals.v1
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
/**
* Abstract vertex that holds only an identifier.
* It can be used for accessing properties of some vertex of some polytopic construction.
*/
public class AbstractVertex internal constructor(public val id: Uuid = Uuid.random()) {
override fun toString(): String = "AbstractVertex#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractVertex) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
/**
* Abstract edge that holds only an identifier.
* It can be used for accessing properties of some edge of some polytopic construction.
*/
public class AbstractEdge internal constructor(public val id: Uuid = Uuid.random()) {
override fun toString(): String = "AbstractEdge#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractEdge) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
/**
* Abstract polygon that holds only an identifier.
* It can be used for accessing properties of some polygon of some polytopic construction.
*/
public class AbstractPolygon internal constructor(public val id: Uuid = Uuid.random()) {
override fun toString(): String = "AbstractPolygon#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractPolygon) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
/**
* Abstract polyhedron that holds only an identifier.
* It can be used for accessing properties of some polyhedron of some polytopic construction.
*/
public class AbstractPolyhedron internal constructor(public val id: Uuid = Uuid.random()) {
override fun toString(): String = "AbstractPolyhedron#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractPolyhedron) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
/**
* Abstract polytope that holds only an identifier.
* It can be used for accessing properties of some polytope of some polytopic construction.
*/
public class AbstractPolytope internal constructor(public val id: Uuid = Uuid.random()) {
override fun toString(): String = "AbstractPolytope#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractPolytope) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public typealias AbstractPolytopicConstruction2D<Vector> = PolytopicConstruction2D<Vector, AbstractVertex, AbstractEdge, AbstractPolygon>
public typealias MutableAbstractPolytopicConstruction2D<Vector> = MutablePolytopicConstruction2D<Vector, AbstractVertex, AbstractEdge, AbstractPolygon>
public typealias AbstractPolytopicConstruction3D<Vector> = PolytopicConstruction3D<Vector, AbstractVertex, AbstractEdge, AbstractPolygon, AbstractPolyhedron>
public typealias MutableAbstractPolytopicConstruction3D<Vector> = MutablePolytopicConstruction3D<Vector, AbstractVertex, AbstractEdge, AbstractPolygon, AbstractPolyhedron>
public typealias AbstractPolytopicConstruction<Vector> = PolytopicConstruction<Vector, AbstractVertex, AbstractPolytope>
public typealias MutableAbstractPolytopicConstruction<Vector> = MutablePolytopicConstruction<Vector, AbstractVertex, AbstractPolytope>
/**
* Builder of [AbstractPolytopicConstruction2D].
*/
public inline fun <Vector> AbstractPolytopicConstruction2D(
block: MutableAbstractPolytopicConstruction2D<Vector>.() -> Unit
): AbstractPolytopicConstruction2D<Vector> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return MutableAbstractPolytopicConstruction2DImpl<Vector>().apply(block)
}
@Suppress("EqualsOrHashCode")
@PublishedApi
internal class MutableAbstractPolytopicConstruction2DImpl<Vector> : MutableAbstractPolytopicConstruction2D<Vector> {
private class ActualVertex<Vector>(
val vertex: AbstractVertex,
val position: Vector,
) {
override fun equals(other: Any?): Boolean = this === other
}
private class ActualEdge<Vector>(
val edge: AbstractEdge,
val start: ActualVertex<Vector>,
val end: ActualVertex<Vector>,
) {
override fun equals(other: Any?): Boolean = this === other
}
private class ActualPolygon<Vector>(
val polygon: AbstractPolygon,
val vertices: Set<ActualVertex<Vector>>,
val edges: Set<ActualEdge<Vector>>,
) {
override fun equals(other: Any?): Boolean = this === other
}
private val _vertices: MutableMap<AbstractVertex, ActualVertex<Vector>> = mutableMapOf()
override val vertices: Set<AbstractVertex> get() = _vertices.keys
private val _edges: MutableMap<AbstractEdge, ActualEdge<Vector>> = mutableMapOf()
override val edges: Set<AbstractEdge> get() = _edges.keys
private val _polygons: MutableMap<AbstractPolygon, ActualPolygon<Vector>> = mutableMapOf()
override val polygons: Set<AbstractPolygon> = _polygons.keys
override val AbstractVertex.position: Vector get() = (_vertices[this] ?: error("No such vertex in the construction")).position
override fun addVertex(position: Vector): AbstractVertex {
val abstractVertex = AbstractVertex()
val actualVertex = ActualVertex(
vertex = abstractVertex,
position = position,
)
_vertices[abstractVertex] = actualVertex
return abstractVertex
}
override fun AbstractVertex.remove() {
val actualVertex = _vertices[this] ?: return
val abstractEdges = _edges.keys
for (abstractEdge in abstractEdges) {
val actualEdge = _edges[abstractEdge]!!
if (actualVertex == actualEdge.start || actualVertex == actualEdge.end) _edges.remove(abstractEdge)
}
val abstractPolygons = _polygons.keys
for (abstractPolygon in abstractPolygons) {
val actualPolygon = _polygons[abstractPolygon]!!
if (actualVertex in actualPolygon.vertices) _polygons.remove(abstractPolygon)
}
_vertices.remove(this)
}
override val AbstractEdge.start: AbstractVertex get() = (_edges[this] ?: error("No such edge in the construction")).start.vertex
override val AbstractEdge.end: AbstractVertex get() = (_edges[this] ?: error("No such edge in the construction")).end.vertex
override fun addEdge(start: AbstractVertex, end: AbstractVertex): AbstractEdge {
val abstractEdge = AbstractEdge()
val actualEdge = ActualEdge(
edge = abstractEdge,
start = _vertices[start] ?: error("No such vertex in the construction"),
end = _vertices[end] ?: error("No such vertex in the construction"),
)
_edges[abstractEdge] = actualEdge
return abstractEdge
}
override fun AbstractEdge.remove() {
val actualEdge = _edges[this] ?: return
val abstractPolygons = _polygons.keys
for (abstractPolygon in abstractPolygons) {
val actualPolygon = _polygons[abstractPolygon]!!
if (actualEdge in actualPolygon.edges) _polygons.remove(abstractPolygon)
}
_edges.remove(this)
}
override val AbstractPolygon.vertices: Set<AbstractVertex>
get() = (_polygons[this] ?: error("No such polygon in the construction")).vertices.mapTo(mutableSetOf()) { it.vertex }
override val AbstractPolygon.edges: Set<AbstractEdge>
get() = (_polygons[this] ?: error("No such polygon in the construction")).edges.mapTo(mutableSetOf()) { it.edge }
override fun addPolygon(vertices: Set<AbstractVertex>, edges: Set<AbstractEdge>): AbstractPolygon {
val abstractPolygon = AbstractPolygon()
val actualPolygon = ActualPolygon(
polygon = abstractPolygon,
vertices = vertices.mapTo(mutableSetOf()) { _vertices[it] ?: error("No such vertex in the construction") },
edges = edges.mapTo(mutableSetOf()) { _edges[it] ?: error("No such edge in the construction") },
)
_polygons[abstractPolygon] = actualPolygon
return abstractPolygon
}
override fun AbstractPolygon.remove() {
_polygons.remove(this)
}
}
/**
* Builder of [AbstractPolytopicConstruction3D].
*/
public inline fun <Vector> AbstractPolytopicConstruction3D(
block: MutableAbstractPolytopicConstruction3D<Vector>.() -> Unit
): AbstractPolytopicConstruction3D<Vector> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return MutableAbstractPolytopicConstruction3DImpl<Vector>().apply(block)
}
@Suppress("EqualsOrHashCode")
@PublishedApi
internal class MutableAbstractPolytopicConstruction3DImpl<Vector> : MutableAbstractPolytopicConstruction3D<Vector> {
private class ActualVertex<Vector>(
val vertex: AbstractVertex,
val position: Vector,
) {
override fun equals(other: Any?): Boolean = this === other
}
private class ActualEdge<Vector>(
val edge: AbstractEdge,
val start: ActualVertex<Vector>,
val end: ActualVertex<Vector>,
) {
override fun equals(other: Any?): Boolean = this === other
}
private class ActualPolygon<Vector>(
val polygon: AbstractPolygon,
val vertices: Set<ActualVertex<Vector>>,
val edges: Set<ActualEdge<Vector>>,
) {
override fun equals(other: Any?): Boolean = this === other
}
private class ActualPolyhedron<Vector>(
val polyhedron: AbstractPolyhedron,
val vertices: Set<ActualVertex<Vector>>,
val edges: Set<ActualEdge<Vector>>,
val faces: Set<ActualPolygon<Vector>>,
) {
override fun equals(other: Any?): Boolean = this === other
}
private val _vertices: MutableMap<AbstractVertex, ActualVertex<Vector>> = mutableMapOf()
override val vertices: Set<AbstractVertex> get() = _vertices.keys
private val _edges: MutableMap<AbstractEdge, ActualEdge<Vector>> = mutableMapOf()
override val edges: Set<AbstractEdge> get() = _edges.keys
private val _polygons: MutableMap<AbstractPolygon, ActualPolygon<Vector>> = mutableMapOf()
override val polygons: Set<AbstractPolygon> get() = _polygons.keys
private val _polyhedra: MutableMap<AbstractPolyhedron, ActualPolyhedron<Vector>> = mutableMapOf()
override val polyhedra: Set<AbstractPolyhedron> get() = _polyhedra.keys
override val AbstractVertex.position: Vector get() = (_vertices[this] ?: error("No such vertex in the construction")).position
override fun addVertex(position: Vector): AbstractVertex {
val abstractVertex = AbstractVertex()
val actualVertex = ActualVertex(
vertex = abstractVertex,
position = position,
)
_vertices[abstractVertex] = actualVertex
return abstractVertex
}
override fun AbstractVertex.remove() {
val actualVertex = _vertices[this] ?: return
val abstractEdges = _edges.keys
for (abstractEdge in abstractEdges) {
val actualEdge = _edges[abstractEdge]!!
if (actualVertex == actualEdge.start || actualVertex == actualEdge.end) _edges.remove(abstractEdge)
}
val abstractPolygons = _polygons.keys
for (abstractPolygon in abstractPolygons) {
val actualPolygon = _polygons[abstractPolygon]!!
if (actualVertex in actualPolygon.vertices) _polygons.remove(abstractPolygon)
}
val abstractPolyhedra = _polyhedra.keys
for (abstractPolyhedron in abstractPolyhedra) {
val actualPolyhedron = _polyhedra[abstractPolyhedron]!!
if (actualVertex in actualPolyhedron.vertices) _polyhedra.remove(abstractPolyhedron)
}
_vertices.remove(this)
}
override val AbstractEdge.start: AbstractVertex get() = (_edges[this] ?: error("No such edge in the construction")).start.vertex
override val AbstractEdge.end: AbstractVertex get() = (_edges[this] ?: error("No such edge in the construction")).end.vertex
override fun addEdge(start: AbstractVertex, end: AbstractVertex): AbstractEdge {
val abstractEdge = AbstractEdge()
val actualEdge = ActualEdge(
edge = abstractEdge,
start = _vertices[start] ?: error("No such vertex in the construction"),
end = _vertices[end] ?: error("No such vertex in the construction"),
)
_edges[abstractEdge] = actualEdge
return abstractEdge
}
override fun AbstractEdge.remove() {
val actualEdge = _edges[this] ?: return
val abstractPolygons = _polygons.keys
for (abstractPolygon in abstractPolygons) {
val actualPolygon = _polygons[abstractPolygon]!!
if (actualEdge in actualPolygon.edges) _polygons.remove(abstractPolygon)
}
val abstractPolyhedra = _polyhedra.keys
for (abstractPolyhedron in abstractPolyhedra) {
val actualPolyhedron = _polyhedra[abstractPolyhedron]!!
if (actualEdge in actualPolyhedron.edges) _polyhedra.remove(abstractPolyhedron)
}
_edges.remove(this)
}
override val AbstractPolygon.vertices: Set<AbstractVertex>
get() = (_polygons[this] ?: error("No such polygon in the construction")).vertices.mapTo(mutableSetOf()) { it.vertex }
override val AbstractPolygon.edges: Set<AbstractEdge>
get() = (_polygons[this] ?: error("No such polygon in the construction")).edges.mapTo(mutableSetOf()) { it.edge }
override fun addPolygon(vertices: Set<AbstractVertex>, edges: Set<AbstractEdge>): AbstractPolygon {
val abstractPolygon = AbstractPolygon()
val actualPolygon = ActualPolygon(
polygon = abstractPolygon,
vertices = vertices.mapTo(mutableSetOf()) { _vertices[it] ?: error("No such vertex in the construction") },
edges = edges.mapTo(mutableSetOf()) { _edges[it] ?: error("No such edge in the construction") },
)
_polygons[abstractPolygon] = actualPolygon
return abstractPolygon
}
override fun AbstractPolygon.remove() {
val actualPolygon = _polygons[this] ?: return
val abstractPolyhedra = _polyhedra.keys
for (abstractPolyhedron in abstractPolyhedra) {
val actualPolyhedron = _polyhedra[abstractPolyhedron]!!
if (actualPolygon in actualPolyhedron.faces) _polyhedra.remove(abstractPolyhedron)
}
_polygons.remove(this)
}
override val AbstractPolyhedron.vertices: Set<AbstractVertex>
get() = (_polyhedra[this] ?: error("No such polyhedron in the construction")).vertices.mapTo(mutableSetOf()) { it.vertex }
override val AbstractPolyhedron.edges: Set<AbstractEdge>
get() = (_polyhedra[this] ?: error("No such polyhedron in the construction")).edges.mapTo(mutableSetOf()) { it.edge }
override val AbstractPolyhedron.faces: Set<AbstractPolygon>
get() = (_polyhedra[this] ?: error("No such polyhedron in the construction")).faces.mapTo(mutableSetOf()) { it.polygon }
override fun addPolyhedron(
vertices: Set<AbstractVertex>,
edges: Set<AbstractEdge>,
faces: Set<AbstractPolygon>
): AbstractPolyhedron {
val abstractPolyhedron = AbstractPolyhedron()
val actualPolyhedron = ActualPolyhedron(
polyhedron = abstractPolyhedron,
vertices = vertices.mapTo(mutableSetOf()) { _vertices[it] ?: error("No such vertex in the construction") },
edges = edges.mapTo(mutableSetOf()) { _edges[it] ?: error("No such edge in the construction") },
faces = faces.mapTo(mutableSetOf()) { _polygons[it] ?: error("No such polygon in the construction") },
)
_polyhedra[abstractPolyhedron] = actualPolyhedron
return abstractPolyhedron
}
override fun AbstractPolyhedron.remove() {
_polyhedra.remove(this)
}
}
/**
* Builder for [AbstractPolytopicConstruction].
*/
public inline fun <Vector> AbstractPolytopicConstruction(
dimension: Int,
block: MutableAbstractPolytopicConstruction<Vector>.() -> Unit
): AbstractPolytopicConstruction<Vector> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return MutableAbstractPolytopicConstructionImpl<Vector>(dimension).apply(block)
}
@Suppress("EqualsOrHashCode")
@PublishedApi
internal class MutableAbstractPolytopicConstructionImpl<Vector>(
override val dimension: Int,
) : MutableAbstractPolytopicConstruction<Vector> {
private class ActualVertex<Vector>(
val vertex: AbstractVertex,
correspondingAbstractPolytope: AbstractPolytope,
val position: Vector,
) {
val correspondingPolytope: ActualPolytope<Vector> =
ActualPolytope(
polytope = correspondingAbstractPolytope,
correspondingVertex = this,
dimension = 0,
vertices = setOf(this),
faces = emptyList()
)
override fun equals(other: Any?): Boolean = this === other
}
private class ActualPolytope<Vector>(
val polytope: AbstractPolytope,
val correspondingVertex: ActualVertex<Vector>?,
val dimension: Int,
val vertices: Set<ActualVertex<Vector>>,
val faces: List<Set<ActualPolytope<Vector>>>
) {
override fun equals(other: Any?): Boolean = this === other
}
private val _vertices: MutableMap<AbstractVertex, ActualVertex<Vector>> = mutableMapOf()
override val vertices: Set<AbstractVertex> get() = _vertices.keys
private val _polytopes: List<MutableMap<AbstractPolytope, ActualPolytope<Vector>>> = List(dimension + 1) { mutableMapOf() }
override val polytopes: List<Set<AbstractPolytope>> get() = _polytopes.map { it.keys }
private val allPolytopes: MutableMap<AbstractPolytope, ActualPolytope<Vector>> = mutableMapOf()
override val AbstractVertex.position: Vector get() = (_vertices[this] ?: error("No such vertex in the construction")).position
override fun AbstractVertex.asPolytope(): AbstractPolytope =
(_vertices[this] ?: error("No such vertex in the construction")).correspondingPolytope.polytope
override fun addVertex(position: Vector): AbstractVertex {
val abstractVertex = AbstractVertex()
val actualVertex = ActualVertex(
vertex = abstractVertex,
correspondingAbstractPolytope = AbstractPolytope(),
position = position,
)
_vertices[abstractVertex] = actualVertex
_polytopes[0][actualVertex.correspondingPolytope.polytope] = actualVertex.correspondingPolytope
allPolytopes[actualVertex.correspondingPolytope.polytope] = actualVertex.correspondingPolytope
return abstractVertex
}
override fun AbstractVertex.remove() {
val actualVertex = _vertices[this] ?: return
_polytopes.forEach {
val abstractPolytopes = it.keys
for (abstractPolytope in abstractPolytopes) {
val actualPolytope = it[abstractPolytope]!!
if (actualVertex in actualPolytope.vertices) it.remove(abstractPolytope)
}
}
_vertices.remove(this)
}
override val AbstractPolytope.dimension: Int
get() = (allPolytopes[this] ?: error("No such polytope in the construction")).dimension
override val AbstractPolytope.vertices: Set<AbstractVertex>
get() = (allPolytopes[this] ?: error("No such polytope in the construction")).vertices.mapTo(mutableSetOf()) { it.vertex }
override val AbstractPolytope.faces: List<Set<AbstractPolytope>>
get() = (allPolytopes[this] ?: error("No such polytope in the construction")).faces.map { facesOfDimension -> facesOfDimension.mapTo(mutableSetOf()) { it.polytope } }
override fun addPolytope(
dimension: Int,
vertices: Set<AbstractVertex>,
faces: List<Set<AbstractPolytope>>
): AbstractPolytope {
require(dimension > 0) { "0-dimensional polytopes should created via 'addVertex' method" }
val abstractPolytope = AbstractPolytope()
val actualPolytope = ActualPolytope(
polytope = abstractPolytope,
correspondingVertex = null,
dimension = dimension,
vertices = vertices.mapTo(mutableSetOf()) { _vertices[it] ?: error("No such vertex in the construction") },
faces = faces.mapIndexed { dim, faces -> faces.mapTo(mutableSetOf()) { _polytopes[dim][it] ?: error("No such polytope in the construction") } },
)
_polytopes[dimension][abstractPolytope] = actualPolytope
allPolytopes[abstractPolytope] = actualPolytope
return abstractPolytope
}
override fun AbstractPolytope.remove() {
val thisActualPolytope = allPolytopes[this] ?: return
for (dim in thisActualPolytope.dimension + 1 .. this@MutableAbstractPolytopicConstructionImpl.dimension) {
val abstractPolytopes = _polytopes[dim].keys
for (abstractPolytope in abstractPolytopes) {
val actualPolytope = _polytopes[dim][abstractPolytope]!!
if (thisActualPolytope in actualPolytope.faces[thisActualPolytope.dimension]) {
_polytopes[dim].remove(abstractPolytope)
allPolytopes.remove(abstractPolytope)
}
}
}
_polytopes[thisActualPolytope.dimension].remove(this)
allPolytopes.remove(this)
thisActualPolytope.correspondingVertex?.also { _vertices.remove(it.vertex) }
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v1
/**
* The polytopic construction.
*/
public interface PolytopicConstruction<Vector, Vertex, Polytope> {
/**
* Dimension of the polytopic construction.
*/
public val dimension: Int
/**
* Contains all the polytopes in the construction.
* Each index `i` corresponds to set of all polytopes of dimension `i`.
* Its size is [dimension]` + 1`.
*/
public val polytopes: List<Set<Polytope>>
/**
* Contains all the vertices in the construction.
* Actually, it is the first set in the [polytopes] list but with right type.
*/
public val vertices: Set<Vertex>
/**
* Dimension of the polytope in the construction.
*/
public val Polytope.dimension: Int
/**
* Contains all the faces of [this] polytope.
* Each index `i` corresponds to set of all faces of dimension `i`.
* Its size is `dimension` (where `dimension` is the polytope's dimension).
*/
public val Polytope.faces: List<Set<Polytope>>
/**
* Contains all the vertices in [this] polytope.
* Actually, it is the first set in the [faces] list but with right type.
*/
public val Polytope.vertices: Set<Vertex>
/**
* Position of [this] vertex in Euclidean space.
*/
public val Vertex.position: Vector
/**
* Returns 0-dimensional polytope associated with the vertex.
*/
public fun Vertex.asPolytope(): Polytope
}
/**
* The mutable polytopic construction.
*/
public interface MutablePolytopicConstruction<Vector, Vertex, Polytope> : PolytopicConstruction<Vector, Vertex, Polytope> {
/**
* Creates new vertex with provided position.
*/
public fun addVertex(position: Vector): Vertex
/**
* Creates new polytope by its dimension, its faces, and its vertices.
*/
public fun addPolytope(
dimension: Int,
vertices: Set<Vertex>,
faces: List<Set<Polytope>>,
): Polytope
/**
* Removes the vertex.
* Also removes all polytopes that contain the vertex.
*/
public fun Vertex.remove()
/**
* Removes the polytope.
* Also removes all polytopes that contain the polytope.
*/
public fun Polytope.remove()
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v1
/**
* The 2D polytopic construction.
*/
public interface PolytopicConstruction2D<Vector, Vertex, Edge, Polygon> {
/**
* Contains all the vertices in the construction.
*/
public val vertices: Set<Vertex>
/**
* Contains all the edges in the construction.
*/
public val edges: Set<Edge>
/**
* Contains all the polygons in the construction.
*/
public val polygons: Set<Polygon>
/**
* Returns position of the vertex.
*/
public val Vertex.position: Vector
/**
* Returns start vertex of the edge. It is just some one vertex of the edge.
*/
public val Edge.start: Vertex
/**
* Returns end vertex of the edge. It is just some one vertex of the edge.
*/
public val Edge.end: Vertex
/**
* Returns all vertices of the polygon.
*/
public val Polygon.vertices: Set<Vertex>
/**
* Returns all edges of the polytope.
*/
public val Polygon.edges: Set<Edge>
}
/**
* The 2D mutable polytopic construction.
*/
public interface MutablePolytopicConstruction2D<Vector, Vertex, Edge, Polygon> : PolytopicConstruction2D<Vector, Vertex, Edge, Polygon> {
/**
* Creates new vertex with provided position.
*/
public fun addVertex(position: Vector): Vertex
/**
* Creates new edge with provided ends.
*/
public fun addEdge(start: Vertex, end: Vertex): Edge
/**
* Creates new polygon with provided vertices and edges.
*/
public fun addPolygon(vertices: Set<Vertex>, edges: Set<Edge>): Polygon
/**
* Removes the vertex.
* Also removes all edges and polygons that contain the vertex.
*/
public fun Vertex.remove()
/**
* Removes the edge.
* Also removes all polygons that contain the edge.
*/
public fun Edge.remove()
/**
* Removes the polygon.
*/
public fun Polygon.remove()
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v1
/**
* The 3D polytopic construction.
*/
public interface PolytopicConstruction3D<Vector, Vertex, Edge, Polygon, Polyhedron> {
/**
* Contains all the vertices in the construction.
*/
public val vertices: Set<Vertex>
/**
* Contains all the edges in the construction.
*/
public val edges: Set<Edge>
/**
* Contains all the polygons in the construction.
*/
public val polygons: Set<Polygon>
/**
* Contains all the polyhedra in the construction.
*/
public val polyhedra: Set<Polyhedron>
/**
* Returns position of the vertex.
*/
public val Vertex.position: Vector
/**
* Returns start vertex of the edge. It is just some one vertex of the edge.
*/
public val Edge.start: Vertex
/**
* Returns end vertex of the edge. It is just some one vertex of the edge.
*/
public val Edge.end: Vertex
/**
* Returns all vertices of the polygon.
*/
public val Polygon.vertices: Set<Vertex>
/**
* Returns all edges of the polytope.
*/
public val Polygon.edges: Set<Edge>
/**
* Returns all vertices of the polyhedron.
*/
public val Polyhedron.vertices: Set<Vertex>
/**
* Returns all edges of the polyhedron.
*/
public val Polyhedron.edges: Set<Edge>
/**
* Returns all faces of the polyhedron.
*/
public val Polyhedron.faces: Set<Polygon>
}
public interface MutablePolytopicConstruction3D<Vector, Vertex, Edge, Polygon, Polyhedron> : PolytopicConstruction3D<Vector, Vertex, Edge, Polygon, Polyhedron> {
/**
* Creates new vertex with provided position.
*/
public fun addVertex(position: Vector): Vertex
/**
* Creates new edge with provided ends.
*/
public fun addEdge(start: Vertex, end: Vertex): Edge
/**
* Creates new polygon with provided vertices and edges.
*/
public fun addPolygon(vertices: Set<Vertex>, edges: Set<Edge>): Polygon
/**
* Creates new polyhedron with provided vertices, edges, and faces.
*/
public fun addPolyhedron(vertices: Set<Vertex>, edges: Set<Edge>, faces: Set<Polygon>): Polyhedron
/**
* Removes the vertex.
* Also removes all edges, polygons, and polyhedra that contain the vertex.
*/
public fun Vertex.remove()
/**
* Removes the edge.
* Also removes all polygons and polyhedra that contain the edge.
*/
public fun Edge.remove()
/**
* Removes the polygon.
* Also removes all polyhedra that contain the edge.
*/
public fun Polygon.remove()
/**
* Removes the polyhedra.
*/
public fun Polyhedron.remove()
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v1
import space.kscience.kmath.geometry.GeometrySpace
import space.kscience.kmath.geometry.projectAlong
/**
* Projects the [projectedPolytopicConstruction] along [normal] onto hyperplane normal to the [normal]
* and going through [base] and adds projection results to [targetPolytopicConstruction].
*/
public fun <V: Any, PVertex, PPolytope, TVertex, TPolytope> GeometrySpace<V, *>.projectAlong(
projectedPolytopicConstruction: PolytopicConstruction<V, PVertex, PPolytope>,
targetPolytopicConstruction: MutablePolytopicConstruction<V, TVertex, TPolytope>,
normal: V,
base: V,
) {
require(targetPolytopicConstruction.dimension >= projectedPolytopicConstruction.dimension - 1)
with(projectedPolytopicConstruction) {
with(targetPolytopicConstruction) {
val newVertices: Map<PVertex, TVertex> = projectedPolytopicConstruction.vertices.associateWith { vertex ->
addVertex(projectAlong(vertex.position, normal, base))
}
val newPolytopes: MutableList<Map<PPolytope, TPolytope>> =
mutableListOf(
buildMap {
for ((pVertex, tVertex) in newVertices) put(pVertex.asPolytope(), tVertex.asPolytope())
}
)
for (dim in 1 ..< projectedPolytopicConstruction.dimension)
newPolytopes += buildMap {
for (pPolytope in projectedPolytopicConstruction.polytopes[dim]) {
@Suppress("UNCHECKED_CAST")
val tVertices = pPolytope.vertices.mapTo(mutableSetOf()) { newVertices[it] as TVertex }
val tFaces: MutableList<Set<TPolytope>> = mutableListOf()
for (subdim in 0 ..< dim)
@Suppress("UNCHECKED_CAST")
tFaces += pPolytope.faces[subdim].mapTo(mutableSetOf()) { newPolytopes[subdim][it] as TPolytope }
put(
pPolytope,
addPolytope(
dimension = dim,
vertices = tVertices,
faces = tFaces,
)
)
}
}
}
}
}
/**
* Projects the [polytopicConstruction3D] along [normal] onto hyperplane normal to the [normal] and going through [base].
* Result is a new [AbstractPolytopicConstruction2D].
*/
public fun <
V: Any,
PVertex,
PEdge,
PPolygon,
> GeometrySpace<V, *>.projectAlongToAbstractPolytopicConstruction2D(
polytopicConstruction3D: PolytopicConstruction3D<V, PVertex, PEdge, PPolygon, *>,
normal: V,
base: V,
): AbstractPolytopicConstruction2D<V> = with(polytopicConstruction3D) {
AbstractPolytopicConstruction2D {
val newVertices = polytopicConstruction3D.vertices.associateWith { vertex ->
addVertex(projectAlong(vertex.position, normal, base))
}
val newEdges = polytopicConstruction3D.edges.associateWith { edge ->
addEdge(newVertices[edge.start]!!, newVertices[edge.end]!!)
}
polytopicConstruction3D.polygons.forEach { polygon ->
addPolygon(
vertices = polygon.vertices.mapTo(mutableSetOf()) { newVertices[it]!! },
edges = polygon.edges.mapTo(mutableSetOf()) { newEdges[it]!! }
)
}
}
}
/**
* Returns vertex of [polytopicConstruction] nearest to the [point].
*/
public fun <
Vector: Any,
Vertex
> GeometrySpace<Vector, *>.nearestVertexOfTo(
polytopicConstruction: PolytopicConstruction<Vector, Vertex, *>,
point: Vector,
): Vertex =
with(polytopicConstruction) { vertices.minBy { it.position.distanceTo(point) } }
/**
* Removes vertex of [polytopicConstruction] nearest to the [point].
*/
public fun <
Vector: Any,
Vertex
> GeometrySpace<Vector, *>.removeNearestVertexOfTo(
polytopicConstruction: MutablePolytopicConstruction<Vector, Vertex, *>,
point: Vector,
) {
val vertexToRemove = nearestVertexOfTo(polytopicConstruction, point)
with(polytopicConstruction) { vertexToRemove.remove() }
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:OptIn(ExperimentalUuidApi::class)
package proposals.v2.v1
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
public class AbstractVertex<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction<Vector>,
override val position: Vector
) : MutablePolytopicConstruction.Vertex<Vector, AbstractVertex<Vector>, AbstractPolytope<Vector>> {
public val id: Uuid = Uuid.random()
private val correspondingPolytope = AbstractPolytope(
construction = construction,
correspondingVertex = this,
dimension = 0,
vertices = setOf(this),
faces = emptyList(),
)
override fun asPolytope(): AbstractPolytope<Vector> = correspondingPolytope
override fun remove() {
construction._polytopes.forEach { polytopes -> polytopes.removeAll { this in it.vertices } }
construction._vertices.remove(this)
}
override fun toString(): String = "AbstractVertex#${id.toHexString()} at $position"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractVertex<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolytope<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction<Vector>,
private val correspondingVertex: AbstractVertex<Vector>?,
override val dimension: Int,
override val vertices: Set<AbstractVertex<Vector>>,
override val faces: List<Set<AbstractPolytope<Vector>>>,
) : MutablePolytopicConstruction.Polytope<Vector, AbstractVertex<Vector>, AbstractPolytope<Vector>> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._polytopes[dimension].remove(this)
for (i in dimension + 1 .. construction.dimension)
construction._polytopes[i].removeAll { this in it.faces[dimension] }
correspondingVertex?.also { construction._vertices.remove(it) }
}
override fun toString(): String = "AbstractPolytope#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractPolytope<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolytopicConstruction<Vector>(
override val dimension: Int,
) : MutablePolytopicConstruction<Vector, AbstractVertex<Vector>, AbstractPolytope<Vector>> {
internal val _vertices: MutableSet<AbstractVertex<Vector>> = mutableSetOf()
override val vertices: Set<AbstractVertex<Vector>> get() = _vertices
internal val _polytopes: List<MutableSet<AbstractPolytope<Vector>>> = List(dimension + 1) { mutableSetOf() }
override val polytopes: List<Set<AbstractPolytope<Vector>>> get() = _polytopes
override fun addVertex(position: Vector): AbstractVertex<Vector> {
val vertex = AbstractVertex(
construction = this,
position = position,
)
_vertices.add(vertex)
_polytopes[0].add(vertex.asPolytope())
return vertex
}
override fun addPolytope(
dimension: Int,
vertices: Set<AbstractVertex<Vector>>,
faces: List<Set<AbstractPolytope<Vector>>>
): AbstractPolytope<Vector> {
require(dimension > 0)
val polytope = AbstractPolytope(
construction = this,
correspondingVertex = null,
dimension = dimension,
vertices = vertices,
faces = faces,
)
_polytopes[dimension].add(polytope)
return polytope
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:OptIn(ExperimentalUuidApi::class)
package proposals.v2.v1
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
public class AbstractVertex2D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction2D<Vector>,
override val position: Vector
) : MutablePolytopicConstruction2D.Vertex<Vector> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._vertices.remove(this)
construction._edges.removeAll { this == it.start || this == it.end }
construction._polygons.removeAll { this in it.vertices }
}
override fun toString(): String = "AbstractVertex2D#${id.toHexString()} at $position"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractVertex2D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractEdge2D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction2D<Vector>,
override val start: AbstractVertex2D<Vector>,
override val end: AbstractVertex2D<Vector>,
) : MutablePolytopicConstruction2D.Edge<Vector, AbstractVertex2D<Vector>> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._edges.remove(this)
construction._polygons.removeAll { this in it.edges }
}
override fun toString(): String = "AbstractEdge2D#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractEdge2D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolygon2D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction2D<Vector>,
override val vertices: Set<AbstractVertex2D<Vector>>,
override val edges: Set<AbstractEdge2D<Vector>>,
) : MutablePolytopicConstruction2D.Polygon<Vector, AbstractVertex2D<Vector>, AbstractEdge2D<Vector>> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._polygons.remove(this)
}
override fun toString(): String = "AbstractEdge2D#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractEdge2D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolytopicConstruction2D<Vector> : MutablePolytopicConstruction2D<Vector, AbstractVertex2D<Vector>, AbstractEdge2D<Vector>, AbstractPolygon2D<Vector>> {
internal val _vertices: MutableSet<AbstractVertex2D<Vector>> = mutableSetOf()
override val vertices: Set<AbstractVertex2D<Vector>> get() = _vertices
internal val _edges: MutableSet<AbstractEdge2D<Vector>> = mutableSetOf()
override val edges: Set<AbstractEdge2D<Vector>> get() = _edges
internal val _polygons: MutableSet<AbstractPolygon2D<Vector>> = mutableSetOf()
override val polygons: Set<AbstractPolygon2D<Vector>> get() = _polygons
override fun addVertex(position: Vector): AbstractVertex2D<Vector> {
val vertex = AbstractVertex2D(
construction = this,
position = position,
)
_vertices.add(vertex)
return vertex
}
override fun addEdge(start: AbstractVertex2D<Vector>, end: AbstractVertex2D<Vector>): AbstractEdge2D<Vector> {
val edge = AbstractEdge2D(
construction = this,
start = start,
end = end,
)
_edges.add(edge)
return edge
}
override fun addPolygon(
vertices: Set<AbstractVertex2D<Vector>>,
edges: Set<AbstractEdge2D<Vector>>
): AbstractPolygon2D<Vector> {
val polygon = AbstractPolygon2D(
construction = this,
vertices = vertices,
edges = edges,
)
_polygons.add(polygon)
return polygon
}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:OptIn(ExperimentalUuidApi::class)
package proposals.v2.v1
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
public class AbstractVertex3D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction3D<Vector>,
override val position: Vector
) : MutablePolytopicConstruction3D.Vertex<Vector> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._vertices.remove(this)
construction._edges.removeAll { this == it.start || this == it.end }
construction._polygons.removeAll { this in it.vertices }
construction._polyhedra.removeAll { this in it.vertices }
}
override fun toString(): String = "AbstractVertex3D#${id.toHexString()} at $position"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractVertex3D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractEdge3D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction3D<Vector>,
override val start: AbstractVertex3D<Vector>,
override val end: AbstractVertex3D<Vector>,
) : MutablePolytopicConstruction3D.Edge<Vector, AbstractVertex3D<Vector>> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._edges.remove(this)
construction._polygons.removeAll { this in it.edges }
construction._polyhedra.removeAll { this in it.edges }
}
override fun toString(): String = "AbstractEdge3D#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractEdge3D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolygon3D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction3D<Vector>,
override val vertices: Set<AbstractVertex3D<Vector>>,
override val edges: Set<AbstractEdge3D<Vector>>,
) : MutablePolytopicConstruction3D.Polygon<Vector, AbstractVertex3D<Vector>, AbstractEdge3D<Vector>> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._polygons.remove(this)
construction._polyhedra.removeAll { this in it.faces }
}
override fun toString(): String = "AbstractEdge3D#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractEdge3D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolyhedron3D<Vector> internal constructor(
private val construction: AbstractPolytopicConstruction3D<Vector>,
override val vertices: Set<AbstractVertex3D<Vector>>,
override val edges: Set<AbstractEdge3D<Vector>>,
override val faces: Set<AbstractPolygon3D<Vector>>,
) : MutablePolytopicConstruction3D.Polyhedron<Vector, AbstractVertex3D<Vector>, AbstractEdge3D<Vector>, AbstractPolygon3D<Vector>> {
public val id: Uuid = Uuid.random()
override fun remove() {
construction._polyhedra.remove(this)
}
override fun toString(): String = "AbstractEdge3D#${id.toHexString()}"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AbstractEdge3D<*>) return false
return id == other.id
}
override fun hashCode(): Int = id.hashCode()
}
public class AbstractPolytopicConstruction3D<Vector> : MutablePolytopicConstruction3D<Vector, AbstractVertex3D<Vector>, AbstractEdge3D<Vector>, AbstractPolygon3D<Vector>, AbstractPolyhedron3D<Vector>> {
internal val _vertices: MutableSet<AbstractVertex3D<Vector>> = mutableSetOf()
override val vertices: Set<AbstractVertex3D<Vector>> get() = _vertices
internal val _edges: MutableSet<AbstractEdge3D<Vector>> = mutableSetOf()
override val edges: Set<AbstractEdge3D<Vector>> get() = _edges
internal val _polygons: MutableSet<AbstractPolygon3D<Vector>> = mutableSetOf()
override val polygons: Set<AbstractPolygon3D<Vector>> get() = _polygons
internal val _polyhedra: MutableSet<AbstractPolyhedron3D<Vector>> = mutableSetOf()
override val polyhedra: Set<AbstractPolyhedron3D<Vector>> get() = _polyhedra
override fun addVertex(position: Vector): AbstractVertex3D<Vector> {
val vertex = AbstractVertex3D(
construction = this,
position = position,
)
_vertices.add(vertex)
return vertex
}
override fun addEdge(start: AbstractVertex3D<Vector>, end: AbstractVertex3D<Vector>): AbstractEdge3D<Vector> {
val edge = AbstractEdge3D(
construction = this,
start = start,
end = end,
)
_edges.add(edge)
return edge
}
override fun addPolygon(
vertices: Set<AbstractVertex3D<Vector>>,
edges: Set<AbstractEdge3D<Vector>>
): AbstractPolygon3D<Vector> {
val polygon = AbstractPolygon3D(
construction = this,
vertices = vertices,
edges = edges,
)
_polygons.add(polygon)
return polygon
}
override fun addPolyhedron(
vertices: Set<AbstractVertex3D<Vector>>,
edges: Set<AbstractEdge3D<Vector>>,
faces: Set<AbstractPolygon3D<Vector>>
): AbstractPolyhedron3D<Vector> {
val polyhedron = AbstractPolyhedron3D(
construction = this,
vertices = vertices,
edges = edges,
faces = faces,
)
_polyhedra.add(polyhedron)
return polyhedron
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v1
public interface PolytopicConstruction<
out Vector,
out VertexType: PolytopicConstruction.Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: PolytopicConstruction.Polytope<Vector, VertexType, PolytopeType>,
> {
public val dimension: Int
public val vertices: Set<VertexType>
public val polytopes: List<Set<PolytopeType>>
public interface Vertex<
out Vector,
out VertexType: Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: Polytope<Vector, VertexType, PolytopeType>,
> {
public val position: Vector
public fun asPolytope(): PolytopeType
}
public interface Polytope<
out Vector,
out VertexType: Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: Polytope<Vector, VertexType, PolytopeType>,
> {
public val dimension: Int
public val vertices: Set<VertexType>
public val faces: List<Set<PolytopeType>>
}
}
public interface MutablePolytopicConstruction<
Vector,
VertexType: MutablePolytopicConstruction.Vertex<Vector, VertexType, PolytopeType>,
PolytopeType: MutablePolytopicConstruction.Polytope<Vector, VertexType, PolytopeType>,
> : PolytopicConstruction<Vector, VertexType, PolytopeType> {
public fun addVertex(position: Vector): VertexType
public fun addPolytope(
dimension: Int,
vertices: Set<VertexType>,
faces: List<Set<PolytopeType>>,
): PolytopeType
public interface Vertex<
out Vector,
out VertexType: Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: Polytope<Vector, VertexType, PolytopeType>,
> : PolytopicConstruction.Vertex<Vector, VertexType, PolytopeType> {
public fun remove()
}
public interface Polytope<
out Vector,
out VertexType: Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: Polytope<Vector, VertexType, PolytopeType>,
> : PolytopicConstruction.Polytope<Vector, VertexType, PolytopeType> {
public fun remove()
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v1
public interface PolytopicConstruction2D<
out Vector,
out VertexType: PolytopicConstruction2D.Vertex<Vector>,
out EdgeType: PolytopicConstruction2D.Edge<Vector, VertexType>,
out PolygonType: PolytopicConstruction2D.Polygon<Vector, VertexType, EdgeType>,
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
public val polygons: Set<PolygonType>
public interface Vertex<
out Vector,
> {
public val position: Vector
}
public interface Edge<
out Vector,
out VertexType: Vertex<Vector>,
> {
public val start: VertexType
public val end: VertexType
}
public interface Polygon<
out Vector,
out VertexType: Vertex<Vector>,
out EdgeType: Edge<Vector, VertexType>,
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
}
}
public interface MutablePolytopicConstruction2D<
Vector,
VertexType: MutablePolytopicConstruction2D.Vertex<Vector>,
EdgeType: MutablePolytopicConstruction2D.Edge<Vector, VertexType>,
out PolygonType: MutablePolytopicConstruction2D.Polygon<Vector, VertexType, EdgeType>,
> : PolytopicConstruction2D<Vector, VertexType, EdgeType, PolygonType> {
public fun addVertex(position: Vector): VertexType
public fun addEdge(
start: VertexType,
end: VertexType,
): EdgeType
public fun addPolygon(
vertices: Set<VertexType>,
edges: Set<EdgeType>,
): PolygonType
public interface Vertex<
out Vector,
> : PolytopicConstruction2D.Vertex<Vector> {
public fun remove()
}
public interface Edge<
out Vector,
out VertexType: Vertex<Vector>,
> : PolytopicConstruction2D.Edge<Vector, VertexType> {
public fun remove()
}
public interface Polygon<
out Vector,
out VertexType: Vertex<Vector>,
out EdgeType: Edge<Vector, VertexType>,
> : PolytopicConstruction2D.Polygon<Vector, VertexType, EdgeType> {
public fun remove()
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v1
public interface PolytopicConstruction3D<
out Vector,
out VertexType: PolytopicConstruction3D.Vertex<Vector>,
out EdgeType: PolytopicConstruction3D.Edge<Vector, VertexType>,
out PolygonType: PolytopicConstruction3D.Polygon<Vector, VertexType, EdgeType>,
out PolyhedronType: PolytopicConstruction3D.Polyhedron<Vector, VertexType, EdgeType, PolygonType>,
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
public val polygons: Set<PolygonType>
public val polyhedra: Set<PolyhedronType>
public interface Vertex<
out Vector,
> {
public val position: Vector
}
public interface Edge<
out Vector,
out VertexType: Vertex<Vector>,
> {
public val start: VertexType
public val end: VertexType
}
public interface Polygon<
out Vector,
out VertexType: Vertex<Vector>,
out EdgeType: Edge<Vector, VertexType>,
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
}
public interface Polyhedron<
out Vector,
out VertexType: Vertex<Vector>,
out EdgeType: Edge<Vector, VertexType>,
out PolygonType: Polygon<Vector, VertexType, EdgeType>,
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
public val faces: Set<PolygonType>
}
}
public interface MutablePolytopicConstruction3D<
Vector,
VertexType: MutablePolytopicConstruction3D.Vertex<Vector>,
EdgeType: MutablePolytopicConstruction3D.Edge<Vector, VertexType>,
PolygonType: MutablePolytopicConstruction3D.Polygon<Vector, VertexType, EdgeType>,
out PolyhedronType: MutablePolytopicConstruction3D.Polyhedron<Vector, VertexType, EdgeType, PolygonType>,
> : PolytopicConstruction3D<Vector, VertexType, EdgeType, PolygonType, PolyhedronType> {
public fun addVertex(position: Vector): VertexType
public fun addEdge(
start: VertexType,
end: VertexType,
): EdgeType
public fun addPolygon(
vertices: Set<VertexType>,
edges: Set<EdgeType>,
): PolygonType
public fun addPolyhedron(
vertices: Set<VertexType>,
edges: Set<EdgeType>,
faces: Set<PolygonType>,
): PolyhedronType
public interface Vertex<
out Vector,
> : PolytopicConstruction3D.Vertex<Vector> {
public fun remove()
}
public interface Edge<
out Vector,
out VertexType: Vertex<Vector>,
> : PolytopicConstruction3D.Edge<Vector, VertexType> {
public fun remove()
}
public interface Polygon<
out Vector,
out VertexType: Vertex<Vector>,
out EdgeType: Edge<Vector, VertexType>,
> : PolytopicConstruction3D.Polygon<Vector, VertexType, EdgeType> {
public fun remove()
}
public interface Polyhedron<
out Vector,
out VertexType: Vertex<Vector>,
out EdgeType: Edge<Vector, VertexType>,
out PolygonType: Polygon<Vector, VertexType, EdgeType>,
> : PolytopicConstruction3D.Polyhedron<Vector, VertexType, EdgeType, PolygonType> {
public fun remove()
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v1
import space.kscience.kmath.geometry.GeometrySpace
import space.kscience.kmath.geometry.projectAlong
public fun <
V: Any,
PVertex : PolytopicConstruction.Vertex<V, PVertex, PPolytope>,
PPolytope : PolytopicConstruction.Polytope<V, PVertex, PPolytope>,
TVertex : MutablePolytopicConstruction.Vertex<V, TVertex, TPolytope>,
TPolytope : MutablePolytopicConstruction.Polytope<V, TVertex, TPolytope>
> GeometrySpace<V, *>.projectAlong(
projectedPolytopicConstruction: PolytopicConstruction<V, PVertex, PPolytope>,
targetPolytopicConstruction: MutablePolytopicConstruction<V, TVertex, TPolytope>,
normal: V,
base: V,
) {
require(targetPolytopicConstruction.dimension >= projectedPolytopicConstruction.dimension - 1)
with(targetPolytopicConstruction) {
val newVertices: Map<PVertex, TVertex> = projectedPolytopicConstruction.vertices.associateWith { vertex ->
addVertex(projectAlong(vertex.position, normal, base))
}
val newPolytopes: MutableList<Map<PPolytope, TPolytope>> =
mutableListOf(
buildMap {
for ((pVertex, tVertex) in newVertices) put(pVertex.asPolytope(), tVertex.asPolytope())
}
)
for (dim in 1 ..< projectedPolytopicConstruction.dimension)
newPolytopes += buildMap {
for (pPolytope in projectedPolytopicConstruction.polytopes[dim]) {
val tVertices = pPolytope.vertices.mapTo(mutableSetOf()) { newVertices[it]!! }
val tFaces: MutableList<Set<TPolytope>> = mutableListOf()
for (subdim in 0 ..< dim)
tFaces += pPolytope.faces[subdim].mapTo(mutableSetOf()) { newPolytopes[subdim][it]!! }
put(
pPolytope,
addPolytope(
dimension = dim,
vertices = tVertices,
faces = tFaces,
)
)
}
}
}
}
public fun <
V: Any,
PVertex : PolytopicConstruction3D.Vertex<V>,
PEdge : PolytopicConstruction3D.Edge<V, PVertex>,
PPolygon : PolytopicConstruction3D.Polygon<V, PVertex, PEdge>,
> GeometrySpace<V, *>.projectAlongToAbstractPolytopicConstruction2D(
polytopicConstruction3D: PolytopicConstruction3D<V, PVertex, PEdge, PPolygon, *>,
normal: V,
base: V,
): AbstractPolytopicConstruction2D<V> = AbstractPolytopicConstruction2D<V>().apply {
val newVertices = polytopicConstruction3D.vertices.associateWith { vertex ->
addVertex(projectAlong(vertex.position, normal, base))
}
val newEdges = polytopicConstruction3D.edges.associateWith { edge ->
addEdge(newVertices[edge.start]!!, newVertices[edge.end]!!)
}
polytopicConstruction3D.polygons.forEach { polygon ->
addPolygon(
vertices = polygon.vertices.mapTo(mutableSetOf()) { newVertices[it]!! },
edges = polygon.edges.mapTo(mutableSetOf()) { newEdges[it]!! }
)
}
}
public fun <
Vector: Any,
VertexType: PolytopicConstruction.Vertex<Vector, VertexType, *>
> GeometrySpace<Vector, *>.nearestVertexOfTo(
polytopicConstruction: PolytopicConstruction<Vector, VertexType, *>,
point: Vector,
): VertexType =
polytopicConstruction.vertices.minBy { it.position.distanceTo(point) }
public fun <
Vector: Any,
VertexType: MutablePolytopicConstruction.Vertex<Vector, VertexType, *>
> GeometrySpace<Vector, *>.removeNearestVertexOfTo(
polytopicConstruction: MutablePolytopicConstruction<Vector, VertexType, *>,
point: Vector,
) {
nearestVertexOfTo(polytopicConstruction, point).remove()
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v2
import kotlin.experimental.ExperimentalTypeInference
public interface PolytopicConstruction<out V> {
public val dimension: Int
public val vertices: Set<Vertex<V>>
public val polytopes: List<Set<Polytope<V>>>
public interface Vertex<out V> {
public val position: V
public fun asPolytope(): Polytope<V>
}
public interface Polytope<out V> {
public val dimension: Int
public val vertices: Set<Vertex<V>>
public val faces: List<Set<Polytope<V>>>
}
}
public interface MutablePolytopicConstruction<V> : PolytopicConstruction<V> {
override val vertices: Set<Vertex<V>>
override val polytopes: List<Set<Polytope<V>>>
public fun addVertex(position: V): Vertex<V>
public fun addPolytope(dimension: Int, vertices: Set<Vertex<V>>, faces: List<Set<Polytope<V>>>): Polytope<V>
public interface Vertex<V> : PolytopicConstruction.Vertex<V> {
override fun asPolytope(): Polytope<V>
public fun remove()
}
public interface Polytope<V> : PolytopicConstruction.Polytope<V> {
override val vertices: Set<Vertex<V>>
override val faces: List<Set<Polytope<V>>>
public fun remove()
}
}
@OptIn(ExperimentalTypeInference::class)
public inline fun <V> PolytopicConstruction(
dimension: Int,
@BuilderInference block: MutablePolytopicConstruction<V>.() -> Unit
): PolytopicConstruction<V> =
MutablePolytopicConstructionImpl<V>(dimension).apply(block)
@Suppress("UNCHECKED_CAST")
@PublishedApi
internal class MutablePolytopicConstructionImpl<V> @PublishedApi internal constructor(
override val dimension: Int,
): MutablePolytopicConstruction<V> {
override val vertices: MutableSet<Vertex<V>> = mutableSetOf()
override val polytopes: List<MutableSet<Polytope<V>>> = List(dimension + 1) { mutableSetOf() }
override fun addVertex(position: V): Vertex<V> {
val vertex = Vertex(
construction = this,
position = position,
)
vertices.add(vertex)
polytopes[0].add(vertex.correspondingPolytope)
return vertex
}
override fun addPolytope(
dimension: Int,
vertices: Set<MutablePolytopicConstruction.Vertex<V>>,
faces: List<Set<MutablePolytopicConstruction.Polytope<V>>>
): Polytope<V> {
check(dimension > 0)
check(vertices.all { it is Vertex<V> } && faces.all { dimFaces -> dimFaces.all { it is Polytope<V> } })
val polytope = Polytope(
construction = this,
correspondingVertex = null,
dimension = dimension,
vertices = vertices as Set<Vertex<V>>,
faces = faces as List<Set<Polytope<V>>>,
)
polytopes[dimension].add(polytope)
return polytope
}
class Vertex<V>(
val construction: MutablePolytopicConstructionImpl<V>,
override val position: V,
) : MutablePolytopicConstruction.Vertex<V> {
val correspondingPolytope: Polytope<V> =
Polytope(
construction = construction,
correspondingVertex = this,
dimension = 0,
vertices = setOf(this),
faces = emptyList(),
)
override fun asPolytope(): MutablePolytopicConstruction.Polytope<V> = correspondingPolytope
override fun remove() {
construction.polytopes.forEach { dimPolytopes -> dimPolytopes.removeAll { this in it.vertices } }
construction.vertices.remove(this)
}
}
class Polytope<V>(
val construction: MutablePolytopicConstructionImpl<V>,
val correspondingVertex: Vertex<V>?,
override val dimension: Int,
override val vertices: Set<Vertex<V>>,
override val faces: List<Set<Polytope<V>>>,
) : MutablePolytopicConstruction.Polytope<V> {
override fun remove() {
construction.polytopes.drop(dimension + 1).forEach { dimPolytopes -> dimPolytopes.removeAll { this in it.faces[dimension] } }
construction.polytopes[dimension].remove(this)
correspondingVertex?.also { construction.vertices.remove(it) }
}
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v2
import kotlin.experimental.ExperimentalTypeInference
public interface PolytopicConstruction2D<out V> {
public val vertices: Set<Vertex<V>>
public val edges: Set<Edge<V>>
public val polygons: Set<Polygon<V>>
public interface Vertex<out V> {
public val position: V
}
public interface Edge<out V> {
public val start: Vertex<V>
public val end: Vertex<V>
}
public interface Polygon<out V> {
public val vertices: Set<Vertex<V>>
public val edges: Set<Edge<V>>
}
}
public interface MutablePolytopicConstruction2D<V> : PolytopicConstruction2D<V> {
override val vertices: Set<Vertex<V>>
override val edges: Set<Edge<V>>
override val polygons: Set<Polygon<V>>
public fun addVertex(position: V): Vertex<V>
public fun addEdge(start: Vertex<V>, end: Vertex<V>): Edge<V>
public fun addPolygon(vertices: Set<Vertex<V>>, edges: Set<Edge<V>>): Polygon<V>
public interface Vertex<V> : PolytopicConstruction2D.Vertex<V> {
public fun remove()
}
public interface Edge<V> : PolytopicConstruction2D.Edge<V> {
override val start: Vertex<V>
override val end: Vertex<V>
public fun remove()
}
public interface Polygon<V> : PolytopicConstruction2D.Polygon<V> {
override val vertices: Set<Vertex<V>>
override val edges: Set<Edge<V>>
public fun remove()
}
}
@OptIn(ExperimentalTypeInference::class)
public inline fun <V> PolytopicConstruction2D(@BuilderInference block: MutablePolytopicConstruction2D<V>.() -> Unit): PolytopicConstruction2D<V> =
MutablePolytopicConstruction2DImpl<V>().apply(block)
@Suppress("UNCHECKED_CAST")
@PublishedApi
internal class MutablePolytopicConstruction2DImpl<V> : MutablePolytopicConstruction2D<V> {
override val vertices: MutableSet<Vertex<V>> = mutableSetOf()
override val edges: MutableSet<Edge<V>> = mutableSetOf()
override val polygons: MutableSet<Polygon<V>> = mutableSetOf()
override fun addVertex(position: V): Vertex<V> =
Vertex(this, position).also { vertices.add(it) }
override fun addEdge(
start: MutablePolytopicConstruction2D.Vertex<V>,
end: MutablePolytopicConstruction2D.Vertex<V>
): Edge<V> {
check(start is Vertex<V> && start.construction === this && end is Vertex<V> && end.construction === this) { "Cannot add edge to polytopic construction with vertices not from the construction" }
val edge = Edge(this, start, end)
edges.add(edge)
return edge
}
override fun addPolygon(
vertices: Set<MutablePolytopicConstruction2D.Vertex<V>>,
edges: Set<MutablePolytopicConstruction2D.Edge<V>>
): MutablePolytopicConstruction2D.Polygon<V> {
check(vertices.all { it is Vertex<V> && it.construction === this } && edges.all { it is Edge<V> && it.construction === this })
val polygon = Polygon(this, vertices as Set<Vertex<V>>, edges as Set<Edge<V>>)
polygons.add(polygon)
return polygon
}
class Vertex<V>(
val construction: MutablePolytopicConstruction2DImpl<V>,
override val position: V,
) : MutablePolytopicConstruction2D.Vertex<V> {
val usedInEdges: MutableSet<Edge<V>> = mutableSetOf()
val usedInPolygons: MutableSet<Polygon<V>> = mutableSetOf()
override fun remove() {
construction.vertices.remove(this)
construction.edges.removeAll { it in usedInEdges }
construction.polygons.removeAll { it in usedInPolygons }
}
}
class Edge<V>(
val construction: MutablePolytopicConstruction2DImpl<V>,
override val start: Vertex<V>,
override val end: Vertex<V>,
) : MutablePolytopicConstruction2D.Edge<V> {
val usedInPolygons: MutableSet<Polygon<V>> = mutableSetOf()
override fun remove() {
construction.edges.remove(this)
construction.polygons.removeAll { it in usedInPolygons }
}
}
class Polygon<V>(
val construction: MutablePolytopicConstruction2DImpl<V>,
override val vertices: Set<Vertex<V>>,
override val edges: Set<Edge<V>>,
) : MutablePolytopicConstruction2D.Polygon<V> {
override fun remove() {
construction.polygons.remove(this)
}
}
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v2
import kotlin.experimental.ExperimentalTypeInference
public interface PolytopicConstruction3D<out V> {
public val vertices: Set<Vertex<V>>
public val edges: Set<Edge<V>>
public val polygons: Set<Polygon<V>>
public val polyhedra: Set<Polyhedron<V>>
public interface Vertex<out V> {
public val position: V
}
public interface Edge<out V> {
public val start: Vertex<V>
public val end: Vertex<V>
}
public interface Polygon<out V> {
public val vertices: Set<Vertex<V>>
public val edges: Set<Edge<V>>
}
public interface Polyhedron<out V> {
public val vertices: Set<Vertex<V>>
public val edges: Set<Edge<V>>
public val faces: Set<Polygon<V>>
}
}
public interface MutablePolytopicConstruction3D<V> : PolytopicConstruction3D<V> {
override val vertices: Set<Vertex<V>>
override val edges: Set<Edge<V>>
override val polygons: Set<Polygon<V>>
override val polyhedra: Set<Polyhedron<V>>
public fun addVertex(position: V): Vertex<V>
public fun addEdge(start: Vertex<V>, end: Vertex<V>): Edge<V>
public fun addPolygon(vertices: Set<Vertex<V>>, edges: Set<Edge<V>>): Polygon<V>
public fun addPolyhedron(vertices: Set<Vertex<V>>, edges: Set<Edge<V>>, faces: Set<Polygon<V>>): Polyhedron<V>
public interface Vertex<V> : PolytopicConstruction3D.Vertex<V> {
public fun remove()
}
public interface Edge<V> : PolytopicConstruction3D.Edge<V> {
override val start: Vertex<V>
override val end: Vertex<V>
public fun remove()
}
public interface Polygon<V> : PolytopicConstruction3D.Polygon<V> {
override val vertices: Set<Vertex<V>>
override val edges: Set<Edge<V>>
public fun remove()
}
public interface Polyhedron<V> : PolytopicConstruction3D.Polyhedron<V> {
override val vertices: Set<Vertex<V>>
override val edges: Set<Edge<V>>
override val faces: Set<Polygon<V>>
public fun remove()
}
}
@OptIn(ExperimentalTypeInference::class)
public inline fun <V> PolytopicConstruction3D(@BuilderInference block: MutablePolytopicConstruction3D<V>.() -> Unit): PolytopicConstruction3D<V> =
MutablePolytopicConstruction3DImpl<V>().apply(block)
@Suppress("UNCHECKED_CAST")
@PublishedApi
internal class MutablePolytopicConstruction3DImpl<V> : MutablePolytopicConstruction3D<V> {
override val vertices: MutableSet<Vertex<V>> = mutableSetOf()
override val edges: MutableSet<Edge<V>> = mutableSetOf()
override val polygons: MutableSet<Polygon<V>> = mutableSetOf()
override val polyhedra: MutableSet<Polyhedron<V>> = mutableSetOf()
override fun addVertex(position: V): Vertex<V> =
Vertex(this, position).also { vertices.add(it) }
override fun addEdge(
start: MutablePolytopicConstruction3D.Vertex<V>,
end: MutablePolytopicConstruction3D.Vertex<V>
): Edge<V> {
check(start is Vertex<V> && start.construction === this && end is Vertex<V> && end.construction === this) { "Cannot add edge to polytopic construction with vertices not from the construction" }
val edge = Edge(this, start, end)
edges.add(edge)
return edge
}
override fun addPolygon(
vertices: Set<MutablePolytopicConstruction3D.Vertex<V>>,
edges: Set<MutablePolytopicConstruction3D.Edge<V>>
): MutablePolytopicConstruction3D.Polygon<V> {
check(vertices.all { it is Vertex<V> && it.construction === this } && edges.all { it is Edge<V> && it.construction === this })
val polygon = Polygon(this, vertices as Set<Vertex<V>>, edges as Set<Edge<V>>)
polygons.add(polygon)
return polygon
}
override fun addPolyhedron(
vertices: Set<MutablePolytopicConstruction3D.Vertex<V>>,
edges: Set<MutablePolytopicConstruction3D.Edge<V>>,
faces: Set<MutablePolytopicConstruction3D.Polygon<V>>
): MutablePolytopicConstruction3D.Polyhedron<V> {
check(vertices.all { it is Vertex<V> && it.construction === this } && edges.all { it is Edge<V> && it.construction === this } && faces.all { it is Polygon<V> && it.construction === this })
val polyhedron = Polyhedron(this, vertices as Set<Vertex<V>>, edges as Set<Edge<V>>, faces as Set<Polygon<V>>)
polyhedra.add(polyhedron)
return polyhedron
}
class Vertex<V>(
val construction: MutablePolytopicConstruction3DImpl<V>,
override val position: V,
) : MutablePolytopicConstruction3D.Vertex<V> {
val usedInEdges: MutableSet<Edge<V>> = mutableSetOf()
val usedInPolygons: MutableSet<Polygon<V>> = mutableSetOf()
val usedInPolyhedra: MutableSet<Polyhedron<V>> = mutableSetOf()
override fun remove() {
construction.vertices.remove(this)
construction.edges.removeAll { it in usedInEdges }
construction.polygons.removeAll { it in usedInPolygons }
construction.polyhedra.removeAll { it in usedInPolyhedra }
}
}
class Edge<V>(
val construction: MutablePolytopicConstruction3DImpl<V>,
override val start: Vertex<V>,
override val end: Vertex<V>
) : MutablePolytopicConstruction3D.Edge<V> {
val usedInPolygons: MutableSet<Polygon<V>> = mutableSetOf()
val usedInPolyhedra: MutableSet<Polyhedron<V>> = mutableSetOf()
override fun remove() {
construction.edges.remove(this)
construction.polygons.removeAll { it in usedInPolygons }
construction.polyhedra.removeAll { it in usedInPolyhedra }
}
}
class Polygon<V>(
val construction: MutablePolytopicConstruction3DImpl<V>,
override val vertices: Set<Vertex<V>>,
override val edges: Set<Edge<V>>,
) : MutablePolytopicConstruction3D.Polygon<V> {
val usedInPolyhedra: MutableSet<Polyhedron<V>> = mutableSetOf()
override fun remove() {
construction.polygons.remove(this)
construction.polyhedra.removeAll { it in usedInPolyhedra }
}
}
class Polyhedron<V>(
val construction: MutablePolytopicConstruction3DImpl<V>,
override val vertices: Set<Vertex<V>>,
override val edges: Set<Edge<V>>,
override val faces: Set<Polygon<V>>,
) : MutablePolytopicConstruction3D.Polyhedron<V> {
override fun remove() {
construction.polyhedra.remove(this)
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v2.v2
import space.kscience.kmath.geometry.GeometrySpace
import space.kscience.kmath.geometry.projectAlong
public fun <V: Any> GeometrySpace<V, *>.projectAlong(
projectedPolytopicConstruction: PolytopicConstruction<V>,
targetPolytopicConstruction: MutablePolytopicConstruction<V>,
normal: V,
base: V,
) {
require(targetPolytopicConstruction.dimension >= projectedPolytopicConstruction.dimension - 1)
with(targetPolytopicConstruction) {
val newVertices: Map<PolytopicConstruction.Vertex<V>, MutablePolytopicConstruction.Vertex<V>> =
projectedPolytopicConstruction.vertices.associateWith { vertex ->
addVertex(projectAlong(vertex.position, normal, base))
}
val newPolytopes: MutableList<Map<PolytopicConstruction.Polytope<V>, MutablePolytopicConstruction.Polytope<V>>> =
mutableListOf(
buildMap {
for ((pVertex, tVertex) in newVertices) put(pVertex.asPolytope(), tVertex.asPolytope())
}
)
for (dim in 1 ..< projectedPolytopicConstruction.dimension)
newPolytopes += buildMap {
for (pPolytope in projectedPolytopicConstruction.polytopes[dim]) {
val tVertices = pPolytope.vertices.mapTo(mutableSetOf()) { newVertices[it]!! }
val tFaces: MutableList<Set<MutablePolytopicConstruction.Polytope<V>>> = mutableListOf()
for (subdim in 0 ..< dim)
tFaces += pPolytope.faces[subdim].mapTo(mutableSetOf()) { newPolytopes[subdim][it]!! }
put(
pPolytope,
addPolytope(
dimension = dim,
vertices = tVertices,
faces = tFaces,
)
)
}
}
}
}
public fun <V: Any> GeometrySpace<V, *>.projectAlong(
polytopicConstruction3D: PolytopicConstruction3D<V>,
normal: V,
base: V,
): PolytopicConstruction2D<V> = PolytopicConstruction2D {
val newVertices = polytopicConstruction3D.vertices.associateWith { vertex ->
addVertex(projectAlong(vertex.position, normal, base))
}
val newEdges = polytopicConstruction3D.edges.associateWith { edge ->
addEdge(newVertices[edge.start]!!, newVertices[edge.end]!!)
}
polytopicConstruction3D.polygons.forEach { polygon ->
addPolygon(
vertices = polygon.vertices.mapTo(mutableSetOf()) { newVertices[it]!! },
edges = polygon.edges.mapTo(mutableSetOf()) { newEdges[it]!! }
)
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v1
public interface Vertex<
out Vector,
out VertexType: Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: Polytope<Vector, VertexType, PolytopeType>
> {
public val position: Vector
public fun asPolytope(): PolytopeType
}
public interface Polytope<
out Vector,
out VertexType: Vertex<Vector, VertexType, PolytopeType>,
out PolytopeType: Polytope<Vector, VertexType, PolytopeType>
> {
public val dimension: Int
public val vertices: Set<VertexType>
public val faces: List<Set<PolytopeType>>
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v1
public interface Vertex2D<
Vector
> {
public val position: Vector
}
public interface Edge2D<
Vector,
VertexType: Vertex2D<Vector>,
> {
public val start: VertexType
public val end: VertexType
}
public interface Polygon2D<
Vector,
VertexType: Vertex2D<Vector>,
EdgeType: Edge2D<Vector, VertexType>
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v1
public interface Vertex3D<
Vector
> {
public val position: Vector
}
public interface Edge3D<
Vector,
VertexType: Vertex3D<Vector>,
> {
public val start: VertexType
public val end: VertexType
}
public interface Polygon3D<
Vector,
VertexType: Vertex3D<Vector>,
EdgeType: Edge3D<Vector, VertexType>
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
}
public interface Polyhedron3D<
Vector,
VertexType: Vertex3D<Vector>,
EdgeType: Edge3D<Vector, VertexType>,
PolygonType: Polygon3D<Vector, VertexType, EdgeType>,
> {
public val vertices: Set<VertexType>
public val edges: Set<EdgeType>
public val faces: Set<PolygonType>
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v1
import space.kscience.kmath.geometry.GeometrySpace
public fun <
Vector: Any,
VertexType: Vertex<Vector, VertexType, *>
> GeometrySpace<Vector, *>.nearestVertexOfTo(
polytopeVertices: Collection<VertexType>,
point: Vector,
): VertexType =
polytopeVertices.minBy { it.position.distanceTo(point) }
//public fun <
// Vector: Any,
// VertexType: Vertex<Vector, VertexType, *>
//> GeometrySpace<Vector, *>.removeNearestVertexOfTo(
// polytopeVertices: Collection<VertexType>,
// point: Vector,
//) {
// nearestVertexOfTo(polytopeVertices, point).remove()
//}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v2
public interface Vertex<Vector> {
public val position: Vector
public fun asPolytope(): Polytope<Vector>
}
public interface Polytope<Vector> {
public val dimension: Int
public val vertices: Set<Vertex<Vector>>
public val faces: List<Set<Polytope<Vector>>>
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v2
public interface Vertex2D<out Vector> {
public val position: Vector
}
public interface Edge2D<out Vector> {
public val start: Vertex2D<Vector>
public val end: Vertex2D<Vector>
}
public interface Polygon2D<out Vector> {
public val vertices: Set<Vertex2D<Vector>>
public val edges: Set<Vertex2D<Vector>>
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v2
public interface Vertex3D<out Vector> {
public val position: Vector
}
public interface Edge3D<out Vector> {
public val start: Vertex3D<Vector>
public val end: Vertex3D<Vector>
}
public interface Polygon3D<out Vector> {
public val vertices: Set<Vertex3D<Vector>>
public val edges: Set<Edge3D<Vector>>
}
public interface Polyhedron3D<out Vector> {
public val vertices: Set<Vertex3D<Vector>>
public val edges: Set<Edge3D<Vector>>
public val faces: Set<Polygon3D<Vector>>
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v3.v2
import space.kscience.kmath.geometry.GeometrySpace
public fun <
Vector: Any,
VertexType: Vertex<Vector>
> GeometrySpace<Vector, *>.nearestVertexOfTo(
polytopeVertices: Collection<VertexType>,
point: Vector,
): VertexType =
polytopeVertices.minBy { it.position.distanceTo(point) }
//public fun <
// Vector: Any,
// VertexType: Vertex<Vector, VertexType, *>
//> GeometrySpace<Vector, *>.removeNearestVertexOfTo(
// polytopeVertices: Collection<VertexType>,
// point: Vector,
//) {
// nearestVertexOfTo(polytopeVertices, point).remove()
//}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v4
public interface Polytope<Vector> {
public val dimension: Int
public val vertices: Set<Vertex<Vector>>
public val faces: List<Set<Polytope<Vector>>>
}
public interface Vertex<Vector> : Polytope<Vector> {
public val position: Vector
override val dimension: Int get() = 0
override val vertices: Set<Vertex<Vector>> get() = setOf(this)
override val faces: List<Set<Polytope<Vector>>> get() = emptyList()
}
public interface Edge<Vector> : Polytope<Vector> {
public val start: Vertex<Vector>
public val end: Vertex<Vector>
override val dimension: Int get() = 1
override val vertices: Set<Vertex<Vector>> get() = setOf(start, end)
override val faces: List<Set<Polytope<Vector>>> get() = listOf(vertices)
}
public interface Polygon<Vector> : Polytope<Vector> {
public val edges: Set<Edge<Vector>>
override val dimension: Int get() = 2
override val faces: List<Set<Polytope<Vector>>> get() = listOf(vertices, edges)
}
public interface Polyhedron<Vector> : Polytope<Vector> {
public val edges: Set<Edge<Vector>>
public val polygons: Set<Polygon<Vector>>
override val dimension: Int get() = 3
override val faces: List<Set<Polytope<Vector>>> get() = listOf(vertices, edges, polygons)
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v5
public interface PolytopicConstruction<Vector, Vertex, Polytope> {
public val dimension: Int
public val polytopes: List<Set<Polytope>>
public val vertices: Set<Vertex>
public val Vertex.position: Vector
public fun Vertex.asPolytope(): Polytope
public val Polytope.dimension: Int
public val Polytope.faces: List<Set<Polytope>>
public val Polytope.vertices: Set<Vertex>
}
public interface MutablePolytopicConstruction<Vector, Vertex, Polytope> : PolytopicConstruction<Vector, Vertex, Polytope> {
public fun Vertex.bind(position: Vector, correspondingPolytope: Polytope)
public fun Polytope.bind(
dimension: Int,
vertices: Set<Vertex>,
faces: List<Set<Polytope>>,
)
public fun Vertex.unbind()
public fun Polytope.unbind()
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v5
public interface PolytopicConstruction2D<Vector, Vertex, Edge, Polygon> {
public val vertices: Set<Vertex>
public val edges: Set<Edge>
public val polygons: Set<Polygon>
public val Vertex.position: Vector
public val Edge.start: Vertex
public val Edge.end: Vertex
public val Polygon.vertices: Set<Vertex>
public val Polygon.edges: Set<Edge>
}
public interface MutablePolytopicConstruction2D<Vector, Vertex, Edge, Polygon> : PolytopicConstruction2D<Vector, Vertex, Edge, Polygon> {
public fun Vertex.bind(position: Vector)
public fun Edge.bind(start: Vertex, end: Vertex)
public fun Polygon.bind(vertices: Set<Vertex>, edges: Set<Edge>)
public fun Vertex.remove()
public fun Edge.remove()
public fun Polygon.remove()
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v5
public interface PolytopicConstruction3D<Vector, Vertex, Edge, Polygon, Polyhedron> {
public val vertices: Set<Vertex>
public val edges: Set<Edge>
public val polygons: Set<Polygon>
public val polyhedra: Set<Polyhedron>
public val Vertex.position: Vector
public val Edge.start: Vertex
public val Edge.end: Vertex
public val Polygon.vertices: Set<Vertex>
public val Polygon.edges: Set<Edge>
public val Polyhedron.vertices: Set<Vertex>
public val Polyhedron.edges: Set<Edge>
public val Polyhedron.faces: Set<Polygon>
}
public interface MutablePolytopicConstruction3D<Vector, Vertex, Edge, Polygon, Polyhedron> : PolytopicConstruction3D<Vector, Vertex, Edge, Polygon, Polyhedron> {
public fun addVertex(position: Vector): Vertex
public fun addEdge(start: Vertex, end: Vertex): Edge
public fun addPolygon(vertices: Set<Vertex>, edges: Set<Edge>): Polygon
public fun addPolyhedron(vertices: Set<Vertex>, edges: Set<Edge>, faces: Set<Polygon>): Polyhedron
public fun Vertex.remove()
public fun Edge.remove()
public fun Polygon.remove()
public fun Polyhedron.remove()
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v5
import space.kscience.kmath.geometry.GeometrySpace
import space.kscience.kmath.geometry.projectAlong
public fun <V: Any, Vertex, Polytope> GeometrySpace<V, *>.projectAlong(
projectedPolytopicConstruction: PolytopicConstruction<V, Vertex, Polytope>,
targetPolytopicConstruction: MutablePolytopicConstruction<V, Vertex, Polytope>,
normal: V,
base: V,
) {
require(targetPolytopicConstruction.dimension >= projectedPolytopicConstruction.dimension - 1)
projectedPolytopicConstruction.vertices.forEach { vertex ->
val correspondingPolytope = with(projectedPolytopicConstruction) { vertex.asPolytope() }
with(targetPolytopicConstruction) { vertex.bind(projectAlong(vertex.position, normal, base), correspondingPolytope) }
}
for (dim in 1 ..< projectedPolytopicConstruction.dimension)
for (polytope in projectedPolytopicConstruction.polytopes[dim]) {
@Suppress("UNCHECKED_CAST")
val vertices = with(projectedPolytopicConstruction) { polytope.vertices }
val faces = with(projectedPolytopicConstruction) { polytope.faces }
with(targetPolytopicConstruction) { polytope.bind(dim, vertices, faces) }
}
}
public fun <
Vector: Any,
Vertex
> GeometrySpace<Vector, *>.nearestVertexOfTo(
polytopicConstruction: PolytopicConstruction<Vector, Vertex, *>,
point: Vector,
): Vertex =
with(polytopicConstruction) { vertices.minBy { it.position.distanceTo(point) } }
public fun <
Vector: Any,
Vertex,
> GeometrySpace<Vector, *>.removeNearestVertexOfTo(
polytopicConstruction: MutablePolytopicConstruction<Vector, Vertex, *>,
point: Vector,
) {
val vertexToRemove = nearestVertexOfTo(polytopicConstruction, point)
with(polytopicConstruction) { vertexToRemove.unbind() }
}

View File

@@ -7,7 +7,7 @@ package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point
public interface Vector2D<T> : Point<T> {
public interface Vector2D<out T> : Point<T> {
public val x: T
public val y: T
override val size: Int get() = 2

View File

@@ -8,7 +8,7 @@ package space.kscience.kmath.geometry
import space.kscience.kmath.linear.Point
import space.kscience.kmath.structures.Buffer
public interface Vector3D<T> : Point<T> {
public interface Vector3D<out T> : Point<T> {
public val x: T
public val y: T
public val z: T

View File

@@ -24,4 +24,4 @@ public fun <V : Any> GeometrySpace<V, *>.projectToLine(vector: V, line: Line<V>)
* @param base point belonging to a hyper-plane to which vector should be projected
*/
public fun <V : Any> GeometrySpace<V, *>.projectAlong(vector: V, normal: V, base: V): V =
vector + normal * ((base - vector) dot normal) / (normal dot normal)
vector + normal * ((base - vector) dot normal) / (normal dot normal)

View File

@@ -0,0 +1,16 @@
/*
* Copyright 2018-2025 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package proposals.v1
import kotlin.test.Test
class Applications {
@Test
fun projectAlong() {
}
}