All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.data2viz.voronoi.Circle.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2018-2019. data2viz sàrl.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.data2viz.voronoi

import kotlin.math.sqrt


internal var firstCircle: RedBlackNode? = null

internal val circles = RedBlackTree()
internal val circlePool = mutableListOf>()

class Circle {
    var x: Double = .0
    var y: Double = .0
    var cy: Double = .0
    lateinit var site: Site

    var arcNode: RedBlackNode? = null
}

var RedBlackNode.x: Double
    get() = node.x
    set(value) {node.x = value}

var RedBlackNode.y: Double
    get() = node.y
    set(value) {node.y = value}

var RedBlackNode.cy: Double
    get() = node.cy
    set(value) {node.cy = value}

var RedBlackNode.site: Site
    get() = node.site
    set(value) {node.site = value}


fun attachCircle(arcNode: RedBlackNode) {
    val lArc = arcNode.P
    val rArc = arcNode.N

    if (lArc == null || rArc == null) return

    val lSite = lArc.site
    val cSite = arcNode.site
    val rSite = rArc.site

    if (lSite === rSite) return

    val bx = cSite.x
    val by = cSite.y
    val ax = lSite.x - bx
    val ay = lSite.y - by
    val cx = rSite.x - bx
    val cy = rSite.y - by

    val d = 2 * (ax * cy - ay * cx)
    if (d >= -epsilon2) return

    val ha = ax * ax + ay * ay
    val hc = cx * cx + cy * cy
    val x = (cy * ha - ay * hc) / d
    val y = (ax * hc - cx * ha) / d

    val circle = if (circlePool.isEmpty()) Circle().redBlackNode() else circlePool.pop()!!
    circle.node.arcNode= arcNode
    circle.site = cSite
    circle.x = x + bx
    circle.cy = y + by
    circle.y = y + by + sqrt(x * x + y * y) // y bottom

    arcNode.node.circleNode = circle

    var before: RedBlackNode? = null
    var node = circles.root

    while (node != null) {
        if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
            if (node.L != null) node = node.L
            else {
                before = node.P; break; }
        } else {
            if (node.R != null) node = node.R
            else {
                before = node; break; }
        }
    }

    circles.insert(circle, before)
    if (before == null)
        firstCircle = circle
}

fun detachCircle(arcNode: RedBlackNode) {
    val circle = arcNode.node.circleNode
    if (circle != null) {
        if (circle.P == null) {
            firstCircle = circle.N
        }
        circles.remove(circle)
        circle.clean()
        circlePool.add(circle)
        arcNode.node.circleNode = null
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy