diff --git a/SandWorm/Analysis.cs b/SandWorm/Analysis.cs
index c66b1ca..aed12f9 100644
--- a/SandWorm/Analysis.cs
+++ b/SandWorm/Analysis.cs
@@ -1,8 +1,6 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
-using System.Windows.Media.Media3D;
using Rhino.Display;
using Rhino.Geometry;
@@ -10,6 +8,7 @@ namespace SandWorm
{
public static class Analysis
{
+ /// Abstractions for managing analysis state.
public static class AnalysisManager
{
/// Stories copies of each analysis option and interfaces their use with components.
@@ -19,26 +18,37 @@ static AnalysisManager() // Note that the order of items here determines their m
{
options = new List
{
- new Water(), new Contours(),
- new None(),
- new Elevation(), new Slope(), new Aspect()
+ new Analytics.Water(), new Analytics.Contours(),
+ new Analytics.None(),
+ new Analytics.Elevation(), new Analytics.Slope(), new Analytics.Aspect()
};
// Default to showing elevation analysis
- options[3].IsEnabled = true;
+ options[3].isEnabled = true;
}
- public static List GetEnabledAnalyses() => options.FindAll(x => x.IsEnabled);
+ public static List GetEnabledAnalyses()
+ {
+ return options.FindAll(x => x.isEnabled);
+ }
public static MeshColorAnalysis GetEnabledMeshColoring()
{
foreach (var enabledOption in GetEnabledAnalyses())
- {
- var optionType = enabledOption.GetType();
- var optionTest = optionType.IsSubclassOf(typeof(MeshColorAnalysis));
if (enabledOption.GetType().IsSubclassOf(typeof(MeshColorAnalysis)))
return enabledOption as MeshColorAnalysis;
+ return null; // Shouldn't happen; a mesh coloring option (even no color) is always set
+ }
+
+ public static List GetEnabledMeshAnalytics()
+ {
+ var enabledGeometryAnalysis = new List();
+ foreach (var enabledOption in GetEnabledAnalyses())
+ {
+ // Testing inheritance with generics is not going to work; so just check if the option is not a color one
+ if (enabledOption.GetType().IsSubclassOf(typeof(MeshGeometryAnalysis)))
+ enabledGeometryAnalysis.Add(enabledOption as MeshGeometryAnalysis);
}
- return null; // Shouldn't happen; a mesh color (even no color) is always set
+ return enabledGeometryAnalysis;
}
public static void SetEnabledOptions(ToolStripMenuItem selectedMenuItem)
@@ -46,10 +56,10 @@ public static void SetEnabledOptions(ToolStripMenuItem selectedMenuItem)
var selectedOption = options.Find(x => x.MenuItem == selectedMenuItem);
if (selectedOption.IsExclusive)
foreach (var exclusiveOption in options.FindAll(x => x.IsExclusive))
- exclusiveOption.IsEnabled =
+ exclusiveOption.isEnabled =
selectedOption == exclusiveOption; // Toggle selected item; untoggle other exclusive items
else
- selectedOption.IsEnabled = !selectedOption.IsEnabled; // Simple toggle for independent items
+ selectedOption.isEnabled = !selectedOption.isEnabled; // Simple toggle for independent items
}
public static void ComputeLookupTables(double sensorElevation)
@@ -61,8 +71,8 @@ public static void ComputeLookupTables(double sensorElevation)
public class VisualisationRangeWithColor
{
/// Describes a numeric range (e.g. elevation or slope values) and color range to visualise it.
- public int ValueStart { get; set; }
- public int ValueEnd { get; set; }
+ public int ValueSpan { get; set; }
+
public ColorHSL ColorStart { get; set; }
public ColorHSL ColorEnd { get; set; }
@@ -79,8 +89,7 @@ public ColorHSL InterpolateColor(double progress) // Progress is assumed to be a
public abstract class MeshAnalysis
{
/// Some form of analysis that applies, or derives from, the mesh.
-
- public bool IsEnabled; // Whether to apply the analysis
+ public bool isEnabled; // Whether to apply the analysis
public MeshAnalysis(string menuName, bool exclusive)
{
@@ -98,7 +107,14 @@ public MeshAnalysis(string menuName, bool exclusive)
public abstract class MeshGeometryAnalysis : MeshAnalysis
{
/// A form of analysis that outputs geometry (i.e. contours) based on the mesh
- public MeshGeometryAnalysis(string menuName) : base(menuName, false) { } // Note: not mutually exclusive
+ public MeshGeometryAnalysis(string menuName) : base(menuName, false)
+ {
+ } // Note: not mutually exclusive
+
+ // Note that the use of may potentially exclude some geometric types as returnable
+ // Note also the need to hard-code params useful to any of the analytics; operator overloading wont work :(
+ public abstract void GetGeometryForAnalysis(ref List outputGeometry, int wl, int ci,
+ Mesh mesh);
}
public abstract class MeshColorAnalysis : MeshAnalysis
@@ -106,144 +122,30 @@ public abstract class MeshColorAnalysis : MeshAnalysis
/// A form of analysis that colors the vertices of the entire mesh
public Color[] lookupTable; // Dictionary of integers that map to color values
- public MeshColorAnalysis(string menuName) : base(menuName, true) { } // Note: is mutually exclusive
+ public MeshColorAnalysis(string menuName) : base(menuName, true)
+ {
+ } // Note: is mutually exclusive
- public abstract int GetPixelIndexForAnalysis(Point3d vertex, params Point3d[] analysisPts);
+ public abstract int GetPixelIndexForAnalysis(Point3d vertex, List analysisPts);
public abstract void ComputeLookupTableForAnalysis(double sensorElevation);
public void ComputeLinearRanges(params VisualisationRangeWithColor[] lookUpRanges)
{
- var lookupTableMaximumSize = 1;
- foreach (var range in lookUpRanges) lookupTableMaximumSize += range.ValueEnd - range.ValueStart;
- lookupTable = new Color[lookupTableMaximumSize];
+ var lookupTableMaximumSize = lookUpRanges.Length;
+ foreach (var range in lookUpRanges) lookupTableMaximumSize += range.ValueSpan;
+ lookupTable = new Color[lookupTableMaximumSize];
// Populate dict values by interpolating colors within each of the lookup ranges
+ var index = 0;
foreach (var range in lookUpRanges)
- for (var i = range.ValueStart; i < range.ValueEnd; i++)
+ for (var i = 0; i <= range.ValueSpan; i++)
{
- var progress = ((double)i - range.ValueStart) / (range.ValueEnd - range.ValueStart);
- lookupTable[i] = range.InterpolateColor(progress);
+ var progress = (double) i / range.ValueSpan;
+ lookupTable[index] = range.InterpolateColor(progress);
+ index++;
}
}
}
-
- public class None : MeshColorAnalysis
- {
- public None() : base("No Visualisation") { }
-
- public override int GetPixelIndexForAnalysis(Point3d vertex, params Point3d[] analysisPts)
- {
- return 0; // Should never be called (see below)
- }
-
- public override void ComputeLookupTableForAnalysis(double sensorElevation)
- {
- lookupTable = new Color[0]; // Empty color table allows pixel loop to skip lookup
- }
- }
-
- public class Elevation : MeshColorAnalysis
- {
- public Elevation() : base("Visualise Elevation") { }
-
- public override int GetPixelIndexForAnalysis(Point3d vertex, params Point3d[] analysisPts)
- {
- return (int)vertex.Z;
- }
-
- public override void ComputeLookupTableForAnalysis(double sensorElevation)
- {
- var normalElevationRange = new VisualisationRangeWithColor
- {
- ValueStart = 0,
- ValueEnd = (int)sensorElevation - 201,
- ColorStart = new ColorHSL(0.20, 0.35, 0.02),
- ColorEnd = new ColorHSL(0.50, 0.85, 0.85)
- }; // A clear gradient for pixels inside the expected normal model height
-
- var extraElevationRange = new VisualisationRangeWithColor
- {
- ValueStart = (int)sensorElevation - 200,
- ValueEnd = (int)sensorElevation + 1,
- ColorStart = new ColorHSL(1.00, 0.85, 0.76),
- ColorEnd = new ColorHSL(0.50, 0.85, 0.99)
- }; // A fallback gradiend for those outside (TODO: set sensible colors here)
- ComputeLinearRanges(normalElevationRange, extraElevationRange);
- }
- }
-
- private class Slope : MeshColorAnalysis
- {
- public Slope() : base("Visualise Slope") { }
-
- public override int GetPixelIndexForAnalysis(Point3d vertex, params Point3d[] neighbours)
- {
- return 22; // TODO: benchmark different methods for passing pixels before enabling a real calculation
- // Loop over the neighbouring pixels; calculate slopes relative to vertex
- //double slopeSum = 0;
- //for (int i = 0; i < neighbours.Length; i++)
- //{
- // double rise = vertex.Z - neighbours[i].Z;
- // double run = Math.Sqrt(Math.Pow(vertex.X - neighbours[i].X, 2) + Math.Pow(vertex.Y - neighbours[i].Y, 2));
- // slopeSum += rise / run;
- //}
- //double slopeAverage = Math.Abs(slopeSum / neighbours.Length);
- //double slopeAsPercent = slopeAverage * 100; // Array is keyed as 0 - 100
- //return (int)slopeAsPercent; // Cast to int as its cross-referenced to the lookup
- }
-
- public override void ComputeLookupTableForAnalysis(double sensorElevation)
- {
- var slopeRange = new VisualisationRangeWithColor
- {
- ValueStart = 0,
- ValueEnd = 100,
- ColorStart = new ColorHSL(1.0, 1.0, 1.0), // White
- ColorEnd = new ColorHSL(1.0, 1.0, 0.3) // Dark Red
- };
- ComputeLinearRanges(slopeRange);
- }
- }
-
- private class Aspect : MeshColorAnalysis
- {
- public Aspect() : base("Visualise Aspect") { }
-
- public override int GetPixelIndexForAnalysis(Point3d vertex, params Point3d[] analysisPts)
- {
- return 44;
- }
-
- public override void ComputeLookupTableForAnalysis(double sensorElevation)
- {
- var rightAspect = new VisualisationRangeWithColor
- {
- ValueStart = 0,
- ValueEnd = 180,
- ColorStart = new ColorHSL(1.0, 1.0, 1.0), // White
- ColorEnd = new ColorHSL(1.0, 1.0, 0.3) // Dark Red
- };
- var leftAspect = new VisualisationRangeWithColor
- {
- ValueStart = 180, // For the other side of the aspect we loop back to the 0 value
- ValueEnd = 359,
- ColorStart = new ColorHSL(1.0, 1.0, 0.3), // Dark Red
- ColorEnd = new ColorHSL(1.0, 1.0, 1.0) // White
- };
- ComputeLinearRanges(rightAspect, leftAspect);
- }
- }
-
-
- public class Contours : MeshGeometryAnalysis
- {
- public Contours() : base("Show Contour Lines") { }
- }
-
- public class Water : MeshGeometryAnalysis
- {
- public Water() : base("Show Water Level") { }
- }
}
}
\ No newline at end of file
diff --git a/SandWorm/Analytics.cs b/SandWorm/Analytics.cs
new file mode 100644
index 0000000..9ab62bd
--- /dev/null
+++ b/SandWorm/Analytics.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using Rhino.Display;
+using Rhino.Geometry;
+
+namespace SandWorm
+{
+ class Analytics
+ {
+ /// Implementations of particular analysis options
+
+ public class None : Analysis.MeshColorAnalysis
+ {
+ public None() : base("No Visualisation") { }
+
+ public override int GetPixelIndexForAnalysis(Point3d vertex, List analysisPts)
+ {
+ return 0; // Should never be called (see below)
+ }
+
+ public override void ComputeLookupTableForAnalysis(double sensorElevation)
+ {
+ lookupTable = new Color[0]; // Empty color table allows pixel loop to skip lookup
+ }
+ }
+
+ public class Elevation : Analysis.MeshColorAnalysis
+ {
+ public Elevation() : base("Visualise Elevation")
+ {
+ }
+
+ public override int GetPixelIndexForAnalysis(Point3d vertex, List analysisPts)
+ {
+ if (vertex.Z > 0)
+ return (int) vertex.Z;
+ return 0; // Usually occurs when sensor height is configured incorrectly
+ }
+
+ public override void ComputeLookupTableForAnalysis(double sensorElevation)
+ {
+ var sElevationRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 50,
+ ColorStart = new ColorHSL(0.40, 0.35, 0.3), // Dark Green
+ ColorEnd = new ColorHSL(0.30, 0.85, 0.4) // Green
+ };
+ var mElevationRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 50,
+ ColorStart = new ColorHSL(0.30, 0.85, 0.4), // Green
+ ColorEnd = new ColorHSL(0.20, 0.85, 0.5) // Yellow
+ };
+ var lElevationRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 50,
+ ColorStart = new ColorHSL(0.20, 0.85, 0.5), // Yellow
+ ColorEnd = new ColorHSL(0.10, 0.85, 0.6) // Orange
+ };
+ var xlElevationRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 50,
+ ColorStart = new ColorHSL(0.10, 1, 0.6), // Orange
+ ColorEnd = new ColorHSL(0.00, 1, 0.7) // Red
+ };
+ ComputeLinearRanges(sElevationRange, mElevationRange, lElevationRange, xlElevationRange);
+ }
+ }
+
+ public class Slope : Analysis.MeshColorAnalysis
+ {
+ private readonly int slopeCap = 500; // As measuring in % need an uppper limit on the value
+
+ public Slope() : base("Visualise Slope")
+ {
+ }
+
+ public override int GetPixelIndexForAnalysis(Point3d vertex, List neighbours)
+ {
+ // Loop over the neighbouring pixels; calculate slopes relative to vertex
+ double slopeSum = 0;
+ for (var i = 0; i < neighbours.Count; i++)
+ {
+ var rise = vertex.Z - neighbours[i].Z;
+ var run = Math.Sqrt(Math.Pow(vertex.X - neighbours[i].X, 2) +
+ Math.Pow(vertex.Y - neighbours[i].Y, 2));
+ slopeSum += Math.Abs(rise / run);
+ }
+
+ var slopeAverage = slopeSum / neighbours.Count;
+ var slopeAsPercent = slopeAverage * 100; // Array is keyed as 0 - 100
+
+ if (slopeAsPercent >= slopeCap)
+ return slopeCap;
+ return (int) slopeAsPercent; // Cast to int as its then cross-referenced to the lookup
+ }
+
+ public override void ComputeLookupTableForAnalysis(double sensorElevation)
+ {
+ var slightSlopeRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 30,
+ ColorStart = new ColorHSL(0.30, 1.0, 0.5), // Green
+ ColorEnd = new ColorHSL(0.15, 1.0, 0.5) // Yellow
+ };
+ var moderateSlopeRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 30,
+ ColorStart = new ColorHSL(0.15, 1.0, 0.5), // Green
+ ColorEnd = new ColorHSL(0.0, 1.0, 0.5) // Red
+ };
+ var extremeSlopeRange = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 200,
+ ColorStart = new ColorHSL(0.0, 1.0, 0.5), // Red
+ ColorEnd = new ColorHSL(0.0, 1.0, 0.0) // Black
+ };
+ ComputeLinearRanges(slightSlopeRange, moderateSlopeRange, extremeSlopeRange);
+ }
+ }
+
+ public class Aspect : Analysis.MeshColorAnalysis
+ {
+ public Aspect() : base("Visualise Aspect")
+ {
+ }
+
+ public override int GetPixelIndexForAnalysis(Point3d vertex, List analysisPts)
+ {
+ return 44;
+ }
+
+ public override void ComputeLookupTableForAnalysis(double sensorElevation)
+ {
+ var rightAspect = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 180,
+ ColorStart = new ColorHSL(1.0, 1.0, 1.0), // White
+ ColorEnd = new ColorHSL(1.0, 1.0, 0.3) // Dark Red
+ };
+ var leftAspect = new Analysis.VisualisationRangeWithColor
+ {
+ ValueSpan = 180, // For the other side of the aspect we loop back to the 0 value
+ ColorStart = new ColorHSL(1.0, 1.0, 0.3), // Dark Red
+ ColorEnd = new ColorHSL(1.0, 1.0, 1.0) // White
+ };
+ ComputeLinearRanges(rightAspect, leftAspect);
+ }
+ }
+
+ public class Contours : Analysis.MeshGeometryAnalysis
+ {
+ public Contours() : base("Show Contour Lines")
+ {
+ }
+
+ public override void GetGeometryForAnalysis(ref List outputGeometry, int wl,
+ int contourInterval, Mesh mesh)
+ {
+ var bounds = mesh.GetBoundingBox(false);
+ var originStart = new Point3d(0, 0, bounds.Min.Z);
+ var originEnd = new Point3d(0, 0, bounds.Max.Z);
+ var contours = Mesh.CreateContourCurves(mesh, originStart, originEnd, contourInterval);
+ outputGeometry.AddRange(contours);
+ }
+ }
+
+ public class Water : Analysis.MeshGeometryAnalysis
+ {
+ public Water() : base("Show Water Level")
+ {
+ }
+
+ public override void GetGeometryForAnalysis(ref List outputGeometry, int waterLevel, int ci,
+ Mesh mesh)
+ {
+ var bounds = mesh.GetBoundingBox(false);
+ var waterPlane = new Plane(new Point3d(bounds.Max.X, bounds.Max.Y, waterLevel), new Vector3d(0, 0, 1));
+ var waterSrf = new PlaneSurface(waterPlane,
+ new Interval(bounds.Min.X, bounds.Max.X),
+ new Interval(bounds.Min.Y, bounds.Max.Y)
+ );
+ outputGeometry.Add(waterSrf);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SandWorm/SandWorm.csproj b/SandWorm/SandWorm.csproj
index 2d78817..a66d2ac 100644
--- a/SandWorm/SandWorm.csproj
+++ b/SandWorm/SandWorm.csproj
@@ -86,6 +86,7 @@
+
diff --git a/SandWorm/SandWormComponent.cs b/SandWorm/SandWormComponent.cs
index 65b10a5..8a88be3 100644
--- a/SandWorm/SandWormComponent.cs
+++ b/SandWorm/SandWormComponent.cs
@@ -16,6 +16,7 @@ public class SandWorm : GH_Component
private KinectSensor kinectSensor = null;
private Point3d[] pointCloud;
private List outputMesh = null;
+ private List outputGeometry = null;
public static List output = null;//debugging
private LinkedList renderBuffer = new LinkedList();
public int[] runningSum = Enumerable.Range(1, 217088).Select(i => new int()).ToArray();
@@ -39,7 +40,8 @@ public class SandWorm : GH_Component
public static double unitsMultiplier;
// Analysis state
- private int waterLevel = 1000;
+ private int waterLevel = 50;
+ private int contourInterval = 10;
///
/// Each implementation of GH_Component must provide a public
@@ -60,7 +62,8 @@ public SandWorm()
///
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
- pManager.AddIntegerParameter("WaterLevel", "WL", "WaterLevel", GH_ParamAccess.item, 1000);
+ pManager.AddIntegerParameter("WaterLevel", "WL", "WaterLevel", GH_ParamAccess.item, 1000);
+ pManager.AddIntegerParameter("ContourInterval", "CI", "The interval (if this analysis is enabled)", GH_ParamAccess.item, 1000);
pManager.AddIntegerParameter("AverageFrames", "AF", "Amount of depth frames to average across. This number has to be greater than zero.", GH_ParamAccess.item, averageFrames);
pManager.AddIntegerParameter("BlurRadius", "BR", "Radius for Gaussian blur.", GH_ParamAccess.item, blurRadius);
pManager.AddNumberParameter("SandWormOptions", "SWO", "Setup & Calibration options", GH_ParamAccess.list);
@@ -68,6 +71,7 @@ protected override void RegisterInputParams(GH_Component.GH_InputParamManager pM
pManager[1].Optional = true;
pManager[2].Optional = true;
pManager[3].Optional = true;
+ pManager[4].Optional = true;
}
///
@@ -75,7 +79,8 @@ protected override void RegisterInputParams(GH_Component.GH_InputParamManager pM
///
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
- pManager.AddMeshParameter("Mesh", "M", "Resulting Mesh", GH_ParamAccess.list);
+ pManager.AddMeshParameter("Mesh", "M", "Resulting mesh", GH_ParamAccess.list);
+ pManager.AddGeometryParameter("Analysis", "A", "Additional mesh analysis", GH_ParamAccess.list);
pManager.AddTextParameter("Output", "O", "Output", GH_ParamAccess.list); //debugging
}
@@ -84,7 +89,7 @@ protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown men
base.AppendAdditionalComponentMenuItems(menu);
foreach (Analysis.MeshAnalysis option in Analysis.AnalysisManager.options) // Add analysis items to menu
{
- Menu_AppendItem(menu, option.Name, SetMeshVisualisation, true, option.IsEnabled);
+ Menu_AppendItem(menu, option.Name, SetMeshVisualisation, true, option.isEnabled);
// Create reference to the menu item in the analysis class
option.MenuItem = (ToolStripMenuItem)menu.Items[menu.Items.Count - 1];
if (!option.IsExclusive)
@@ -115,9 +120,10 @@ protected override void SolveInstance(IGH_DataAccess DA)
{
options = new List();
DA.GetData(0, ref waterLevel);
- DA.GetData(1, ref averageFrames);
- DA.GetData(2, ref blurRadius);
- DA.GetDataList(3, options);
+ DA.GetData(1, ref contourInterval);
+ DA.GetData(2, ref averageFrames);
+ DA.GetData(3, ref blurRadius);
+ DA.GetDataList(4, options);
if (options.Count != 0) // TODO add more robust checking whether all the options have been provided by the user
{
@@ -154,9 +160,9 @@ protected override void SolveInstance(IGH_DataAccess DA)
// initialize outputs
outputMesh = new List();
+ outputGeometry = new List();
output = new List(); //debugging
-
Point3d tempPoint = new Point3d();
Core.PixelSize depthPixelSize = Core.GetDepthPixelSpacing(sensorElevation);
@@ -215,16 +221,6 @@ protected override void SolveInstance(IGH_DataAccess DA)
timer.Restart(); //debugging
}
-
- // Setup variables for the coloring process
- Analysis.AnalysisManager.ComputeLookupTables(sensorElevation); // First-run computing of tables
- var enabledMeshColoring = Analysis.AnalysisManager.GetEnabledMeshColoring();
- var enabledColorTable = enabledMeshColoring.lookupTable;
- var hasColorTable = enabledColorTable.Length > 0; // Setting the 'no analysis' option == empty table
- vertexColors = new Color[hasColorTable ? trimmedWidth * trimmedHeight : 0]; // A 0-length array wont be used in meshing
- var pixelsForAnalysis = new Point3d[4];
-
-
// Setup variables for per-pixel loop
pointCloud = new Point3d[trimmedWidth * trimmedHeight];
int arrayIndex = 0;
@@ -236,39 +232,85 @@ protected override void SolveInstance(IGH_DataAccess DA)
tempPoint.X = columns * -unitsMultiplier * depthPixelSize.x;
tempPoint.Y = rows * -unitsMultiplier * depthPixelSize.y;
tempPoint.Z = (depthPoint - sensorElevation) * -unitsMultiplier;
-
pointCloud[arrayIndex] = tempPoint; // Add new point to point cloud itself
+ arrayIndex++;
+ }
+ }
+
+ //debugging
+ timer.Stop();
+ output.Add("Point cloud generation: ".PadRight(30, ' ') + timer.ElapsedMilliseconds.ToString() + " ms");
+ timer.Restart(); //debugging
- if (hasColorTable) // Perform analysis as needed and lookup result in table
+ // Setup variables for the coloring process
+ Analysis.AnalysisManager.ComputeLookupTables(sensorElevation); // First-run computing of tables
+ var enabledMeshColoring = Analysis.AnalysisManager.GetEnabledMeshColoring();
+ var enabledColorTable = enabledMeshColoring.lookupTable;
+ // Loop through point cloud to assign colors (TODO: should be very amenable to parallelising?)
+ if (enabledColorTable.Length > 0) // Setting the 'no analysis' option == empty table
+ {
+ vertexColors = new Color[pointCloud.Length]; // A 0-length array wont be used in meshing
+ var neighbourPixels = new List();
+ // TODO: replace below with a more robust method of determing analytic method
+ bool usingNeighbours = enabledMeshColoring.Name == "Visualise Slope" || enabledMeshColoring.Name == "Visualise Aspect";
+ for (int i = 0; i < pointCloud.Length; i++)
+ {
+ if (usingNeighbours) // If analysis needs to be passed adjacent pixels
{
- var pixelIndex = enabledMeshColoring.GetPixelIndexForAnalysis(tempPoint, pixelsForAnalysis);
- vertexColors[arrayIndex] = enabledColorTable[pixelIndex];
+ neighbourPixels.Clear();
+ if (i >= trimmedWidth)
+ neighbourPixels.Add(pointCloud[i - trimmedWidth]); // North neighbour
+ if ((i + 1) % (trimmedWidth) != 0)
+ neighbourPixels.Add(pointCloud[i + 1]); // East neighbour
+ if (i < trimmedWidth * (trimmedHeight - 1))
+ neighbourPixels.Add(pointCloud[i + trimmedWidth]); // South neighbour
+ if (i % trimmedWidth != 0)
+ neighbourPixels.Add(pointCloud[i - 1]); // West neighbour
}
- arrayIndex++;
+ var colorIndex = enabledMeshColoring.GetPixelIndexForAnalysis(pointCloud[i], neighbourPixels);
+ if (colorIndex >= enabledColorTable.Length)
+ colorIndex = enabledColorTable.Length - 1; // Happens if sensorHeight is out of whack
+
+ vertexColors[i] = enabledColorTable[colorIndex];
}
}
-
- //keep only the desired amount of frames in the buffer
- while (renderBuffer.Count >= averageFrames)
+ else
{
- renderBuffer.RemoveFirst();
+ vertexColors = new Color[0]; // Unset vertex colors to clear previous results
}
//debugging
timer.Stop();
- output.Add("Point cloud generation/color: ".PadRight(30, ' ') + timer.ElapsedMilliseconds.ToString() + " ms");
+ output.Add("Point cloud coloring: ".PadRight(30, ' ') + timer.ElapsedMilliseconds.ToString() + " ms");
timer.Restart(); //debugging
+ //keep only the desired amount of frames in the buffer
+ while (renderBuffer.Count >= averageFrames)
+ {
+ renderBuffer.RemoveFirst();
+ }
+
quadMesh = Core.CreateQuadMesh(quadMesh, pointCloud, vertexColors, trimmedWidth, trimmedHeight);
outputMesh.Add(quadMesh);
timer.Stop(); //debugging
output.Add("Meshing: ".PadRight(30, ' ') + timer.ElapsedMilliseconds.ToString() + " ms");
+ timer.Restart(); //debugging
+
+ // Add extra outputs (water planes; contours; etc) based on the mesh and currently enabled analysis
+ foreach (var enabledAnalysis in Analysis.AnalysisManager.GetEnabledMeshAnalytics())
+ {
+ enabledAnalysis.GetGeometryForAnalysis(ref outputGeometry, waterLevel, contourInterval, quadMesh);
+ }
+
+ timer.Stop(); //debugging
+ output.Add("Analysing: ".PadRight(30, ' ') + timer.ElapsedMilliseconds.ToString() + " ms");
}
DA.SetDataList(0, outputMesh);
- DA.SetDataList(1, output); //debugging
+ DA.SetDataList(1, outputGeometry);
+ DA.SetDataList(2, output); //debugging
}
if (tickRate > 0) // Allow users to force manual recalculation