/**
* Copyright (c) 2009-2011, chunquedong(YangJiandong)
*
* This file is part of ChunMap project
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
*
* History:
* 2010-05-05 Jed Young Creation
*/
package chunmap.view;
import chunmap.model.coord.Coordinate2D;
import chunmap.model.coord.CPoint;
import chunmap.model.coord.Transform;
import chunmap.model.elem.Envelope;
import chunmap.model.elem.EnvelopeBuf;
public class ViewPort implements View{
private double _scale;
private EnvelopeBuf _viewEnvelop;
private double _buffer;
private EnvelopeBuf _bufferEnvelop;
private CPoint _center;
private int _viewHeight;//屏幕高
private int _viewWidth;//屏幕宽
public ViewPort(int width, int height, double buffer)
{
_viewHeight = height;
_viewWidth = width;
_scale = 1f;
_viewEnvelop = new EnvelopeBuf(0, 0, width, height);
setBufferEnvelope();
_center = _viewEnvelop.getCenter();
_buffer = buffer;
}
//------------------------------------------------------------------------setter
public int getWidth() { return _viewWidth; }
public int getHeight() { return _viewHeight; }
public void resetSize(int width, int height)
{
_viewHeight = height;
_viewWidth = width;
computerEnvelope();
}
public Envelope getBufferEnvelop() { return _bufferEnvelop; }
private void setBufferEnvelope()
{
_bufferEnvelop = _viewEnvelop.clone();
_bufferEnvelop.bufferEnvelop(this.dis2World(_buffer));
}
public double getScale(){ return _scale; }
public void setScale(double value) {
_scale = value;
computerEnvelope();
}
public Envelope getViewEnvelop(){ return _viewEnvelop; }
public void setViewEnvelop(Envelope value)
{
if (value == null) return;
if (value.getWidth() == 0 || value.getHeight() == 0)
{
//因为点的边框宽度无穷小
EnvelopeBuf eb= new EnvelopeBuf(value);
eb.bufferEnvelop(0.1);
value = eb;
}
_scale = computeScale(value);
_center = value.getCenter();
computerEnvelope();
}
public CPoint getCenter(){ return _center; }
public void setCenter(CPoint value)
{
double dx = value.getX() - _center.getX();
double dy = value.getY() - _center.getY();
_center = new Coordinate2D(value.getX(), value.getY());
_viewEnvelop.moveEnvelop(dx, dy);
_bufferEnvelop.moveEnvelop(dx, dy);
}
private void computerEnvelope()
{
double x = _center.getX();
double y = _center.getY();
double dx = (_viewWidth / _scale) / 2d;
double dy = (_viewHeight / _scale) / 2d;
_viewEnvelop = new EnvelopeBuf(x - dx, y - dy, x + dx, y + dy);
setBufferEnvelope();
}
private double computeScale(Envelope envelop)
{
double expectedEnvelopHeight = envelop.getMaxY() - envelop.getMinY();
double expectedEnvelopWidth = envelop.getMaxX() - envelop.getMinX();
double s1 = _viewHeight / expectedEnvelopHeight;
double s2 = _viewWidth / expectedEnvelopWidth;
return Math.min(s1, s2);
}
//------------------------------------------------------------------------util
public void zoom(double s, double x, double y)
{
//world
double dx0 = x - this.getCenter().getX();
double dy0 = y - this.getCenter().getY();
//view
double dx = dx0 * this.getScale();
double dy = dy0 * this.getScale();
this.setCenter( new Coordinate2D(x, y));
this.setScale(this.getScale() * s);
//world
double xx = dx / this.getScale();
double yy = dy / this.getScale();
this.setCenter ( new Coordinate2D(x - xx, y - yy));
}
//#region 坐标转换
//------------------------------------------------------------------------coordinateTransform
public double x2Screen(double x)
{
double newX;
newX = x - getViewEnvelop().getMinX();
newX = newX * getScale();
return newX;
}
public double y2Screen(double y)
{
double newY;
newY = getViewEnvelop().getMaxY() - y;
newY = newY * getScale();
return newY;
}
public Transform world2Screen()
{
Transform t = new Transform(){
@Override
public CPoint convert(CPoint p) {
double x = x2Screen(p.getX());
double y = y2Screen(p.getY());
return new Coordinate2D(x, y);
}};
return t;
}
public double x2World(double x)
{
double newX;
newX = x / getScale();
newX = newX + getViewEnvelop().getMinX();
return newX;
}
public double y2World(double y)
{
double newY;
newY = y / getScale();
newY = getViewEnvelop().getMaxY() - newY;
return newY;
}
public Transform screen2World()
{
Transform t = new Transform(){
@Override
public CPoint convert(CPoint p) {
double x = x2World(p.getX());
double y = y2World(p.getY());
return new Coordinate2D(x, y);
}};
return t;
}
public double dis2Screen(double d)
{
return d * getScale();
}
public double dis2World(double d)
{
return d / getScale();
}
//#endregion
}