package org.aisen.weibo.sina.ui.widget.io.codetail.animation.arcanimator;
import android.graphics.PointF;
import java.util.Arrays;
class ArcMetric {
PointF mStartPoint = new PointF();
PointF mEndPoint = new PointF();
PointF mMidPoint = new PointF();
PointF mAxisPoint[] = new PointF[2];
PointF mZeroPoint = new PointF();
//SEGMENTS. This Segments create virtual triangle except mZeroStartSegment
float mStartEndSegment;
float mRadius;
float mMidAxisSegment;
float mZeroStartSegment;
//DEGREES.
float mAnimationDegree;
float mSideDegree;
float mZeroStartDegree;
float mStartDegree;
float mEndDegree;
//Side of animation
Side mSide;
private void createAxisVariables(){
for(int i=0; i<mAxisPoint.length; i++)
mAxisPoint[i] = new PointF();
}
private void calcStartEndSeg(){
mStartEndSegment = (float) Math.sqrt(Math.pow(mStartPoint.x - mEndPoint.x, 2)+
Math.pow(mStartPoint.y - mEndPoint.y, 2));
}
private void calcRadius(){
mSideDegree = (180 - mAnimationDegree)/2;
mRadius = mStartEndSegment/ Utils.sin(mAnimationDegree)* Utils.sin(mSideDegree);
}
private void calcMidAxisSeg(){
mMidAxisSegment = mRadius * Utils.sin(mSideDegree);
}
private void calcMidPoint(){
mMidPoint.x = mStartPoint.x + mStartEndSegment/2*(mEndPoint.x - mStartPoint.x)/mStartEndSegment;
mMidPoint.y = mStartPoint.y + mStartEndSegment/2*(mEndPoint.y - mStartPoint.y)/mStartEndSegment;
}
private void calcAxisPoints(){
if(mStartPoint.y > mEndPoint.y || mStartPoint.y == mEndPoint.y){
mAxisPoint[0].x = mMidPoint.x + mMidAxisSegment*(mEndPoint.y-mStartPoint.y)/mStartEndSegment;
mAxisPoint[0].y = mMidPoint.y - mMidAxisSegment*(mEndPoint.x-mStartPoint.x)/mStartEndSegment;
mAxisPoint[1].x = mMidPoint.x - mMidAxisSegment*(mEndPoint.y-mStartPoint.y)/mStartEndSegment;
mAxisPoint[1].y = mMidPoint.y + mMidAxisSegment*(mEndPoint.x-mStartPoint.x)/mStartEndSegment;
}else{
mAxisPoint[0].x = mMidPoint.x - mMidAxisSegment*(mEndPoint.y-mStartPoint.y)/mStartEndSegment;
mAxisPoint[0].y = mMidPoint.y + mMidAxisSegment*(mEndPoint.x-mStartPoint.x)/mStartEndSegment;
mAxisPoint[1].x = mMidPoint.x + mMidAxisSegment*(mEndPoint.y-mStartPoint.y)/mStartEndSegment;
mAxisPoint[1].y = mMidPoint.y - mMidAxisSegment*(mEndPoint.x-mStartPoint.x)/mStartEndSegment;
}
}
private void calcZeroPoint(){
switch (mSide){
case RIGHT:
mZeroPoint.x = mAxisPoint[Side.RIGHT.value].x + mRadius;
mZeroPoint.y = mAxisPoint[Side.RIGHT.value].y;
break;
case LEFT:
mZeroPoint.x = mAxisPoint[Side.LEFT.value].x - mRadius;
mZeroPoint.y = mAxisPoint[Side.LEFT.value].y;
break;
}
}
private void calcDegrees(){
mZeroStartSegment = (float) Math.sqrt(Math.pow(mZeroPoint.x - mStartPoint.x, 2)+
Math.pow(mZeroPoint.y - mStartPoint.y, 2));
mZeroStartDegree = Utils.acos((2*Math.pow(mRadius,2)-Math.pow(mZeroStartSegment,2))/(2*Math.pow(mRadius,2)));
switch(mSide){
case RIGHT:
if(mStartPoint.y <= mZeroPoint.y){
if(mStartPoint.y > mEndPoint.y ||
(mStartPoint.y == mEndPoint.y && mStartPoint.x > mEndPoint.x)){
mStartDegree = mZeroStartDegree;
mEndDegree = mStartDegree + mAnimationDegree;
}else{
mStartDegree = mZeroStartDegree;
mEndDegree = mStartDegree - mAnimationDegree;
}
}else if(mStartPoint.y >= mZeroPoint.y){
if(mStartPoint.y < mEndPoint.y ||
(mStartPoint.y == mEndPoint.y && mStartPoint.x > mEndPoint.x)){
mStartDegree = 0 - mZeroStartDegree;
mEndDegree = mStartDegree - mAnimationDegree;
}else {
mStartDegree = 0 - mZeroStartDegree;
mEndDegree = mStartDegree + mAnimationDegree;
}
}
break;
case LEFT:
if(mStartPoint.y <= mZeroPoint.y){
if(mStartPoint.y > mEndPoint.y ||
(mStartPoint.y == mEndPoint.y && mStartPoint.x < mEndPoint.x)){
mStartDegree = 180 - mZeroStartDegree;
mEndDegree = mStartDegree - mAnimationDegree;
}else{
mStartDegree = 180 - mZeroStartDegree;
mEndDegree = mStartDegree + mAnimationDegree;
}
}else if(mStartPoint.y >= mZeroPoint.y){
if(mStartPoint.y < mEndPoint.y ||
(mStartPoint.y == mEndPoint.y && mStartPoint.x < mEndPoint.x)){
mStartDegree = 180 + mZeroStartDegree;
mEndDegree = mStartDegree + mAnimationDegree;
}else{
mStartDegree = 180 + mZeroStartDegree;
mEndDegree = mStartDegree - mAnimationDegree;
}
}
break;
}
}
/**
* Create new {@link org.aisen.android.component.io.codetail.animation.arcanimator.ArcMetric} instance and do all calculations below
* and finally return ready to use object
*/
public static ArcMetric evaluate(float startX, float startY,
float endX, float endY,
float degree, Side side){
//TODO return ready to use object with have done computations
ArcMetric arcMetric = new ArcMetric();
arcMetric.mStartPoint.set(startX, startY);
arcMetric.mEndPoint.set(endX, endY);
arcMetric.setDegree(degree);
arcMetric.mSide = side;
arcMetric.createAxisVariables();
arcMetric.calcStartEndSeg();
arcMetric.calcRadius();
arcMetric.calcMidAxisSeg();
arcMetric.calcMidPoint();
arcMetric.calcAxisPoints();
arcMetric.calcZeroPoint();
arcMetric.calcDegrees();
return arcMetric;
}
public void setDegree(float degree) {
degree = Math.abs(degree);
if(degree>180)
setDegree(degree%180);
else if(degree == 180)
setDegree(degree-1);
else if(degree<30)
setDegree(30);
else
this.mAnimationDegree = degree;
}
PointF getAxisPoint(){
return mAxisPoint[mSide.value];
}
/**
* Return evaluated start degree
*
* @return the start degree
*/
public float getStartDegree(){
return mStartDegree;
}
/**
* Return evaluated end degree
*
* @return the end degree
*/
public float getEndDegree(){
return mEndDegree;
}
@Override
public String toString() {
return "ArcMetric{" +
"\nmStartPoint=" + mStartPoint +
"\n mEndPoint=" + mEndPoint +
"\n mMidPoint=" + mMidPoint +
"\n mAxisPoint=" + Arrays.toString(mAxisPoint) +
"\n mZeroPoint=" + mZeroPoint +
"\n mStartEndSegment=" + mStartEndSegment +
"\n mRadius=" + mRadius +
"\n mMidAxisSegment=" + mMidAxisSegment +
"\n mZeroStartSegment=" + mZeroStartSegment +
"\n mAnimationDegree=" + mAnimationDegree +
"\n mSideDegree=" + mSideDegree +
"\n mZeroStartDegree=" + mZeroStartDegree +
"\n mStartDegree=" + mStartDegree +
"\n mEndDegree=" + mEndDegree +
"\n mSide=" + mSide +
'}';
}
}