diff --git a/docs/Contour-Lines.md b/docs/Contour-Lines.md
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/contour0.png b/docs/contour0.png
new file mode 100644
index 00000000..33f54345
Binary files /dev/null and b/docs/contour0.png differ
diff --git a/docs/contour1.png b/docs/contour1.png
new file mode 100644
index 00000000..4219bb7f
Binary files /dev/null and b/docs/contour1.png differ
diff --git a/docs/contourTeaser.png b/docs/contourTeaser.png
new file mode 100644
index 00000000..81a12e5b
Binary files /dev/null and b/docs/contourTeaser.png differ
diff --git a/docs/multitexture-ui.png b/docs/multitexture-ui.png
new file mode 100644
index 00000000..31bddbf8
Binary files /dev/null and b/docs/multitexture-ui.png differ
diff --git a/provex/index.html b/provex/index.html
new file mode 100644
index 00000000..7010f48d
--- /dev/null
+++ b/provex/index.html
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/PRo3D.Core/VisualizationAndTFApp.fs b/src/PRo3D.Core/VisualizationAndTFApp.fs
new file mode 100644
index 00000000..c98b52a1
--- /dev/null
+++ b/src/PRo3D.Core/VisualizationAndTFApp.fs
@@ -0,0 +1,42 @@
+namespace PRo3D.Core
+
+open Adaptify.FSharp
+open Aardvark.Base
+open PRo3D.Core
+open Aardvark.UI
+open Aardvark.UI.Primitives
+open PRo3D.Base
+open FSharp.Data.Adaptive
+open PRo3D.Core
+open PRo3D.Core.Surface
+
+module ContourLineApp =
+
+ type Action =
+ | SetDistance of Numeric.Action
+ | SetLineWidth of Numeric.Action
+ | SetBorder of Numeric.Action
+ | ToggleEnabled
+ | SetTargetTexture of Option
+
+
+
+ let update (m : ContourLineModel) (action : Action) =
+ match action with
+ | SetDistance a -> { m with distance = Numeric.update m.distance a }
+ | SetLineWidth a -> { m with width = Numeric.update m.width a }
+ | SetBorder a -> { m with border = Numeric.update m.border a }
+ | ToggleEnabled -> { m with enabled = not m.enabled }
+ | SetTargetTexture a -> { m with targetLayer = a }
+
+
+ let view (model : AdaptiveContourLineModel) =
+ require GuiEx.semui (
+ Html.table [
+ Html.row "" []
+ Html.row "enabled" [GuiEx.iconCheckBox model.enabled ToggleEnabled]
+ Html.row "distance: " [Numeric.view' [NumericInputType.Slider; NumericInputType.InputBox] model.distance |> UI.map SetDistance ]
+ Html.row "width: " [Numeric.view' [NumericInputType.Slider; NumericInputType.InputBox] model.width |> UI.map SetLineWidth ]
+ Html.row "border: " [Numeric.view' [NumericInputType.Slider; NumericInputType.InputBox] model.border |> UI.map SetBorder ]
+ ]
+ )
\ No newline at end of file
diff --git a/src/PRo3D.Core/VisualizationAndTFModel.fs b/src/PRo3D.Core/VisualizationAndTFModel.fs
new file mode 100644
index 00000000..27231560
--- /dev/null
+++ b/src/PRo3D.Core/VisualizationAndTFModel.fs
@@ -0,0 +1,140 @@
+namespace PRo3D.Core
+
+open Adaptify
+open Aardvark.Base
+open Aardvark.UI
+open PRo3D.Base
+open Chiron
+
+[]
+type ScalarLayer = {
+ version : int
+ label : string
+ actualRange : Range1d
+ definedRange : Range1d
+ index : int
+ colorLegend : FalseColorsModel
+}
+module ScalarLayer =
+ let current = 0
+
+ let read0 =
+ json {
+ let! label = Json.read "label"
+ let! actualRange = Json.read "actualRange"
+ let! definedRange = Json.read "definedRange"
+ let! index = Json.read "index"
+ let! colorLegend = Json.read "colorLegend"
+
+ return
+ {
+ version = current
+ label = label
+ actualRange = actualRange |> Range1d.Parse
+ definedRange = definedRange |> Range1d.Parse
+ index = index
+ colorLegend = colorLegend
+ }
+ }
+
+type ScalarLayer with
+ static member FromJson(_ : ScalarLayer) =
+ json {
+ let! v = Json.read "version"
+ match v with
+ | 0 -> return! ScalarLayer.read0
+ | _ ->
+ return! v
+ |> sprintf "don't know version %A of ScalarLayer"
+ |> Json.error
+ }
+ static member ToJson (x : ScalarLayer) =
+ json {
+ do! Json.write "version" x.version
+ do! Json.write "label" x.label
+ do! Json.write "actualRange" (x.actualRange.ToString())
+ do! Json.write "definedRange" (x.definedRange.ToString())
+ do! Json.write "index" x.index
+ do! Json.write "colorLegend" x.colorLegend
+ }
+
+type TextureLayer = {
+ version : int
+ label : string
+ index : int
+}
+
+module TextureLayer =
+ let current = 0
+ let read0 =
+ json {
+ let! label = Json.read "label"
+ let! index = Json.read "index"
+
+ return {
+ version = current
+ label = label
+ index = index
+ }
+ }
+
+type TextureLayer with
+ static member FromJson(_ : TextureLayer) =
+ json {
+ let! v = Json.read "version"
+ match v with
+ | 0 -> return! TextureLayer.read0
+ | _ ->
+ return! v
+ |> sprintf "don't know version %A of TextureLayer"
+ |> Json.error
+ }
+ static member ToJson (x : TextureLayer) =
+ json {
+ do! Json.write "version" x.version
+ do! Json.write "label" x.label
+ do! Json.write "index" x.index
+ }
+
+type AttributeLayer =
+ | ScalarLayer of ScalarLayer
+ | TextureLayer of TextureLayer
+
+[]
+type ContourLineModel =
+ {
+ enabled : bool
+ targetLayer : Option
+ distance : NumericInput
+ width : NumericInput
+ border : NumericInput
+ }
+
+module ContourLineModel =
+
+ let initial =
+ {
+ enabled = false
+ distance = {
+ value = 0
+ min = 0.0
+ max = 100.0
+ step = 0.0001
+ format = "{0:0.0000}"
+ }
+ width = {
+ value = 0.01
+ min = 0.0
+ max = 10.0
+ step = 0.0001
+ format = "{0:0.0000}"
+ }
+ border = {
+ value = 0.01
+ min = 0.0
+ max = 10.0
+ step = 0.0001
+ format = "{0:0.0000}"
+ }
+ targetLayer = None
+ }