Skip to content

Commit

Permalink
Merge branch 'mooc'
Browse files Browse the repository at this point in the history
Conflicts:
	README.md
	project/Build.scala
	src/main/scala/scalismo/image/DiscreteImageDomain.scala
	src/main/scala/scalismo/io/ImageIO.scala
  • Loading branch information
Ghazi-Bouabene committed Jan 21, 2016
2 parents e804cba + 245dc30 commit 767e559
Show file tree
Hide file tree
Showing 81 changed files with 843 additions and 886 deletions.
10 changes: 9 additions & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import com.typesafe.sbt.SbtGit.git

import com.banno.license.Plugin.LicenseKeys._
import com.banno.license.Licenses._
import sbtbuildinfo.Plugin._


object BuildSettings {
val buildOrganization = "ch.unibas.cs.gravis"
val buildVersion = "0.9.0"
val buildVersion = "0.10.0"
val buildScalaVersion = "2.10.5"
val publishURL = Resolver.file("file", new File("/export/contrib/statismo/repo/public"))

Expand Down Expand Up @@ -95,6 +97,12 @@ object STKBuild extends Build {
++ ghpages.settings ++
Seq(
git.remoteRepo := "[email protected]:unibas-gravis/scalismo.git"
)++
buildInfoSettings ++
Seq(
sourceGenerators in Compile <+= buildInfo,
buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion),
buildInfoPackage := "scalismo"
)
)
// Sub-project specific dependencies
Expand Down
2 changes: 2 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.6.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.1")

addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.3")

addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.3.2")
10 changes: 8 additions & 2 deletions src/main/scala/scalismo/common/DiscreteDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package scalismo.common
import scalismo.geometry._

final case class PointId(id: Int) extends AnyVal
final case class PointWithId[D <: Dim](point: Point[D], id: PointId)

