明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1923|回复: 8

[源码] LISP、.NET计算两个圆的交点(附带EXCEL)2024.6.11更新

[复制链接]
发表于 2022-5-6 08:19:48 | 显示全部楼层 |阅读模式
本帖最后由 fangmin723 于 2024-6-11 10:40 编辑

2022.5.9更新:优化当X轴相同时报错!
  1. ;;说明:求两圆交点
  2. ;;参数:cen1:圆心1
  3. ;;参数:r1:半径1
  4. ;;参数:cen2:圆心2
  5. ;;参数:r2:半径2
  6. ;;返回:有交点侧返回交点列表,没有则返回nil
  7. (defun 2ci(cen1 r1 cen2 r2 / a1 a2 a3 b2 b3 c3 cx1 cx2 cy1 cy2 delta x1 x12 x2 y1 y12 y2)
  8.   (setq cx1 (car cen1) cy1 (cadr cen1) cx2 (car cen2) cy2 (cadr cen2))
  9.         (cond
  10.                 ((and (= cx1 cx2) (/= cy1 cy2))
  11.                         (setq y12 (/ (+ (- (* r1 r1) (* r2 r2)) (- (* cy2 cy2) (* cy1 cy1))) 2.0 (- cy2 cy1)))
  12.                         (setq a3 1 b3 (* -2 cx1) c3 (+ (* (- y12 cy1) (- y12 cy1)) (* cx1 cx1) (* -1.0 r1 r1)))
  13.                         (setq delta (- (* b3 b3) (* 4.0 a3 c3)))
  14.                         (cond
  15.                                 ((> delta 0)
  16.                                         (setq x1 (/ (+ (* -1.0 b3) (sqrt (- (* b3 b3) (* 4.0 a3 c3)))) (* 2.0 a3)))
  17.                                         (setq x2 (/ (- (* -1.0 b3) (sqrt (- (* b3 b3) (* 4.0 a3 c3)))) (* 2.0 a3)))
  18.                                         (list (list x1 y12) (list x2 y12))
  19.                                 )
  20.                                 ((= delta 0) (list (list (/ (* -1.0 b3) (* 2.0 a3)) y12)))
  21.                                 (t (princ "\n没有交点!") nil)
  22.                         )
  23.                 )
  24.                 ((and (/= cx1 cx2) (= cy1 cy2))
  25.                         (setq x12 (/ (+ (- (* r1 r1) (* r2 r2)) (- (* cx2 cx2) (* cx1 cx1))) 2.0 (- cx2 cx1)))
  26.                         (setq a3 1 b3 (* -2 cy1) c3 (+ (* (- x12 cx1) (- x12 cx1)) (* cy1 cy1) (* -1.0 r1 r1)))
  27.                         (setq delta (- (* b3 b3) (* 4.0 a3 c3)))
  28.                         (cond
  29.                                 ((> delta 0)
  30.                                         (setq y1 (/ (+ (* -1.0 b3) (sqrt (- (* b3 b3) (* 4.0 a3 c3)))) (* 2.0 a3)))
  31.                                         (setq y2 (/ (- (* -1.0 b3) (sqrt (- (* b3 b3) (* 4.0 a3 c3)))) (* 2.0 a3)))
  32.                                         (list (list x12 y1) (list x12 y2))
  33.                                 )
  34.                                 ((= delta 0) (list (list x12 (/ (* -1.0 b3) (* 2.0 a3)))))
  35.                                 (t (princ "\n没有交点!") nil)
  36.                         )
  37.                 )
  38.                 ((and (= cx1 cx2) (= cy1 cy2))
  39.                         (cond
  40.                                 ((= r1 r2) (alert "\n同一个圆求交点,怕不是个傻子吧你!"))
  41.                                 (t (alert "\n同心圆求交点,你没毛病吧!"))
  42.                         )
  43.                         nil
  44.                 )
  45.                 (t
  46.                         (setq a1 (+ (- (* r1 r1) (* r2 r2)) (- (* cx2 cx2) (* cx1 cx1)) (- (* cy2 cy2) (* cy1 cy1))))
  47.                         (setq a2 (/ a1 2.0 (- cy2 cy1)))
  48.                         (setq b2 (/ (* 1.0 (- cx2 cx1)) (- cy2 cy1)))
  49.                         (setq a3 (+ 1.0 (* b2 b2)))
  50.                         (setq b3 (* -1 (+ (* 2.0 cx1) (* 2.0 (- a2 cy1) b2))))
  51.                         (setq c3 (- (+ (* cx1 cx1) (* (- a2 cy1) (- a2 cy1))) (* r1 r1)))
  52.                         (setq delta (- (* b3 b3) (* 4.0 a3 c3)))
  53.                         (cond
  54.                                 ((> delta 0)
  55.                                         (setq x1 (/ (+ (* -1.0 b3) (sqrt (- (* b3 b3) (* 4.0 a3 c3)))) (* 2.0 a3)))
  56.                                         (setq x2 (/ (- (* -1.0 b3) (sqrt (- (* b3 b3) (* 4.0 a3 c3)))) (* 2.0 a3)))
  57.                                         (setq y1 (- a2 (* b2 x1)))
  58.                                         (setq y2 (- a2 (* b2 x2)))
  59.                                         (list (list x1 y1) (list x2 y2))
  60.                                 )
  61.                                 ((= delta 0) (list (list (setq x1 (/ (* -1.0 b3) (* 2.0 a3))) (- a2 (* b2 x1)))))
  62.                                 (t (princ "\n没有交点!") nil)
  63.                         )
  64.                 )
  65.         )
  66. )

  67. (2ci (list 100.0 100.0) 50 (list 120.0 30.0) 70.0)

  68. ((149.569 93.4483) (61.3745 68.2499))

