List of usage examples for android.graphics PathMeasure getLength
public float getLength()
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())); } }