EPA, 求嵌入深度和嵌入方向 (fix)

参考: http://www.dyn4j.org/2010/05/epa-expanding-polytope-algorithm/

一个在线演示: http://sandbox.runjs.cn/show/xseojpfa

GJK可以判断两个凸图形是否重叠, EPA可以基于GJK的工作找出分离两个图形的最小向量.

如果原点在闵可夫斯基差内部, 那么两个图形重叠. 而闵可夫斯基差边界上离原点最近的点的向量就是这个最小分离向量.

EPA把GJK结束时的simplex进行扩展, 从闵可夫斯基差的边界上用和GJK相同的getSupportPoint函数选取顶点, 直到扩展后的多边形包含了闵可夫斯基差上离原点最近的那条边.

getPenetration: function (tolerance) {
    var epa = new Contact.EPA(
        this._simplexA,
        this._simplexB,
        this._simplexC,
        this,
        tolerance
    );
    return this.penetration = epa.solve();
}
getClosestPointToOrigin: function (a, b) {
    var ab = b.sub(a).norm(),
        ao = a.negate();
    return a.add(ab.mul(ab.dot(ao))); //把原点投影到ab上
}
getPenetration: function (tolerance) {
    var epa = new Contact.EPA(
        this._simplexA,
        this._simplexB,
        this._simplexC,
        this,
        tolerance
    );
    return this.penetration = epa.solve();
}

getClosestPointToOrigin: function (a, b) {
    var ab = b.sub(a).norm(),
        ao = a.negate();
    return a.add(ab.mul(ab.dot(ao)));
}

EPA: pngx.Class(
    null,
    function (simplexA, simplexB, simplexC, contact, tolerance) {
        this.vertices = [simplexA, simplexB, simplexC];
        this.contact = contact;
        this.tolerance = tolerance || 0.05;
    },
    {
        vertices: null,
        contact: null,
        tolerance: null,
        closestIndex: null,
        closestNormal: null,
        closestDistance: null,
        penetration: null,
        findClosestEdge: function () { //找出当前扩展多边形内离原点最近的一条边
            var bestDistance = Infinity,
                bestNormal,
                bestIndex,
                vertices = this.vertices,
                len = vertices.length;
            for (var i = 0; i < len; ++i) {
                var v0 = vertices[i], //多边形的一个顶点, 同时也是从原点指向多边形外部的一个向量
                    v1 = vertices[(i + 1) % len],
                    v01 = v1.sub(v0),
                    normal = pngx.Vector2D.tripleProduct(v01, v0, v01).norm(),//取指向多边形外部的, 垂直于V0-V1的边的向量
                    distance = v0.dot(normal); //从原点到当前边的距离
                if (distance < bestDistance) {
                    bestDistance = distance;
                    bestNormal = normal;
                    bestIndex = i;
                }
            }
            this.closestIndex = bestIndex;
            this.closestNormal = bestNormal;
            this.closestDistance = bestDistance;
        },
        insert: function (index, point) {
            var vertices = this.vertices,
                len = vertices.length;
            vertices.splice((index + 1) % len, 0, point);
        },
        solve: function () {
            var contact = this.contact,
                tolerance = this.tolerance;
            for (; ;) { //多数情况迭代两三次就能完成
                this.findClosestEdge(); //取扩展多边形中离原点最近的那条边的法向量为搜索方向, 在这个方向上最有可能找出最接近原点的闵可夫斯基差上的边
                var normal = this.closestNormal,
                    point = contact.getSupportPoint(normal),
                    distance = point.dot(normal); //新找出的顶点到原点的距离
                if (distance - this.closestDistance <= tolerance) { //新找出点和上一次找出的点非常接近, point已经足够接近闵可夫斯基差边界上离原点最近的那个点了
                    return this.penetration = normal.mul(distance);
                }

                this.insert(this.closestIndex, point);
            }
        }
    }
)

  

时间: 2024-10-21 18:31:22

EPA, 求嵌入深度和嵌入方向 (fix)的相关文章

求二叉树深度

