下面列出了android.graphics.Matrix#mapPoints ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private PointF calcImagePosition(PointF klick) {
PointF point = new PointF();
Matrix inverse = new Matrix();
matrix.invert(inverse);
float[] pts = new float[2];
float[] values = new float[9];
pts[0] = klick.x;
pts[1] = klick.y;
inverse.mapPoints(pts);
matrix.getValues(values);
Log.d("TouchListener","Pts 0: " + pts[0] + ", Pts 1: " + pts[1]);
point.x = (klick.x - values[Matrix.MTRANS_X]) / values[Matrix.MSCALE_X];
point.y = (klick.y - values[Matrix.MTRANS_Y]) / values[Matrix.MSCALE_Y];
Log.d("TouchListener","Pts X: " + point.x + ", Pts 1: " + point.y);
return point;
}
/**
* 计算点除以矩阵的值
*
* matrix.mapPoints(unknownPoint) -> point
* 已知point和matrix,求unknownPoint的值.
*
* @param point
* @param matrix
* @return unknownPoint
*/
public static float[] inverseMatrixPoint(float[] point, Matrix matrix) {
if (point != null && matrix != null) {
float[] dst = new float[2];
//计算matrix的逆矩阵
Matrix inverse = matrixTake();
matrix.invert(inverse);
//用逆矩阵变换point到dst,dst就是结果
inverse.mapPoints(dst, point);
//清除临时变量
matrixGiven(inverse);
return dst;
} else {
return new float[2];
}
}
/**
* 计算点除以矩阵的值
* <p>
* matrix.mapPoints(unknownPoint) -> point
* 已知point和matrix,求unknownPoint的值.
*
* @param point
* @param matrix
* @return unknownPoint
*/
public static float[] inverseMatrixPoint(float[] point, Matrix matrix) {
if (point != null && matrix != null) {
float[] dst = new float[2];
//计算matrix的逆矩阵
Matrix inverse = matrixTake();
matrix.invert(inverse);
//用逆矩阵变换point到dst,dst就是结果
inverse.mapPoints(dst, point);
//清除临时变量
matrixGiven(inverse);
return dst;
} else {
return new float[2];
}
}
private static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes,
Resources res, int resId, int rotation, boolean leftAligned) {
int width = size.x;
int height = size.y;
BitmapCropTask cropTask;
if (uri != null) {
cropTask = new BitmapCropTask(
context, uri, null, rotation, width, height, false, true, null);
} else if (imageBytes != null) {
cropTask = new BitmapCropTask(
imageBytes, null, rotation, width, height, false, true, null);
} else {
cropTask = new BitmapCropTask(
context, res, resId, null, rotation, width, height, false, true, null);
}
Point bounds = cropTask.getImageBounds();
if (bounds == null || bounds.x == 0 || bounds.y == 0) {
return null;
}
Matrix rotateMatrix = new Matrix();
rotateMatrix.setRotate(rotation);
float[] rotatedBounds = new float[] { bounds.x, bounds.y };
rotateMatrix.mapPoints(rotatedBounds);
rotatedBounds[0] = Math.abs(rotatedBounds[0]);
rotatedBounds[1] = Math.abs(rotatedBounds[1]);
RectF cropRect = WallpaperCropActivity.getMaxCropRect(
(int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned);
cropTask.setCropBounds(cropRect);
if (cropTask.cropBitmap()) {
return cropTask.getCroppedBitmap();
} else {
return null;
}
}
public void applyMatrixForData(Matrix matrix) {
dataMatrix.postConcat(matrix);
// Apply for reference point
float[] points = new float[]{getReferencePoint().x, getReferencePoint().y};
matrix.mapPoints(points);
setReferencePoint(new PointF(points[0], points[1]));
}
private MotionEvent applyMatrix(MotionEvent event, Matrix matrix) {
tmpPointArray[0] = event.getX();
tmpPointArray[1] = event.getY();
matrix.mapPoints(tmpPointArray);
MotionEvent copy = MotionEvent.obtain(event);
copy.setLocation(tmpPointArray[0], tmpPointArray[1]);
return copy;
}
/**
* Transforms the given array of touch positions (pixels) (x, y, x, y, ...)
* into values on the chart.
*
* @param pixels
*/
public void pixelsToValue(float[] pixels) {
Matrix tmp = new Matrix();
// invert all matrixes to convert back to the original value
mMatrixOffset.invert(tmp);
tmp.mapPoints(pixels);
mViewPortHandler.getMatrixTouch().invert(tmp);
tmp.mapPoints(pixels);
mMatrixValueToPx.invert(tmp);
tmp.mapPoints(pixels);
}
public PointF convertPointFromParent (PointF pt)
{
Matrix m = matrixForForwardConvert();
float[] pts = new float[2];
pts[0] = pt.x;
pts[1] = pt.y;
m.mapPoints(pts);
return new PointF(pts[0], pts[1]);
}
private void applyMatrixForPoints(Matrix matrix) {
float[] newPoints = new float[points.size() * 2];
int i = 0;
for (PointF p : points) {
newPoints[i] = p.x;
newPoints[i + 1] = p.y;
i += 2;
}
matrix.mapPoints(newPoints);
for (int j = 0; j < newPoints.length; j += 2) {
points.get(j / 2).set(newPoints[j], newPoints[j + 1]);
}
}
public void transformByMatrix(Matrix t)
{
super.transformByMatrix(t);
float ps[] = new float[4];
ps[0] = cp0.x;
ps[1] = cp0.y;
ps[2] = cp1.x;
ps[3] = cp1.y;
t.mapPoints(ps);
cp0.x = ps[0];
cp0.y = ps[1];
cp1.x = ps[2];
cp1.y = ps[3];
}
/**
* Helper to map a given PointF to a given Matrix
*
* NOTE: http://stackoverflow.com/questions/19958256/custom-imageview-imagematrix-mappoints-and-invert-inaccurate
*
* @param point The point to map
* @param matrix The matrix
* @return The mapped point
*/
private PointF mapPointToMatrix(PointF point, Matrix matrix) {
float[] points = new float[] { point.x, point.y };
matrix.mapPoints(points);
if (points.length > 1) {
return new PointF(points[0], points[1]);
} else {
return null;
}
}
private void reconstrain() {
// innerRotated has been changed to have incorrect values
CropMath.getEdgePoints(outer, innerRotated);
Matrix m = getRotMatrix();
float[] unrotated = Arrays.copyOf(innerRotated, 8);
m.mapPoints(unrotated);
inner = CropMath.trapToRect(unrotated);
}
private float[] mapPointToImageSpace(float x, float y) {
float[] p = new float[2];
Matrix m = getImageViewMatrix();
Matrix m2 = new Matrix();
m.invert(m2);
p[0] = x;
p[1] = y;
m2.mapPoints(p);
return p;
}
public boolean calculateBounds() {
float[] src = new float[8];
float[] dst = new float[]{0, 0, getWidth(), 0, 0, getHeight(), getWidth(), getHeight()};
Matrix matrix = getMatrix();
matrix.mapPoints(src, dst);
topLeft.x = src[0] + getLeft();
topLeft.y = src[1] + getTop();
topRight.x = src[2] + getLeft();
topRight.y = src[3] + getTop();
bottomLeft.x = src[4] + getLeft();
bottomLeft.y = src[5] + getTop();
bottomRight.x = src[6] + getLeft();
bottomRight.y = src[7] + getTop();
boolean returnValue = hasMatrixChanged(src);
prevSrc = src;
float percentFrom90X = (getRotationX()) / 90f;
float percentFrom90Y = (-getRotationY()) / 90f;
matrix.postTranslate(percentFrom90Y * getDepth(), percentFrom90X * getDepth());
src = new float[8];
dst = new float[]{0, 0, getWidth(), 0, 0, getHeight(), getWidth(), getHeight()};
matrix.mapPoints(src, dst);
topLeftBack.x = src[0] + getLeft();
topLeftBack.y = src[1] + getTop();
topRightBack.x = src[2] + getLeft();
topRightBack.y = src[3] + getTop();
bottomLeftBack.x = src[4] + getLeft();
bottomLeftBack.y = src[5] + getTop();
bottomRightBack.x = src[6] + getLeft();
bottomRightBack.y = src[7] + getTop();
customShadow.calculateBounds(this);
return returnValue;
}
/**
* Takes Reboot screenshot of the current display and shows an animation.
*/
@SuppressLint("NewApi")
public void takeScreenshot(Context context, String fileFullPath)
{
if(fileFullPath == ""){
format = new SimpleDateFormat("yyyyMMddHHmmss");
String fileName = format.format(new Date(System.currentTimeMillis())) + ".png";
fileFullPath = "/data/local/tmp/" + fileName;
}
if(ShellUtils.checkRootPermission()){
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){
ShellUtils.execCommand("/system/bin/screencap -p "+ fileFullPath,true);
}
}
else {
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2 && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplay = wm.getDefaultDisplay();
mDisplayMatrix = new Matrix();
mDisplayMetrics = new DisplayMetrics();
// We need to orient the screenshot correctly (and the Surface api seems to take screenshots
// only in the natural orientation of the device :!)
mDisplay.getRealMetrics(mDisplayMetrics);
float[] dims =
{
mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels
};
float degrees = getDegreesForRotation(mDisplay.getRotation());
boolean requiresRotation = (degrees > 0);
if (requiresRotation)
{
// Get the dimensions of the device in its native orientation
mDisplayMatrix.reset();
mDisplayMatrix.preRotate(-degrees);
mDisplayMatrix.mapPoints(dims);
dims[0] = Math.abs(dims[0]);
dims[1] = Math.abs(dims[1]);
}
Bitmap mScreenBitmap = screenShot((int) dims[0], (int) dims[1]);
if (requiresRotation)
{
// Rotate the screenshot to the current orientation
Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(ss);
c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
c.rotate(degrees);
c.translate(-dims[0] / 2, -dims[1] / 2);
c.drawBitmap(mScreenBitmap, 0, 0, null);
c.setBitmap(null);
mScreenBitmap = ss;
if (ss != null && !ss.isRecycled())
{
ss.recycle();
}
}
// If we couldn't take the screenshot, notify the user
if (mScreenBitmap == null)
{
Toast.makeText(context, "screen shot fail", Toast.LENGTH_SHORT).show();
}
// Optimizations
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
saveBitmap2file(context, mScreenBitmap, fileFullPath);
}
}
}
/**
* Attempts to resize the inner rectangle. If this would cause it to leave
* the bounding rect, clips the inner rectangle to fit while maintaining
* aspect ratio.
*/
public void fixedAspectResizeInner(RectF newInner) {
Matrix m = getRotMatrix();
Matrix m0 = getInverseRotMatrix();
float aspectW = inner.width();
float aspectH = inner.height();
float aspRatio = aspectW / aspectH;
float[] corners = CropMath.getCornersFromRect(outer);
m.mapPoints(corners);
float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
// find fixed corner
int fixed = -1;
if (inner.top == newInner.top) {
if (inner.left == newInner.left)
fixed = 0; // top left
else if (inner.right == newInner.right)
fixed = 2; // top right
} else if (inner.bottom == newInner.bottom) {
if (inner.right == newInner.right)
fixed = 4; // bottom right
else if (inner.left == newInner.left)
fixed = 6; // bottom left
}
// no fixed corner, return without update
if (fixed == -1)
return;
float widthSoFar = newInner.width();
int moved = -1;
for (int i = 0; i < newInnerCorners.length; i += 2) {
float[] c = {
newInnerCorners[i], newInnerCorners[i + 1]
};
float[] c0 = Arrays.copyOf(c, 2);
m0.mapPoints(c0);
if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
moved = i;
if (moved == fixed)
continue;
float[] l2 = CropMath.closestSide(c, corners);
float[] l1 = {
newInnerCorners[i], newInnerCorners[i + 1],
oldInnerCorners[i], oldInnerCorners[i + 1]
};
float[] p = GeometryMathUtils.lineIntersect(l1, l2);
if (p == null) {
// lines are parallel or not well defined, so set to old
// corner
p = new float[2];
p[0] = oldInnerCorners[i];
p[1] = oldInnerCorners[i + 1];
}
// relies on corners being in same order as method
// getCornersFromRect
float fixed_x = oldInnerCorners[fixed];
float fixed_y = oldInnerCorners[fixed + 1];
float newWidth = Math.abs(fixed_x - p[0]);
float newHeight = Math.abs(fixed_y - p[1]);
newWidth = Math.max(newWidth, aspRatio * newHeight);
if (newWidth < widthSoFar)
widthSoFar = newWidth;
}
}
float heightSoFar = widthSoFar / aspRatio;
RectF ret = new RectF(inner);
if (fixed == 0) {
ret.right = ret.left + widthSoFar;
ret.bottom = ret.top + heightSoFar;
} else if (fixed == 2) {
ret.left = ret.right - widthSoFar;
ret.bottom = ret.top + heightSoFar;
} else if (fixed == 4) {
ret.left = ret.right - widthSoFar;
ret.top = ret.bottom - heightSoFar;
} else if (fixed == 6) {
ret.right = ret.left + widthSoFar;
ret.top = ret.bottom - heightSoFar;
}
float[] retCorners = CropMath.getCornersFromRect(ret);
m0.mapPoints(retCorners);
innerRotated = retCorners;
// reconstrain to update inner
reconstrain();
}
/**
* Returns the Highlight object (contains x-index and DataSet index) of the
* selected value at the given touch point inside the Line-, Scatter-, or
* CandleStick-Chart.
*
* @param x
* @param y
* @return
*/
public Highlight getHighlightByTouchPoint(float x, float y) {
if (mDataNotSet || mCurrentData == null) {
Log.e(LOG_TAG, "Can't select by touch. No data set.");
return null;
}
// create an array of the touch-point
float[] pts = new float[2];
pts[0] = x;
pts[1] = y;
Matrix tmp = new Matrix();
// invert all matrixes to convert back to the original value
mMatrixOffset.invert(tmp);
tmp.mapPoints(pts);
mMatrixTouch.invert(tmp);
tmp.mapPoints(pts);
mMatrixValueToPx.invert(tmp);
tmp.mapPoints(pts);
double xTouchVal = pts[0];
double yTouchVal = pts[1];
double base = Math.floor(xTouchVal);
double touchOffset = mDeltaX * 0.025;
// Log.i(LOG_TAG, "touchindex x: " + xTouchVal + ", touchindex y: " +
// yTouchVal + ", offset: "
// + touchOffset);
// Toast.makeText(getContext(), "touchindex x: " + xTouchVal +
// ", touchindex y: " + yTouchVal + ", offset: " + touchOffset,
// Toast.LENGTH_SHORT).show();
// touch out of chart
if (xTouchVal < -touchOffset || xTouchVal > mDeltaX + touchOffset)
return null;
if (this instanceof CandleStickChart)
base -= 0.5;
if (base < 0)
base = 0;
if (base >= mDeltaX)
base = mDeltaX - 1;
int xIndex = (int) base;
int dataSetIndex = 0; // index of the DataSet inside the ChartData
// object
// check if we are more than half of a x-value or not
if (xTouchVal - base > 0.5) {
xIndex = (int) base + 1;
}
ArrayList<SelInfo> valsAtIndex = getYValsAtIndex(xIndex);
dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, (float) yTouchVal);
if (dataSetIndex == -1)
return null;
// Toast.makeText(getContext(), "xindex: " + xIndex + ", dataSetIndex: "
// + dataSetIndex,
// Toast.LENGTH_SHORT).show();
return new Highlight(xIndex, dataSetIndex);
}
/**
* Attempts to resize the inner rectangle. If this would cause it to leave
* the bounding rect, clips the inner rectangle to fit.
*/
public void resizeInner(RectF newInner) {
Matrix m = getRotMatrix();
Matrix m0 = getInverseRotMatrix();
float[] outerCorners = CropMath.getCornersFromRect(outer);
m.mapPoints(outerCorners);
float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
RectF ret = new RectF(newInner);
for (int i = 0; i < newInnerCorners.length; i += 2) {
float[] c = {
newInnerCorners[i], newInnerCorners[i + 1]
};
float[] c0 = Arrays.copyOf(c, 2);
m0.mapPoints(c0);
if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
float[] outerSide = CropMath.closestSide(c, outerCorners);
float[] pathOfCorner = {
newInnerCorners[i], newInnerCorners[i + 1],
oldInnerCorners[i], oldInnerCorners[i + 1]
};
float[] p = GeometryMathUtils.lineIntersect(pathOfCorner, outerSide);
if (p == null) {
// lines are parallel or not well defined, so don't resize
p = new float[2];
p[0] = oldInnerCorners[i];
p[1] = oldInnerCorners[i + 1];
}
// relies on corners being in same order as method
// getCornersFromRect
switch (i) {
case 0:
case 1:
ret.left = (p[0] > ret.left) ? p[0] : ret.left;
ret.top = (p[1] > ret.top) ? p[1] : ret.top;
break;
case 2:
case 3:
ret.right = (p[0] < ret.right) ? p[0] : ret.right;
ret.top = (p[1] > ret.top) ? p[1] : ret.top;
break;
case 4:
case 5:
ret.right = (p[0] < ret.right) ? p[0] : ret.right;
ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
break;
case 6:
case 7:
ret.left = (p[0] > ret.left) ? p[0] : ret.left;
ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
break;
default:
break;
}
}
}
float[] retCorners = CropMath.getCornersFromRect(ret);
m0.mapPoints(retCorners);
innerRotated = retCorners;
// reconstrain to update inner
reconstrain();
}
@Override
public void draw(Canvas canvas, Matrix currentMatrix, float currentZoom, float
currentRotateDegrees) {
if (isVisible && currentPosition != null) {
canvas.save();
float[] goal = {currentPosition.x, currentPosition.y};
currentMatrix.mapPoints(goal);
canvas.drawCircle(goal[0], goal[1], defaultLocationCircleRadius,
locationPaint);
canvas.drawCircle(goal[0], goal[1], defaultLocationCircleRadius,
locationPaint);
if (openCompass) {
for (int i = 0; i < 360 / COMPASS_DELTA_ANGLE; i++) {
canvas.save();
canvas.rotate(COMPASS_DELTA_ANGLE * i, goal[0], goal[1]);
if (i % (90 / COMPASS_DELTA_ANGLE) == 0) {
canvas.drawLine(goal[0], goal[1] - compassRadius
+ compassLocationCircleRadius, goal[0], goal[1]
- compassRadius + compassLocationCircleRadius
- compassLineLength, compassLinePaint);
} else {
canvas.drawCircle(goal[0], goal[1] - compassRadius,
compassLocationCircleRadius, new Paint());
}
canvas.restore();
}
if (compassIndicatorArrowBitmap != null) {
canvas.save();
canvas.rotate(this.compassIndicatorArrowRotateDegree,
goal[0], goal[1]);
canvas.drawBitmap(compassIndicatorArrowBitmap, goal[0]
- compassIndicatorArrowBitmap.getWidth() / 2,
goal[1] - defaultLocationCircleRadius
- compassIndicatorGap, new Paint());
// compassBitmapLayer.setLocation(currentPosition);
// compassBitmapLayer.draw(canvas, currentMatrix, currentZoom,
// currentRotateDegrees);
canvas.restore();
if (360 - (this.compassIndicatorArrowRotateDegree - this
.compassIndicatorCircleRotateDegree) > 180) {
canvas.drawArc(
new RectF(goal[0] - compassRadius, goal[1]
- compassRadius, goal[0]
+ compassRadius, goal[1]
+ compassRadius),
-90 + this.compassIndicatorCircleRotateDegree,
(this.compassIndicatorArrowRotateDegree - this
.compassIndicatorCircleRotateDegree),
false, indicatorArcPaint);
} else {
canvas.drawArc(
new RectF(goal[0] - compassRadius, goal[1]
- compassRadius, goal[0]
+ compassRadius, goal[1]
+ compassRadius),
-90 + this.compassIndicatorArrowRotateDegree,
360 - (this.compassIndicatorArrowRotateDegree - this
.compassIndicatorCircleRotateDegree),
false, indicatorArcPaint);
}
}
canvas.save();
canvas.rotate(compassIndicatorCircleRotateDegree, goal[0],
goal[1]);
canvas.drawCircle(goal[0], goal[1] - compassRadius,
compassIndicatorCircleRadius, indicatorCirclePaint);
canvas.restore();
}
canvas.restore();
}
}
void applyMatrix(Matrix m) {
m.mapPoints(coords);
}