2024.6.11新增:.NET方式求交:
  1. /// <summary>
  2. /// 数学方式求两圆交点
  3. /// </summary>
  4. /// <param name="center1">圆心1</param>
  5. /// <param name="radius1">半径1</param>
  6. /// <param name="center2">圆心2</param>
  7. /// <param name="radius2">半径2</param>
  8. /// <returns>两圆焦点集合</returns>
  9. public static List<Point3d> CircleInsert(this Point3d center1, double radius1, Point3d center2, double radius2)
  10. {
  11.     //两圆同心
  12.     if ((center1.X - center2.X).Abs() <= 1e-8 && (center1.Y - center2.Y).Abs() <= 1e-8 && (center1.Z - center2.Z).Abs() <= 1e-8)
  13.         return [];
  14.     //两圆相离或大圆包含小圆
  15.     if (center1.DistanceTo(center2) > radius1 + radius2 || (center1.DistanceTo(center2) + radius1.Min(radius2)) < radius1.Max(radius2))
  16.         return [];
  17.     var centerX1 = center1.X;
  18.     var centerY1 = center1.Y;
  19.     var centerX2 = center2.X;
  20.     var centerY2 = center2.Y;
  21.     if (centerX1 == centerX2 && centerY1 != centerY2)
  22.     {
  23.         var resultY = (radius1.Pow() - radius2.Pow() + (centerY2.Pow() - centerY1.Pow())) / 2.0 / (centerY2 - centerY1);
  24.         var argA = 1.0;
  25.         var argB = -2 * centerX1;
  26.         var argC = centerX1.Pow() + (resultY - centerY1).Pow() - radius1.Pow();
  27.         var delta = argB.Pow() - (4.0 * argA * argC);
  28.         return delta switch
  29.         {
  30.             > 0 =>
  31.             [
  32.                 new(((-1 * argB ) + delta.Sqrt()) / 2.0 / argA, resultY, 0),
  33.                 new(((-1 * argB ) - delta.Sqrt()) / 2.0 / argA, resultY, 0)
  34.             ],
  35.             0 => [new((-1 * argB) / 2.0 / argA, resultY, 0)],
  36.             _ => [],
  37.         };
  38.     }
  39.     else if (centerX1 != centerX2 && centerY1 == centerY2)
  40.     {
  41.         var resultX = (radius1.Pow() - radius2.Pow() + (centerX2.Pow() - centerX1.Pow())) / 2.0 / (centerX2 - centerX1);
  42.         var argA = 1.0;
  43.         var argB = -2 * centerY1;
  44.         var argC = centerY1.Pow() + (resultX - centerX1).Pow() - radius1.Pow();
  45.         var delta = argB.Pow() - (4.0 * argA * argC);
  46.         return delta switch
  47.         {
  48.             > 0 =>
  49.             [
  50.                 new( resultX,((-1 * argB ) + delta.Sqrt()) / 2.0 / argA, 0),
  51.                 new( resultX,((-1 * argB ) - delta.Sqrt()) / 2.0 / argA, 0)
  52.             ],
  53.             0 => [new(resultX, (-1 * argB) / 2.0 / argA, 0)],
  54.             _ => [],
  55.         };
  56.     }
  57.     else
  58.     {
  59.         var argA1 = radius1.Pow() - radius2.Pow() + (centerX2.Pow() - centerX1.Pow()) + (centerY2.Pow() - centerY1.Pow());
  60.         var argA2 = argA1 / 2.0 / (centerY2 - centerY1);
  61.         var argB2 = (centerX2 - centerX1) / (centerY2 - centerY1);
  62.         var argA3 = 1 + argB2.Pow();
  63.         var argB3 = -2 * (centerX1 + (argA2 - centerY1) * argB2);
  64.         var argC3 = centerX1.Pow() + (argA2 - centerY1).Pow() - radius1.Pow();
  65.         var delta = argB3.Pow() - (4.0 * argA3 * argC3);
  66.         if (delta > 0)
  67.         {
  68.             var x1 = ((-1 * argB3) + delta.Sqrt()) / 2.0 / argA3;
  69.             var x2 = ((-1 * argB3) - delta.Sqrt()) / 2.0 / argA3;
  70.             var y1 = argA2 - (argB2 * x1);
  71.             var y2 = argA2 - (argB2 * x2);
  72.             return [new(x1, y1, 0), new(x2, y2, 0)];
  73.         }
  74.         else if (delta == 0)
  75.         {
  76.             var x1 = (-1 * argB3) / 2.0 / argA3;
  77.             var y1 = argA2 - (argB2 * x1);
  78.             return [new(x1, y1, 0)];
  79.         }
  80.         else return [];
  81.     }
  82. }

