public CartesianSegment FindSegmentWithSharedEndPoint(CartesianSegment aSegment) { if (!BranchContains(aSegment)) { return(null); } if (branches == null) { foreach (CartesianSegment sc in segments) { int pc = sc.SharedPointCount(aSegment); if (pc == 1) { return(sc); } } } else { for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { CartesianSegment cs = branches[row, col].FindSegmentWithSharedEndPoint(aSegment); if (cs != null) { return(cs); } } } } return(null); }
public List <CartesianSegment> GetSegments(VoxelRegion region) { int flag; List <CartesianSegment> result = new List <CartesianSegment>(); List <int2> voxelsToRemove = new List <int2>(); // NOTE: 0,0 is in the bottom-left. for (int x = 0; x < region.width; ++x) { for (int z = 0; z < region.depth; ++z) { flag = ((x < 1 || z < 1) ? 0 : (region[x - 1, z - 1] != 0 ? 0x1 : 0x0)) | ((z < 1) ? 0 : (region[x, z - 1] != 0 ? 0x2 : 0x0)) | (region[x, z] != 0 ? 0x4 : 0x0) | ((x < 1) ? 0 : (region[x - 1, z] != 0 ? 0x8 : 0x0)); int x0 = Mathf.Clamp(x - 1, 0, region.width - 1); int z0 = Mathf.Clamp(z - 1, 0, region.depth - 1); byte usedMaterial = MathUtil.ModeIgnore(0, region[x0, z0], region[x, z0], region[x, z], region[x0, z]); if (usedMaterial == 0) { continue; } float[] tableRow = kContourTable[flag]; int numSegments = (int)tableRow[0]; if (numSegments != 0) { voxelsToRemove.Add(new int2(x, z)); voxelsToRemove.Add(new int2(x0, z)); voxelsToRemove.Add(new int2(x, z0)); voxelsToRemove.Add(new int2(x0, z0)); } for (int aSegment = 0; aSegment < numSegments; ++aSegment) { Vector2 p0 = VoxelBlob.kVoxelSizeInMm * new Vector2( x + tableRow[aSegment * 4 + 1], z + tableRow[aSegment * 4 + 2]); Vector2 p1 = VoxelBlob.kVoxelSizeInMm * new Vector2( x + tableRow[aSegment * 4 + 3], z + tableRow[aSegment * 4 + 4]); CartesianSegment product = new CartesianSegment(p0, p1, usedMaterial); result.Add(product); } } } foreach (int2 vox in voxelsToRemove) { region[vox.x, vox.y] = 0; } //Text.Log(@"{0} segment{1} found in outlines and {2} voxels removed.", result.Count, Text.S(result.Count), voxelsToRemove.Count); return(result); }
public void AddSegment(CartesianSegment aSegment) { if (segments.Count == 0 || CartesianSegment.Approximately(aSegment.p0, segments[segments.Count - 1].p1)) { segments.Add(aSegment); return; } aSegment.FlipPoints(); Contract.Assert(CartesianSegment.Approximately(aSegment.p0, segments[segments.Count - 1].p1), @"Added a segment to an outline that did not have matching end " + "to previous segment, Segments : {0}, {1}", aSegment.ToString(), segments[segments.Count - 1].ToString()); segments.Add(aSegment); }
public void InsertSegmentAtStart(CartesianSegment aSegment) { if (segments.Count == 0 || CartesianSegment.Approximately(aSegment.p1, segments[0].p0)) { segments.Insert(0, aSegment); return; } aSegment.FlipPoints(); Contract.Assert(CartesianSegment.Approximately(aSegment.p1, segments[0].p0), @"Insertion failure. s[0].p1 = {0}, {1}; aSegment.p0 = {0}, {1}", segments[0].p1.x, segments[0].p1.y, aSegment.p0.x, aSegment.p0.x); segments.Insert(0, aSegment); }
public CartesianSegment FindSegmentClosestToPoint(Vector2 aPoint) { //if (!BranchContains(aPoint)) return null; //Debug.Log("Found that " + aPoint + " was in branch " + this.ToString()); if (branches == null) { float minDistance = float.MaxValue; CartesianSegment closestCs = null; foreach (CartesianSegment cs in segments) { float dist = cs.MinSqrMagnitudeFromEndpoint(aPoint); if (dist < minDistance) { minDistance = dist; closestCs = cs; //Debug.Log("This point was closer " + cs); } } return(closestCs); } else { CartesianSegment closestCs = null; float minDistance = float.MaxValue; CartesianSegment[] branchSegments = new CartesianSegment[4]; for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { branchSegments[2 * row + col] = branches[row, col].FindSegmentClosestToPoint(aPoint); } } foreach (CartesianSegment cs in branchSegments) { if (cs == null) { continue; } float dist = cs.MinSqrMagnitudeFromEndpoint(aPoint); if (dist < minDistance) { minDistance = dist; closestCs = cs; //Debug.Log("This point was closer " + cs); } } return(closestCs); } }
public void RemoveSegmentFromTree(CartesianSegment aSegment) { bool segmentInList = segments.Remove(aSegment); if (branches == null || !segmentInList) { return; } for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { branches[row, col].RemoveSegmentFromTree(aSegment); } } }
/// <summary> /// Determines whether this line segment is in the specified bounds. /// </summary> /// <returns> /// <c>true</c> if this instance is line in bounds the specified aSegment aLowerBound anUpperBound; otherwise, <c>false</c>. /// </returns> /// <param name='aSegment'> /// If set to <c>true</c> a segment. /// </param> /// <param name='aLowerBound'> /// If set to <c>true</c> a lower bound. /// </param> /// <param name='anUpperBound'> /// If set to <c>true</c> an upper bound. /// </param> private bool IsLineInBounds(CartesianSegment aSegment, Vector2 aLowerBound, Vector2 anUpperBound) { if (aSegment.p0.x >= aLowerBound.x && aSegment.p0.x <= anUpperBound.x) { if (aSegment.p0.y >= aLowerBound.y && aSegment.p0.y <= anUpperBound.y) { return(true); } } if (aSegment.p1.x >= aLowerBound.x && aSegment.p1.x <= anUpperBound.x) { if (aSegment.p1.y >= aLowerBound.y && aSegment.p1.y <= anUpperBound.y) { return(true); } } return(false); }
public int SharedPointCount(CartesianSegment otherSegment) { return(Convert.ToInt32(Approximately(p0, otherSegment.p0)) + Convert.ToInt32(Approximately(p0, otherSegment.p1)) + Convert.ToInt32(Approximately(p1, otherSegment.p0)) + Convert.ToInt32(Approximately(p1, otherSegment.p1))); }
public bool BranchContains(Vector2 aPoint) { CartesianSegment cs = new CartesianSegment(aPoint, aPoint, 0); return(IsLineInBounds(cs, lowerBound, upperBound)); }
public bool BranchContains(CartesianSegment aSegment) { return(IsLineInBounds(aSegment, lowerBound, upperBound)); }
public List <Outline> CreateOutlines(List <CartesianSegment> layerSegments, Printer forPrinter) { List <Outline> layerOutlines = new List <Outline>(); List <List <CartesianSegment> > matLines = new List <List <CartesianSegment> >(); for (int mat = 1; mat < 5; mat++) { /// Grab all of the line segments for this material type matLines.Add(CollectMaterialSegments((byte)mat, layerSegments)); if (matLines[mat - 1].Count == 0) { continue; } // Create a quadtree for all of the line segments of mat type QuadTree qt = new QuadTree(matLines[mat - 1]); CartesianSegment currentSegment = null; PrinterExtruder[] extrudersForMaterial = forPrinter.GetExtrudersWithMaterial((byte)mat); float bestDistance = float.MaxValue; foreach (PrinterExtruder pe in extrudersForMaterial) { Vector2 extruderPosition = (Vector2)forPrinter.GetExtruderCartesianPosition(pe); extruderPosition += Vector2.one * forPrinter.platformRadiusInMm; CartesianSegment aSegment = qt.FindSegmentClosestToPoint(extruderPosition); //Debug.Log("Starting search with extruder " + pe.id + " at position " + extruderPosition + " and found best Segment = " + aSegment); if (aSegment != null && ((extruderPosition - aSegment.p0).sqrMagnitude < bestDistance || (extruderPosition - aSegment.p1).sqrMagnitude < bestDistance)) { bestDistance = Mathf.Min((extruderPosition - aSegment.p0).sqrMagnitude, (extruderPosition - aSegment.p1).sqrMagnitude); currentSegment = aSegment; //Debug.LogWarning("Started at ext pos = " + extruderPosition + " and selected " + currentSegment); } } // Make complete outlines by ordering connected segments layerOutlines.Add(new Outline((byte)mat)); if (currentSegment == null) { Text.Warning("Search for closest line segment returned null, grabbing first point in outline, " + qt.segments[0].ToString()); currentSegment = qt.segments[0]; } layerOutlines[layerOutlines.Count - 1].AddSegment(currentSegment); qt.RemoveSegmentFromTree(currentSegment); //Debug.Log("Starting at position " + aStartingPoint + " and found the closest point to be " + currentSegment); while (qt.segments.Count > 0) { CartesianSegment nextSegment = null; if (currentSegment != null) { nextSegment = qt.FindSegmentWithSharedEndPoint(currentSegment); } if (nextSegment != null && (CartesianSegment.Approximately(nextSegment.p0, currentSegment.p1) || CartesianSegment.Approximately(nextSegment.p1, currentSegment.p1))) { // If the quadtree returns a connected segment, add it to the current outline and then search again layerOutlines[layerOutlines.Count - 1].AddSegment(nextSegment); currentSegment = nextSegment; qt.RemoveSegmentFromTree(currentSegment); } else { // Check to see if there are any segments that match the initial segment nextSegment = qt.FindSegmentWithSharedEndPoint(layerOutlines[layerOutlines.Count - 1].segments[0]); if (nextSegment != null) { layerOutlines[layerOutlines.Count - 1].InsertSegmentAtStart(nextSegment); currentSegment = null; qt.RemoveSegmentFromTree(nextSegment); } else // Start a new outline! { currentSegment = qt.FindSegmentClosestToPoint( layerOutlines[layerOutlines.Count - 1].segments[layerOutlines[layerOutlines.Count - 1].segments.Count - 1].p1); if (currentSegment == null) { currentSegment = qt.segments[0]; } layerOutlines.Add(new Outline((byte)mat)); layerOutlines[layerOutlines.Count - 1].AddSegment(currentSegment); qt.RemoveSegmentFromTree(currentSegment); } } } } layerOutlines = CollapseOutlines(layerOutlines); return(layerOutlines); }