Example usage for android.graphics PathMeasure getLength

List of usage examples for android.graphics PathMeasure getLength

Introduction

In this page you can find the example usage for android.graphics PathMeasure getLength.

Prototype

public float getLength() 

Source Link

Document

Return the total length of the current contour, or 0 if no path is associated with this measure object.

Usage

From source file:com.facebook.keyframes.util.KFPathInterpolator.java

public KFPathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2) {
    Path path = new Path();
    path.moveTo(0, 0);/*from   ww  w .j  av a2 s. c  o m*/
    path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1f, 1f);
    final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);
    final float pathLength = pathMeasure.getLength();
    final int numPoints = (int) (pathLength / PRECISION) + 1;
    mX = new float[numPoints];
    mY = new float[numPoints];
    final float[] position = new float[2];
    for (int i = 0; i < numPoints; ++i) {
        final float distance = (i * pathLength) / (numPoints - 1);
        pathMeasure.getPosTan(distance, position, null /* tangent */);
        mX[i] = position[0];
        mY[i] = position[1];
    }
}

From source file:android.support.transition.PatternPathMotion.java

/**
 * Sets the Path defining a pattern of motion between two coordinates.
 * The pattern will be translated, rotated, and scaled to fit between the start and end points.
 * The pattern must not be empty and must have the end point differ from the start point.
 *
 * @param patternPath A Path to be used as a pattern for two-dimensional motion.
 *//*w ww.  ja  v a2  s  .c  o  m*/
public void setPatternPath(Path patternPath) {
    PathMeasure pathMeasure = new PathMeasure(patternPath, false);
    float length = pathMeasure.getLength();
    float[] pos = new float[2];
    pathMeasure.getPosTan(length, pos, null);
    float endX = pos[0];
    float endY = pos[1];
    pathMeasure.getPosTan(0, pos, null);
    float startX = pos[0];
    float startY = pos[1];

    if (startX == endX && startY == endY) {
        throw new IllegalArgumentException("pattern must not end at the starting point");
    }

    mTempMatrix.setTranslate(-startX, -startY);
    float dx = endX - startX;
    float dy = endY - startY;
    float distance = distance(dx, dy);
    float scale = 1 / distance;
    mTempMatrix.postScale(scale, scale);
    double angle = Math.atan2(dy, dx);
    mTempMatrix.postRotate((float) Math.toDegrees(-angle));
    patternPath.transform(mTempMatrix, mPatternPath);
    mOriginalPatternPath = patternPath;
}

From source file:android.support.graphics.drawable.AnimatorInflaterCompat.java

private static void setupPathMotion(Path path, ObjectAnimator oa, float precision, String propertyXName,
        String propertyYName) {/*from   w  w w. j a  v  a  2  s.  co  m*/
    // Measure the total length the whole path.
    final PathMeasure measureForTotalLength = new PathMeasure(path, false);
    float totalLength = 0;
    // The sum of the previous contour plus the current one. Using the sum here b/c we want to
    // directly substract from it later.
    ArrayList<Float> contourLengths = new ArrayList<>();
    contourLengths.add(0f);
    do {
        final float pathLength = measureForTotalLength.getLength();
        totalLength += pathLength;
        contourLengths.add(totalLength);

    } while (measureForTotalLength.nextContour());

    // Now determine how many sample points we need, and the step for next sample.
    final PathMeasure pathMeasure = new PathMeasure(path, false);

    final int numPoints = min(MAX_NUM_POINTS, (int) (totalLength / precision) + 1);

    float[] mX = new float[numPoints];
    float[] mY = new float[numPoints];
    final float[] position = new float[2];

    int contourIndex = 0;
    float step = totalLength / (numPoints - 1);
    float currentDistance = 0;

    // For each sample point, determine whether we need to move on to next contour.
    // After we find the right contour, then sample it using the current distance value minus
    // the previously sampled contours' total length.
    for (int i = 0; i < numPoints; ++i) {
        pathMeasure.getPosTan(currentDistance, position, null);
        pathMeasure.getPosTan(currentDistance, position, null);

        mX[i] = position[0];
        mY[i] = position[1];
        currentDistance += step;
        if ((contourIndex + 1) < contourLengths.size()
                && currentDistance > contourLengths.get(contourIndex + 1)) {
            currentDistance -= contourLengths.get(contourIndex + 1);
            contourIndex++;
            pathMeasure.nextContour();
        }
    }

    // Given the x and y value of the sample points, setup the ObjectAnimator properly.
    PropertyValuesHolder x = null;
    PropertyValuesHolder y = null;
    if (propertyXName != null) {
        x = PropertyValuesHolder.ofFloat(propertyXName, mX);
    }
    if (propertyYName != null) {
        y = PropertyValuesHolder.ofFloat(propertyYName, mY);
    }
    if (x == null) {
        oa.setValues(y);
    } else if (y == null) {
        oa.setValues(x);
    } else {
        oa.setValues(x, y);
    }
}

