arc.java
来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 1,554 行 · 第 1/3 页
JAVA
1,554 行
* Get the bounds of this arc.
*
* @return The bounds rectangle.
*
*/
public Rect getBounds(){
JFPoint center =getCenter();
double radius =center.distance(m_startPoint);
return new Rect(center.getX()-radius,center.getY()-radius,2*radius,2*radius);
}
/**
* Get start angle of this arc.
* A start angle of an arc is constructed
* by the horizontal line(from left to right) and the line from center to start point.
*
* @return The start angle.
*
*/
public double getStartAngle(){
JFPoint center =getCenter();
return Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
}
/**
* Get end angle of this arc.
* A end angle of an arc is constructed
* by the horizontal line(from left to right) and the line from center to end point.
*
* @return The ending angle.
*
*/
public double getEndAngle(){
return Angle.getValidAngle(getStartAngle()+getAngle());
}
/**
* Set value of current Arc.
*
* @param val A new Arc object.
*
*/
public void setValue(Arc arc){
setValueByControl(arc.getStartPoint(),arc.getEndPoint(),arc.getControlPoint(),arc.getArcType());
}
/**
* Set value of current Arc.
* Attention: The distance from startPoint to center must equal to the distance from endPoint to center.
* Otherwise we will make a correction for the difference.
*
* @param center The center point of this arc.
*
* @param startPoint The start point of this arc.
*
* @param angle The angle of this arc.
*
*/
public void setValue(JFPoint center,JFPoint startPoint,double angle){
setValue(center,startPoint,angle,m_arcType);
}
/**
* Set value of current Arc.
* Attention: The distance from startPoint to center must equal to the distance from endPoint to center.
* Otherwise we will make a correction for the difference.
*
* @param center The center point of this arc.
*
* @param startPoint The start point of this arc.
*
* @param angle The angle of this arc.
*
* @param arcType type of current arc.
*
*/
public void setValue(JFPoint center,JFPoint startPoint,double angle, int arcType){
m_startPoint.setValue(startPoint);
//set angle, then adjust the end point and control point.
if (!setAngle(angle,m_startPoint,center)){
//if failed to set the angle, may be the angle is too small, so we consider an 1 degree angle.
setAngle(1/180*Angle.PI,m_startPoint,center);
}
m_arcType =arcType;
}
/**
* Set value of current Arc.
*
* @param center The center point of this arc.
*
* @param startPoint The start point of this arc.
*
* @param endPoint The end point of this arc.
*
* @param clockwiseControl If control point is under clockwise side of the vector from start point to end point. False default.
*
* @param arcType type of current arc.
*
*/
public void setValue(JFPoint center,JFPoint startPoint,JFPoint endPoint, boolean clockwiseControl,int arcType){
m_startPoint.setValue(startPoint);
m_endPoint.setValue(endPoint);
double radius =center.distance(m_startPoint);
//slope of the line from start point to end point.
double slope =m_startPoint.getSlope(m_endPoint);
//slope of the erect perpendicular bisector of the line from startpoint to end point
if (slope==GeomConst.LARGE_VALUE)
slope =0;
else if (slope==0)
slope =GeomConst.LARGE_VALUE;
else
slope =-1/slope;
m_controlPoint =center.nearPoint(slope,radius,m_startPoint,!clockwiseControl);
m_arcType =arcType;
}
/**
* Get a default control point decided by start point and end point of an arc.
*
* @param startPoint The start point of this arc.
*
* @param endPoint The end point of this arc.
*
* @return The default control point.
*
*/
private static JFPoint getDefaultControlPoint(JFPoint startPoint, JFPoint endPoint){
if (startPoint==null || endPoint==null)
return null;
//length of the line from center of arc to centerPoint.
double chordHeight =startPoint.distance(endPoint)/3;
return JFPoint.getMiddleUprightPoint(startPoint,endPoint,chordHeight,false);
}
/**
* Set value of current Arc.
* We decide an arc by a startpoint and an endpoint. This method is always used while
* drawing an arc when two end points are decided.
*
* @param startPoint The start point of this arc.
*
* @param endPoint The end point of this arc.
*
* @param arcType type of current arc.
*
*/
public void setValueByDraw(JFPoint startPoint, JFPoint endPoint,int arcType){
JFPoint controlPoint =getDefaultControlPoint(startPoint, endPoint);
if (controlPoint==null)
return;
setValueByControl(startPoint,endPoint,controlPoint,arcType);
}
/**
* Set value of current Arc.
* We decide an arc by a startpoint ,an endpoint and a control point. This method is always used while
* adjusting an arc when two end points and a control point are decided.
*
* @param startPoint The start point of this arc.
*
* @param endPoint The end point of this arc.
*
* @param controlPoint The control point of this arc.
*
* @param arcType type of current arc.
*
*/
public void setValueByControl(JFPoint startPoint, JFPoint endPoint,JFPoint controlPoint,int arcType){
if (startPoint==null || endPoint==null || controlPoint==null)
return;
//test if a control point is actuall a control point that is on the middle upright line of
//the line from start Point to end point.
if ((float)controlPoint.distance(startPoint)!=(float)controlPoint.distance(endPoint)){
//default control point of arc.
JFPoint defaultControlPoint =getDefaultControlPoint(startPoint,endPoint);
//center point between startpoint and endpoint.
JFPoint centerPoint =startPoint.midPoint(endPoint);
//line from center point to default control point.
LineSeg line = new LineSeg(centerPoint,defaultControlPoint);
//projective upright foot on line above by 'control point'.
controlPoint =line.uprightFoot(controlPoint.getX(), controlPoint.getY());
if (controlPoint==null)
return;
}
m_startPoint.setValue(startPoint);
m_endPoint.setValue(endPoint);
m_controlPoint.setValue(controlPoint);
m_arcType =arcType;
}
/**
* Move control point of current Arc to a new position.
*
* @param controlPoint A new position of control point.
*
*/
public void moveControlPointTo(JFPoint controlPoint){
setControlPoint(controlPoint,true);
}
/**
* Move center point of current Arc to a new position.
*
* @param centerPoint A new position of center point.
*
*/
public void moveCenterPointTo(JFPoint centerPoint){
//if control point is under clockwise side of vector from startpoint to endpoint.
boolean clockwise =JFVector.underClockwiseSide(m_startPoint,m_controlPoint,m_startPoint,m_endPoint);
JFPoint midPoint =m_startPoint.midPoint(m_endPoint);
JFPoint defaultControl =getDefaultControlPoint(m_startPoint,m_endPoint);
LineSeg line =new LineSeg(midPoint,defaultControl);
//projective upright foot on line above by 'center point'.
JFPoint newCenter =line.uprightFoot(centerPoint.getX(),centerPoint.getY());
if (newCenter==null || newCenter.distance(midPoint)<GeomConst.MIN_LINELENGTH)
return;
setValue(newCenter,m_startPoint,m_endPoint,clockwise,m_arcType);
}
/**
* Move start point of current Arc to a new position.
*
* @param newStartPoint A new position of start point.
*
*/
public void moveStartPointTo(JFPoint newStartPoint){
setStartPoint(newStartPoint,true);
}
/**
* Move end point of current Arc to a new position.
*
* @param newEndPoint A new position of end point.
*
*/
public void moveEndPointTo(JFPoint newEndPoint){
setEndPoint(newEndPoint,true);
}
/**
* Constructor for Arc.
*/
public Arc(){
}
/**
* Constructor for Arc.
*
* @param arc A Arc object.
*/
public Arc(Arc arc){
setValue(arc);
}
/**
* Constructor for Arc.
*
* @param center The center point of this arc.
*
* @param startPoint The start point of this arc.
*
* @param angle the angle of this arc.
*
*/
public Arc(JFPoint center,JFPoint startPoint,double angle){
setValue(center,startPoint,angle);
}
/**
* Constructor for Arc.
*
* @param center The center point of this arc.
*
* @param startPoint The start point of this arc.
*
* @param angle the angle of this arc.
*
* @param arcType type of this arc.
*
*/
public Arc(JFPoint center,JFPoint startPoint,double angle, int arcType){
setValue(center,startPoint,angle,arcType);
}
/**
* Constructor for Arc.
*
* @param center The center point of this arc.
*
* @param startPoint The start point of this arc.
*
* @param endPoint the end point of this arc.
*
* @param clockwiseControl If control point is under clockwise side of the vector from start point to end point. False default.
*
* @param arcType type of this arc.
*
*/
public Arc(JFPoint center,JFPoint startPoint,JFPoint endPoint, boolean clockwiseControl,int arcType){
setValue(center,startPoint,endPoint,clockwiseControl,arcType);
}
/**
* Test if a point is within this arc.
*
* @param pnt A point to be measured.
*
* @return True if the point is within the arc, false otherwise.
*
*/
public boolean contains(JFPoint pnt){
return contains(pnt.getX(),pnt.getY());
}
/**
* Test if the line that from center to this point is in the PIE angle of this arc.
*
* @param x, y A point to be measured.
*
* @return True if the line from center to this point is within the arc, false otherwise.
*
*/
private boolean ifInPie(double x, double y){
JFPoint center =getCenter();
double angle =getAngle();
double startAngle =Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
double endAngle =Angle.getValidAngle(Angle.getAngle(center,m_endPoint));
double thisAngle =Angle.getValidAngle(Angle.getAngle(center.getX(),center.getY(),x,y));
if (angle==0){
return (thisAngle==startAngle);
}else if (startAngle<endAngle){
if (angle>=0){
return (thisAngle>=startAngle && thisAngle<=endAngle);
}else{
return (thisAngle<startAngle || thisAngle>endAngle);
}
}else{
if (angle>=0){
return (thisAngle>startAngle || thisAngle<endAngle);
}else{
return (thisAngle>=endAngle && thisAngle<=startAngle);
}
}
}
/**
* Test if a point is within this arc.
*
* @param x, y A point to be measured.
*
* @return True if the point is within the arc, false otherwise.
*
*/
public boolean contains(double x, double y){
JFPoint center =getCenter();
double radius =getRadius();
double angle =getAngle();
//test if this angle is in pie
boolean inPie =ifInPie(x,y);
double dist =center.distance(x,y);
//if this point is inside the circle that its center is at center and with a radius m_radius
if ((Math.abs(dist-radius)<=GeomConst.PICK_OFFSET) && inPie)
return true;
else if (dist>radius)
return false;
if (m_arcType==OPEN)
return false;
//test if the line from start point to end point and the line from center to target point
//are intersected.
//line from start point to end point.
LineSeg line1 =new LineSeg(getStartPoint(),getEndPoint());
//if intersect with line from center to target point.
boolean intersected =line1.intersects(center.getX(),center.getY(),x,y);
if (intersected){
return Math.abs(angle)<Angle.PI && inPie;
}else{
if (Math.abs(angle)>=Angle.PI)
if (m_arcType!=PIE)
return true;
else
return inPie;
else{
if (!inPie)
return false;
else{
return m_arcType==PIE;
}
}
}
}
/**
* Test if current arc intersects the point at a position.
*
* @param x; y A point to be measured.
* @param pickOffset An analog offset for 'pick' this arc.
* @return A result arcPoint that represents an intersected point.
*
*/
public JFArcPoint intersectsAt(double x, double y, double pickOffset){
JFArcPoint resultPoint =new JFArcPoint();
JFPoint center =getCenter();
JFPoint startPoint =getStartPoint();
JFPoint endPoint =getEndPoint();
double radius =getRadius();
double radius1 =center.distance(x,y);
double angle =getAngle();
//test if this angle is in pie
boolean inPie =ifInPie(x,y);
//if this point is on the curve.
if (Math.abs(radius1-radius)<=pickOffset && inPie){
double startAngle =Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
double endAngle =Angle.getValidAngle(Angle.getAngle(center,m_endPoint));
double thisAngle =Angle.getValidAngle(Angle.getAngle(center.getX(),center.getY(),x,y));
double minus =thisAngle-startAngle;
double scale =0;
if ((float)angle==0){
scale =0;
}else if (startAngle<endAngle){
if (angle>0){
//this angle must between start angle and end angle.
scale =minus/angle;
}else{
if (thisAngle<startAngle){//this angle must less than endangle.
scale =minus/angle;
}else{//this angle must greater than endAngle
scale =(Angle.PI*2-Math.abs(minus))/angle;
}
}
}else{
if (angle>0){
if (thisAngle>startAngle){//this angle must greater than endangle.
scale =minus/angle;
}else{//this angle must less than start angle.
scale =(Angle.PI*2-Math.abs(minus))/angle;
}
}else{
//this angle must greater than end angle or less than start angle.
scale =minus/angle;
}
}
//get the result point's position
resultPoint.setValue(getPoint(thisAngle));
resultPoint.setScale(Math.abs(scale));
resultPoint.setType(JFArcPoint.POINTTYPE_CURVE);
return resultPoint;
}
//if radius is out side the circle, return false.
if (radius1>radius)
return null;
LineSeg line =new LineSeg();
JFPoint pnt =new JFPoint();
double dist;
boolean intersectLine =false;
int portType=0;
//point is on the chord.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?