예제 #1
0
 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);
 }
예제 #2
0
    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);
    }
예제 #3
0
 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);
 }
예제 #4
0
 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);
 }
예제 #5
0
 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);
     }
 }
예제 #6
0
    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);
            }
        }
    }
예제 #7
0
 /// <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);
 }
예제 #8
0
 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)));
 }
예제 #9
0
    public bool BranchContains(Vector2 aPoint)
    {
        CartesianSegment cs = new CartesianSegment(aPoint, aPoint, 0);

        return(IsLineInBounds(cs, lowerBound, upperBound));
    }
예제 #10
0
 public bool BranchContains(CartesianSegment aSegment)
 {
     return(IsLineInBounds(aSegment, lowerBound, upperBound));
 }
예제 #11
0
    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);
    }