diff --git a/OSCADSharp/OSCADSharp/OSCADSharp.csproj b/OSCADSharp/OSCADSharp/OSCADSharp.csproj
index 41a2b7c..6508a65 100644
--- a/OSCADSharp/OSCADSharp/OSCADSharp.csproj
+++ b/OSCADSharp/OSCADSharp/OSCADSharp.csproj
@@ -48,11 +48,13 @@
+
+
diff --git a/OSCADSharp/OSCADSharp/Solids/Imported/AdjacentPixelMatrix.cs b/OSCADSharp/OSCADSharp/Solids/Imported/AdjacentPixelMatrix.cs
new file mode 100644
index 0000000..917d9c7
--- /dev/null
+++ b/OSCADSharp/OSCADSharp/Solids/Imported/AdjacentPixelMatrix.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSCADSharp.Solids.Imported
+{
+ ///
+ /// A matrix for finding neighbors in regions of pixels
+ ///
+ internal class AdjacentPixelMatrix
+ {
+ private Point topLeft;
+ private Point bottomRight;
+ private KeyValuePair?[,] grid;
+
+ public Point TopLeft { get { return this.topLeft; } }
+ public Point BottomRight { get { return this.bottomRight; } }
+
+ internal AdjacentPixelMatrix(List> pixelGrouping)
+ {
+ this.createGrid(pixelGrouping);
+ }
+
+ public bool IsOutOfBounds(Point pt)
+ {
+ if (pt.X < topLeft.X || pt.X > bottomRight.X || pt.Y < topLeft.Y || pt.Y > bottomRight.Y)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public KeyValuePair? At(int x, int y)
+ {
+ return this.grid[x, y];
+ }
+
+ private KeyValuePair?[,] createGrid(List> colorGrouping)
+ {
+ this.topLeft = new Point(int.MaxValue, int.MaxValue);
+ this.bottomRight = new Point(int.MinValue, int.MinValue);
+
+ foreach (var pair in colorGrouping)
+ {
+ if (pair.Key.X < topLeft.X)
+ topLeft.X = pair.Key.X;
+
+ if (pair.Key.Y < topLeft.Y)
+ topLeft.Y = pair.Key.Y;
+
+ if (pair.Key.X > bottomRight.X)
+ bottomRight.X = pair.Key.X;
+
+ if (pair.Key.Y > bottomRight.Y)
+ bottomRight.Y = pair.Key.Y;
+ }
+
+ int width = bottomRight.X - topLeft.X + 1;
+ int height = bottomRight.Y - topLeft.Y + 1;
+ this.grid = new KeyValuePair?[width, height];
+
+ foreach (var pair in colorGrouping)
+ {
+ var pt = pair.Key;
+ grid[pt.X - topLeft.X, pt.Y - topLeft.Y] = pair;
+ }
+
+ return grid;
+ }
+ }
+}
diff --git a/OSCADSharp/OSCADSharp/Solids/Imported/NeighboringPointFinder.cs b/OSCADSharp/OSCADSharp/Solids/Imported/NeighboringPointFinder.cs
new file mode 100644
index 0000000..aee7f3c
--- /dev/null
+++ b/OSCADSharp/OSCADSharp/Solids/Imported/NeighboringPointFinder.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSCADSharp.Solids.Imported
+{
+ ///
+ /// Helper class to reuse code in image processing for finding adjacent pixels
+ ///
+ internal class NeighboringPointFinder
+ {
+ bool cardinalOnly = false;
+
+ internal NeighboringPointFinder(bool cardinalDirectionsOnly = false)
+ {
+ this.cardinalOnly = cardinalDirectionsOnly;
+ }
+
+ internal Point Above(Point origin)
+ {
+ return new Point(origin.X, origin.Y + 1);
+ }
+
+ internal Point Below(Point origin)
+ {
+ return new Point(origin.X, origin.Y - 1);
+ }
+
+ internal Point Left(Point origin)
+ {
+ return new Point(origin.X - 1, origin.Y);
+ }
+
+ internal Point Right(Point origin)
+ {
+ return new Point(origin.X + 1, origin.Y);
+ }
+
+ internal Point UpperLeft(Point origin)
+ {
+ return new Point(origin.X - 1, origin.Y + 1);
+ }
+
+ internal Point UpperRight(Point origin)
+ {
+ return new Point(origin.X + 1, origin.Y + 1);
+ }
+
+ internal Point LowerLeft(Point origin)
+ {
+ return new Point(origin.X - 1, origin.Y - 1);
+ }
+
+ internal Point LowerRight(Point origin)
+ {
+ return new Point(origin.X + 1, origin.Y - 1);
+ }
+
+ internal List GetNeighbors(Point origin)
+ {
+ if (this.cardinalOnly)
+ {
+ return new List()
+ {
+ this.Above(origin),
+ this.Below(origin),
+ this.Left(origin),
+ this.Right(origin)
+ };
+ }
+ else
+ {
+ return new List()
+ {
+ this.Above(origin),
+ this.Below(origin),
+ this.Left(origin),
+ this.Right(origin),
+ this.UpperLeft(origin),
+ this.UpperRight(origin),
+ this.LowerLeft(origin),
+ this.LowerRight(origin)
+ };
+ }
+ }
+ }
+}
diff --git a/OSCADSharp/OSCADSharp/Solids/Imported/PolygonalImageProcessor.cs b/OSCADSharp/OSCADSharp/Solids/Imported/PolygonalImageProcessor.cs
index ec41126..485d826 100644
--- a/OSCADSharp/OSCADSharp/Solids/Imported/PolygonalImageProcessor.cs
+++ b/OSCADSharp/OSCADSharp/Solids/Imported/PolygonalImageProcessor.cs
@@ -146,6 +146,7 @@ namespace OSCADSharp.Solids.Imported
//TODO: Reorder sections for correct polygon winding
//var color = section[0].Value;
+ //var orderedSection = this.getOrderedPoints(section);
//OSCADObject pgon = new Polygon(section.Select(sec => sec.Key).ToList());
//pgon = pgon.Color(String.Format("[{0}, {1}, {2}]", color.R == 0 ? 0 : color.R / 255, color.G == 0 ? 0 : color.G / 255, color.B == 0 ? 0 : color.B / 255), color.A);
//objects.Add(pgon);
@@ -165,30 +166,54 @@ namespace OSCADSharp.Solids.Imported
return objects;
}
+ private List getOrderedPoints(List> section)
+ {
+ List orderedPoints = new List(section.Count);
+ var grid = new AdjacentPixelMatrix(section);
+ var traversed = new HashSet();
+ var neighborFinder = new NeighboringPointFinder(true);
+ Stack toTraverse = new Stack();
+ toTraverse.Push(section[0].Key);
+
+ while(toTraverse.Count > 0)
+ {
+ var origin = toTraverse.Pop();
+ traversed.Add(origin);
+ orderedPoints.Add(origin);
+
+ var below = neighborFinder.Below(origin);
+ if (!grid.IsOutOfBounds(below) && grid.At(below.X, below.Y) != null)
+ {
+ continue;
+ }
+ }
+
+ return orderedPoints;
+ }
+
private List>> getContiguousSections(List> colorGrouping)
{
- Point topLeft;
- Point bottomRight;
- KeyValuePair?[,] grid = createGrid(colorGrouping, out topLeft, out bottomRight);
+ var grid = new AdjacentPixelMatrix(colorGrouping);
var sections = new List>>();
while (colorGrouping.Count > 0)
{
var origin = colorGrouping[0];
colorGrouping.RemoveAt(0);
- sections.Add(this.getConnectedPixelsOfSameColor(origin, grid, colorGrouping, topLeft, bottomRight));
+ sections.Add(this.getConnectedPixelsOfSameColor(origin, grid, colorGrouping));
}
foreach (var section in sections)
{
- this.removeCenterPixels(section, grid, topLeft, bottomRight);
+ this.removeCenterPixels(section, grid);
}
return sections;
}
- private void removeCenterPixels(List> section, KeyValuePair?[,] grid, Point topLeft, Point bottomRight)
+ private void removeCenterPixels(List> section, AdjacentPixelMatrix grid)
{
+ var neighborFinder = new NeighboringPointFinder(true);
for (int i = section.Count - 1; i >= 0; i--)
{
@@ -197,35 +222,30 @@ namespace OSCADSharp.Solids.Imported
// We only care about cardinal directions for the purpose of removing pixels
// that lie in the center of a grouping (to avoid redundant vertexes
- List neighboringPoints = new List() {
- new Point(origin.X, origin.Y + 1), //Above
- new Point(origin.X, origin.Y - 1), //Below
- new Point(origin.X - 1, origin.Y), //Left
- new Point(origin.X + 1, origin.Y), //Right
- };
+ List neighboringPoints = neighborFinder.GetNeighbors(origin);
bool isOnanEdge = false;
foreach (var pt in neighboringPoints)
{
//If out of bounds, we found an edge
- if (pt.X < topLeft.X || pt.X > bottomRight.X || pt.Y < topLeft.Y || pt.Y > bottomRight.Y)
+ if (grid.IsOutOfBounds(pt))
{
isOnanEdge = true;
break;
}
- int x = pt.X - topLeft.X;
- int y = pt.Y - topLeft.Y;
+ int x = pt.X - grid.TopLeft.X;
+ int y = pt.Y - grid.TopLeft.Y;
- if(grid[x, y] == null)
+ if(grid.At(x, y) == null)
{
isOnanEdge = true;
break;
}
- if (grid[x, y] != null)
+ if (grid.At(x, y) != null)
{
- var nbr = (KeyValuePair)grid[x, y];
+ var nbr = (KeyValuePair)grid.At(x, y);
if(!nbr.Value.Equals(color))
{
isOnanEdge = true;
@@ -238,14 +258,14 @@ namespace OSCADSharp.Solids.Imported
{
section.RemoveAt(i);
}
-
}
}
- private List> getConnectedPixelsOfSameColor(KeyValuePair origin, KeyValuePair?[,] grid,
- List> colorGrouping, Point topLeft, Point bottomRight)
+ private List> getConnectedPixelsOfSameColor(KeyValuePair origin, AdjacentPixelMatrix grid, List> colorGrouping)
{
+ var neighborFinder = new NeighboringPointFinder();
+
List> neighbors = new List>();
HashSet> traversed = new HashSet>();
Queue> nextOrigins = new Queue>();
@@ -255,33 +275,23 @@ namespace OSCADSharp.Solids.Imported
while (nextOrigins.Count > 0)
{
- origin = nextOrigins.Dequeue();
-
- List neighboringPoints = new List() {
- new Point(origin.Key.X, origin.Key.Y + 1), //Above
- new Point(origin.Key.X, origin.Key.Y - 1), //Below
- new Point(origin.Key.X - 1, origin.Key.Y), //Left
- new Point(origin.Key.X + 1, origin.Key.Y), //Right
- new Point(origin.Key.X - 1, origin.Key.Y+1), //UpperLeft
- new Point(origin.Key.X + 1, origin.Key.Y + 1), //UpperRight
- new Point(origin.Key.X - 1, origin.Key.Y - 1), //LowerLeft
- new Point(origin.Key.X + 1, origin.Key.Y - 1), //LowerRight
- };
+ origin = nextOrigins.Dequeue();
+ List neighboringPoints = neighborFinder.GetNeighbors(origin.Key);
foreach (var pt in neighboringPoints)
{
//Ignore if out of bounds
- if(pt.X < topLeft.X || pt.X > bottomRight.X || pt.Y < topLeft.Y || pt.Y > bottomRight.Y)
+ if(grid.IsOutOfBounds(pt))
{
continue;
}
- int x = pt.X - topLeft.X;
- int y = pt.Y - topLeft.Y;
+ int x = pt.X - grid.TopLeft.X;
+ int y = pt.Y - grid.TopLeft.Y;
- if(grid[x, y] != null)
+ if(grid.At(x, y) != null)
{
- var nbr = (KeyValuePair)grid[x, y];
+ var nbr = (KeyValuePair)grid.At(x, y);
if (!traversed.Contains(nbr) && nbr.Value.Equals(origin.Value))
{
nextOrigins.Enqueue(nbr);
@@ -297,39 +307,7 @@ namespace OSCADSharp.Solids.Imported
return neighbors;
}
- private static KeyValuePair?[,] createGrid(List> colorGrouping, out Point topLeft, out Point bottomRight)
- {
- topLeft = new Point(int.MaxValue, int.MaxValue);
- bottomRight = new Point(int.MinValue, int.MinValue);
-
-
- foreach (var pair in colorGrouping)
- {
- if (pair.Key.X < topLeft.X)
- topLeft.X = pair.Key.X;
-
- if (pair.Key.Y < topLeft.Y)
- topLeft.Y = pair.Key.Y;
-
- if (pair.Key.X > bottomRight.X)
- bottomRight.X = pair.Key.X;
-
- if (pair.Key.Y > bottomRight.Y)
- bottomRight.Y = pair.Key.Y;
- }
-
- int width = bottomRight.X - topLeft.X + 1;
- int height = bottomRight.Y - topLeft.Y + 1;
- var grid = new KeyValuePair?[width, height];
-
- foreach (var pair in colorGrouping)
- {
- var pt = pair.Key;
- grid[pt.X - topLeft.X, pt.Y - topLeft.Y] = pair;
- }
-
- return grid;
- }
+
private Dictionary>> separateColors(Bitmap img)
{