package com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.manager; import android.graphics.RectF; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.data.Entry; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.utils.RectD; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.utils.SingleD_XY; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.utils.SingleF_XY; /** * 数据源与绘出来的图之间的映射关系 * ------------------- * 人与照片直接的映射关系 *
*/ public class MappingManager { /** * 区域视图 */ RectF _contentRect; /** * 数据视图 */ RectD _maxViewPort; RectD _currentViewPort; /** * 数据视图的约束 */ float fatFactor = 1f;//肥胖因子 RectD _constrainViewPort; int maxScaleX = 5;//最大放大倍数 public MappingManager(RectF rectMain) { _contentRect = rectMain; _maxViewPort = new RectD(); _currentViewPort = new RectD(); _constrainViewPort = new RectD(); } public void prepareRelation(double xMin, double xMax, double yMin, double yMax) { _maxViewPort.left = xMin; _maxViewPort.right = xMax; _maxViewPort.bottom = yMin; _maxViewPort.top = yMax; _currentViewPort.setRectD(_maxViewPort); setFatFactor(fatFactor); } /** * 根据像素位置变换成数值 * * @param x * @param y * @return */ public SingleD_XY getValueByPx(float x, float y) { SingleD_XY value = SingleD_XY.getInstance(); value.setX(p2v_x(x)).setY(p2v_y(y)); return value; } public SingleF_XY getPxByEntry(Entry entry) { return getPxByValue(entry.getX(), entry.getY()); } /** * 根据数值变换成像素 * * @param x * @param y * @return */ public SingleF_XY getPxByValue(double x, double y) { SingleF_XY value = SingleF_XY.getInstance(); value.setX(v2p_x(x)).setY(v2p_y(y)); return value; } /** * x方向 * --------------- * 数值转换成像素 * * @param xValue * @return */ public float v2p_x(double xValue) { double px = _contentRect.left + _contentRect.width() * (xValue - _currentViewPort.left) / _currentViewPort.width(); return (float) px; } /** * y方向 * ---------------- * 数值转换成像素 * * @param yValue * @return */ public float v2p_y(double yValue) { double py = _contentRect.top + _contentRect.height() - _contentRect.height() * (yValue - _currentViewPort.bottom) / _currentViewPort.height(); return (float) py; } /** * x方向 * --------------- * 像素转换成数值 * * @param xPix * @return */ public double p2v_x(float xPix) { double value = xPix - _contentRect.left; value = value / _contentRect.width() * _currentViewPort.width(); value = value + _currentViewPort.left; return value; } /** * y方向 * -------------- * 像素转换成数值 * * @param yPix * @return */ public double p2v_y(float yPix) { double value = yPix - (_contentRect.top + _contentRect.height()); value = value / -_contentRect.height() * _currentViewPort.height(); value = value + _currentViewPort.bottom; return value; } public void zoom(float scaleX, float scaleY, float cx, float cy) { double newWidth = scaleX * _currentViewPort.width(); double newHeight = scaleY * _currentViewPort.height(); double hitValueX = p2v_x(cx); double left = hitValueX - newWidth * (cx - _contentRect.left) / _contentRect.width(); double hitValueY = p2v_y(cy); double bottom = hitValueY - newHeight * (_contentRect.bottom - cy) / _contentRect.height(); if ((_maxViewPort.right - _maxViewPort.left) / newWidth> maxScaleX){ //超过最大放大倍数 return; } _currentViewPort.left = left; _currentViewPort.bottom = bottom; _currentViewPort.right = _currentViewPort.left + newWidth; _currentViewPort.top = _currentViewPort.bottom + newHeight; constrainViewPort(_currentViewPort); } public void zoom(float level, double oldStartW, double oldStartH, float cx, float cy, boolean canX, boolean canY) { double newWidth = canX ? oldStartW * level : oldStartW; double newHeight = canY ? oldStartH * level : oldStartH; double hitValueX = p2v_x(cx); double left = hitValueX - newWidth * (cx - _contentRect.left) / _contentRect.width(); double hitValueY = p2v_y(cy); double bottom = hitValueY - newHeight * (_contentRect.bottom - cy) / _contentRect.height(); if ((_maxViewPort.right - _maxViewPort.left) / newWidth> maxScaleX){ //超过最大放大倍数 return; } _currentViewPort.left = left; _currentViewPort.bottom = bottom; _currentViewPort.right = _currentViewPort.left + newWidth; _currentViewPort.top = _currentViewPort.bottom + newHeight; constrainViewPort(_currentViewPort); } /** * 根据移动的像素偏离---》计算出数据视图的偏离 * * @param dx * @param dy */ public void translate(float dx, float dy) { double w = _currentViewPort.width(); double h = _currentViewPort.height(); double ddx = w * dx / _contentRect.width(); double ddy = h * dy / _contentRect.height(); _currentViewPort.left += -ddx; _currentViewPort.bottom += ddy; // 约束 currentViewPort 的位置 constrainViewPort(_currentViewPort, w, h); _currentViewPort.right = _currentViewPort.left + w; _currentViewPort.top = _currentViewPort.bottom + h; } /** * 约束当前的viewport * --------------------- * 针对平移的方式 */ private void constrainViewPort(RectD currentViewPort, double currentWidth, double currentHeight) { currentViewPort.left = Math.max(_constrainViewPort.left, Math.min(_constrainViewPort.right - currentWidth, currentViewPort.left)); currentViewPort.bottom = Math.max(_constrainViewPort.bottom, Math.min(_constrainViewPort.top - currentHeight, currentViewPort.bottom)); } /** * 约束当前的viewport * --------------------- * 针对缩放的方式 * * @param currentViewPort */ private void constrainViewPort(RectD currentViewPort) { currentViewPort.left = Math.max(_constrainViewPort.left, currentViewPort.left); currentViewPort.right = Math.min(_constrainViewPort.right, currentViewPort.right); currentViewPort.bottom = Math.max(_constrainViewPort.bottom, currentViewPort.bottom); currentViewPort.top = Math.min(_constrainViewPort.top, currentViewPort.top); } public RectD get_constrainViewPort() { return _constrainViewPort; } public void set_constrainViewPort(RectD _constrainViewPort) { this._constrainViewPort = _constrainViewPort; } public RectD get_maxViewPort() { return _maxViewPort; } public void set_maxViewPort(RectD _maxViewPort) { this._maxViewPort = _maxViewPort; } public RectD get_currentViewPort() { return _currentViewPort; } public void set_currentViewPort(RectD _currentViewPort) { this._currentViewPort = _currentViewPort; } public float getFatFactor() { return fatFactor; } /** * 设置约束视图的肥胖因子 * ------------------- * 和最大的数据视图做比较: * 1. 约束视图 是 最大视图的 1.1 倍,那么这个肥胖因子就是 1.1 * * @param fatFactor */ public void setFatFactor(float fatFactor) { if (fatFactor < 1) { throw new RuntimeException("肥胖因子必须大于1!"); } this.fatFactor = fatFactor; double w = _maxViewPort.width(); double h = _maxViewPort.height(); fatFactor = fatFactor - 1; _constrainViewPort.left = _maxViewPort.left - w * fatFactor; _constrainViewPort.right = _maxViewPort.right + w * fatFactor; _constrainViewPort.top = _maxViewPort.top + h * fatFactor; _constrainViewPort.bottom = _maxViewPort.bottom - h * fatFactor; } public void setMaxScaleX(int maxScaleX) { this.maxScaleX = maxScaleX; } }