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