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

scalismo.mesh.TriangleList.scala Maven / Gradle / Ivy

There is a newer version: 1.0-RC1
Show newest version
/*
 * Copyright 2015 University of Basel, Graphics and Vision Research Group
 *
 * 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 scalismo.mesh

import scalismo.common.PointId

/** express a triangulation, contains only triangle information, no points */
case class TriangleList(triangles: IndexedSeq[TriangleCell]) {

  val pointIds = extractRange(triangles)
  val triangleIds = triangles.indices.map(i => TriangleId(i))

  def triangle(id: TriangleId): TriangleCell = triangles(id.id)

  /** triangles adjacent to each point */
  lazy val adjacentTrianglesForPoint: PointId => IndexedSeq[TriangleId] = {
    // list structure
    val emptyMapData = for (p <- pointIds) yield p -> collection.mutable.Set.empty[TriangleId]
    val triangleMap = emptyMapData.toMap

    for (t <- triangleIds) {
      val triangle = triangles(t.id)
      triangleMap(triangle.ptId1) += t
      triangleMap(triangle.ptId2) += t
      triangleMap(triangle.ptId3) += t
    }
    val data = triangleMap.view.mapValues(s => s.toSet) // make immutable

    val dataSeq = IndexedSeq.tabulate(pointIds.size) { i =>
      data(pointIds(i)).toIndexedSeq
    }
    id => dataSeq(id.id)
  }

  /** points adjacent to a point */
  lazy val adjacentPointsForPoint: PointId => IndexedSeq[PointId] = {
    // all co-occurrences in triangle list: all points reachable by a link
    val emptyMapData = for (p <- pointIds) yield p -> collection.mutable.Set.empty[PointId]
    val pointMap = emptyMapData.toMap

    for (t <- triangleIds) {
      val triangle = triangles(t.id)
      pointMap(triangle.ptId1) ++= triangle.pointIds
      pointMap(triangle.ptId2) ++= triangle.pointIds
      pointMap(triangle.ptId3) ++= triangle.pointIds
    }
    for (p <- pointIds) {
      pointMap(p) -= p
    }
    val mapData = pointMap.view.mapValues(s => s.toSet) // make immutable
    val seqData = IndexedSeq.tabulate(pointIds.size) { i =>
      mapData(pointIds(i)).toIndexedSeq
    }
    id => seqData(id.id)
  }

  /** triangles connected to triangle via common point */
  lazy val adjacentTrianglesForTriangle: TriangleId => IndexedSeq[TriangleId] = {
    // for each triangle get the 3 defining vertices, for each of those get all surrounding triangles, remove self
    val emptyMapData = for (t <- triangleIds) yield t -> collection.mutable.Set.empty[TriangleId]
    val triangleMap = emptyMapData.toMap

    for (t <- triangleIds) {
      triangleMap(t) ++= triangles(t.id).pointIds.flatMap(p => adjacentTrianglesForPoint(p))
      triangleMap(t) -= t
    }
    val mapData = triangleMap.view.mapValues(s => s.toSet)
    val seqData = IndexedSeq.tabulate(triangleIds.size) { i =>
      mapData(triangleIds(i)).toIndexedSeq
    }
    id => seqData(id.id)
  }

  /** points connected to a triangle, this information is contained in triangles */
  lazy val adjacentPointsForTriangle: TriangleId => IndexedSeq[PointId] = { id =>
    triangle(id).pointIds
  }

  private[this] def extractRange(triangles: IndexedSeq[TriangleCell]): IndexedSeq[PointId] = {
    if (triangles.isEmpty) {
      IndexedSeq[PointId]()
    } else {
      val min = triangles.flatMap(t => t.pointIds).minBy(_.id)
      val max = triangles.flatMap(t => t.pointIds).maxBy(_.id)
      (min.id to max.id).map(id => PointId(id))
    }
  }
}

final case class TriangleId(id: Int) extends AnyVal {
  def isValid: Boolean = this != TriangleId.invalid
}

object TriangleId {
  val invalid = TriangleId(-1)
}

object TriangleList {
  val empty = TriangleList(IndexedSeq.empty[TriangleCell])
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy