|
|
//
|
|
|
// SWPosPointcut.c
|
|
|
// DrawTest
|
|
|
//
|
|
|
// Created by 王阳阳 on 2022/9/6.
|
|
|
//
|
|
|
|
|
|
#include "SWPosPointcut.h"
|
|
|
#include <QDebug>
|
|
|
|
|
|
#define MaxPoints 6000.f
|
|
|
#define MaxSegment 100.f
|
|
|
#define MaxWidthScale 1.5f
|
|
|
#define MinRadius 0.3f
|
|
|
#define MaxSteps 0.13f
|
|
|
#define MinShake 130
|
|
|
#define MaxShake 170
|
|
|
#define M_PI 3.14159265358979323846264338327950288f
|
|
|
#define RadianTodegrees(x) (x * 180.f / M_PI)
|
|
|
|
|
|
static SWPosPoint lastePos;
|
|
|
static SWLineSegment *curLeftLine = NULL;
|
|
|
static SWLineSegment *curRightLine = NULL;
|
|
|
static int pointStep = 0;
|
|
|
|
|
|
void SWPosRest(SWPosPoint pos) {
|
|
|
|
|
|
lastePos = pos;
|
|
|
pointStep = 0;
|
|
|
SWLineSegment *onSegment = curLeftLine;
|
|
|
if (curLeftLine != NULL) {
|
|
|
|
|
|
while (onSegment) {
|
|
|
|
|
|
SWLineSegment *tempSeg = (SWLineSegment *)onSegment->preSegment;
|
|
|
onSegment->preSegment = NULL;
|
|
|
free(onSegment);
|
|
|
if (tempSeg != NULL) {
|
|
|
|
|
|
onSegment = tempSeg;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
onSegment = NULL;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
onSegment = curRightLine;
|
|
|
if (curRightLine != NULL) {
|
|
|
|
|
|
while (onSegment) {
|
|
|
|
|
|
SWLineSegment *tempSeg = (SWLineSegment *)onSegment->preSegment;
|
|
|
onSegment->preSegment = NULL;
|
|
|
free(onSegment);
|
|
|
if (tempSeg != NULL) {
|
|
|
|
|
|
onSegment = tempSeg;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
onSegment = NULL;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
curLeftLine = NULL;
|
|
|
curRightLine = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
SWPosRet SWGetTangentcurPoint(SWPosPoint prevPoint,SWPosPoint curPoint,
|
|
|
SWLineSegment leftLine,SWLineSegment rightLine,
|
|
|
int circle) {
|
|
|
|
|
|
double distance = GetPointDistance(prevPoint, curPoint);
|
|
|
double radiusDistance = (prevPoint.radius + curPoint.radius);
|
|
|
if ((distance < radiusDistance) || distance < 1) {
|
|
|
|
|
|
if (prevPoint.realPoint.x != lastePos.realPoint.x && prevPoint.realPoint.y != lastePos.realPoint.y){
|
|
|
|
|
|
double rads = SWBetweenLinesrads(lastePos.realPoint, prevPoint.realPoint,
|
|
|
curPoint.realPoint, prevPoint.realPoint);
|
|
|
double angle = RadianTodegrees(rads);
|
|
|
if (angle > 150) {
|
|
|
|
|
|
SWPosRet retPos;
|
|
|
retPos.prevLeftPoint = SWPointCutMake(0, 0);
|
|
|
retPos.prevLeftIntersectPoint = SWPointCutMake(0, 0);
|
|
|
retPos.prevRightPoint = SWPointCutMake(0, 0);
|
|
|
retPos.prevRightIntersectPoint = SWPointCutMake(0, 0);
|
|
|
retPos.curLeftPoint = SWPointCutMake(0, 0);
|
|
|
retPos.curRightPoint = SWPointCutMake(0, 0);
|
|
|
retPos.circlePoints.clear();
|
|
|
retPos.circleCount = 0;
|
|
|
retPos.status = SWPosRetFail;
|
|
|
return retPos;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
if (circle == 1 || pointStep == 0) {
|
|
|
|
|
|
return getCircleSegments(prevPoint, curPoint, leftLine, rightLine, distance,pointStep);
|
|
|
|
|
|
}
|
|
|
if (distance > fabs(prevPoint.radius - curPoint.radius)) {
|
|
|
|
|
|
SWPointcut pointFa= {0,0};//左侧切点
|
|
|
SWPointcut pointFa1 = {0,0};//右侧切点
|
|
|
SWPointcut pointFb = {0,0};//左侧切点
|
|
|
SWPointcut pointFb1 = {0,0};//右侧切点
|
|
|
|
|
|
double base = atan2(curPoint.realPoint.y - prevPoint.realPoint.y, curPoint.realPoint.x - prevPoint.realPoint.x);
|
|
|
double ang = acos((prevPoint.radius - curPoint.radius) / distance);
|
|
|
pointFa = GetMaleTangentPointValue(prevPoint, base + ang);
|
|
|
pointFb = GetMaleTangentPointValue(curPoint, base + ang);
|
|
|
pointFb1 = GetMaleTangentPointValue(curPoint, base - ang);
|
|
|
pointFa1 = GetMaleTangentPointValue(prevPoint, base - ang);
|
|
|
SWPointcut pointLeftIntersect = {0,0};//左侧切点
|
|
|
SWPointcut pointRightIntersect = {0,0};//右侧切点
|
|
|
if (leftLine.status == SWPosRetFail && rightLine.status == SWPosRetFail) {
|
|
|
|
|
|
pointStep++;
|
|
|
lastePos = prevPoint;
|
|
|
SWPosRet retPos1;
|
|
|
retPos1.prevLeftPoint = pointFa;//左侧切点
|
|
|
retPos1.prevLeftIntersectPoint = pointLeftIntersect;//左侧切点交点
|
|
|
retPos1.prevRightPoint = pointFa1;//右侧切点
|
|
|
retPos1.prevRightIntersectPoint = pointRightIntersect;//右侧切点交点
|
|
|
retPos1.curLeftPoint = pointFb;//当前点左侧切点
|
|
|
retPos1.curRightPoint = pointFb1;//当前点右侧切点
|
|
|
retPos1.circlePoints.clear();
|
|
|
retPos1.circleCount = 0;
|
|
|
retPos1.status = SWPosRetSuccess;//计算结果状态
|
|
|
return retPos1;
|
|
|
}
|
|
|
|
|
|
pointRightIntersect = SWgetEdgePoint(rightLine.startPoint,rightLine.endPoint,pointFa1,pointFb1,prevPoint.realPoint,0);
|
|
|
pointLeftIntersect = SWgetEdgePoint(leftLine.startPoint,leftLine.endPoint,pointFa,pointFb,prevPoint.realPoint,1);
|
|
|
if ((pointRightIntersect.x == 0 && pointRightIntersect.y ==0) || (pointLeftIntersect.x == 0 && pointLeftIntersect.y == 0)) {
|
|
|
|
|
|
return getCircleSegments(prevPoint, curPoint, leftLine, rightLine, distance,pointStep);
|
|
|
}
|
|
|
/**
|
|
|
* 处理切点极端情况(0,0)
|
|
|
*/
|
|
|
double lDistance = GetPointDistance(prevPoint,SWPosPointMake(pointLeftIntersect.x,pointLeftIntersect.y,0));
|
|
|
if (lDistance > prevPoint.radius*10) {
|
|
|
|
|
|
pointLeftIntersect = SWPointCutMake((leftLine.endPoint.x + pointFa.x)/2.f,(leftLine.endPoint.y + pointFa.y)/2.f);
|
|
|
}
|
|
|
double rDistance = GetPointDistance(prevPoint,SWPosPointMake(pointRightIntersect.x,pointRightIntersect.y,0));
|
|
|
if (rDistance > prevPoint.radius*10) {
|
|
|
|
|
|
pointRightIntersect = SWPointCutMake((rightLine.endPoint.x + pointFa1.x)/2.f,(rightLine.endPoint.y + pointFa1.y)/2.f);
|
|
|
}
|
|
|
SWPosRet retPos2;
|
|
|
retPos2.prevLeftPoint = pointFa;//左侧切点
|
|
|
retPos2.prevLeftIntersectPoint = pointLeftIntersect;//左侧切点交点
|
|
|
retPos2.prevRightPoint = pointFa1;//右侧切点
|
|
|
retPos2.prevRightIntersectPoint = pointRightIntersect;//右侧切点交点
|
|
|
retPos2.curLeftPoint = pointFb;//当前点左侧切点
|
|
|
retPos2.curRightPoint = pointFb1;//当前点右侧切点
|
|
|
retPos2.circlePoints.clear();
|
|
|
retPos2.circleCount = 0;
|
|
|
retPos2.status = SWPosRetSuccess;//计算结果状态
|
|
|
lastePos = prevPoint;
|
|
|
pointStep++;
|
|
|
return retPos2;
|
|
|
|
|
|
}
|
|
|
SWPosRet retPos;
|
|
|
retPos.prevLeftPoint = SWPointCutMake(0, 0);
|
|
|
retPos.prevLeftIntersectPoint = SWPointCutMake(0, 0);
|
|
|
retPos.prevRightPoint = SWPointCutMake(0, 0);
|
|
|
retPos.prevRightIntersectPoint = SWPointCutMake(0, 0);
|
|
|
retPos.curLeftPoint = SWPointCutMake(0, 0);
|
|
|
retPos.curRightPoint = SWPointCutMake(0, 0);
|
|
|
retPos.circlePoints.clear();
|
|
|
retPos.circleCount = 0;
|
|
|
retPos.status = SWPosRetFail;
|
|
|
return retPos;
|
|
|
}
|
|
|
|
|
|
SWPosRet getCircleSegments(SWPosPoint prevPoint,SWPosPoint curPoint,SWLineSegment leftLine,
|
|
|
SWLineSegment rightLine,double distance,int step) {
|
|
|
|
|
|
SWPointcut controlPoint = SWPointCutMake(prevPoint.realPoint.x, prevPoint.realPoint.y);
|
|
|
int segements = distance/0.2f;
|
|
|
if (segements < 5) {
|
|
|
|
|
|
segements = 5;
|
|
|
}
|
|
|
double preRadius = 0;
|
|
|
if (leftLine.status == SWPosRetSuccess && rightLine.status == SWPosRetSuccess) {
|
|
|
|
|
|
preRadius = GetPointDistance(SWPosPointMake(leftLine.endPoint.x, leftLine.endPoint.y, 0),
|
|
|
SWPosPointMake(rightLine.endPoint.x, rightLine.endPoint.y, 0))/2.f;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
preRadius = prevPoint.radius;
|
|
|
}
|
|
|
double circleRadius = curPoint.radius - preRadius;
|
|
|
QList<SWCirclePoint> circleAry;
|
|
|
for (int i = 0; i < segements; i ++) {
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
|
SWCirclePoint cPoint = SWCircleMake(SWPosPointMake(prevPoint.realPoint.x,
|
|
|
prevPoint.realPoint.y, preRadius));
|
|
|
circleAry.append(cPoint);
|
|
|
|
|
|
} else if (i == (segements - 1)) {
|
|
|
|
|
|
SWCirclePoint cPoint = SWCircleMake(SWPosPointMake(curPoint.realPoint.x,
|
|
|
curPoint.realPoint.y, preRadius + circleRadius));
|
|
|
circleAry.append(cPoint);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
double t = (double)i/segements;
|
|
|
double x = pow(1 - t, 2) * prevPoint.realPoint.x + 2.0 * (1 - t) * t * controlPoint.x + t * t * curPoint.realPoint.x;
|
|
|
double y = pow(1 - t, 2) * prevPoint.realPoint.y + 2.0 * (1 - t) * t * controlPoint.y + t * t * curPoint.realPoint.y;
|
|
|
SWCirclePoint cPoint = SWCircleMake(SWPosPointMake(x, y, preRadius + circleRadius*t));
|
|
|
circleAry.append(cPoint);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
pointStep++;
|
|
|
SWPosRet retPos;
|
|
|
retPos.prevLeftPoint = SWPointCutMake(0, 0);//左侧切点
|
|
|
retPos.prevLeftIntersectPoint = SWPointCutMake(0, 0);//左侧切点交点
|
|
|
retPos.prevRightPoint = SWPointCutMake(0, 0);//右侧切点
|
|
|
retPos.prevRightIntersectPoint = SWPointCutMake(0, 0);//右侧切点交点
|
|
|
retPos.curLeftPoint = SWPointCutMake(0, 0);//当前点左侧切点
|
|
|
retPos.curRightPoint = SWPointCutMake(0, 0);//当前点右侧切点
|
|
|
retPos.circlePoints = circleAry;
|
|
|
retPos.circleCount = segements;
|
|
|
retPos.status = SWPosRetSuccess;//计算结果状态
|
|
|
return retPos;
|
|
|
}
|
|
|
|
|
|
|
|
|
QList<SWPosPoint> fillPoints(SWPosPoint prevPoint,SWPosPoint curPoint,double distance) {
|
|
|
|
|
|
SWPointcut controlPoint = SWPointCutMake(prevPoint.realPoint.x, prevPoint.realPoint.y);
|
|
|
int segements = distance/0.5f;
|
|
|
double preRadius = prevPoint.radius;
|
|
|
double circleRadius = curPoint.radius - preRadius;
|
|
|
QList<SWPosPoint> circleAry;
|
|
|
for (int i = 0; i < segements; i ++) {
|
|
|
|
|
|
double t = (double)i/segements;
|
|
|
double x = pow(1 - t, 2) * prevPoint.realPoint.x + 2.0 * (1 - t) * t * controlPoint.x + t * t * curPoint.realPoint.x;
|
|
|
double y = pow(1 - t, 2) * prevPoint.realPoint.y + 2.0 * (1 - t) * t * controlPoint.y + t * t * curPoint.realPoint.y;
|
|
|
SWPosPoint cPoint = SWPosPointMake(x, y, preRadius + circleRadius*t);
|
|
|
circleAry.append(cPoint);
|
|
|
}
|
|
|
return circleAry;
|
|
|
}
|
|
|
|
|
|
|
|
|
SWPosStatus IsPointInMatrix(SWPointcut p1 ,SWPointcut p2,SWPointcut p3 ,SWPointcut p4,SWPointcut p)
|
|
|
{
|
|
|
if (GetCross(p1,p2,p) * GetCross(p3,p4,p) >= 0 && GetCross(p2,p3,p) * GetCross(p4,p1,p) >= 0) {
|
|
|
|
|
|
return SWPosRetSuccess;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return SWPosRetFail;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
double GetCross(SWPointcut p1, SWPointcut p2,SWPointcut p)
|
|
|
{
|
|
|
return (p2.x - p1.x) * (p.y - p1.y) -(p.x - p1.x) * (p2.y - p1.y);
|
|
|
}
|
|
|
|
|
|
|
|
|
SWPointcut SWratioPoint(SWPointcut startPoint, SWPointcut endPoint, double ratio) {
|
|
|
|
|
|
SWPointcut ret = {0,0};
|
|
|
double x = endPoint.x - startPoint.x;
|
|
|
double y = endPoint.y - startPoint.y;
|
|
|
ret.x = x*ratio + startPoint.x;
|
|
|
ret.y = y*ratio + startPoint.y;
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
SWPointcut SWrotatePoint(SWPointcut point, SWPointcut center, double angle) {
|
|
|
|
|
|
SWPointcut ret = {0,0};
|
|
|
double x = point.x - center.x;
|
|
|
double y = point.y - center.y;
|
|
|
ret.x = (x*cos(angle) - y*sin(angle)) + center.x;
|
|
|
ret.y = (x*sin(angle) + y*cos(angle)) + center.y;
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
SWPointcut GetMaleTangentPointValue(SWPosPoint point, double a)
|
|
|
{
|
|
|
SWPointcut ret = {0,0};
|
|
|
ret.x = (double) (point.realPoint.x + point.radius * cos(a));
|
|
|
ret.y = (double) (point.realPoint.y + point.radius * sin(a));
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
SWPointcut SWgetEdgePoint(SWPointcut a, SWPointcut b, SWPointcut c,SWPointcut d,SWPointcut e,int leftLine) {
|
|
|
|
|
|
|
|
|
double dx1 = a.x - b.x;
|
|
|
double dy1 = a.y - b.y;
|
|
|
double dx2 = d.x - c.x;
|
|
|
double dy2 = d.y - c.y;
|
|
|
SWPointcut edgePointf = {0,0};
|
|
|
SWPointcut pointf = {0,0};
|
|
|
if (dx1 == 0 && dx2 != 0) {//ab垂直x轴
|
|
|
double k2 = dy2 / dx2;//第二条直线斜率
|
|
|
double h2 = d.y - k2 * d.x;//第二条直线截距
|
|
|
//交点在a.x或者b.x
|
|
|
double x = a.x;
|
|
|
double y = k2 * x + h2;
|
|
|
pointf = SWPointCutMake(x,y);
|
|
|
if (isPointOnLine(x, y, a, b) == 1 && isPointOnLine(x, y, c, d) == 1) {//焦点在线段上
|
|
|
|
|
|
edgePointf = pointf;
|
|
|
}
|
|
|
} else if (dx1 != 0 && dx2 == 0) {//cd垂直x轴
|
|
|
double k1 = dy1 / dx1;//第一条直线斜率
|
|
|
double h1 = b.y - k1 * b.x;//第一条直线的截距
|
|
|
//交点在c.x或者d.x
|
|
|
double x = c.x;
|
|
|
double y = k1 * x + h1;
|
|
|
pointf = SWPointCutMake(x,y);
|
|
|
if (isPointOnLine(x, y, a, b) == 1 && isPointOnLine(x, y, c, d) == 1) {//焦点在线段上
|
|
|
edgePointf = pointf;
|
|
|
}
|
|
|
} else if (dx1 == 0 && dx2 == 0) {//ab cd都垂直x轴
|
|
|
//无交点
|
|
|
} else {
|
|
|
double k1 = dy1 / dx1;//第一条直线斜率
|
|
|
double h1 = b.y - k1 * b.x;//第一条直线的截距
|
|
|
double k2 = dy2 / dx2;//第二条直线斜率
|
|
|
double h2 = d.y - k2 * d.x;//第二条直线截距
|
|
|
if (k1 == k2) {//两直线平行
|
|
|
if (h1 == h2) {//重合
|
|
|
|
|
|
} else {//平行
|
|
|
|
|
|
}
|
|
|
} else {
|
|
|
double x = (h1 - h2) / (k2 - k1);
|
|
|
double y = k1 * x + h1;
|
|
|
pointf = SWPointCutMake(x,y);
|
|
|
if (isPointOnLine(x, y, a, b) == 1 && isPointOnLine(x, y, c, d) == 1) {//焦点在线段上
|
|
|
edgePointf = pointf;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (edgePointf.x > 0 && edgePointf.y > 0) {//有交点
|
|
|
return edgePointf;
|
|
|
} else {//无交点
|
|
|
// // 向量1的坐标:(x1,y1),向量2的坐标:(x2,y2); 则
|
|
|
double tmpDegree = getAngle(dx1, dy1, dx2, dy2);
|
|
|
if ((pointf.x > 0 && pointf.y > 0) && tmpDegree >= 90 && tmpDegree < 180) {
|
|
|
|
|
|
return pointf;
|
|
|
} else if (tmpDegree == 180) {
|
|
|
|
|
|
return b;
|
|
|
} else {
|
|
|
|
|
|
//角度小于阈值进行补点操作
|
|
|
if (tmpDegree <= 90) {
|
|
|
|
|
|
return SWPointCutMake(0,0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
double rads = SWBetweenLinesrads(b, e, c, e);
|
|
|
double angle = RadianTodegrees(rads);
|
|
|
if (leftLine == 1) {
|
|
|
|
|
|
return SWrotatePoint(b,e,angle/2.f);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return SWrotatePoint(c,e,angle/2.f);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
int isPointOnLine(double x, double y, SWPointcut start, SWPointcut end) {
|
|
|
|
|
|
if (start.x <= end.x) {
|
|
|
if (x < start.x || x > end.x) return 0;
|
|
|
} else {
|
|
|
if (x < end.x || x > start.x) return 0;
|
|
|
}
|
|
|
if (start.y <= end.y) {
|
|
|
if (y < start.y || y > end.y) return 0;
|
|
|
} else {
|
|
|
if (y < end.y || y > start.y) return 0;
|
|
|
}
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
double getAngle(double x1, double y1, double x2, double y2) {
|
|
|
float value = (x1 * x2 + y1 * y2) / (hypot(x1, y1) * hypot(x2, y2)); // 余弦值
|
|
|
if(value < -1) {
|
|
|
|
|
|
value = -1;
|
|
|
}
|
|
|
if(value > 1) {
|
|
|
|
|
|
value = 1;
|
|
|
}
|
|
|
double angle = RadianTodegrees(acos(value)); // 角度
|
|
|
return angle;
|
|
|
}
|
|
|
|
|
|
|
|
|
SWPointcut getSamllAngleVertex(SWPointcut b, SWPointcut c,double cosAngle) {
|
|
|
double dx = c.x - b.x;
|
|
|
double dy = c.y - b.y;
|
|
|
// double disBC = Math.hypot(dx, dy);
|
|
|
// double betweenP = Math.cos((45f / 180f) * Math.PI) * disBC;
|
|
|
double ratio = (double) cos((cosAngle / 180.f) * M_PI);
|
|
|
SWPointcut betweenP = SWPointCutMake(b.x + dx * ratio, b.y + dy * ratio);
|
|
|
SWPointcut anglePointf = calcNewPoint(betweenP, b, (cosAngle / 180.f) * M_PI);
|
|
|
return anglePointf;
|
|
|
}
|
|
|
SWPointcut SWExtendPoint(SWPointcut a, SWPointcut b, SWPointcut c,SWPointcut d) {
|
|
|
|
|
|
SWPointcut point = {0,0};
|
|
|
double k1 = 0;
|
|
|
double k2 = 0;
|
|
|
int k1Vaild = 0;
|
|
|
int k2Vaild = 0;
|
|
|
double b1 = 0;
|
|
|
double b2 = 0;
|
|
|
if (b.x != a.x) {
|
|
|
|
|
|
k1 = (b.y - a.y)/(b.x - a.x);
|
|
|
k1Vaild = 1;
|
|
|
|
|
|
}
|
|
|
if (d.x != c.x) {
|
|
|
|
|
|
k2 = (d.y - c.y)/(d.x - c.x);
|
|
|
k2Vaild = 1;
|
|
|
|
|
|
}
|
|
|
if ( (k1Vaild == k2Vaild) && k1 == k2) {
|
|
|
|
|
|
return point;
|
|
|
|
|
|
}
|
|
|
if (k1Vaild == 1) {
|
|
|
|
|
|
b1 = (b.x*a.y - a.x*b.y)/(b.x - a.x);
|
|
|
}
|
|
|
if (k2Vaild == 1) {
|
|
|
|
|
|
b2 = (d.x*c.y - c.x*d.y)/(d.x - c.x);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (k1Vaild == 0) {
|
|
|
|
|
|
point.x = a.x;
|
|
|
point.y = k2 * point.x + b2;
|
|
|
|
|
|
} else if (k2Vaild == 0) {
|
|
|
|
|
|
point.x = c.x;
|
|
|
point.y = k1 *point.x + b1;
|
|
|
|
|
|
} else if (k1 == 0) {
|
|
|
|
|
|
point.x = (a.y - b2)/k2;
|
|
|
point.y = a.y;
|
|
|
|
|
|
|
|
|
} else if (k2 == 0) {
|
|
|
|
|
|
point.x = (c.y - b1)/k1;
|
|
|
point.y = c.y;
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
point.x = (double)((b2 - b1) / (k1 - k2));
|
|
|
point.y = (double)((k2 * b1 - k1 * b2) / (k2 - k1));
|
|
|
|
|
|
}
|
|
|
return point;
|
|
|
|
|
|
}
|
|
|
|
|
|
double GetPointDistance(SWPosPoint start, SWPosPoint end) {
|
|
|
|
|
|
return sqrtf(pow((start.realPoint.x - end.realPoint.x), 2) + pow((start.realPoint.y - end.realPoint.y), 2))/1.f;
|
|
|
}
|
|
|
|
|
|
SWPointcut SWPointCutMake(double x,double y) {
|
|
|
|
|
|
SWPointcut pointCut = {x,y};
|
|
|
return pointCut;
|
|
|
}
|
|
|
|
|
|
SWPosPoint SWPosPointMake(double x,double y,double radius) {
|
|
|
|
|
|
SWPosPoint posPoint = {{x,y},radius};
|
|
|
return posPoint;
|
|
|
}
|
|
|
|
|
|
SWPointcut calcNewPoint(SWPointcut p, SWPointcut pCenter, double theta) {
|
|
|
double cosv = (double) cos(theta);
|
|
|
double sinv = (double) sin(theta);
|
|
|
|
|
|
// calc new point
|
|
|
double newX = (p.x - pCenter.x) * cosv - (p.y - pCenter.y) * sinv + pCenter.x;
|
|
|
double newY = (p.x - pCenter.x) * sinv + (p.y - pCenter.y) * cosv + pCenter.y;
|
|
|
return SWPointCutMake(newX, newY);
|
|
|
}
|
|
|
|
|
|
SWLineSegment SWLineMake(double x1,double y1,double x2, double y2) {
|
|
|
|
|
|
// SWLineSegment linePoint = {{x1,y1},{x2,y2},SWPosRetSuccess,NULL};
|
|
|
SWLineSegment linePoint;
|
|
|
// linePoint.startPoint = {x1,y1};
|
|
|
linePoint.startPoint.x = x1;
|
|
|
linePoint.startPoint.y = y1;
|
|
|
// linePoint.endPoint = {x2,y2};
|
|
|
linePoint.endPoint.x = x2;
|
|
|
linePoint.endPoint.y = y2;
|
|
|
linePoint.status = SWPosRetSuccess;
|
|
|
return linePoint;
|
|
|
}
|
|
|
|
|
|
|
|
|
SWLineSegment SWLineMakeZero(void) {
|
|
|
|
|
|
// SWLineSegment linePoint = {{0,0},{0,0},SWPosRetFail,NULL};
|
|
|
SWLineSegment linePoint;
|
|
|
// linePoint.startPoint = {0,0};
|
|
|
linePoint.startPoint.x = 0;
|
|
|
linePoint.startPoint.y = 0;
|
|
|
// linePoint.endPoint = {0,0};
|
|
|
linePoint.endPoint.x = 0;
|
|
|
linePoint.endPoint.y = 0;
|
|
|
linePoint.status = SWPosRetFail;
|
|
|
return linePoint;
|
|
|
}
|
|
|
|
|
|
|
|
|
double SWBetweenLinesrads(SWPointcut line1Start, SWPointcut line1End, SWPointcut line2Start, SWPointcut line2End) {
|
|
|
|
|
|
double a = line1End.x - line1Start.x;
|
|
|
double b = line1End.y - line1Start.y;
|
|
|
double c = line2End.x - line2Start.x;
|
|
|
double d = line2End.y - line2Start.y;
|
|
|
float value = ((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d)));
|
|
|
if(value < -1) {
|
|
|
|
|
|
value = -1;
|
|
|
}
|
|
|
if(value > 1) {
|
|
|
|
|
|
value = 1;
|
|
|
}
|
|
|
float rads = acos(value);
|
|
|
return rads;
|
|
|
}
|
|
|
|
|
|
double CalculatePointradius(double speed,double prevPointradius,
|
|
|
double radius,double force ,double maxForce,
|
|
|
double stressSpl,int forceEnable,
|
|
|
double distance) {
|
|
|
|
|
|
if (speed > MaxPoints) {
|
|
|
|
|
|
speed = MaxPoints;
|
|
|
}
|
|
|
if (forceEnable == 1) {
|
|
|
|
|
|
double forceScale = force/maxForce;
|
|
|
forceScale = forceScale * (1 + stressSpl);
|
|
|
double newRadius = radius*forceScale;
|
|
|
double dropSize = newRadius - prevPointradius ;
|
|
|
if (dropSize > prevPointradius *MaxSteps) {
|
|
|
|
|
|
dropSize = prevPointradius *MaxSteps;
|
|
|
|
|
|
}
|
|
|
if (dropSize < - prevPointradius *MaxSteps) {
|
|
|
|
|
|
dropSize = - prevPointradius *MaxSteps;
|
|
|
}
|
|
|
newRadius = prevPointradius + dropSize;
|
|
|
newRadius = newRadius > MaxWidthScale*radius ? MaxWidthScale*radius : newRadius;
|
|
|
if(newRadius < 0.7f) {
|
|
|
|
|
|
newRadius = 0.7f;
|
|
|
}
|
|
|
return newRadius;
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
double speedScale = MaxPoints/MaxSegment;
|
|
|
double fragments = speed/speedScale;
|
|
|
double radiusScale = fragments/MaxSegment;
|
|
|
double newRadius = radius - radius*radiusScale;
|
|
|
double dropSize = prevPointradius - newRadius;
|
|
|
if (dropSize > prevPointradius *MaxSteps) {
|
|
|
|
|
|
dropSize = prevPointradius *MaxSteps;
|
|
|
|
|
|
}
|
|
|
if (dropSize < - prevPointradius *MaxSteps) {
|
|
|
|
|
|
dropSize = - prevPointradius *MaxSteps;
|
|
|
}
|
|
|
newRadius = prevPointradius - dropSize;
|
|
|
newRadius = newRadius < MinRadius*radius ? MinRadius*radius : newRadius;
|
|
|
if(newRadius < 0.7f) {
|
|
|
|
|
|
newRadius = 0.7f;
|
|
|
}
|
|
|
return newRadius;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
SWPosPoint *CalculateStroke(SWPosPoint posAry[],int length,double preRadius) {
|
|
|
|
|
|
for (int k = 0; k < length; k ++) {
|
|
|
|
|
|
SWPosPoint pos = posAry[k];
|
|
|
double pointRadius = preRadius /(length - 1);
|
|
|
pos.radius = preRadius - pointRadius*k;
|
|
|
if (pos.radius <= 0.4) {
|
|
|
|
|
|
pos.radius = 0.4f;
|
|
|
}
|
|
|
posAry[k] = pos;
|
|
|
}
|
|
|
return posAry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
SWPosStatus CalculateShake(SWPosPoint prePoint,SWPosPoint curPoint,SWPosPoint nextPoint) {
|
|
|
|
|
|
double distance = GetPointDistance(curPoint, nextPoint);
|
|
|
double rads = SWBetweenLinesrads(SWPointCutMake(prePoint.realPoint.x, prePoint.realPoint.y),
|
|
|
SWPointCutMake(curPoint.realPoint.x, curPoint.realPoint.y),
|
|
|
SWPointCutMake(nextPoint.realPoint.x, nextPoint.realPoint.y),
|
|
|
SWPointCutMake(curPoint.realPoint.x, curPoint.realPoint.y));
|
|
|
double angle = RadianTodegrees(rads);
|
|
|
if (angle > MinShake && angle < MaxShake && distance < 1) {
|
|
|
|
|
|
return SWPosRetFail;
|
|
|
}
|
|
|
return SWPosRetFail;
|
|
|
}
|
|
|
|
|
|
|
|
|
SWPosStatus SWPosEqualToPos(SWPosPoint pos1,SWPosPoint pos2) {
|
|
|
|
|
|
if (pos1.realPoint.x == pos2.realPoint.x && pos1.realPoint.y == pos2.realPoint.y) {
|
|
|
|
|
|
return SWPosRetSuccess;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return SWPosRetFail;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
SWPosPoint SWPosPointMakeZero(void) {
|
|
|
|
|
|
return SWPosPointMake(0, 0, 0);
|
|
|
}
|
|
|
|
|
|
SWPointcut ExPandLine(SWPointcut pt1,SWPointcut pt2,double nLen)
|
|
|
{
|
|
|
SWPointcut OutPt = SWPointCutMake(0, 0);
|
|
|
if (pt1.x - pt2.x == 0)
|
|
|
{
|
|
|
OutPt.x = pt1.x;
|
|
|
if (pt1.y - pt2.y > 0)
|
|
|
{
|
|
|
OutPt.y = pt2.y - nLen;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
OutPt.y = pt2.y + nLen;
|
|
|
}
|
|
|
}
|
|
|
else if (pt1.y - pt2.y == 0)
|
|
|
{
|
|
|
OutPt.y = pt1.y;
|
|
|
if (pt1.x - pt2.x > 0)
|
|
|
{
|
|
|
OutPt.x = pt2.x - nLen;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
OutPt.x = pt2.x + nLen;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
double k = 0.0;
|
|
|
double b = 0.0;
|
|
|
k = (pt1.y - pt2.y)/(pt1.x-pt2.x);
|
|
|
b = pt1.y - k * pt1.x;
|
|
|
double zoom = 0.0;
|
|
|
zoom = nLen/sqrt((pt2.x-pt1.x)*(pt2.x-pt1.x)+(pt2.y-pt1.y)*(pt2.y-pt1.y));
|
|
|
|
|
|
if(k > 0)
|
|
|
{
|
|
|
if (pt1.x-pt2.x > 0)
|
|
|
{
|
|
|
OutPt.x = pt2.x - zoom * (pt1.x-pt2.x);
|
|
|
OutPt.y = k*OutPt.x + b;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
OutPt.x = pt2.x + zoom * (pt2.x-pt1.x);
|
|
|
OutPt.y = k*OutPt.x + b;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (pt1.x-pt2.x > 0)
|
|
|
{
|
|
|
OutPt.x = pt2.x - zoom * (pt1.x-pt2.x) ;
|
|
|
OutPt.y = k*OutPt.x + b;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
OutPt.x = pt2.x + zoom * (pt2.x - pt1.x);
|
|
|
OutPt.y = k*OutPt.x + b;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return OutPt;
|
|
|
}
|
|
|
|
|
|
SWCirclePoint SWCircleMake(SWPosPoint center) {
|
|
|
|
|
|
double radian = 2*M_PI/4.f;
|
|
|
double cosa = cos(radian);
|
|
|
double sina = sin(radian);
|
|
|
double h = center.radius*(4*(1 - cos(radian/2.f)))/(3*sin(radian/2.f));
|
|
|
|
|
|
SWPointcut pointA = SWPointCutMake(center.radius + center.realPoint.x, center.realPoint.y);
|
|
|
SWPointcut pointB = SWPointCutMake(center.radius + center.realPoint.x, center.realPoint.y - h);
|
|
|
SWPointcut pointC = SWPointCutMake(center.radius*cosa + h*sina + center.realPoint.x, center.realPoint.y - (center.radius*sina - h*cosa));
|
|
|
SWPointcut pointD = SWPointCutMake(center.realPoint.x,center.realPoint.y - center.radius);
|
|
|
|
|
|
SWPointcut pointE = SWPointCutMake(center.realPoint.x - (center.radius*cosa + h*sina), pointC.y);
|
|
|
SWPointcut pointF = SWPointCutMake(center.realPoint.x - center.radius, pointB.y);
|
|
|
SWPointcut pointG = SWPointCutMake(center.realPoint.x - center.radius, center.realPoint.y);
|
|
|
|
|
|
SWPointcut pointH = SWPointCutMake(pointF.x, center.realPoint.y + h);
|
|
|
SWPointcut pointI = SWPointCutMake(pointE.x, center.realPoint.y + (center.radius*sina - h*cosa));
|
|
|
SWPointcut pointJ = SWPointCutMake(center.realPoint.x, center.realPoint.y + center.radius);
|
|
|
|
|
|
SWPointcut pointK = SWPointCutMake(pointC.x, pointI.y);
|
|
|
SWPointcut pointL = SWPointCutMake(pointB.x, pointH.y);
|
|
|
SWPointcut pointM = SWPointCutMake(center.radius + center.realPoint.x, center.realPoint.y);
|
|
|
|
|
|
SWCirclePoint cPoint = {pointA,pointB,pointC,pointD,pointE,pointF,pointG,pointH,pointI,pointJ,pointK,pointL,pointM};
|
|
|
|
|
|
return cPoint;
|
|
|
}
|