android.graphics.Matrix#mapPoints ( )源码实例Demo

下面列出了android.graphics.Matrix#mapPoints ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: WaveHeartRate   文件: BarLineChartTouchListener.java
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;
}
 
源代码2 项目: UGank   文件: PinchImageView.java
/**
 * 计算点除以矩阵的值
 *
 * 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];
    }
}
 
源代码3 项目: ImagePicker   文件: PinchImageView.java
/**
 * 计算点除以矩阵的值
 * <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];
    }
}
 
源代码4 项目: LB-Launcher   文件: WallpaperPickerActivity.java
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;
    }
}
 
源代码5 项目: cidrawing   文件: DrawElement.java
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]));
}
 
源代码6 项目: GestureViews   文件: GestureFrameLayout.java
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;
}
 
源代码7 项目: JNChartDemo   文件: Transformer.java
/**
 * 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);
}
 
源代码8 项目: GLEXP-Team-onebillion   文件: OBControl.java
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]);
}
 
源代码9 项目: cidrawing   文件: StrokeElement.java
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]);
    }
}
 
源代码10 项目: GLEXP-Team-onebillion   文件: UCurve.java
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;
    }
}
 
源代码12 项目: imageCrop   文件: BoundedRect.java
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);
}
 
源代码13 项目: CVScanner   文件: CropImageView.java
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;
}
 
源代码14 项目: Depth   文件: DepthRelativeLayout.java
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);
        }
    }

}
 
源代码16 项目: imageCrop   文件: BoundedRect.java
/**
 * 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();
}
 
源代码17 项目: Notification-Analyser   文件: BarLineChartBase.java
/**
 * 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);
}
 
源代码18 项目: imageCrop   文件: BoundedRect.java
/**
 * 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();
}
 
源代码19 项目: MapView   文件: LocationLayer.java
@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();
        }
    }
 
源代码20 项目: TelePlus-Android   文件: CropView.java
void applyMatrix(Matrix m) {
    m.mapPoints(coords);
}