Example #1
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);
    }
Example #2
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);
    }