【计算几何】闵可夫斯基差演示

本文涉及知识点

数学 几何

演示工具

演示工具基于Cad,支持Cad2013及更高版本。

亲士库版本:2026.9.4

Cliper库版本:2.0.0.0

点击下载亲士数学演示工具箱

相关定义

闵可夫斯基和:数学定义: A ⊕ B = { a + b ∣ a ∈ A , b ∈ B } A \oplus B =\{a+b \mid a \in A,b \in B \} A⊕B={a+b∣a∈A,b∈B}

直观理解:将B的副本放置到A的每个点上,取并集。

形态学(膨胀腐蚀、开闭操作)和集合论的闵可夫斯基差和计算几何(机器人学)的闵可夫斯基差不同。

计算几何的闵可夫斯基差: A ⊖ B = { a − b ∣ a ∈ A , b ∈ B } A \ominus B=\{a - b \mid a\in A,b\in B\} A⊖B={a−b∣a∈A,b∈B}。

主要用途

临界多边形(NFP)--排样算法的核心

N F P ( P , Q ) = P ⊕ ( − Q ) NFP(P,Q)=P\oplus (-Q) NFP(P,Q)=P⊕(−Q)。它表示零件P绕着Q滑动时,参考点的轨迹。

碰撞检测(配置空间障碍)

A ⊕ ( − B ) A \oplus (-B) A⊕(−B)定义了配置空间的障碍物区域。

多边形偏移

对多边形膨胀(向外偏移)本质求 P ⊖ 圆盘。 P \ominus 圆盘。 P⊖圆盘。

操作说明

一,选择闵可夫斯基差的被减数(模板图像)。

二,选择闵可夫斯基的减数。

注意 :只能选择多义线,无论多义线是否闭合都当闭合处理。

三,计算出闵可夫斯基差。

四,将闵可夫斯基差的结果转成闭合多义线,逆时针红色,顺时针黄色。

代码

csharp 复制代码
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Clipper2Lib;
using QinShiZACad;
using QinShiMath;
using QinShiBase;
csharp 复制代码
               [CommandMethod("MinkowskiDiff")]
        public void MinkowskiDiff()
        {
            Minkowski("闵可夫斯基差", (p1, p2) => Clipper.MinkowskiDiff(p1, p2,true));
        }
        [CommandMethod("MinkowskiSum")]
        public void MinkowskiSum()
        {
            Minkowski("闵可夫斯基和", (p1, p2) => Clipper.MinkowskiSum(p1, p2, true));
        }
        void Minkowski(string strName, MinkowskiFun fun)
        {
            QinShiZACad.CSelAEntity sel1 = new CSelAEntity($"请选择一个多义线做为{strName}的被减数(模板图像)\n");
            var pr1 = sel1.Sel();
            if (pr1.Status != PromptStatus.OK)
            {
                return;
            }
            QinShiZACad.CSelAEntity sel2 = new CSelAEntity($"请选择一个多义线做为{strName}的减数\n");
            var pr2 = sel2.Sel();
            if (pr2.Status != PromptStatus.OK)
            {
                return;
            }

            Polyline pl1, pl2;
            using (var tr = CadBase.GetDefaultDatabase().TransactionManager.StartTransaction())
            {
                pl1 = tr.GetObject(pr1.ObjectId, OpenMode.ForRead) as Polyline;
                pl2 = tr.GetObject(pr2.ObjectId, OpenMode.ForRead) as Polyline;
            }
            if (null == pl1) { return; }
            if (null == pl2) { return; }
            PathD path1 = PolylineToPath(pl1);
            PathD path2 = PolylineToPath(pl2);
            PathsD path3 = fun(path1, path2);

            PathD PolylineToPath(Polyline pl)
            {
                PathD path = new PathD();
                for (int i = 0; i < pl.NumberOfVertices; i++)
                {
                    var pt = pl.GetPoint2dAt(i);
                    path.Add(new PointD(pt.X, pt.Y));
                }
                return path;
            }
            var pls = path3.ToPolylines();
            for (int i = 0; i < Math.Min(7, pls.Count); i++)
            {
                double area = Clipper.Area(path3[i]);
                int iColor = 0;
                if (Math.Abs(area) < 1e-9)
                {//退化情况
                    iColor = 0;
                }
                else if (area > 0)
                {
                    iColor = 1;
                }
                else
                {
                    iColor = 2;
                }
                pls[i].ColorIndex = iColor;//外边界红色,孔洞黄色
            }
            CadBase.AddEnitys(pls.ToArray(), "0", CadBase.GetDefaultDatabase());
        }
        delegate PathsD MinkowskiFun(PathD path1, PathD path2);
