Last active
July 3, 2018 19:35
-
-
Save dg1an3/2af602331c10707cdfce8d557c367a29 to your computer and use it in GitHub Desktop.
Isocurve Generation via simple marching squares
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// | |
/// </summary> | |
public class ComplexGeometry : List<LineSegments> | |
{ | |
// stores the dictionary | |
Dictionary<Point, LineSegments> _segments = | |
new Dictionary<Point, LineSegments>(); | |
/// <summary> | |
/// creates or adds a segment to the collections | |
/// </summary> | |
/// <param name="x"></param> | |
/// <param name="y"></param> | |
/// <param name="startOffset"></param> | |
/// <param name="endOffset"></param> | |
public void CreateOrAddSegment(int x, int y, Vector startOffset, Vector endOffset) | |
{ | |
Point ptMiddle = new Point(x, y); | |
Point startPoint = ptMiddle + startOffset; | |
Point endPoint = ptMiddle + endOffset; | |
if (_segments.ContainsKey(startPoint)) | |
{ | |
var pc = _segments[startPoint]; | |
_segments.Remove(startPoint); | |
if (pc.First() == startPoint) | |
{ | |
pc.Insert(0, endPoint); | |
} | |
else if (pc.Last() == startPoint) | |
{ | |
pc.Add(endPoint); | |
} | |
if (!_segments.ContainsKey(endPoint)) | |
_segments.Add(endPoint, pc); | |
} | |
else if (_segments.ContainsKey(endPoint)) | |
{ | |
var pc = _segments[endPoint]; | |
_segments.Remove(endPoint); | |
if (pc.First() == endPoint) | |
{ | |
pc.Insert(0, startPoint); | |
} | |
else if (pc.Last() == endPoint) | |
{ | |
pc.Add(startPoint); | |
} | |
if (!_segments.ContainsKey(startPoint)) | |
_segments.Add(startPoint, pc); | |
} | |
else | |
{ | |
var pc = new LineSegments(); | |
pc.Add(startPoint); | |
pc.Add(endPoint); | |
_segments.Add(startPoint, pc); | |
_segments.Add(endPoint, pc); | |
this.Add(pc); | |
} | |
} | |
} | |
/// <summary> | |
/// | |
/// </summary> | |
public class LineSegments : List<Point> { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class IsocurveGenerator | |
{ | |
public static ComplexGeometry GenerateIsocurve(byte[,] pixels, float threshold) | |
{ | |
var geometry = new ComplexGeometry(); | |
int height = pixels.GetLength(0); | |
int width = pixels.GetLength(1); | |
byte byteThreshold = (byte)threshold; | |
// Y is increasing as we move down the image | |
// Upper is -Y | |
// Lower is +Y | |
// for (int y = -height / 2; y < height / 2 - 1; y++) | |
Parallel.For(-height / 2, height / 2 - 1, | |
y => | |
{ | |
for (int x = -width / 2; x < width / 2 - 1; x++) | |
{ | |
// UL---UR Bit order: | |
// |/ \| (UL) (UR) (LR) (LL) | |
// |\ /| | |
// LL---LR | |
byte ul = pixels[y + height / 2, x + width / 2]; | |
byte ur = pixels[y + height / 2, x + width / 2 + 1]; | |
byte lr = pixels[y + height / 2 + 1, x + width / 2 + 1]; | |
byte ll = pixels[y + height / 2 + 1, x + width / 2]; | |
uint index = 0; | |
index |= (uint)((ul < byteThreshold) ? 0 : 1) << 3; // 1000 | |
index |= (uint)((ur < byteThreshold) ? 0 : 1) << 2; // 0100 | |
index |= (uint)((lr < byteThreshold) ? 0 : 1) << 1; // 0010 | |
index |= (uint)((ll < byteThreshold) ? 0 : 1) << 0; // 0001 | |
System.Diagnostics.Trace.Assert(index <= 0xF); | |
System.Diagnostics.Trace.Assert(index >= 0x0); | |
lock (geometry) | |
{ | |
switch (index) | |
{ | |
// UL---UR | |
// | | | |
// |\ | | |
// LL---LR | |
case 0x1: // 0001 | |
case 0xE: // 1110 | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(-0.5, 0.0), | |
new Vector(0.0, 0.5)); | |
break; | |
// UL---UR | |
// | | | |
// | /| | |
// LL---LR | |
case 0x2: // 0010 | |
case 0xD: // 1101 | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(0.0, 0.5), | |
new Vector(0.5, 0.0)); | |
break; | |
// UL---UR | |
// |___| | |
// | | | |
// LL---LR | |
case 0x3: // 0011 | |
case 0xC: // 1100 | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(-0.5, 0.0), | |
new Vector(0.5, 0.0)); | |
break; | |
// UL---UR | |
// | \| | |
// | | | |
// LL---LR | |
case 0x4: // 0100 | |
case 0xB: // 1011 | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(0.0, -0.5), | |
new Vector(0.5, 0.0)); | |
break; | |
// UL---UR | |
// | \| | |
// |\ | | |
// LL---LR | |
case 0x5: // 0101 | |
case 0xA: // 1010 | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(0.0, -0.5), | |
new Vector(0.5, 0.0)); | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(-0.5, 0.0), | |
new Vector(0.0, 0.5)); | |
break; | |
// UL---UR | |
// | | | | |
// | | | | |
// LL---LR | |
case 0x6: // 0110 | |
case 0x9: // 1001 | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(0.0, -0.5), | |
new Vector(0.0, 0.5)); | |
break; | |
// UL---UR | |
// |/ | | |
// | | | |
// LL---LR | |
case 0x7: | |
case 0x8: | |
geometry.CreateOrAddSegment(x, y, | |
new Vector(-0.5, 0.0), | |
new Vector(0.0, -0.5)); | |
break; | |
case 0xF: | |
case 0x0: | |
default: | |
// all on same side - do nothing | |
break; | |
} | |
} | |
} | |
}); | |
return geometry; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment