在视图上绘制折线时坐标比例不正确 [英] Coordinates scale not correct when drawing a polyline on an View

查看:97
本文介绍了在视图上绘制折线时坐标比例不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在视图上绘制折线。我不想在 MapView 上绘制它,因为我只希望 polyline 没有任何背景。

I want to draw a polyline on a view. I don't want to draw it on a MapView because I only want the polyline without any background.

我有折线坐标,也有边界(东北和西南坐标)。

I have the polyline coordinates and I also have its bounds (northeast and southwest coordinates).

想法是创建一个自定义的视图并在其中绘制路径。我相信我遇到的问题是秤的问题。我可以将 LatLng 坐标转换为 x y 坐标但是视图上显示的折线太小。 视图的宽度和高度设置为 64dp

The idea was to create a custom view and draw the path there. The problem I believe I'm having is with the scale. I can convert the LatLng coordinates to x and y coordinates but the polyline that is shown on the view is too small. The view is set with a 64dp width and height.

这是我在做什么:

public PolylineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    polylineSize = (int) context.getResources().getDimension(R.dimen.polyline_size);
    setupAttributes(attrs);
}

private void setupAttributes(AttributeSet attrs) {
    // Obtain a typed array of attributes
    TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PolylineView, 0, 0);
    // Extract custom attributes into member variables
    try {
        polylineColor = a.getColor(R.styleable.PolylineView_polylineColor, Color.BLACK);

    } finally {
        // TypedArray objects are shared and must be recycled.
        a.recycle();
    }

    polyline = new Paint(Paint.ANTI_ALIAS_FLAG);
    polyline.setAntiAlias(true);
    polyline.setStyle(Paint.Style.STROKE);
    polyline.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics()));
    polyline.setStrokeCap(Paint.Cap.ROUND);
    polyline.setColor(polylineColor);

    path = new Path();
    smp = new SphericalMercatorProjection(polylineSize);
}

@Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    point = smp.toPoint(polylineCoordinates.get(0));

    path.moveTo((float) (point.x * scale), (float) (point.y * scale));

    for (int i = 1; i < polylineCoordinates.size(); i++) {
        point = smp.toPoint(polylineCoordinates.get(i));

        path.lineTo((float) (point.x * scale), (float) (point.y * scale));
    }

    canvas.drawPath(path, polyline);
}

public void setPolyline(List<LatLng> polylineCoordinates, RealmLatLngBounds polylineBounds) {
    this.polylineBounds = polylineBounds;
    this.polylineCoordinates = polylineCoordinates;

    //Find the scale
    Point northeast = smp.toPoint(polylineBounds.getNortheast());
    Point southwest = smp.toPoint(polylineBounds.getSouthwest());
    scale = polylineSize / Math.max(Math.max(northeast.x, southwest.x), Math.max(northeast.y, southwest.y));

    invalidate();
    requestLayout();
}

之后可以转换折线坐标以便使用视图的完整大小?

After can I transform the polyline coordinates so that the full size of the view is used?

编辑:

我能看到的问题之一是当转换为 x y ,值是两个接近(精确)的

One of the problems that I can see is when converting to x and y, values are two close (precision)

推荐答案

在@pskink的帮助下,我设法实现了这一目标

With the help of @pskink I've managed to achieve this

private int polylineSize;
private Paint polyline;
private SphericalMercatorProjection smp;


PointF northeast;
PointF[] points;
PointF southwest;

Path originalPath;
Path transformedPath;


public PolylineView(Context context) {
    super(context);
}

public PolylineView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    polylineSize = (int) context.getResources().getDimension(R.dimen.polyline_size);
    setupAttributes(attrs);
}

public PolylineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    polylineSize = (int) context.getResources().getDimension(R.dimen.polyline_size);
    setupAttributes(attrs);
}

private void setupAttributes(AttributeSet attrs) {
    // Obtain a typed array of attributes
    TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PolylineView, 0, 0);
    // Extract custom attributes into member variables
    int polylineColor;
    try {
        polylineColor = a.getColor(R.styleable.PolylineView_polylineColor, Color.BLACK);

    } finally {
        // TypedArray objects are shared and must be recycled.
        a.recycle();
    }

    polyline = new Paint(Paint.ANTI_ALIAS_FLAG);
    polyline.setAntiAlias(true);
    polyline.setStyle(Paint.Style.STROKE);
    polyline.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics()));
    polyline.setStrokeCap(Paint.Cap.ROUND);
    polyline.setColor(polylineColor);

    smp = new SphericalMercatorProjection(polylineSize);

}

public void setPolylineData(List<LatLng> polylineCoordinates, RealmLatLngBounds polylineBounds) {

    originalPath = new Path();
    transformedPath = new Path();

    Point point = smp.toPoint(polylineBounds.getNortheast());
    northeast = new PointF((float) point.x, (float) point.y);

    point = smp.toPoint(polylineBounds.getSouthwest());
    southwest = new PointF((float) point.x, (float) point.y);

    points = new PointF[polylineCoordinates.size()];

    for (int i = 0; i < polylineCoordinates.size(); i++) {
        point = smp.toPoint(polylineCoordinates.get(i));
        points[i] = new PointF((float) point.x, (float) point.y);
    }

    originalPath.moveTo(points[0].x, points[0].y);

    for (PointF p : points) {
        originalPath.lineTo(p.x, p.y);
    }

    RectF src = new RectF(southwest.x, northeast.y, northeast.x, southwest.y);
    RectF dst = new RectF(0, 0, polylineSize, polylineSize);
    Matrix matrix = new Matrix();
    matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
    originalPath.transform(matrix, transformedPath);

    invalidate();
    requestLayout();
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawPath(transformedPath, polyline);
}

此视图用于 RecyclerView 并将数据设置在 onBindViewHolder

This view is used on a RecyclerView and the data is set on onBindViewHolder

这篇关于在视图上绘制折线时坐标比例不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