chipmunk几何算法
/* Copyright (c) 2007 Scott Lembcke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "chipmunk_private.h"
void
cpMessage(const char *condition, const char *file, int line, cpBool isError, cpBool isHardError, const char *message, ...)
{
fprintf(stderr, (isError ? "Aborting due to Chipmunk error: " : "Chipmunk warning: "));
va_list vargs;
va_start(vargs, message); {
vfprintf(stderr, message, vargs);
fprintf(stderr, "\n");
} va_end(vargs);
fprintf(stderr, "\tFailed condition: %s\n", condition);
fprintf(stderr, "\tSource:%s:%d\n", file, line);
if(isError) abort();
}
#define STR(s) #s
#define XSTR(s) STR(s)
const char *cpVersionString = XSTR(CP_VERSION_MAJOR)"."XSTR(CP_VERSION_MINOR)"."XSTR(CP_VERSION_RELEASE);
void
cpInitChipmunk(void)
{
cpAssertWarn(cpFalse, "cpInitChipmunk is deprecated and no longer required. It will be removed in the future.");
}
//MARK: Misc Functions
cpFloat
cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)
{
return m*(0.5f*(r1*r1 + r2*r2) + cpvlengthsq(offset));
}
cpFloat
cpAreaForCircle(cpFloat r1, cpFloat r2)
{
return (cpFloat)M_PI*cpfabs(r1*r1 - r2*r2);
}
cpFloat
cpMomentForSegment(cpFloat m, cpVect a, cpVect b)
{
cpVect offset = cpvmult(cpvadd(a, b), 0.5f);
return m*(cpvdistsq(b, a)/12.0f + cpvlengthsq(offset));
}
cpFloat
cpAreaForSegment(cpVect a, cpVect b, cpFloat r)
{
return r*((cpFloat)M_PI*r + 2.0f*cpvdist(a, b));
}
cpFloat
cpMomentForPoly(cpFloat m, const int numVerts, const cpVect *verts, cpVect offset)
{
cpFloat sum1 = 0.0f;
cpFloat sum2 = 0.0f;
for(int i=0; i<numVerts; i++){
cpVect v1 = cpvadd(verts[i], offset);
cpVect v2 = cpvadd(verts[(i+1)%numVerts], offset);
cpFloat a = cpvcross(v2, v1);
cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);
sum1 += a*b;
sum2 += a;
}
return (m*sum1)/(6.0f*sum2);
}
cpFloat
cpAreaForPoly(const int numVerts, const cpVect *verts)
{
cpFloat area = 0.0f;
for(int i=0; i<numVerts; i++){
area += cpvcross(verts[i], verts[(i+1)%numVerts]);
}
return -area/2.0f;
}
cpVect
cpCentroidForPoly(const int numVerts, const cpVect *verts)
{
cpFloat sum = 0.0f;
cpVect vsum = cpvzero;
for(int i=0; i<numVerts; i++){
cpVect v1 = verts[i];
cpVect v2 = verts[(i+1)%numVerts];
cpFloat cross = cpvcross(v1, v2);
sum += cross;
vsum = cpvadd(vsum, cpvmult(cpvadd(v1, v2), cross));
}
return cpvmult(vsum, 1.0f/(3.0f*sum));
}
void
cpRecenterPoly(const int numVerts, cpVect *verts){
cpVect centroid = cpCentroidForPoly(numVerts, verts);
for(int i=0; i<numVerts; i++){
verts[i] = cpvsub(verts[i], centroid);
}
}
cpFloat
cpMomentForBox(cpFloat m, cpFloat width, cpFloat height)
{
return m*(width*width + height*height)/12.0f;
}
cpFloat
cpMomentForBox2(cpFloat m, cpBB box)
{
cpFloat width = box.r - box.l;
cpFloat height = box.t - box.b;
cpVect offset = cpvmult(cpv(box.l + box.r, box.b + box.t), 0.5f);
// TODO NaN when offset is 0 and m is INFINITY
return cpMomentForBox(m, width, height) + m*cpvlengthsq(offset);
}
//MARK: Quick Hull
void
cpLoopIndexes(cpVect *verts, int count, int *start, int *end)
{
(*start) = (*end) = 0;
cpVect min = verts[0];
cpVect max = min;
for(int i=1; i<count; i++){
cpVect v = verts[i];
if(v.x < min.x || (v.x == min.x && v.y < min.y)){
min = v;
(*start) = i;
} else if(v.x > max.x || (v.x == max.x && v.y > max.y)){
max = v;
(*end) = i;
}
}
}
#define SWAP(__A__, __B__) {cpVect __TMP__ = __A__; __A__ = __B__; __B__ = __TMP__;}
static int
QHullPartition(cpVect *verts, int count, cpVect a, cpVect b, cpFloat tol)
{
if(count == 0) return 0;
cpFloat max = 0;
int pivot = 0;
cpVect delta = cpvsub(b, a);
cpFloat valueTol = tol*cpvlength(delta);
int head = 0;
for(int tail = count-1; head <= tail;){
cpFloat value = cpvcross(delta, cpvsub(verts[head], a));
if(value > valueTol){
if(value > max){
max = value;
pivot = head;
}
head++;
} else {
SWAP(verts[head], verts[tail]);
tail--;
}
}
// move the new pivot to the front if it's not already there.
if(pivot != 0) SWAP(verts[0], verts[pivot]);
return head;
}
static int
QHullReduce(cpFloat tol, cpVect *verts, int count, cpVect a, cpVect pivot, cpVect b, cpVect *result)
{
if(count < 0){
return 0;
} else if(count == 0) {
result[0] = pivot;
return 1;
} else {
int left_count = QHullPartition(verts, count, a, pivot, tol);
int index = QHullReduce(tol, verts + 1, left_count - 1, a, verts[0], pivot, result);
result[index++] = pivot;
int right_count = QHullPartition(verts + left_count, count - left_count, pivot, b, tol);
return index + QHullReduce(tol, verts + left_count + 1, right_count - 1, pivot, verts[left_count], b, result + index);
}
}
// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets.
// My implementation performs an in place reduction using the result array as scratch space.
int
cpConvexHull(int count, cpVect *verts, cpVect *result, int *first, cpFloat tol)
{
if(result){
// Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer.
memcpy(result, verts, count*sizeof(cpVect));
} else {
// If a result array was not specified, reduce the input instead.
result = verts;
}
// Degenerate case, all poins are the same.
int start, end;
cpLoopIndexes(verts, count, &start, &end);
if(start == end){
if(first) (*first) = 0;
return 1;
}
SWAP(result[0], result[start]);
SWAP(result[1], result[end == 0 ? start : end]);
cpVect a = result[0];
cpVect b = result[1];
if(first) (*first) = start;
int resultCount = QHullReduce(tol, result + 2, count - 2, a, b, a, result + 1) + 1;
cpAssertSoft(cpPolyValidate(result, resultCount),
"Internal error: cpConvexHull() and cpPolyValidate() did not agree."
"Please report this error with as much info as you can.");
return resultCount;
}
//MARK: Alternate Block Iterators
#if defined(__has_extension)
#if __has_extension(blocks)
static void IteratorFunc(void *ptr, void (^block)(void *ptr)){block(ptr);}
void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body)){
cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)IteratorFunc, block);
}
void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape)){
cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)IteratorFunc, block);
}
void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint)){
cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)IteratorFunc, block);
}
static void BodyIteratorFunc(cpBody *body, void *ptr, void (^block)(void *ptr)){block(ptr);}
void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape)){
cpBodyEachShape(body, (cpBodyShapeIteratorFunc)BodyIteratorFunc, block);
}
void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint)){
cpBodyEachConstraint(body, (cpBodyConstraintIteratorFunc)BodyIteratorFunc, block);
}
void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter)){
cpBodyEachArbiter(body, (cpBodyArbiterIteratorFunc)BodyIteratorFunc, block);
}
static void NearestPointQueryIteratorFunc(cpShape *shape, cpFloat distance, cpVect point, cpSpaceNearestPointQueryBlock block){block(shape, distance, point);}
void cpSpaceNearestPointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpSpaceNearestPointQueryBlock block){
cpSpaceNearestPointQuery(space, point, maxDistance, layers, group, (cpSpaceNearestPointQueryFunc)NearestPointQueryIteratorFunc, block);
}
static void SegmentQueryIteratorFunc(cpShape *shape, cpFloat t, cpVect n, cpSpaceSegmentQueryBlock block){block(shape, t, n);}
void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryBlock block){
cpSpaceSegmentQuery(space, start, end, layers, group, (cpSpaceSegmentQueryFunc)SegmentQueryIteratorFunc, block);
}
void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryBlock block){
cpSpaceBBQuery(space, bb, layers, group, (cpSpaceBBQueryFunc)IteratorFunc, block);
}
static void ShapeQueryIteratorFunc(cpShape *shape, cpContactPointSet *points, cpSpaceShapeQueryBlock block){block(shape, points);}
cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block){
return cpSpaceShapeQuery(space, shape, (cpSpaceShapeQueryFunc)ShapeQueryIteratorFunc, block);
}
#endif
#endif
#include "chipmunk_ffi.h"
chipmunk几何算法的更多相关文章
- 数据结构(DataStructure)与算法(Algorithm)、STL应用
catalogue . 引论 . 数据结构的概念 . 逻辑结构实例 2.1 堆栈 2.2 队列 2.3 树形结构 二叉树 . 物理结构实例 3.1 链表 单向线性链表 单向循环链表 双向线性链表 双向 ...
- C 实现的算法篇
算法的定义:算法是解决实际问题的一种精确的描述方法,目前,广泛认同的定义是:算法的模型分析的一组可行的确定的和有穷的规则 算法的五个特性:有穷性,确切性,输入,输出,可行性.目前算法的可执行的步骤非常 ...
- (Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO
http://www.cnblogs.com/sxiszero/p/3618737.html 下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年 ...
- 算法竞赛入门经典+挑战编程+USACO
下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...
- JS算法之A*(A星)寻路算法
今天写一个连连看的游戏的时候,接触到了一些寻路算法,我就大概讲讲其中的A*算法. 这个是我学习后的一点个人理解,有错误欢迎各位看官指正. 寻路模式主要有三种:广度游戏搜索.深度优先搜索和启发式搜索. ...
- 算法 A-Star(A星)寻路
一.简介 在游戏中,有一个很常见地需求,就是要让一个角色从A点走向B点,我们期望是让角色走最少的路.嗯,大家可能会说,直线就是最短的.没错,但大多数时候,A到B中间都会出现一些角色无法穿越的东西,比如 ...
- Cesium原理篇:GroundPrimitive
今天来看看GroundPrimitive,选择GroundPrimitive有三个目的:1 了解GroundPrimitive和Primitive的区别和关系 2 createGeometry的特殊处 ...
- OpneCv2.x 模块结构
转自:http://blog.csdn.net/huang9012/article/details/21811271 之前啃了不少OpenCV的官方文档,发现如果了解了一些OpenCV整体的模块架构后 ...
- 学习 opencv---(1) opencv3.1.0 组件结构浅析
本系列是根据 浅墨大神 的opencv系列而写的,,应该大部分内容会一样..如有侵权还请告知........... 开发环境:win7 + VS2013 + opencv3.1.0 至于OpenCV组 ...
随机推荐
- Tmux (转)
Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“ ...
- 在Windows10系统中配置和运行MongoDB数据库,linux开启mongdb
参考链接:http://jingyan.baidu.com/article/11c17a2c03081ef446e39d02.html linux中开启mongodb服务: 1. 进入到/data/ ...
- Django实现支付宝付款和微信支付
支付宝支付和微信支付是当今互联网产品常用的功能,我使用Django Rest Framework实现了网页上支付宝支付和微信支付的一个通用服务,提供rpc接口给其他服务,包括获取支付宝支付页面url的 ...
- (转) Linux下配置nfs并远程挂载
nfs是网络文件系统,允许一个节点通过网络访问远程计算机的文件系统,远程文件系统可以被直接挂载到本地,文件操作和本地没有区别,如果是局域网的nfs那么io的性能也可以保证,下面就以CentOS 7.x ...
- 【CodeForces148D】Bag of mice
题意 dragon和princess玩一个游戏.开始的时候袋子里有w个白老鼠和b个黑老鼠.两个人轮流从袋子里面往外摸老鼠.谁先拿到白老鼠谁先获胜.dragon每次抓出一只老鼠,剩下老鼠里面都会有一只跳 ...
- Ubuntu设置屏幕分辨率
Ubuntu设置屏幕分辨率 原创 2016年10月14日 13:01:24 14900 在虚拟机装好Ubuntu,进入系统分辨率是800*600,打开显示界面设置下分辨率,设置完怎么也选不上应用,于是 ...
- MYSQL中GROUP BY的细节及SELECT语句顺序
一.GROUP BY语句的细节 我们知道,在sql中,GROUP BY语句主要用来给数据分组,以便能对每个组进行聚集计算,但是GROUP BY也有一些限制需要知道: 1. GROUP BY字句可以包含 ...
- mysql5.6新建的user为啥会看到没有授权过的db?
数据库版本Server version: 5.6.22-log MySQL Community Server (GPL) root用户登录后,新建db,叫test2mysql> create d ...
- c#反射泛型方法
private void GetByEnumType() { var EnumType = Context.Request["EnumType"] ?? ""; ...
- python 文件操作(二)
一. 文件的读写 1.找到文件 文件路径:./test.py 2.打开文件 open('文件路径','模式') 模式: r, 以只读的方式打开 w, 打开一个文件只用于写入,如文件已存在,直接重 ...