示例#1
0
    public IEnumerator CreateArcTest(VoxelRegion region)
    {
        m_innerRing = int.MaxValue;
        m_outerRing = int.MinValue;

        Clear();

        Text.Log(@"Max rings: {0}=========================<<<<<<<<<<<<<<<<<<<<<<<<", m_maxRings);

        // NOTE:
        // This assumes ring 0 is at the origin of the plate;
        // a slightly better version could have ring 0 start
        // nozzleSize * 0.5f mm away from the origin. This
        // would help account for the slight spill over from
        // the nozzle into adjacent rings…
        for (int forRing = 0; forRing < 72; forRing += 3)
        {
            Arc testingArc = Extend(null, (byte)1, 0000, forRing);
            Close(testingArc, 1600, forRing);
            Text.Log(@"Ring {0}: Added testing arc {1}.", forRing, testingArc);
            UpdateRingBounds(forRing);

            if (Scheduler.ShouldYield())
            {
                yield return(null);
            }
        }

        Contract.Assert(m_ringCount <= m_maxRings,
                        @"Ring count ({0}) is larger than max rings ({1}).",
                        m_ringCount, m_maxRings);
        Contract.Assert(m_ringCount <= layerWidthInRings,
                        @"Ring count of {0} larger than width of {1}.",
                        m_ringCount, layerWidthInRings);
    }
示例#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
 /// <summary>
 /// Region voxels with non-zero material are removed from the blob.
 /// </summary>
 /// <param name="r">The voxel region to subtract.</param>
 /// <param name="layer">The layer height of the region.</param>
 public void SubtractRegion(VoxelRegion r, int layer)
 {
     for (int col = 0; col < width; col++)
     {
         for (int row = 0; row < depth; row++)
         {
             if (r[col, row] != 0)
             {
                 this[col, layer, row] = 0;
             }
         }
     }
 }
示例#4
0
    /// <summary>
    /// Converts a layer of voxels to a layer of arcs.
    /// </summary>
    /// <param name='aBlob'>
    /// A 3D voxel blob.
    /// </param>
    /// <param name='atLayer'>
    /// The layer to sample at.
    /// </param>
    public IEnumerator ConvertVoxelLayer(VoxelRegion region)
    {
        m_innerRing = int.MaxValue;
        m_outerRing = int.MinValue;

        Clear();

        // NOTE:
        // This assumes ring 0 is at the origin of the plate;
        // a slightly better version could have ring 0 start
        // nozzleSize * 0.5f mm away from the origin. This
        // would help account for the slight spill over from
        // the nozzle into adjacent rings…
        for (int forRing = 0; forRing < m_maxRings; forRing += infillStep)
        {
            SampleArcsFrom(region, forRing);

            if (Scheduler.ShouldYield())
            {
                yield return(null);
            }
        }

        // NOTE for TESTING
        // If we didn't added anything for ring 0, add a complete ring.
        if (m_arcs[0].Count == 0)
        {
            int  origin   = Mathf.RoundToInt(region.GetSampleFromMm(m_printer.platformRadiusInMm));
            byte material = region.IsValidPoint(origin, origin)
                                ? region[origin, origin] : (byte)0;
            Arc currentArc = null;
            Extend(currentArc, material, 0, 0);
            Extend(currentArc, 0, m_printer.platform.stepsPerRotation, 0);
            UpdateRingBounds(0);
        }
        else
        {
            Text.Log(@"No worries!");
        }
        //*/

        Contract.Assert(m_ringCount <= m_maxRings,
                        @"Ring count ({0}) is larger than max rings ({1}).",
                        m_ringCount, m_maxRings);
        Contract.Assert(m_ringCount <= layerWidthInRings,
                        @"Ring count of {0} larger than width of {1}.",
                        m_ringCount, layerWidthInRings);
    }
示例#5
0
    /// <summary>
    /// Samples the blob for the given [ring, layer] by sampling
    /// kSamplingScale * the circumference points moving in a
    /// positive (ccw) angle.
    /// </summary>
    /// <param name='aBlob'>
    /// A BLOB.
    /// </param>
    /// <param name='atLayer'>
    /// At layer.
    /// </param>
    /// <param name='forRing'>
    /// For ring.
    /// </param>
    void SampleArcsFrom(VoxelRegion region, int forRing)
    {
        Contract.Assert(forRing >= 0, @"Negative ring: {0}", forRing);
        Contract.Assert(forRing < m_maxRings, @"Ring {0} out of bounds.", forRing);

        float platformStepInDeg = m_printer.platform.degreesPerStep;
        int   stepsPerRotation  = m_printer.platform.stepsPerRotation;

        int   samplesToTake       = Mathf.CeilToInt(forRing * MathUtil.kTau * kSamplingScale);
        float sampleSizeInRadians = MathUtil.kTau / samplesToTake;

        Arc currentArc = null;

        // Origin of the platform, in voxels.
        int origin = Mathf.RoundToInt(region.GetSampleFromMm(m_printer.platformRadiusInMm));

        // Rings -> Mm -> Voxels
        float voxelRadius = region.GetSampleFromMm(forRing * m_printer.nozzleWidthInMm);

        for (int sampleIndex = 0; sampleIndex < samplesToTake; ++sampleIndex)
        {
            float radians = sampleIndex * sampleSizeInRadians;

            // Since the number of samples we're taking depends on the radius,
            // we can't pre-compute the angles and use them for everything…
            float sampleX = voxelRadius * Mathf.Cos(radians);
            float sampleY = voxelRadius * Mathf.Sin(radians);

            // NOTE: This should probably be rounded, not floored.
            int sampleXInt = Mathf.RoundToInt(sampleX);
            int sampleYInt = Mathf.RoundToInt(sampleY);

            float sampleXFractional = sampleX - sampleXInt;
            float sampleYFractional = sampleY - sampleYInt;

            float xFractionalSqr = sampleXFractional * sampleXFractional;
            float yFractionalSqr = sampleYFractional * sampleYFractional;

            // If the sample is sufficiently good, then take the sample
            // and update the arc.
            if (xFractionalSqr + yFractionalSqr <= kSampleThresholdSqr)
            {
                int  sampleAtWidth = sampleXInt + origin;
                int  sampleAtDepth = sampleYInt + origin;
                byte material      = region.IsValidPoint(sampleAtWidth, sampleAtDepth)
                                        ? region[sampleAtWidth, sampleAtDepth]
                                        : (byte)0;
                // NOTE: If we round to int, then we can get the same step
                // number even if we sample different points! Doing so
                // could lead to 0-length arcs.
                int platformStep = Mathf.FloorToInt(radians * Mathf.Rad2Deg / platformStepInDeg);
                platformStep = Mathf.Min(platformStep, stepsPerRotation);

                currentArc = Extend(currentArc, material, platformStep, forRing);
            }
        }

        // Close off the arc if open.
        Extend(currentArc, 0, stepsPerRotation, forRing);
        UpdateRingBounds(forRing);
    }