arc.java
来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 1,554 行 · 第 1/3 页
JAVA
1,554 行
if (m_arcType==CHORD){
//line from start point to end point.
line.setValue(startPoint,endPoint);
if (line.contains(x,y,pickOffset)){
intersectLine =true;
portType =JFArcPoint.POINTTYPE_CHORD;
}
}else if (m_arcType==PIE){
//line from center to start point
line.setValue(center,startPoint);
if (line.contains(x,y,pickOffset)){
intersectLine =true;
portType =JFArcPoint.POINTTYPE_PIE_START;
}else{
//line from center to start point
line.setValue(center,endPoint);
if (line.contains(x,y,pickOffset)){
intersectLine =true;
portType =JFArcPoint.POINTTYPE_PIE_END;
}
}
}
if (intersectLine){
JFPoint pnt1 =line.getPoint1();
JFPoint pnt2 =line.getPoint2();
if (pnt1.distance(x,y)<=pickOffset)
pnt =pnt1;
else if (pnt2.distance(x,y)<=pickOffset)
pnt =pnt2;
else
pnt =line.uprightFoot(x,y);
dist =pnt1.distance(pnt2);
if (dist<1) dist=1;
resultPoint.setValue(pnt);
resultPoint.setScale(pnt.distance(pnt1)/dist);
resultPoint.setType(portType);
return resultPoint;
}
return null;
}
/**
* Get a point on the arc by an angle. We assume this point will always on the arc.
*
* @param angle An angle from 0 to 2*PI, counter-clockwise angle is plus angle.
* @return The point on the arc.
*
*/
public JFPoint getPoint(double angle){
JFPoint center =getCenter();
double radius =getRadius();
angle =Angle.getValidAngle(angle);
double x =radius * Math.cos(angle);
double y =radius * Math.sin(angle);
x =center.getX()+x;
y =center.getY()-y;
return new JFPoint(x,y);
}
/**
* Get a point by point type and scale.
*
* @param pointType Type of current port.
* @param scale Scale of this port compare to start point or start angle or center.
* @return The point on the arc.
*
*/
public JFPoint getPoint(int pointType, double scale){
JFPoint center =getCenter();
double dist=0;
switch (pointType){
case JFArcPoint.POINTTYPE_CURVE:
double angle =getAngle();
double startAngle =Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
double thisAngle =startAngle + scale * angle;
return getPoint(thisAngle);
case JFArcPoint.POINTTYPE_CHORD:
dist =m_startPoint.distance(m_endPoint) * scale;
return m_startPoint.nearPoint(m_endPoint,dist);
case JFArcPoint.POINTTYPE_PIE_START:
case JFArcPoint.POINTTYPE_PIE_END:
dist =getRadius() * scale;
if (pointType==JFArcPoint.POINTTYPE_PIE_START)
return center.nearPoint(m_startPoint,dist);
else
return center.nearPoint(m_endPoint,dist);
}
return null;
}
/**
* Tests if the specified point intersects the curve of this arc.
*
* @param x1, y1 the specified point.
*
* @param pickOffset An analog offset for 'pick' this line.
*
* @return <code>true</code> if the specified point intersects the curve of this arc.
* false otherwise.
*/
public boolean intersects(double x1, double y1, int pickOffset) {
JFPoint center =getCenter();
//the radius of this arc.
double radius =getRadius();
//the virtual radius from center to this point.
double radius1 =center.distance(x1,y1);
//this new 'radius1' will between the maximum radius and minimum radius.
if (radius1>=radius - pickOffset && radius1<=radius + pickOffset && ifInPie(x1,y1)){
return true;
}
else{
JFPoint startPoint =getStartPoint();
if (startPoint.distance(x1,y1)<=pickOffset)
return true;
JFPoint endPoint =getEndPoint();
if (endPoint.distance(x1,y1)<=pickOffset)
return true;
JFPoint controlPoint =getControlPoint();
if (controlPoint.distance(x1,y1)<=pickOffset)
return true;
if (m_arcType==CHORD){
LineSeg line =new LineSeg(startPoint,endPoint);
return line.contains(x1,y1,pickOffset);
}else if (m_arcType==PIE){
JFPoint centerPoint =getCenter();
if (centerPoint.distance(x1,y1)<=pickOffset)
return true;
LineSeg line =new LineSeg(startPoint,centerPoint);
if (line.contains(x1,y1,pickOffset))
return true;
line.setValue(endPoint,centerPoint);
if (line.contains(x1,y1,pickOffset))
return true;
}
return false;
}
}
/**
* Tests if the specified line intersects the curve of this arc.
*
* @param x1, y1 the start point of line.
*
* @param x2, y2 the end point of line.
*
* @return <code>true</code> if the specified point intersects the curve of this arc.
* false otherwise.
*/
private boolean arcIntersects(double x1, double y1, double x2, double y2) {
JFPoint center =getCenter();
double radius =getRadius();
//test if this line intersected with the whole ellipse
List l =Ellipse.pointsIntersected(x1,y1,x2,y2,center.getX(),center.getY(),radius);
//test if the points intersected with ellipse are actually falling on the arc.
if (l!=null && l.size()>0){
Iterator it =l.iterator();
while (it!=null && it.hasNext()){
JFPoint pnt =(JFPoint)it.next();
if (ifInPie(pnt.getX(),pnt.getY()))
return true;
}
}
return false;
}
/**
* Tests if the specified line intersects this arc.
*
* @param line The specified line segment.
*
* @return <code>true</code> if the specified line segment intersects the curve of this arc.
* false otherwise.
*/
public boolean intersects(LineSeg line) {
if (line==null)
return false;
return intersects(line.getX1(),line.getY1(),line.getX2(),line.getY2());
}
/**
* Tests if the specified line intersects this arc.
*
* @param x1, y1 the start point of line.
*
* @param x2, y2 the end point of line.
*
* @return <code>true</code> if the specified line segment intersects the curve of this arc.
* false otherwise.
*/
public boolean intersects(double x1, double y1, double x2, double y2) {
return intersects(x1,y1,x2,y2,false);
}
/**
* Tests if the specified line intersects this arc.
*
* @param x1, y1 the start point of line.
*
* @param x2, y2 the end point of line.
*
* @param curveOnly Test if line intersects the curve of arc only.
*
* @return <code>true</code> if the specified line segment intersects the curve of this arc.
* false otherwise.
*/
public boolean intersects(double x1, double y1, double x2, double y2, boolean curveOnly) {
//test if arc intersects
if (arcIntersects(x1,y1,x2,y2)){
return true;
}
if (m_arcType==OPEN || curveOnly){
return false;
}
JFPoint startPoint =getStartPoint();
JFPoint endPoint =getEndPoint();
JFPoint center =getCenter();
LineSeg line =new LineSeg(x1,y1,x2,y2);
//test if the chord line intersects while arc type is CHORD.
if (m_arcType==CHORD){
return line.intersects(startPoint,endPoint);
}else if (m_arcType==PIE){
return line.intersects(startPoint,center) || line.intersects(endPoint,center);
}else{
return false;
}
}
/**
* Tests if the specified rectangle intersects the interior of this
* <code>Arc</code>.
* @param rect the specified {@link Rect} to test for intersection
* with the interior of this <code>Arc</code>
* @return <code>true</code> if the specified <code>Rect</code>
* intersects the interior of this <code>Arc</code>;
* <code>false</code> otherwise.
*/
public boolean intersects(Rect rect) {
LineSeg side =null;
//test if each side of rectangle intersects.
for (int i = Rect.SIDETYPE_LEFT; i<=Rect.SIDETYPE_BOTTOM; i++){
side =rect.getSide(i);
if (intersects(side))
return true;
}
//test if current arc is inside the target rectangle.
return rect.contains(getStartPoint()) ||
rect.contains(getEndPoint());
}
/**
* Scale current rectangle by specified points and scale percent.
* We only support a concurrent width-height scale here, suppose width as the length from
* basePoint to refPoint1, height as the length from basePoint to refPoint2, and
* one scale percent acts on both width and height.
*
* @param basePoint A base point that is unmovable.
* @param refPoint1 A 'width' reference point.
* @param refPoint2 A 'height' reference point.
* @param scale A reference scale percent.
*
*/
public void scaleBy(JFPoint basePoint, JFPoint refPoint1, JFPoint refPoint2, double scale){
JFPoint center =getCenter();
if (scale<0) scale =0;
m_startPoint.scaleBy(center.getX(),center.getY(),scale);
m_endPoint.scaleBy(center.getX(),center.getY(),scale);
m_controlPoint.scaleBy(center.getX(),center.getY(),scale);
JFPoint newCenter =Rect.newScaleCenter(center,basePoint,refPoint1,refPoint2,scale);
//move center
moveBy(newCenter.getX()-center.getX(),newCenter.getY()-center.getY());
}
/**
* Scale current object by a specified x and y scale.<br>
* This is a special scale method used to scale a shape in arbitrary x and y scale.<br>
* Please see AbstractShape.scaleBy for detailed description.
*
* @param basePoint A base scale point for scaling reference.
* @param xScale A scale percentage in x coordinate, default to 1.0
* @param yScale A scale percentage in y coordinate, default to 1.0
*
*/
public void scaleBy(JFPoint basePoint,double xScale, double yScale){
if (basePoint==null)
return;
double x =basePoint.getX();
double y =basePoint.getY();
m_startPoint.scaleBy(x,y,xScale,yScale);
m_endPoint.scaleBy(x,y,xScale,yScale);
m_controlPoint.scaleBy(x,y,xScale,yScale);
}
/**
* Move this arc by specific x and y coordinates.
*
* @param x X coordiate to moveby.
*
* @param y Y coordiate to moveby.
*
*/
public void moveBy(double x, double y){
m_startPoint.moveBy(x,y);
m_endPoint.moveBy(x,y);
m_controlPoint.moveBy(x,y);
}
/**
* Rotate this arc by an angle theta.
*
* @param theta A rotate angle.
*
*/
public void rotateBy(double theta){
//get center point of this rectangle.
JFPoint center =getCenter();
//rotate by center
rotateBy(center,theta);
}
/**
* Rotate this arc by a specified point and an angle theta.
*
* @param pnt A rotate center point.
*
* @param theta A rotate angle.
*
*/
public void rotateBy(JFPoint pnt, double theta){
if (pnt!=null)
rotateBy(pnt.getX(),pnt.getY(),theta);
}
/**
* Rotate this arc by a specified point and an angle theta.
*
* @param baseX, baseY A rotate center point.
*
* @param theta A rotate angle.
*
*/
public void rotateBy(double baseX, double baseY, double theta){
m_startPoint.rotateBy(baseX,baseY,theta);
m_endPoint.rotateBy(baseX,baseY,theta);
m_controlPoint.rotateBy(baseX,baseY,theta);
}
/**
* Mirror this arc by a central x coordinate of this arc. We make a up-down flip here.
*/
public void mirrorBy(){
JFPoint center =getCenter();
mirrorBy(center.getX());
}
/**
* Mirror this arc by a x coordinate. We make a left-right mirror here.
*
* @param baseX A mirror base x coordinate.
*
*/
public void mirrorBy(double baseX){
m_startPoint.mirrorBy(baseX);
m_endPoint.mirrorBy(baseX);
m_controlPoint.mirrorBy(baseX);
}
/**
* Reverse this arc by a central y coordinate of this arc. We make a up-down flip here.
*/
public void flipBy(){
JFPoint center =getCenter();
flipBy(center.getY());
}
/**
* Reverse this arc by a y coordinate. We make a up-down flip here.
*
* @param baseY A flip base y coordinate.
*
*/
public void flipBy(double baseY){
m_startPoint.flipBy(baseY);
m_endPoint.flipBy(baseY);
m_controlPoint.flipBy(baseY);
}
/**
* Convert this object to String
*
* @return An string represents the content of the object
*
*/
public String toString(){
StringBuffer buf =new StringBuffer();
buf.append(";startPoint["); buf.append(m_startPoint.toString()); buf.append("]");
buf.append(";endPoint["); buf.append(m_endPoint.toString()); buf.append("]");
buf.append(";controlPoint["); buf.append(m_controlPoint.toString()); buf.append("]");
buf.append(";arcType="); buf.append(m_arcType);
return buf.toString();
}
/**
* Creates a new object of the same class and with the same contents as this object.
*
* @return A clone of this instance.
*
*/
public Object clone() throws CloneNotSupportedException{
try{
return new Arc(this);
}catch(Exception e){
throw new CloneNotSupportedException(e.getMessage());
}
}
/**
* Returns the hashcode for this Object.
*
* @return hash code for this Point2D.
*
*/
public int hashCode(){
return m_startPoint.hashCode() ^
m_endPoint.hashCode() ^
m_controlPoint.hashCode() ^
m_arcType;
}
/**
* Determines whether or not two objects are equal.
*
* @param obj an object to be compared with this object
*
* @return true if the object to be compared is an instance of Port and has the same values; false otherwise.
*
*/
public boolean equals(Object obj){
if (obj == this)
return true;
if (!(obj instanceof Arc))
return false;
Arc arc =(Arc)obj;
return (m_startPoint.equals(arc.m_startPoint)) &&
(m_endPoint.equals(arc.m_endPoint)) &&
(m_controlPoint.equals(arc.m_controlPoint)) &&
(m_arcType==arc.m_arcType);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?