概念: 1.二叉树深度:树中结点的最大层次称为树的深度或高度. 2.二叉树层次:从根开始定义起,根为第一层,根的孩子为第二层,以此类推. 要点: 1.递归. 2.二叉树深度为左右子树深度较大值+1. 代码: /* 求二叉树深度 by Rowandjj 2014/7/13 ------------------------------- 题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 输入: 第一行输入有n,n表示

二叉树(4)----求二叉树深度

1.二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t *m_pElemt; struct BTreeNode_t_ *m_pLeft; struct BTreeNode_t_ *m_pRight; } BTreeNode_t; 2.求二叉树深度 定义:对任意一个子树的根节点来说,它的深度=左右子树

html5权威指南:嵌入另一张HTML文档、通过插件嵌入内容、嵌入数字表现形式

嵌入另一张HTML文档.通过插件嵌入内容.嵌入数字表现形式:http://www.cnblogs.com/yc-755909659/p/5928125.html

html嵌入pdf &amp;&amp; html嵌入多媒体文件,word,flash,pdf,音视频

<object classid="clsid:CA8A9780-280D-11CF-A24D-444553540000" width="1000" height="1200" border="0"> <param name="_Version" value="65539"> <param name="_ExtentX" value=&qu

leetcode104,111,543 求二叉树深度的dfs解法

104.求二叉树的最大深度 class Solution: def maxDepth(self, root: TreeNode) -> int: if root == None: return 0 else: leftdepth = self.maxDepth(root.left) rightdepth = self.maxDepth(root.right) return max(leftdepth, rightdepth) + 1 #!!!关键在于+1 111.求二叉树的最小深度 class

单目视觉SLAM:采用逆深度参数化的方法求取深度信息的过程

一种实时的单目视觉SLAM改进算法 该算法采用一个摄像头作为外部传感器来提取机器人行进过程中周围环境的特征信息,用实时性良好的FAST提取环境特征点,结合逆深度参数化进行特征点非延时初始化,用压缩扩展卡尔曼滤波更新地图.实验研究表明,该方法提高了算法的鲁棒性和实时性. 0 引言 移动机器人自主导航是自治机器人领域研究的热点.而同时定位与地图构建(Simultaneous Localization And Mapping,SLAM)[1]被认为是自主导航的关键,因此研究SLAM算法有着深远意义.一

求二叉树深度和copy二叉树

// operatorTree.cpp // 对树的操作 #include <iostream> #include <cstdio> // 二叉树表示法 typedef struct BiTNode { int data; struct BiTNode *lchild, *rchild; }BiTNode, *BiTree; // 中序遍历 void inOrder(BiTNode *T) { if (T == NULL) { return; } inOrder(T->lch

(伪)EPA(Expanding Polytope Algorithm) 求重叠的凸图形的嵌入方向与深度

参考: http://www.dyn4j.org/2010/05/epa-expanding-polytope-algorithm/ 接前篇, 用GJK可以判断两个凸图形是否重叠, 而EPA可以求重叠其嵌入的深度的与方向. 两个凸图形的闵可夫斯基差如果包含原点, 那么两个凸图形重叠. 而闵可夫斯基差上的一条边到原点的距离就是两个图形的最小嵌入深度, 这条边的垂线方向就是两个图形的最小嵌入方向. 用GJK得到包含原点的单纯形后, EPA对这个单纯形作扩展, 使得扩展后的单纯形包含闵可夫斯基差上距原

Cordys BOP 4平台的子流程与嵌入子流程对比以及子流程建模技术

子流程含义是在某个流程流转过程中可以创建一个新的流程并执行,结束后可以在此返回父流程. 关于子流程 子流程 子流程是BPMN构件,是在一个流程中的复合的活动.子流程可以分解为一系列更精细的活动.子流程通过父流程实例化. 子流程可以设计成交易的一部分,下面列出三种可能的交易结果: 成功完成(Successful completion):流程按顺序执行,并且交易执行成功: 取消(Cancel):交易内的活动回滚,并且补充特定活动: 异常(Exception):出现异常活动不需要回滚,将从错误事件继续