求过圆心直线与圆的两个交点

博主分享了在处理圆心直线与圆交点问题时遇到的精度问题,原本使用float导致计算不准确,修正变量错误后仍存在不精确的情况。改用double类型后,计算精度提高,解决了问题。博主提醒在高精度数值运算时应优先考虑使用double。
摘要由CSDN通过智能技术生成
               

主要是注意所使用的数据类型。

之前用的是float,出现了一些意外,而且花费了我不少时间来反复验证、推导,

做了很多的无用功,而且,反复推导得出来的计算步骤并没有什么不牢靠的地方。

然后计算得到的结果却是让人如此之不省心,梗的我闷得慌。

今天上午发来了一贴,多位朋友各抒己见,

总算是让我发现了一些不足的地方,首当其冲的是一个变量弄错了,

导致大批的计算失准。

后来修正了这个bug以后,还是会出现计算不精确的地方。

再后来便将涉及的所有成员变量由float 纠正为 double 类型,

计算精度果然得到了提高,失准的地方再次被干掉。

这次给自己的教训就是:

涉及到精度比较高的数值运算的时候,还是得统统用 double。

之前还以为 float 已经比较不错,能够满足基本的需求了,

经过这次我总算是懂了,double的存在离我并不遥远。

这个问题堵了我比较久了,大概也有快10个月了,当时没解决就规避之没去用了,

今天能够解决这个遗留已久的问题,真是让人心情愉快!

下面贴出 Objective-C 和 Java 的相关代码:

Objective-C 部分(核心代码摘录)

/** 已知两点,求过该两点的直线表达式~ */- (BYLine) getLine:(b2Vec2)p1 anotherPoint:(b2Vec2)p2 { BYLine line; if((p1.x - p2.x) != 0) {        line.kExists = true;  line.k = (p1.y - p2.y) / (p1.x - p2.x);  line.b = p1.y - line.k * p1.x; } else {  line.kExists = false;  line.extraX = p1.x; } return line;}/** 已知一点和直线斜率,求该直线的表达式~ */- (BYLine) getLine:(b2Vec2)point kParam:(double)kParam { BYLine line;    line.kExists = true; line.k = kParam; line.b = point.y - kParam * point.x; return line;}- (double) getDistanceBetween2Points:(b2Vec2)p0 anotherPoint:(b2Vec2)p1 { return sqrt(pow(p0.y - p1.y, 2) + pow(p0.x - p1.x, 2));}/** 获取一条直线上距离某点一定距离的两个点~ */- (b2Vec2*) get2Points:(BYLine)ln p:(b2Vec2)point pw:(double)pathWidth {    b2Vec2* target = new b2Vec2[2];    double circleRadius = pathWidth / 2;        if(ln.k != 0) {        // 斜率存在且不为 0~        double kOfNewLine = -1 / ln.k;        BYLine newLine = [self getLine:point kParam:kOfNewLine];                // 经过数学运算,得出二元一次方程组的表达式        double A = pow(newLine.k, 2) + 1;        double B = 2 * (newLine.k * newLine.b - newLine.k * point.y - point.x);        double C = pow(point.x, 2) + pow((newLine.b - point.y), 2) - pow(circleRadius, 2);        double delta = pow(B, 2) - 4 * A * C;                if(delta < 0) {    // 经实践检验有一定几率走入该分支,必须做特殊化处理~            NSLog(@"竟然会无解,他妈的怎么回事儿啊!");            target[0] = b2Vec2(point.x, point.y - circleRadius);            target[1] = b2Vec2(point.x, point.y + circleRadius);        } else {            double x1 = (-B + sqrt(delta)) / (2 * A);            double y1 = newLine.k * x1 + newLine.b;            target[0] = b2Vec2(x1, y1);                        double x2 = (-B - sqrt(delta)) / (2 * A);            double y2 = newLine.k * x2 + newLine.b;            target[1] = b2Vec2(x2, y2);        }    } else {        // 斜率存在且为 0~        target[0] = b2Vec2(point.x, point.y - circleRadius);        target[1] = b2Vec2(point.x, point.y + circleRadius);    }    NSLog(@"离中心点的距离为:%f", [self getDistanceBetween2Points:target[0] anotherPoint:point]);    return target;}// 绘制触摸点到移动点的轨迹,1个像素~- (void) drawTouchPath {    if(_mouseDown) {        // 已知(2等分,用分数表示~)        b2Vec2 pStart = _touchSegment.p1;        b2Vec2 pEnd = _touchSegment.p2;                // 推出        b2Vec2 pMiddle = b2Vec2((pStart.x + pEnd.x) / 2, (pStart.y + pEnd.y) / 2);        float pathLength = [self getDistanceBetween2Points:pStart anotherPoint:pEnd];                // 设置触摸轨迹的宽度~        float pathWidth = pathLength / 3.0f;        if(pathWidth > TOUCH_PATH_MAX_WIDTH) {            pathWidth = TOUCH_PATH_MAX_WIDTH;        }                b2Vec2* result;        BYLine expFunc = [self getLine:pStart anotherPoint:pEnd];        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值