/// <summary> /// Returns a new list of points and uvs of an extruded contour, where the uv u-parameters have been undergone convolution filtering to try to smooth out discontinuities. /// </summary> /// <param name="extrudedLinePoints">Points comprising the extruded line contour</param> /// <param name="extrusionAmount">The extrusion amount.</param> public Vector2WithUV[] GetUvAlteredExtrudedContour(Vector2WithUV[] extrudedLinePoints, float extrusionAmount) { Vector2WithUV[] altered; float sigma = _convolutionWidthExtrusionDistanceFraction * extrusionAmount; //Integral from segmentStartArcDistance to segmentEndArcDistance of G(pointArcDistance - x')dx' ConvolutionFunctionIntegral gaussianConvolutionIntegral = (pointArcDistance, segmentStartArcDistance, segmentEndArcDistance) => GaussianConvolutionFunctionIntegral(pointArcDistance, segmentStartArcDistance, segmentEndArcDistance, sigma); //Integral from pointArcDistance - segmentEndArcDistance to pointArcDistance - segmentStartArcDistance of x'G(x')dx' ConvolutionFunctionIntegral gaussianLinearConvolutionIntegral = (pointArcDistance, segmentStartArcDistance, segmentEndArcDistance) => GaussianLinearConvolutionFunctionIntegral(pointArcDistance, segmentStartArcDistance, segmentEndArcDistance, sigma); if (extrudedLinePoints.Length > 2) { bool isPeriodic = extrudedLinePoints[0].Equals(extrudedLinePoints[extrudedLinePoints.Length - 1]); float[] uParameters = GetConvolutionUParameters(extrudedLinePoints, isPeriodic, gaussianConvolutionIntegral, gaussianLinearConvolutionIntegral); altered = UVAlterationUtil.CopyPointsWithOverriddenUParameters(extrudedLinePoints, uParameters); } else { altered = extrudedLinePoints; } return(altered); }
/// <summary> /// Gets the u-parameter of a point determined by arcdistance convolution integral along a contour. /// </summary> /// <param name="pointArcDistance">The point's arcdistance.</param> /// <param name="uParameters">The u-parameters of the contour.</param> /// <param name="arcDistances">The arcdistances of the contour.</param> /// <param name="isPeriodic">If the contour is periodic.</param> /// <param name="convolutionFunctionIntegral">Function for computing arcdistance integral of the convolution function.</param> /// <param name="convolutionLinearFunctionIntegral">Function for computing arcdistance integral of the convolution function multiplied by arcdistance.</param> private static float GetConvolutionUParameter(float pointArcDistance, float[] uParameters, float[] arcDistances, bool isPeriodic, ConvolutionFunctionIntegral convolutionFunctionIntegral, ConvolutionFunctionIntegral convolutionLinearFunctionIntegral) { if (isPeriodic) { arcDistances = PeriodicallyWrappedArcDistances(pointArcDistance, arcDistances); pointArcDistance = 0; } double convolutionSum = 0; for (int segmentIndex = 0; segmentIndex < uParameters.Length - 1; segmentIndex++) { float uStart = uParameters[segmentIndex]; float uEnd = uParameters[segmentIndex + 1]; float arcDistanceSegmentStart = arcDistances[segmentIndex]; float arcDistanceSegmentEnd = arcDistances[segmentIndex + 1]; float segmentLength = arcDistanceSegmentEnd - arcDistanceSegmentStart; float uDifference = uEnd - uStart; //In periodic case, we'll ignore the 'furthest-away' segment regardless of how large the convolution kernel is, since we'd need to chop it in two to deal with periodically wrapped arcdistances properly. if (segmentLength > 0) { var integralConvolutionFunction = convolutionFunctionIntegral(pointArcDistance, arcDistanceSegmentStart, arcDistanceSegmentEnd); var integralConvolutionLinearFunction = convolutionLinearFunctionIntegral(pointArcDistance, arcDistanceSegmentStart, arcDistanceSegmentEnd); var convolutionIntegralFactor = uStart + uDifference * (pointArcDistance - arcDistanceSegmentStart) / segmentLength; var convolutionLinearIntegralFactor = -uDifference / segmentLength; var contribution = convolutionIntegralFactor * integralConvolutionFunction + convolutionLinearIntegralFactor * integralConvolutionLinearFunction; convolutionSum += contribution; } } return((float)convolutionSum); }
/// <summary> /// Returns the u-parameters of an extruded contour determined by arcdistance convolution integral. /// </summary> /// <param name="contourPoints">The contour points.</param> /// <param name="isPeriodic">If the contour is periodic.</param> /// <param name="convolutionFunctionIntegral">Function for computing arcdistance integral of the convolution function.</param> /// <param name="convolutionLinearFunctionIntegral">Function for computing arcdistance integral of the convolution function multiplied by arcdistance.</param> private static float[] GetConvolutionUParameters(Vector2WithUV[] contourPoints, bool isPeriodic, ConvolutionFunctionIntegral convolutionFunctionIntegral, ConvolutionFunctionIntegral convolutionLineareFunctionIntegral) { int pointCount = isPeriodic ? contourPoints.Length - 1 : contourPoints.Length; float[] uParameters = UVAlterationUtil.GetUParameters(contourPoints); float[] arcDistances = UVAlterationUtil.GetPointArcdistances(contourPoints); float[] uParametersConvolved = new float[contourPoints.Length]; for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) { float pointArcDistance = arcDistances[pointIndex]; uParametersConvolved[pointIndex] = GetConvolutionUParameter(pointArcDistance, uParameters, arcDistances, isPeriodic, convolutionFunctionIntegral, convolutionLineareFunctionIntegral); } if (isPeriodic) { uParametersConvolved[contourPoints.Length - 1] = uParametersConvolved[0]; } return(uParametersConvolved); }