From source file:android.support.graphics.drawable.PathInterpolatorCompat.java

private void initPath(Path path) {
    final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);

    final float pathLength = pathMeasure.getLength();
    final int numPoints = min(MAX_NUM_POINTS, (int) (pathLength / PRECISION) + 1);

    if (numPoints <= 0) {
        throw new IllegalArgumentException("The Path has a invalid length " + pathLength);
    }/* ww w  .  j av  a 2  s. c o  m*/

    mX = new float[numPoints];
    mY = new float[numPoints];

    final float[] position = new float[2];
    for (int i = 0; i < numPoints; ++i) {
        final float distance = (i * pathLength) / (numPoints - 1);
        pathMeasure.getPosTan(distance, position, null /* tangent */);

        mX[i] = position[0];
        mY[i] = position[1];
    }

    if (abs(mX[0]) > EPSILON || abs(mY[0]) > EPSILON || abs(mX[numPoints - 1] - 1) > EPSILON
            || abs(mY[numPoints - 1] - 1) > EPSILON) {
        throw new IllegalArgumentException("The Path must start at (0,0) and end at (1,1)" + " start: " + mX[0]
                + "," + mY[0] + " end:" + mX[numPoints - 1] + "," + mY[numPoints - 1]);

    }

    float prevX = 0;
    int componentIndex = 0;
    for (int i = 0; i < numPoints; i++) {
        float x = mX[componentIndex++];
        if (x < prevX) {
            throw new IllegalArgumentException("The Path cannot loop back on itself, x :" + x);
        }
        mX[i] = x;
        prevX = x;
    }

    if (pathMeasure.nextContour()) {
        throw new IllegalArgumentException("The Path should be continuous," + " can't have 2+ contours");
    }
}

From source file:com.ichi2.anki.Whiteboard.java

private void touchUp() {
    PathMeasure pm = new PathMeasure(mPath, false);
    mPath.lineTo(mX, mY);//from  w w  w .  j  a v  a2 s.co  m
    if (pm.getLength() > 0) {
        mCanvas.drawPath(mPath, mPaint);
        mUndo.add(mPath);
    } else {
        mCanvas.drawPoint(mX, mY, mPaint);
        mUndo.add(mX, mY);
    }
    mUndoModeActive = true;
    // kill the path so we don't double draw
    mPath.reset();
    if (mUndo.size() == 1 && mActivity.get() != null) {
        mActivity.get().supportInvalidateOptionsMenu();
    }
}

From source file:android.support.wear.widget.util.ArcSwipe.java

private float[][] interpolate(float[] start, float[] end, int steps, boolean isClockwise) {
    float startAngle = getAngle(start[0], start[1]);
    float endAngle = getAngle(end[0], end[1]);

    Path path = new Path();
    PathMeasure pathMeasure = new PathMeasure();
    path.moveTo(start[0], start[1]);/*from  ww w  .  j a  v  a2 s  . c  om*/
    path.arcTo(mBounds, startAngle, getSweepAngle(startAngle, endAngle, isClockwise));
    pathMeasure.setPath(path, false);
    float pathLength = pathMeasure.getLength();

    float[][] res = new float[steps][2];
    float[] mPathTangent = new float[2];

    for (int i = 1; i < steps + 1; i++) {
        pathMeasure.getPosTan((pathLength * i) / (steps + 2f), res[i - 1], mPathTangent);
    }

    return res;
}

From source file:com.lauszus.dronedraw.DroneDrawActivity.java