csharp 复制代码
   public static class PolylineExtensions2
    {
        /// <summary>
        /// PathD 转回 Polyline(不关联数据库)
        /// </summary>
        public static Polyline ToPolyline(this PathD path, double tolerance = 1e-4)
        {
            Polyline pl = new Polyline();
            for (int i = 0; i < path.Count; i++)
            {
                PointD pt = path[i];
                pl.AddVertexAt(i, new Point2d(pt.x, pt.y), 0, 0, 0);
            }
            // 如果 PathD 首尾点足够接近(差值小于容差),则认为它是闭合的
            if (path.Count > 1)
            {
                PointD first = path[0];
                PointD last = path[path.Count - 1];
                //if (Math.Abs(first.x - last.x) < tolerance &&
                //    Math.Abs(first.y - last.y) < tolerance)
                //{
                //    pl.Closed = true;
                //}
                // 只有至少3个点且面积非零的路径才视为有效闭合多边形
                if (path.Count >= 3 && Math.Abs(Clipper.Area(path)) > 1e-6)
                {
                    pl.Closed = true;
                }
            }
            return pl;
        }

        /// <summary>
        /// 将 PathsD 转换为 Polyline 列表
        /// </summary>
        public static List<Polyline> ToPolylines(this PathsD paths)
        {
            var polylines = new List<Polyline>();
            foreach (var path in paths)
            {
                // 调用已有的单个 PathD → Polyline 扩展方法
                polylines.Add(path.ToPolyline());
            }
            return polylines;
        }
    }

错误解法

直接通过前三个点的差乘判断是逆时针或顺序时针是错误的,一:三点共线。二,可能是凹角。用clipper库的有向面积判断更合理。

查看视频

https://edu.csdn.net/course/detail/41418

如果视频审核中,可以看图。

将原点和被减数一起平移,原点在闵可夫斯基差上,则被减数和减数相切。

边长100的正方形,左下角是圆点,作为模板图像(被减数)

下面部分闵可夫斯基差的颜色不对,工具是正确的。

矩形

原图

效果图:黄色是结果

凹多边形

原图

效果图:黄色是结果

凸多边形

原图

效果图:红色黄色是结果

正100多边形模拟圆作为模板图像

多边形是否重叠

如果两个多边形P、Q重叠,则其闵可夫斯基差D必定包括原点。如果两个多边形不重叠,则P与Q最小距离等于原点到D的最小距离。

扩展阅读

计算几何为骨,排样优化为魂
作品:亲士CAD工具箱
经典文章推荐:二维排样
万物皆数学
查阅鄙人的博文,请点击博文下载学院导航
活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关推荐
ClouGence1 天前
老师备课到底能不能交给 AI?我拿鸡兔同笼实测了一遍
数学·aigc
Tisfy1 天前
LeetCode 3871.统计范围内的逗号 II:每次算一个逗号
数学·算法·leetcode·题解
Tisfy2 天前
LeetCode 3870.统计范围内的逗号:模拟 或 一步计算
数学·算法·leetcode·题解·模拟·遍历
hui-梦苑2 天前
[Math]复合函数极限存在定理:单调连续函数反函数连续性定理推论
学习·数学·定理·函数极限·海涅定理
铸人5 天前
再论勾股定理成立的条件-24
数学·数论·复数
熊猫_豆豆6 天前
圆周率 π 的无理性与超越性证明
数学·代码·无理数·超越数·π
Luhui Dev6 天前
图片几何题如何转成可编辑图形?从识别题图到复用画板的工作流
人工智能·数学·ai·agent·luhuidev
金銀銅鐵6 天前
斐波那契数列的前 n 项和
数学
lvwangshu6 天前
exBSGS 算法
数学·算法