.NET方式求交所用扩展方法:
  1.         /// <summary>
  2.         /// 获取最小值
  3.         /// </summary>
  4.         /// <param name="value">数值参数</param>
  5.         /// <param name="ints">数值参数,可变</param>
  6.         /// <returns>最小值</returns>
  7.         public static int Min(this int value, params int[] ints)
  8.         {
  9.             return Math.Min(value, ints.Min());
  10.         }

  11.         /// <summary>
  12.         /// 获取最大值
  13.         /// </summary>
  14.         /// <param name="value">数值参数</param>
  15.         /// <param name="ints">数值参数,可变</param>
  16.         /// <returns>最大值</returns>
  17.         public static int Max(this int value, params int[] ints)
  18.         {
  19.             return Math.Max(value, ints.Max());
  20.         }

  21.         /// <summary>
  22.         /// 获取最小值
  23.         /// </summary>
  24.         /// <param name="value">数值参数</param>
  25.         /// <param name="doubles">数值参数,可变</param>
  26.         /// <returns>最小值</returns>
  27.         public static double Min(this double value, params double[] doubles)
  28.         {
  29.             return Math.Min(value, doubles.Min());
  30.         }

  31.         /// <summary>
  32.         /// 获取最大值
  33.         /// </summary>
  34.         /// <param name="value">数值参数</param>
  35.         /// <param name="doubles">数值参数,可变</param>
  36.         /// <returns>最大值</returns>
  37.         public static double Max(this double value, params double[] doubles)
  38.         {
  39.             return Math.Max(value, doubles.Max());
  40.         }

  41.         /// <summary>
  42.         /// 返回双精度浮点数字的绝对值。
  43.         /// </summary>
  44.         /// <param name="value">大于或等于 Double.MinValue 但小于或等于 Double.MaxValue 的数字</param>
  45.         /// <returns>双精度浮点数 x,使 0 ≤ x ≤ Double.MaxValue</returns>
  46.         public static double Abs(this double value) => Math.Abs(value);

  47.         /// <summary>
  48.         /// 返回指定数字的指定次幂
  49.         /// </summary>
  50.         /// <param name="x">要乘幂的双精度浮点数</param>
  51.         /// <param name="y">指定幂的双精度浮点数,默认:2</param>
  52.         /// <returns>数字 x 的 y 次幂</returns>
  53.         public static double Pow(this double x, double y = 2) => Math.Pow(x, y);

  54.         /// <summary>
  55.         /// 返回指定数字的平方根
  56.         /// </summary>
  57.         /// <param name="d">将查找其平方根的数字</param>
  58.         /// <returns>
  59.         /// <code>
  60.         /// d为零或正数 => d 的正平方根
  61.         /// d为负数    => NaN
  62.         /// d等于NaN   => NaN
  63.         /// d等于PositiveInfinity => PositiveInfinity
  64.         /// </code>
  65.         /// </returns>
  66.         public static double Sqrt(this double d) => Math.Sqrt(d);



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

点评

纯数学法有点多余,应该直接画出两圆求交  发表于 2022-5-6 20:43

评分

参与人数 3明经币 +3 收起 理由
USER2128 + 1 赞一个!
bssurvey + 1 赞一个!
start4444 + 1 很给力!

查看全部评分

"觉得好,就打赏"
    共1人打赏
 楼主| 发表于 2022-5-9 20:36:47 | 显示全部楼层
5月9日优化更新
发表于 2022-5-10 07:53:55 来自手机 | 显示全部楼层
不知有何用处,谢谢大神分享,
发表于 2022-5-10 09:19:26 | 显示全部楼层
不错的构想,谢谢大神的分享!下载来学习一下
 楼主| 发表于 2022-5-10 16:12:03 | 显示全部楼层
宁静港湾 发表于 2022-5-10 07:53
不知有何用处,谢谢大神分享,

何用,用处大着呢,当你想求两个圆的交点时,你一般会怎么做,先通过函数绘制出两个圆,然后再用交点函数处理,然后再转表,如果不需要圆的时候还得删除,在不需要圆的情况下,这种直接纯数学的方式更为简便!
发表于 2022-5-11 10:26:22 | 显示全部楼层
感谢大佬共享!
发表于 2023-6-18 23:59:46 | 显示全部楼层
感谢大佬分享,学习了
 楼主| 发表于 2024-6-11 10:34:18 | 显示全部楼层
2024.6.11:新增.NET方式求交:
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 15:38 , Processed in 0.183501 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表