private void uploadCsvFile() {
    if (!mDrawView.mFullPath.isEmpty()) {
        File csvFileLocation = new File(getFilesDir(), "path.csv");
        try {/* w  w  w .ja  v a 2s  .  c o  m*/
            CSVWriter writer = new CSVWriter(new FileWriter(csvFileLocation), ',',
                    CSVWriter.NO_QUOTE_CHARACTER);
            final int dataSize = 10 * mDrawView.touchCounter; // Sample path 10 times more than actual touches
            for (int i = 0; i <= dataSize; i++) {
                PathMeasure mPathMeasure = new PathMeasure(mDrawView.mFullPath, false);

                final float t = (float) i / (float) dataSize;
                float[] xy = new float[2];
                mPathMeasure.getPosTan(mPathMeasure.getLength() * t, xy, null);

                // Normalize coordinates based on maximum dimension
                final float maxDimension = Math.max(mDrawView.getWidth(), mDrawView.getHeight());
                final float x = xy[0] / maxDimension;
                final float y = (mDrawView.getHeight() - xy[1]) / maxDimension; // Make y-axis point upward

                writer.writeNext(new String[] { Integer.toString(i), Float.toString(x), Float.toString(y) });

                //if (D) Log.d(TAG, "t: " + t + " x: " + x + " y: " + y);
            }
            writer.close();
            //sendEmail(csvFileLocation);
            uploadFileToDropbox(csvFileLocation);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

From source file:com.github.jorgecastillo.FillableLoader.java

private void buildPathData() {
    SvgPathParser parser = getPathParser();
    pathData = new PathData();
    try {/*w  w  w . java  2  s . c om*/
        pathData.path = parser.parsePath(svgPath);
    } catch (ParseException e) {
        pathData.path = new Path();
    }

    PathMeasure pm = new PathMeasure(pathData.path, true);
    while (true) {
        pathData.length = Math.max(pathData.length, pm.getLength());
        if (!pm.nextContour()) {
            break;
        }
    }
}

From source file:cc.kenai.common.AnimatedSvgView.java

private void rebuildGlyphData() {
    SvgPathParser parser = new SvgPathParser() {
        @Override/*from   w ww  .  j  a v a 2 s  . c o m*/
        protected float transformX(float x) {
            return x * mWidth / mViewport.x;
        }

        @Override
        protected float transformY(float y) {
            return y * mHeight / mViewport.y;
        }
    };

    Log.i(TAG, "---mWidth = " + mWidth + "---mViewport.x = " + mViewport.x);
    Log.i(TAG, "mGlyphStrings.length = " + mGlyphStrings.length);
    mGlyphData = new GlyphData[mGlyphStrings.length];
    for (int i = 0; i < mGlyphStrings.length; i++) {
        mGlyphData[i] = new GlyphData();
        try {
            mGlyphData[i].path = parser.parsePath(mGlyphStrings[i]);
        } catch (ParseException e) {
            mGlyphData[i].path = new Path();
            Log.e(TAG, "Couldn't parse path", e);
        }
        PathMeasure pm = new PathMeasure(mGlyphData[i].path, true);
        while (true) {
            mGlyphData[i].length = Math.max(mGlyphData[i].length, pm.getLength());
            if (!pm.nextContour()) {
                break;
            }
        }
        mGlyphData[i].paint = new Paint();
        mGlyphData[i].paint.setStyle(Paint.Style.STROKE);
        mGlyphData[i].paint.setAntiAlias(true);
        mGlyphData[i].paint.setColor(Color.WHITE);
        mGlyphData[i].paint.setStrokeWidth(
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()));
    }
}

From source file:com.daitu_liang.study.mytest.svg.AnimatedSvgView.java

private void rebuildGlyphData() {
    SvgPathParser parser = new SvgPathParser() {
        @Override/*from   w w  w  .j  av a  2s  .  co m*/
        protected float transformX(float x) {
            return x * mWidth / mViewport.x;
        }

        @Override
        protected float transformY(float y) {
            return y * mHeight / mViewport.y;
        }
    };

    Log.i(TAG, "---mWidth = " + mWidth + "---mViewport.x = " + mViewport.x);
    if (mGlyphStrings != null) {
        mGlyphData = new GlyphData[mGlyphStrings.length];
    }
    for (int i = 0; i < mGlyphStrings.length; i++) {
        mGlyphData[i] = new GlyphData();
        try {
            mGlyphData[i].path = parser.parsePath(mGlyphStrings[i]);
        } catch (ParseException e) {
            mGlyphData[i].path = new Path();
            Log.e(TAG, "Couldn't parse path", e);
        }
        PathMeasure pm = new PathMeasure(mGlyphData[i].path, true);
        while (true) {
            mGlyphData[i].length = Math.max(mGlyphData[i].length, pm.getLength());
            if (!pm.nextContour()) {
                break;
            }
        }
        mGlyphData[i].paint = new Paint();
        mGlyphData[i].paint.setStyle(Paint.Style.STROKE);
        mGlyphData[i].paint.setAntiAlias(true);
        mGlyphData[i].paint.setColor(Color.WHITE);
        mGlyphData[i].paint.setStrokeWidth(
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()));
    }
}