trait Cell {
def pointIds: IndexedSeq[PointId]
Expand All @@ -42,9 +43,14 @@ trait DiscreteDomain[D <: Dim] extends Equals {

def point(id: PointId): Point[D]

def findClosestPoint(pt: Point[D]): (Point[D], PointId)
/**
* *
* Returns the point belonging to the domain that is closest to the indicated position. The point identifier
* within th e domain is also returned.
*/
def findClosestPoint(pt: Point[D]): PointWithId[D]

def findNClosestPoints(pt: Point[D], n: Int): Seq[(Point[D], PointId)]
def findNClosestPoints(pt: Point[D], n: Int): Seq[PointWithId[D]]

def transform(t: Point[D] => Point[D]): DiscreteDomain[D]

Expand Down
13 changes: 6 additions & 7 deletions src/main/scala/scalismo/common/DiscreteField.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@
package scalismo.common

import breeze.linalg.DenseVector
import scalismo.geometry.{ NDSpace, Dim, Vector }
import scalismo.geometry.{ Dim, NDSpace, Point, Vector }

import scala.reflect.ClassTag
import scalismo.geometry.NDSpace
import scalismo.geometry.Point

/**
* Defines a discrete set of values, where each associated to a point of the domain.
Expand All @@ -41,7 +40,7 @@ trait DiscreteField[D <: Dim, A] extends PartialFunction[PointId, A] { self =>
def interpolateNearestNeighbor(): Field[D, A]
// TODO conceptually, we should have a map here too, but it becomes tricky to
// do since the overloaded functions will all require their own version of map
// Maybe a trick with CanBuildFrom and Builder, similar to the scala collectiosn would be required.
// Maybe a trick with CanBuildFrom and Builder, similar to the scala collections would be required.
}

/**
Expand Down Expand Up @@ -73,8 +72,8 @@ class DiscreteScalarField[D <: Dim: NDSpace, A: Scalar: ClassTag](val domain: Di
def canEqual(other: Any): Boolean =
other.isInstanceOf[DiscreteField[D, A]]

def interpolateNearestNeighbor: ScalarField[D, A] = {
ScalarField(RealSpace[D], (p: Point[D]) => apply(domain.findClosestPoint(p)._2))
def interpolateNearestNeighbor(): ScalarField[D, A] = {
ScalarField(RealSpace[D], (p: Point[D]) => apply(domain.findClosestPoint(p).id))
}
override lazy val hashCode: Int = data.hashCode() + domain.hashCode()

Expand All @@ -96,7 +95,7 @@ class DiscreteVectorField[D <: Dim: NDSpace, DO <: Dim: NDSpace](val domain: Dis
override def isDefinedAt(ptId: PointId) = data.isDefinedAt(ptId.id)

def interpolateNearestNeighbor(): VectorField[D, DO] = {
VectorField(RealSpace[D], (p: Point[D]) => apply(domain.findClosestPoint(p)._2))
VectorField(RealSpace[D], (p: Point[D]) => apply(domain.findClosestPoint(p).id))
}

/** map the function f over the values, but ensures that the result is scalar valued as well */
Expand Down
63 changes: 53 additions & 10 deletions src/main/scala/scalismo/common/Domain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
*/
package scalismo.common

import scalismo.geometry.{ Point, Vector, Dim, _1D, _2D, _3D }
import breeze.linalg.DenseVector
import scalismo.geometry._
import scalismo.registration.{ CanInvert, Transformation }

trait Domain[D <: Dim] { self =>
trait Domain[D <: Dim] {
self =>
def isDefinedAt(pt: Point[D]): Boolean

def warp(t: Transformation[D] with CanInvert[D]): Domain[D] = new Domain[D] {
val tinv = t.inverse

override def isDefinedAt(pt: Point[D]): Boolean = {
self.isDefinedAt(tinv(pt))
}
Expand All @@ -47,20 +48,62 @@ object Domain {
class RealSpace[D <: Dim] extends Domain[D] {
override def isDefinedAt(pt: Point[D]) = true
}

object RealSpace {
def apply[D <: Dim] = new RealSpace[D]
}

case class BoxDomain[D <: Dim](origin: Point[D], oppositeCorner: Point[D]) extends Domain[D] {
trait BoxDomain[D <: Dim] extends Domain[D] {

val origin: Point[D]
val oppositeCorner: Point[D]

def isDefinedAt(pt: Point[D]): Boolean = {
isInside(pt)
def isInsideAxis(i: Int) = pt(i) >= origin(i) && pt(i) <= oppositeCorner(i)
(0 until pt.dimensionality).forall(i => isInsideAxis(i))
}

def extent: Vector[D] = oppositeCorner - origin
def volume: Double = (0 until origin.dimensionality).foldLeft(1.0)((prod, i) => prod * (oppositeCorner(i) - origin(i)))
def isInside(pt: Point[D]): Boolean = {
def isInsideAxis(i: Int) = pt(i) >= origin(i) && pt(i) <= oppositeCorner(i)
(0 until pt.dimensionality).foldLeft(true)((defined, i) => defined && isInsideAxis(i))
val extent: Vector[D] = oppositeCorner - origin
val volume: Double = (0 until origin.dimensionality).foldLeft(1.0)((prod, i) => prod * (oppositeCorner(i) - origin(i)))

}

object BoxDomain {
def apply(origin: Point1D, oppositeCorner: Point1D) = BoxDomain1D(origin, oppositeCorner)
def apply(origin: Point2D, oppositeCorner: Point2D) = BoxDomain2D(origin, oppositeCorner)
def apply(origin: Point3D, oppositeCorner: Point3D) = BoxDomain3D(origin, oppositeCorner)

/**
* Creates a BoxDomain of dimensionality D. Attention, due to the fact that it is a generic
* constructor, the isDefinedAt method of the resulting object will not be as optimized as when created for a
* specific dimensionality
*/
def apply[D <: Dim: NDSpace](orig: Point[D], oppCorner: Point[D]) = new BoxDomain[D] {
override lazy val oppositeCorner = oppCorner
override lazy val origin = orig
}
}

case class BoxDomain1D(origin: Point1D, oppositeCorner: Point1D) extends BoxDomain[_1D] {
override def isDefinedAt(p: Point[_1D]): Boolean = {
val pt: Point1D = p
pt.x >= origin.x && pt.x <= oppositeCorner.x
}
}

case class BoxDomain2D(origin: Point2D, oppositeCorner: Point2D) extends BoxDomain[_2D] {
override def isDefinedAt(p: Point[_2D]): Boolean = {
val pt: Point2D = p
pt.x >= origin.x && pt.x <= oppositeCorner.x &&
pt.y >= origin.y && pt.y <= oppositeCorner.y
}
}

case class BoxDomain3D(origin: Point3D, oppositeCorner: Point3D) extends BoxDomain[_3D] {
override def isDefinedAt(p: Point[_3D]): Boolean = {
val pt: Point3D = p
pt.x >= origin.x && pt.x <= oppositeCorner.x &&
pt.y >= origin.y && pt.y <= oppositeCorner.y &&
pt.z >= origin.z && pt.z <= oppositeCorner.z
}
}
19 changes: 10 additions & 9 deletions src/main/scala/scalismo/common/UnstructuredPointsDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package scalismo.common

import scalismo.geometry._
import scalismo.mesh.kdtree.KDTreeMap

import scala.language.implicitConversions

sealed abstract class UnstructuredPointsDomain[D <: Dim: NDSpace] private[scalismo] (pointSeq: IndexedSeq[Point[D]]) extends DiscreteDomain[D] {
Expand All @@ -32,23 +33,23 @@ sealed abstract class UnstructuredPointsDomain[D <: Dim: NDSpace] private[scalis

override def isDefinedAt(pt: Point[D]) = pointIDMap.contains(pt)

override def findClosestPoint(pt: Point[D]): (Point[D], PointId) = {
override def findClosestPoint(pt: Point[D]): PointWithId[D] = {

def kdtreeLookup(pt: Point[D]): (Point[D], PointId) = {
def kdtreeLookup(pt: Point[D]): PointWithId[D] = {
val (nearestPt, nearestInd) = kdTreeMap.findNearest(pt, n = 1).head
(nearestPt, PointId(nearestInd))
PointWithId(nearestPt, PointId(nearestInd))
}

// first we check if the point is part of the domain (i.e. we get a pointId for the point).
// if not, we do a KDtree lookup, which is more expensive
pointId(pt) match {
case Some(id) => (pt, id)
case Some(id) => PointWithId(pt, id)
case None => kdtreeLookup(pt)
}
}

override def findNClosestPoints(pt: Point[D], n: Int): Seq[(Point[D], PointId)] = {
kdTreeMap.findNearest(pt, n).map { case (p, id) => (p, PointId(id)) }
override def findNClosestPoints(pt: Point[D], n: Int): Seq[PointWithId[D]] = {
kdTreeMap.findNearest(pt, n).map { case (p, id) => PointWithId(p, PointId(id)) }
}

override def pointId(pt: Point[D]): Option[PointId] = {
Expand Down Expand Up @@ -86,7 +87,7 @@ class UnstructuredPointsDomain1D private[scalismo] (pointSeq: IndexedSeq[Point[_
override def boundingBox: BoxDomain[_1D] = {
val minx = pointSeq.map(_(0)).min
val maxx = pointSeq.map(_(0)).max
BoxDomain[_1D](Point(minx), Point(maxx))
BoxDomain(Point(minx), Point(maxx))
}

override def transform(t: Point[_1D] => Point[_1D]): UnstructuredPointsDomain1D = {
Expand All @@ -102,7 +103,7 @@ class UnstructuredPointsDomain2D private[scalismo] (pointSeq: IndexedSeq[Point[_
val miny = pointSeq.map(_(1)).min
val maxx = pointSeq.map(_(0)).max
val maxy = pointSeq.map(_(1)).max
BoxDomain[_2D](Point(minx, miny), Point(maxx, maxy))
BoxDomain(Point(minx, miny), Point(maxx, maxy))
}

override def transform(t: Point[_2D] => Point[_2D]): UnstructuredPointsDomain2D = {
Expand All @@ -120,7 +121,7 @@ class UnstructuredPointsDomain3D private[scalismo] (pointSeq: IndexedSeq[Point[_
val maxx = pointSeq.map(_(0)).max
val maxy = pointSeq.map(_(1)).max
val maxz = pointSeq.map(_(2)).max
BoxDomain[_3D](Point(minx, miny, minz), Point(maxx, maxy, maxz))
BoxDomain(Point(minx, miny, minz), Point(maxx, maxy, maxz))
}

override def transform(t: Point[_3D] => Point[_3D]): UnstructuredPointsDomain3D = {
Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/scalismo/geometry/Dim.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ trait _3D extends Dim
trait NDSpace[D <: Dim]
extends Vector.Create[D]
with Point.Create[D]
with Index.Create[D] {
with IntVector.Create[D] {
def dimensionality: Int
}

Expand All @@ -37,21 +37,21 @@ object Dim {
implicit object OneDSpace extends NDSpace[_1D]
with Vector.Create1D
with Point.Create1D
with Index.Create1D {
with IntVector.Create1D {
override val dimensionality = 1
}

implicit object TwoDSpace extends NDSpace[_2D]
with Vector.Create2D
with Point.Create2D
with Index.Create2D {
with IntVector.Create2D {
override val dimensionality = 2
}

implicit object ThreeDSpace extends NDSpace[_3D]
with Vector.Create3D
with Point.Create3D
with Index.Create3D {
with IntVector.Create3D {
override val dimensionality = 3
}
}
Loading

0 comments on commit 767e559

Please sign in to comment.