Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorC. Scott Ananian <cscott@laptop.org>2008-11-03 22:25:39 (GMT)
committer C. Scott Ananian <cscott@laptop.org>2008-11-03 22:25:39 (GMT)
commit1a00411ebeb5efe33af57cd064efa45197860088 (patch)
tree13677b65ca50b85f8bfafab97e04e69aeddccf81
parentaa6d1277c3f990d411821e5791dbdb3380117eb2 (diff)
Fix dos line endings for pippy.physics and regenerate MANIFEST.
-rw-r--r--MANIFEST279
-rw-r--r--library/pippy/physics/add_objects.py1078
-rwxr-xr-xlibrary/pippy/physics/tools_poly.py880
3 files changed, 1118 insertions, 1119 deletions
diff --git a/MANIFEST b/MANIFEST
index a60bec5..63bec2d 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,7 +1,5 @@
NEWS
activity.py
-pippy_app.py
-setup.py
activity/activity-default.svg
activity/activity-icon.svg
activity/activity.info
@@ -18,6 +16,7 @@ data/math/guess
data/math/pascal
data/math/sierpinski
data/math/times
+data/physics/shapes
data/python/function
data/python/if
data/python/interpreter
@@ -31,8 +30,145 @@ data/string/thanks
library/pippy/__init__.py
library/pippy/console.py
library/pippy/game.py
+library/pippy/physics/Box2D2.py
+library/pippy/physics/__init__.py
+library/pippy/physics/add_objects.py
+library/pippy/physics/box2d/__init__.py
+library/pippy/physics/box2d/box2d_linux32/Box2D2.py
+library/pippy/physics/box2d/box2d_linux32/_Box2D2.so
+library/pippy/physics/box2d/box2d_linux32/__init__.py
+library/pippy/physics/box2d/box2d_linux64/Box2D2.py
+library/pippy/physics/box2d/box2d_linux64/_Box2D2.so
+library/pippy/physics/box2d/box2d_linux64/__init__.py
+library/pippy/physics/callbacks.py
+library/pippy/physics/camera.py
+library/pippy/physics/drawing.py
+library/pippy/physics/elements.py
+library/pippy/physics/locals.py
+library/pippy/physics/menu.py
+library/pippy/physics/tools.py
+library/pippy/physics/tools_poly.py
library/pippy/query.py
library/pippy/sound.py
+locale/af/LC_MESSAGES/org.laptop.Pippy.mo
+locale/af/activity.linfo
+locale/am/LC_MESSAGES/org.laptop.Pippy.mo
+locale/am/activity.linfo
+locale/ar/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ar/activity.linfo
+locale/ay/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ay/activity.linfo
+locale/bg/LC_MESSAGES/org.laptop.Pippy.mo
+locale/bg/activity.linfo
+locale/bn/LC_MESSAGES/org.laptop.Pippy.mo
+locale/bn/activity.linfo
+locale/bn_IN/LC_MESSAGES/org.laptop.Pippy.mo
+locale/bn_IN/activity.linfo
+locale/ca/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ca/activity.linfo
+locale/de/LC_MESSAGES/org.laptop.Pippy.mo
+locale/de/activity.linfo
+locale/dz/LC_MESSAGES/org.laptop.Pippy.mo
+locale/dz/activity.linfo
+locale/el/LC_MESSAGES/org.laptop.Pippy.mo
+locale/el/activity.linfo
+locale/en/LC_MESSAGES/org.laptop.Pippy.mo
+locale/en/activity.linfo
+locale/en_US/LC_MESSAGES/org.laptop.Pippy.mo
+locale/en_US/activity.linfo
+locale/es/LC_MESSAGES/org.laptop.Pippy.mo
+locale/es/activity.linfo
+locale/fa/LC_MESSAGES/org.laptop.Pippy.mo
+locale/fa/activity.linfo
+locale/fa_AF/LC_MESSAGES/org.laptop.Pippy.mo
+locale/fa_AF/activity.linfo
+locale/ff/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ff/activity.linfo
+locale/fr/LC_MESSAGES/org.laptop.Pippy.mo
+locale/fr/activity.linfo
+locale/gu/LC_MESSAGES/org.laptop.Pippy.mo
+locale/gu/activity.linfo
+locale/ha/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ha/activity.linfo
+locale/hi/LC_MESSAGES/org.laptop.Pippy.mo
+locale/hi/activity.linfo
+locale/ht/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ht/activity.linfo
+locale/ig/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ig/activity.linfo
+locale/is/LC_MESSAGES/org.laptop.Pippy.mo
+locale/is/activity.linfo
+locale/it/LC_MESSAGES/org.laptop.Pippy.mo
+locale/it/activity.linfo
+locale/ja/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ja/activity.linfo
+locale/km/LC_MESSAGES/org.laptop.Pippy.mo
+locale/km/activity.linfo
+locale/ko/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ko/activity.linfo
+locale/mk/LC_MESSAGES/org.laptop.Pippy.mo
+locale/mk/activity.linfo
+locale/ml/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ml/activity.linfo
+locale/mn/LC_MESSAGES/org.laptop.Pippy.mo
+locale/mn/activity.linfo
+locale/mr/LC_MESSAGES/org.laptop.Pippy.mo
+locale/mr/activity.linfo
+locale/mvo/LC_MESSAGES/org.laptop.Pippy.mo
+locale/mvo/activity.linfo
+locale/nb/LC_MESSAGES/org.laptop.Pippy.mo
+locale/nb/activity.linfo
+locale/ne/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ne/activity.linfo
+locale/nl/LC_MESSAGES/org.laptop.Pippy.mo
+locale/nl/activity.linfo
+locale/pa/LC_MESSAGES/org.laptop.Pippy.mo
+locale/pa/activity.linfo
+locale/pap/LC_MESSAGES/org.laptop.Pippy.mo
+locale/pap/activity.linfo
+locale/pis/LC_MESSAGES/org.laptop.Pippy.mo
+locale/pis/activity.linfo
+locale/pl/LC_MESSAGES/org.laptop.Pippy.mo
+locale/pl/activity.linfo
+locale/ps/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ps/activity.linfo
+locale/pt/LC_MESSAGES/org.laptop.Pippy.mo
+locale/pt/activity.linfo
+locale/pt_BR/LC_MESSAGES/org.laptop.Pippy.mo
+locale/pt_BR/activity.linfo
+locale/qu/LC_MESSAGES/org.laptop.Pippy.mo
+locale/qu/activity.linfo
+locale/ro/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ro/activity.linfo
+locale/ru/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ru/activity.linfo
+locale/rw/LC_MESSAGES/org.laptop.Pippy.mo
+locale/rw/activity.linfo
+locale/sd/LC_MESSAGES/org.laptop.Pippy.mo
+locale/sd/activity.linfo
+locale/si/LC_MESSAGES/org.laptop.Pippy.mo
+locale/si/activity.linfo
+locale/sl/LC_MESSAGES/org.laptop.Pippy.mo
+locale/sl/activity.linfo
+locale/te/LC_MESSAGES/org.laptop.Pippy.mo
+locale/te/activity.linfo
+locale/th/LC_MESSAGES/org.laptop.Pippy.mo
+locale/th/activity.linfo
+locale/tpi/LC_MESSAGES/org.laptop.Pippy.mo
+locale/tpi/activity.linfo
+locale/tr/LC_MESSAGES/org.laptop.Pippy.mo
+locale/tr/activity.linfo
+locale/ur/LC_MESSAGES/org.laptop.Pippy.mo
+locale/ur/activity.linfo
+locale/vi/LC_MESSAGES/org.laptop.Pippy.mo
+locale/vi/activity.linfo
+locale/yo/LC_MESSAGES/org.laptop.Pippy.mo
+locale/yo/activity.linfo
+locale/zh_CN/LC_MESSAGES/org.laptop.Pippy.mo
+locale/zh_CN/activity.linfo
+locale/zh_TW/LC_MESSAGES/org.laptop.Pippy.mo
+locale/zh_TW/activity.linfo
+pippy_app.py
po/Pippy.pot
po/af.po
po/am.po
@@ -75,7 +211,6 @@ po/pap.po
po/pis.po
po/pl.po
po/ps.po
-po/pseudo.po
po/pt.po
po/pt_BR.po
po/qu.po
@@ -94,140 +229,4 @@ po/vi.po
po/yo.po
po/zh_CN.po
po/zh_TW.po
-data/physics/shapes
-library/pippy/physics/drawing.py
-library/pippy/physics/callbacks.py
-library/pippy/physics/camera.py
-library/pippy/physics/__init__.py
-library/pippy/physics/menu.py
-library/pippy/physics/locals.py
-library/pippy/physics/tools.py
-library/pippy/physics/add_objects.py
-library/pippy/physics/tools_poly.py
-library/pippy/physics/elements.py
-library/pippy/physics/Box2D2.py
-library/pippy/physics/box2d/__init__.py
-library/pippy/physics/box2d/box2d_linux32/__init__.py
-library/pippy/physics/box2d/box2d_linux32/_Box2D2.so
-library/pippy/physics/box2d/box2d_linux32/Box2D2.py
-library/pippy/physics/box2d/box2d_linux64/__init__.py
-library/pippy/physics/box2d/box2d_linux64/_Box2D2.so
-library/pippy/physics/box2d/box2d_linux64/Box2D2.py
-locale/af/activity.linfo
-locale/af/LC_MESSAGES/org.laptop.Pippy.mo
-locale/am/activity.linfo
-locale/am/LC_MESSAGES/org.laptop.Pippy.mo
-locale/bg/activity.linfo
-locale/bg/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ar/activity.linfo
-locale/ar/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ca/activity.linfo
-locale/ca/LC_MESSAGES/org.laptop.Pippy.mo
-locale/bn/activity.linfo
-locale/bn/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ay/activity.linfo
-locale/ay/LC_MESSAGES/org.laptop.Pippy.mo
-locale/de/activity.linfo
-locale/de/LC_MESSAGES/org.laptop.Pippy.mo
-locale/el/activity.linfo
-locale/el/LC_MESSAGES/org.laptop.Pippy.mo
-locale/fa/activity.linfo
-locale/fa/LC_MESSAGES/org.laptop.Pippy.mo
-locale/en/activity.linfo
-locale/en/LC_MESSAGES/org.laptop.Pippy.mo
-locale/dz/activity.linfo
-locale/dz/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ff/activity.linfo
-locale/ff/LC_MESSAGES/org.laptop.Pippy.mo
-locale/es/activity.linfo
-locale/es/LC_MESSAGES/org.laptop.Pippy.mo
-locale/fr/activity.linfo
-locale/fr/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ha/activity.linfo
-locale/ha/LC_MESSAGES/org.laptop.Pippy.mo
-locale/hi/activity.linfo
-locale/hi/LC_MESSAGES/org.laptop.Pippy.mo
-locale/gu/activity.linfo
-locale/gu/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ig/activity.linfo
-locale/ig/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ht/activity.linfo
-locale/ht/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ja/activity.linfo
-locale/ja/LC_MESSAGES/org.laptop.Pippy.mo
-locale/is/activity.linfo
-locale/is/LC_MESSAGES/org.laptop.Pippy.mo
-locale/it/activity.linfo
-locale/it/LC_MESSAGES/org.laptop.Pippy.mo
-locale/km/activity.linfo
-locale/km/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ko/activity.linfo
-locale/ko/LC_MESSAGES/org.laptop.Pippy.mo
-locale/mk/activity.linfo
-locale/mk/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ml/activity.linfo
-locale/ml/LC_MESSAGES/org.laptop.Pippy.mo
-locale/nb/activity.linfo
-locale/nb/LC_MESSAGES/org.laptop.Pippy.mo
-locale/mn/activity.linfo
-locale/mn/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ne/activity.linfo
-locale/ne/LC_MESSAGES/org.laptop.Pippy.mo
-locale/mr/activity.linfo
-locale/mr/LC_MESSAGES/org.laptop.Pippy.mo
-locale/nl/activity.linfo
-locale/nl/LC_MESSAGES/org.laptop.Pippy.mo
-locale/pa/activity.linfo
-locale/pa/LC_MESSAGES/org.laptop.Pippy.mo
-locale/pl/activity.linfo
-locale/pl/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ps/activity.linfo
-locale/ps/LC_MESSAGES/org.laptop.Pippy.mo
-locale/pt/activity.linfo
-locale/pt/LC_MESSAGES/org.laptop.Pippy.mo
-locale/qu/activity.linfo
-locale/qu/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ro/activity.linfo
-locale/ro/LC_MESSAGES/org.laptop.Pippy.mo
-locale/sd/activity.linfo
-locale/sd/LC_MESSAGES/org.laptop.Pippy.mo
-locale/si/activity.linfo
-locale/si/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ru/activity.linfo
-locale/ru/LC_MESSAGES/org.laptop.Pippy.mo
-locale/sl/activity.linfo
-locale/sl/LC_MESSAGES/org.laptop.Pippy.mo
-locale/rw/activity.linfo
-locale/rw/LC_MESSAGES/org.laptop.Pippy.mo
-locale/te/activity.linfo
-locale/te/LC_MESSAGES/org.laptop.Pippy.mo
-locale/th/activity.linfo
-locale/th/LC_MESSAGES/org.laptop.Pippy.mo
-locale/tr/activity.linfo
-locale/tr/LC_MESSAGES/org.laptop.Pippy.mo
-locale/ur/activity.linfo
-locale/ur/LC_MESSAGES/org.laptop.Pippy.mo
-locale/vi/activity.linfo
-locale/vi/LC_MESSAGES/org.laptop.Pippy.mo
-locale/yo/activity.linfo
-locale/yo/LC_MESSAGES/org.laptop.Pippy.mo
-locale/mvo/activity.linfo
-locale/mvo/LC_MESSAGES/org.laptop.Pippy.mo
-locale/pap/activity.linfo
-locale/pap/LC_MESSAGES/org.laptop.Pippy.mo
-locale/pis/activity.linfo
-locale/pis/LC_MESSAGES/org.laptop.Pippy.mo
-locale/tpi/activity.linfo
-locale/tpi/LC_MESSAGES/org.laptop.Pippy.mo
-locale/bn_IN/activity.linfo
-locale/bn_IN/LC_MESSAGES/org.laptop.Pippy.mo
-locale/fa_AF/activity.linfo
-locale/fa_AF/LC_MESSAGES/org.laptop.Pippy.mo
-locale/en_US/activity.linfo
-locale/en_US/LC_MESSAGES/org.laptop.Pippy.mo
-locale/pt_BR/activity.linfo
-locale/pt_BR/LC_MESSAGES/org.laptop.Pippy.mo
-locale/zh_CN/activity.linfo
-locale/zh_CN/LC_MESSAGES/org.laptop.Pippy.mo
-locale/zh_TW/activity.linfo
-locale/zh_TW/LC_MESSAGES/org.laptop.Pippy.mo
+setup.py
diff --git a/library/pippy/physics/add_objects.py b/library/pippy/physics/add_objects.py
index 9e90e03..66f3b8f 100644
--- a/library/pippy/physics/add_objects.py
+++ b/library/pippy/physics/add_objects.py
@@ -1,500 +1,500 @@
-"""
-This file is part of the 'Elements' Project
-Elements is a 2D Physics API for Python (supporting Box2D2)
-
-Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>
-
-Home: http://elements.linuxuser.at
-IRC: #elements on irc.freenode.org
-
-Code: http://www.assembla.com/wiki/show/elements
- svn co http://svn2.assembla.com/svn/elements
-
-License: GPLv3 | See LICENSE for the full text
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-"""
-from locals import *
-from elements import box2d
-
-# Imports
-from math import pi
-from math import sqrt
-from math import asin
-
-import tools_poly
-
-class Add:
- element_count = 0
-
- def __init__(self, parent):
- self.parent = parent
-
- def ground(self):
- """ Add a static ground to the scene
-
- Return: box2d.b2Body
- """
- return self._rect((-10.0, 0.0), 50.0, .1, dynamic=False)
-
- def triangle(self, pos, sidelength, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a triangle | pos & a in the current input unit system (meters or pixels)
-
- Parameters:
- pos .... position (x,y)
- sidelength ...... sidelength
- other .. see [physics parameters]
-
- Return: box2d.b2Body
- """
+"""
+This file is part of the 'Elements' Project
+Elements is a 2D Physics API for Python (supporting Box2D2)
+
+Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>
+
+Home: http://elements.linuxuser.at
+IRC: #elements on irc.freenode.org
+
+Code: http://www.assembla.com/wiki/show/elements
+ svn co http://svn2.assembla.com/svn/elements
+
+License: GPLv3 | See LICENSE for the full text
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+from locals import *
+from elements import box2d
+
+# Imports
+from math import pi
+from math import sqrt
+from math import asin
+
+import tools_poly
+
+class Add:
+ element_count = 0
+
+ def __init__(self, parent):
+ self.parent = parent
+
+ def ground(self):
+ """ Add a static ground to the scene
+
+ Return: box2d.b2Body
+ """
+ return self._rect((-10.0, 0.0), 50.0, .1, dynamic=False)
+
+ def triangle(self, pos, sidelength, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a triangle | pos & a in the current input unit system (meters or pixels)
+
+ Parameters:
+ pos .... position (x,y)
+ sidelength ...... sidelength
+ other .. see [physics parameters]
+
+ Return: box2d.b2Body
+ """
vertices = [(-sidelength, 0.0), (sidelength, 0.0), (0.0, 2*sidelength)]
- return self.poly(pos, vertices, dynamic, density, restitution, friction, screenCoord)
-
- def ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic ball at pos after correcting the positions and legths to the internal
- meter system if neccessary (if INPUT_PIXELS), then call self._add_ball(...)
-
- Parameters:
- pos ..... position (x,y)
- radius .. circle radius
- other ... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
-
- if self.parent.input == INPUT_PIXELS:
- x /= self.parent.ppm
- y /= self.parent.ppm
- radius /= self.parent.ppm
-
- return self._ball((x,y), radius, dynamic, density, restitution, friction)
-
- def _ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- # Add a ball without correcting any settings
- # meaning, pos and vertices are in meters
- # Define the body
- x, y = pos
- bodyDef = box2d.b2BodyDef()
- bodyDef.position.Set(x, y)
- bodyDef.sleepFlag = True
-# bodyDef.allowSleep(True)
-
- userData = { 'color' : self.parent.get_color() }
- bodyDef.userData = userData
-
- # Create the Body
- if not dynamic:
- density = 0
-
- body = self.parent.world.CreateBody(bodyDef)
-
- self.parent.element_count += 1
-
- # Add a shape to the Body
- circleDef = box2d.b2CircleDef()
- circleDef.density = density
- circleDef.radius = radius
- circleDef.restitution = restitution
- circleDef.friction = friction
-
- body.CreateShape(circleDef)
- body.SetMassFromShapes();
-
- return body
-
- def rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic rectangle with input unit according to self.input (INPUT_PIXELS or INPUT_METERS)
- Correcting the positions to meters and calling self._add_rect()
-
- Parameters:
- pos ..... position (x,y)
- width ....... horizontal line
- height ....... vertical line
- angle ........ in degrees (0 .. 360)
- other ... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- x /= self.parent.ppm
- y /= self.parent.ppm
- width /= self.parent.ppm
- height /= self.parent.ppm
-
- # grad -> radians
- angle = (angle * pi) / 180
-
- return self._rect((x,y), width, height, angle, dynamic, density, restitution, friction)
-
-
- def wall(self, pos1, pos2, width=5, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a static rectangle between two arbitrary points with input unit according to self.input
- (INPUT_PIXELS or INPUT_METERS) Correcting the positions to meters and calling self._add_rect()
-
- Return: box2d.b2Body
- """
- if width < 5: width = 5
-
- if (pos1[0] < pos2[0]):
- x1, y1 = pos1
- x2, y2 = pos2
- else:
- x1, y1 = pos2
- x2, y2 = pos1
-
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord:
- x1, y1 = self.parent.to_world((x1, y1))
- x2, y2 = self.parent.to_world((x2, y2))
-
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- x1 /= self.parent.ppm
- y1 /= self.parent.ppm
- x2 /= self.parent.ppm
- y2 /= self.parent.ppm
- width /= self.parent.ppm
-
- length = sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )*0.5
-
- if width > 0:
- halfX = x1 + (x2-x1)*0.5
- halfY = y1 + (y2-y1)*0.5
-
- angle = asin( (y2-halfY)/length )
- return self._rect((halfX, halfY), length, width, angle, False, density, restitution, friction)
-
- def _rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- # Add a rect without correcting any settings
- # meaning, pos and vertices are in meters
- # angle is now in radians ((degrees * pi) / 180))
- x, y = pos
- bodyDef = box2d.b2BodyDef()
- bodyDef.position.Set(x, y)
-
- userData = { 'color' : self.parent.get_color() }
- bodyDef.userData = userData
-
- # Create the Body
- if not dynamic:
- density = 0
-
- bodyDef.sleepFlag = True
-
- body = self.parent.world.CreateBody(bodyDef)
-
- self.parent.element_count += 1
-
- # Add a shape to the Body
- boxDef = box2d.b2PolygonDef()
-
- boxDef.SetAsBox(width, height, box2d.b2Vec2(0,0), angle)
- boxDef.density = density
- boxDef.restitution = restitution
- boxDef.friction = friction
- body.CreateShape(boxDef)
-
- body.SetMassFromShapes()
-
- return body
-
- def poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic polygon, which has the vertices arranged around the poly's center at pos
- Correcting the positions to meters if INPUT_PIXELS, and calling self._add_poly()
-
- Parameters:
- pos ....... position (x,y)
- vertices .. vertices arranged around the center
- other ... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
+ return self.poly(pos, vertices, dynamic, density, restitution, friction, screenCoord)
+
+ def ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a dynamic ball at pos after correcting the positions and legths to the internal
+ meter system if neccessary (if INPUT_PIXELS), then call self._add_ball(...)
+
+ Parameters:
+ pos ..... position (x,y)
+ radius .. circle radius
+ other ... see [physics parameters]
+
+ Return: box2d.b2Body
+ """
+ # Bring coordinates into the world coordinate system (flip, camera offset, ...)
+ if screenCoord: x, y = self.parent.to_world(pos)
+ else: x, y = pos
+
+
+ if self.parent.input == INPUT_PIXELS:
+ x /= self.parent.ppm
+ y /= self.parent.ppm
+ radius /= self.parent.ppm
+
+ return self._ball((x,y), radius, dynamic, density, restitution, friction)
+
+ def _ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ # Add a ball without correcting any settings
+ # meaning, pos and vertices are in meters
+ # Define the body
+ x, y = pos
+ bodyDef = box2d.b2BodyDef()
+ bodyDef.position.Set(x, y)
+ bodyDef.sleepFlag = True
+# bodyDef.allowSleep(True)
+
+ userData = { 'color' : self.parent.get_color() }
+ bodyDef.userData = userData
+
+ # Create the Body
+ if not dynamic:
+ density = 0
+
+ body = self.parent.world.CreateBody(bodyDef)
+
+ self.parent.element_count += 1
+
+ # Add a shape to the Body
+ circleDef = box2d.b2CircleDef()
+ circleDef.density = density
+ circleDef.radius = radius
+ circleDef.restitution = restitution
+ circleDef.friction = friction
+
+ body.CreateShape(circleDef)
+ body.SetMassFromShapes();
+
+ return body
+
+ def rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a dynamic rectangle with input unit according to self.input (INPUT_PIXELS or INPUT_METERS)
+ Correcting the positions to meters and calling self._add_rect()
+
+ Parameters:
+ pos ..... position (x,y)
+ width ....... horizontal line
+ height ....... vertical line
+ angle ........ in degrees (0 .. 360)
+ other ... see [physics parameters]
+
+ Return: box2d.b2Body
+ """
+ # Bring coordinates into the world coordinate system (flip, camera offset, ...)
+ if screenCoord: x, y = self.parent.to_world(pos)
+ else: x, y = pos
+
+ # If required, translate pixel -> meters
+ if self.parent.input == INPUT_PIXELS:
+ x /= self.parent.ppm
+ y /= self.parent.ppm
+ width /= self.parent.ppm
+ height /= self.parent.ppm
+
+ # grad -> radians
+ angle = (angle * pi) / 180
+
+ return self._rect((x,y), width, height, angle, dynamic, density, restitution, friction)
+
+
+ def wall(self, pos1, pos2, width=5, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a static rectangle between two arbitrary points with input unit according to self.input
+ (INPUT_PIXELS or INPUT_METERS) Correcting the positions to meters and calling self._add_rect()
+
+ Return: box2d.b2Body
+ """
+ if width < 5: width = 5
+
+ if (pos1[0] < pos2[0]):
+ x1, y1 = pos1
+ x2, y2 = pos2
+ else:
+ x1, y1 = pos2
+ x2, y2 = pos1
+
+ # Bring coordinates into the world coordinate system (flip, camera offset, ...)
+ if screenCoord:
+ x1, y1 = self.parent.to_world((x1, y1))
+ x2, y2 = self.parent.to_world((x2, y2))
+
+ # If required, translate pixel -> meters
+ if self.parent.input == INPUT_PIXELS:
+ x1 /= self.parent.ppm
+ y1 /= self.parent.ppm
+ x2 /= self.parent.ppm
+ y2 /= self.parent.ppm
+ width /= self.parent.ppm
+
+ length = sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )*0.5
+
+ if width > 0:
+ halfX = x1 + (x2-x1)*0.5
+ halfY = y1 + (y2-y1)*0.5
+
+ angle = asin( (y2-halfY)/length )
+ return self._rect((halfX, halfY), length, width, angle, False, density, restitution, friction)
+
+ def _rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ # Add a rect without correcting any settings
+ # meaning, pos and vertices are in meters
+ # angle is now in radians ((degrees * pi) / 180))
+ x, y = pos
+ bodyDef = box2d.b2BodyDef()
+ bodyDef.position.Set(x, y)
+
+ userData = { 'color' : self.parent.get_color() }
+ bodyDef.userData = userData
+
+ # Create the Body
+ if not dynamic:
+ density = 0
+
+ bodyDef.sleepFlag = True
+
+ body = self.parent.world.CreateBody(bodyDef)
+
+ self.parent.element_count += 1
+
+ # Add a shape to the Body
+ boxDef = box2d.b2PolygonDef()
+
+ boxDef.SetAsBox(width, height, box2d.b2Vec2(0,0), angle)
+ boxDef.density = density
+ boxDef.restitution = restitution
+ boxDef.friction = friction
+ body.CreateShape(boxDef)
+
+ body.SetMassFromShapes()
+
+ return body
+
+ def poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
+ """ Add a dynamic polygon, which has the vertices arranged around the poly's center at pos
+ Correcting the positions to meters if INPUT_PIXELS, and calling self._add_poly()
+
+ Parameters:
+ pos ....... position (x,y)
+ vertices .. vertices arranged around the center
+ other ... see [physics parameters]
+
+ Return: box2d.b2Body
+ """
+ # Bring coordinates into the world coordinate system (flip, camera offset, ...)
+ if screenCoord: x, y = self.parent.to_world(pos)
+ else: x, y = pos
#pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.
#5, screenCoord=True
print "self.world.add.poly((", x,",", y, "), ", vertices, ", dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True)"
-#"x = " x "y = " y "vertices = "
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- # translate pixel -> meters
- x /= self.parent.ppm
- y /= self.parent.ppm
-
- # Translate vertices from pixels to meters
- v_new = []
- for v in vertices:
- vx, vy = v
- v_new.append((vx/self.parent.ppm, vy/self.parent.ppm))
- vertices = v_new
-
- return self._poly((x,y), vertices, dynamic, density, restitution, friction)
-
- def _poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- # add a centered poly at pos without correcting any settings
- # meaning, pos and vertices are in meters
- x, y = pos
- bodyDef = box2d.b2BodyDef()
- bodyDef.position.Set(x, y)
- bodyDef.sleepFlag = True
-
- userData = { 'color' : self.parent.get_color() }
- bodyDef.userData = userData
-
- # Create the Body
- if not dynamic:
- density = 0
-
- body = self.parent.world.CreateBody(bodyDef)
-
- self.parent.element_count += 1
-
- # Add a shape to the Body
- polyDef = box2d.b2PolygonDef()
- polyDef.vertexCount = len(vertices)
- for i in range(len(vertices)):
- vx, vy = vertices[i]
- polyDef.setVertex(i, box2d.b2Vec2(vx, vy))
-
- polyDef.density = density
- polyDef.restitution = restitution
- polyDef.friction = friction
-
- body.CreateShape(polyDef)
- body.SetMassFromShapes()
-
- return body
-
- def concavePoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- # 1. Step: Reduce
- # Detect if the polygon is closed or open
- if vertices[0] != vertices[-1]:
- is_closed = False
- else:
- is_closed = True
-
- # Continue reducing the vertecs
- x, y = c = tools_poly.calc_center(vertices)
- vertices = tools_poly.poly_center_vertices(vertices)
-
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(c)
- else: x, y = c
-
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- # translate pixel -> meters
- x /= self.parent.ppm
- y /= self.parent.ppm
-
- # Let's add the body
- bodyDef = box2d.b2BodyDef()
- bodyDef.position.Set(x, y)
- bodyDef.sleepFlag = True
-
- userData = { 'color' : self.parent.get_color() }
- bodyDef.userData = userData
-
- # Create the Body
- if not dynamic:
- density = 0
-
- body = self.parent.world.CreateBody(bodyDef)
-
- self.parent.element_count += 1
-
- # Create the reusable Box2D polygon and circle definitions
- polyDef = box2d.b2PolygonDef()
- polyDef.vertexCount = 4 # rectangle
- polyDef.density = density
- polyDef.restitution = restitution
- polyDef.friction = friction
-
- circleDef = box2d.b2CircleDef()
- circleDef.density = density
- circleDef.radius = 0.086
- circleDef.restitution = restitution
- circleDef.friction = friction
-
- # Set the scale factor
- factor = 8.0
-
- v2 = box2d.b2Vec2().fromTuple(vertices[0])
- for v in vertices[1:]:
- v1 = v2.copy()
- v2 = box2d.b2Vec2().fromTuple(v)
-
- vdir = v2-v1 # (v2x-v1x, v2y-v1y)
- vdir.Normalize()
-
- # we need a little size for the end part
- vn = box2d.b2Vec2(-vdir.y*factor, vdir.x*factor)
-
- v = [ v1+vn, v1-vn, v2-vn, v2+vn ]
-
- # Create a line (rect) for each part of the polygon,
- # and attach it to the body
- for i in range(len(v)):
- polyDef.setVertex(i, v[i] / self.parent.ppm)
-
- if not tools_poly.checkDef(polyDef):
- print "concavePoly: Created an invalid polygon!"
- return [], 0
-
- body.CreateShape(polyDef)
-
- # Now add a circle to the points between the rects
- # to avoid sharp edges and gaps
- if not is_closed and v2.tuple() == vertices[-1]:
- # Don't add a circle at the end
- break
-
- circleDef.localPosition = v2 / self.parent.ppm
- body.CreateShape(circleDef)
-
- # Now, all shapes have been attached
- body.SetMassFromShapes()
-
- # Return hard and soft reduced vertices
- return body
-
- def complexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- # 1. Step: Reduce
- # 2. Step: See if start and end are close, if so then close the polygon
- # 3. Step: Detect if convex or concave
- # 4. Step: Start self.convexPoly or self.concavePoly
- vertices, is_convex = tools_poly.reduce_poly_by_angle(vertices)
- #print "->", is_convex
-
- # If start and endpoints are close to each other, close polygon
- x1, y1 = vertices[0]
- x2, y2 = vertices[-1]
- dx = x2 - x1
- dy = y2 - y1
- l = sqrt((dx*dx)+(dy*dy))
-
- if l < 50:
- vertices[-1] = vertices[0]
- else:
- # Never convex if open (we decide so :)
- is_convex = False
-
- if tools_poly.is_line(vertices):
- # Lines shall be drawn by self.concavePoly(...)
- print "is line"
- is_convex = False
-
- if is_convex:
- print "convex"
- return self.convexPoly(vertices, dynamic, density, restitution, friction), vertices
- else:
- print "concave"
- return self.concavePoly(vertices, dynamic, density, restitution, friction), vertices
-
-
- def convexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- """ Add a complex polygon with vertices in absolute positions (meters or pixels, according
- to INPUT_PIXELS or INPUT_METERS). This function does the reduction and convec hulling
- of the poly, and calls add_poly(...)
-
- Parameters:
- vertices .. absolute vertices positions
- other ..... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # NOTE: Box2D has a maximum poly vertex count, defined in Common/box2d.b2Settings.h (box2d.b2_maxPolygonVertices)
- # We need to make sure, that we reach that by reducing the poly with increased tolerance
- # Reduce Polygon
- tolerance = 10 #5
- v_new = vertices
- while len(v_new) > box2d.b2_maxPolygonVertices:
- tolerance += 1
- v_new = tools_poly.reduce_poly(vertices, tolerance)
-
- print "convexPoly: Polygon reduced from %i to %i vertices | tolerance: %i" % (len(vertices), len(v_new), tolerance)
- vertices = v_new
-
- # So poly should be alright now
- # Continue reducing the vertecs
- vertices_orig_reduced = vertices
- vertices = tools_poly.poly_center_vertices(vertices)
-
- vertices = tools_poly.convex_hull(vertices)
-
- if len(vertices) < 3:
- return
-
- # Define the body
- x, y = c = tools_poly.calc_center(vertices_orig_reduced)
+#"x = " x "y = " y "vertices = "
+ # If required, translate pixel -> meters
+ if self.parent.input == INPUT_PIXELS:
+ # translate pixel -> meters
+ x /= self.parent.ppm
+ y /= self.parent.ppm
+
+ # Translate vertices from pixels to meters
+ v_new = []
+ for v in vertices:
+ vx, vy = v
+ v_new.append((vx/self.parent.ppm, vy/self.parent.ppm))
+ vertices = v_new
+
+ return self._poly((x,y), vertices, dynamic, density, restitution, friction)
+
+ def _poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ # add a centered poly at pos without correcting any settings
+ # meaning, pos and vertices are in meters
+ x, y = pos
+ bodyDef = box2d.b2BodyDef()
+ bodyDef.position.Set(x, y)
+ bodyDef.sleepFlag = True
+
+ userData = { 'color' : self.parent.get_color() }
+ bodyDef.userData = userData
+
+ # Create the Body
+ if not dynamic:
+ density = 0
+
+ body = self.parent.world.CreateBody(bodyDef)
+
+ self.parent.element_count += 1
+
+ # Add a shape to the Body
+ polyDef = box2d.b2PolygonDef()
+ polyDef.vertexCount = len(vertices)
+ for i in range(len(vertices)):
+ vx, vy = vertices[i]
+ polyDef.setVertex(i, box2d.b2Vec2(vx, vy))
+
+ polyDef.density = density
+ polyDef.restitution = restitution
+ polyDef.friction = friction
+
+ body.CreateShape(polyDef)
+ body.SetMassFromShapes()
+
+ return body
+
+ def concavePoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
+ # 1. Step: Reduce
+ # Detect if the polygon is closed or open
+ if vertices[0] != vertices[-1]:
+ is_closed = False
+ else:
+ is_closed = True
+
+ # Continue reducing the vertecs
+ x, y = c = tools_poly.calc_center(vertices)
+ vertices = tools_poly.poly_center_vertices(vertices)
+
+ # Bring coordinates into the world coordinate system (flip, camera offset, ...)
+ if screenCoord: x, y = self.parent.to_world(c)
+ else: x, y = c
+
+ # If required, translate pixel -> meters
+ if self.parent.input == INPUT_PIXELS:
+ # translate pixel -> meters
+ x /= self.parent.ppm
+ y /= self.parent.ppm
+
+ # Let's add the body
+ bodyDef = box2d.b2BodyDef()
+ bodyDef.position.Set(x, y)
+ bodyDef.sleepFlag = True
+
+ userData = { 'color' : self.parent.get_color() }
+ bodyDef.userData = userData
+
+ # Create the Body
+ if not dynamic:
+ density = 0
+
+ body = self.parent.world.CreateBody(bodyDef)
+
+ self.parent.element_count += 1
+
+ # Create the reusable Box2D polygon and circle definitions
+ polyDef = box2d.b2PolygonDef()
+ polyDef.vertexCount = 4 # rectangle
+ polyDef.density = density
+ polyDef.restitution = restitution
+ polyDef.friction = friction
+
+ circleDef = box2d.b2CircleDef()
+ circleDef.density = density
+ circleDef.radius = 0.086
+ circleDef.restitution = restitution
+ circleDef.friction = friction
+
+ # Set the scale factor
+ factor = 8.0
+
+ v2 = box2d.b2Vec2().fromTuple(vertices[0])
+ for v in vertices[1:]:
+ v1 = v2.copy()
+ v2 = box2d.b2Vec2().fromTuple(v)
+
+ vdir = v2-v1 # (v2x-v1x, v2y-v1y)
+ vdir.Normalize()
+
+ # we need a little size for the end part
+ vn = box2d.b2Vec2(-vdir.y*factor, vdir.x*factor)
+
+ v = [ v1+vn, v1-vn, v2-vn, v2+vn ]
+
+ # Create a line (rect) for each part of the polygon,
+ # and attach it to the body
+ for i in range(len(v)):
+ polyDef.setVertex(i, v[i] / self.parent.ppm)
+
+ if not tools_poly.checkDef(polyDef):
+ print "concavePoly: Created an invalid polygon!"
+ return [], 0
+
+ body.CreateShape(polyDef)
+
+ # Now add a circle to the points between the rects
+ # to avoid sharp edges and gaps
+ if not is_closed and v2.tuple() == vertices[-1]:
+ # Don't add a circle at the end
+ break
+
+ circleDef.localPosition = v2 / self.parent.ppm
+ body.CreateShape(circleDef)
+
+ # Now, all shapes have been attached
+ body.SetMassFromShapes()
+
+ # Return hard and soft reduced vertices
+ return body
+
+ def complexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ # 1. Step: Reduce
+ # 2. Step: See if start and end are close, if so then close the polygon
+ # 3. Step: Detect if convex or concave
+ # 4. Step: Start self.convexPoly or self.concavePoly
+ vertices, is_convex = tools_poly.reduce_poly_by_angle(vertices)
+ #print "->", is_convex
+
+ # If start and endpoints are close to each other, close polygon
+ x1, y1 = vertices[0]
+ x2, y2 = vertices[-1]
+ dx = x2 - x1
+ dy = y2 - y1
+ l = sqrt((dx*dx)+(dy*dy))
+
+ if l < 50:
+ vertices[-1] = vertices[0]
+ else:
+ # Never convex if open (we decide so :)
+ is_convex = False
+
+ if tools_poly.is_line(vertices):
+ # Lines shall be drawn by self.concavePoly(...)
+ print "is line"
+ is_convex = False
+
+ if is_convex:
+ print "convex"
+ return self.convexPoly(vertices, dynamic, density, restitution, friction), vertices
+ else:
+ print "concave"
+ return self.concavePoly(vertices, dynamic, density, restitution, friction), vertices
+
+
+ def convexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
+ """ Add a complex polygon with vertices in absolute positions (meters or pixels, according
+ to INPUT_PIXELS or INPUT_METERS). This function does the reduction and convec hulling
+ of the poly, and calls add_poly(...)
+
+ Parameters:
+ vertices .. absolute vertices positions
+ other ..... see [physics parameters]
+
+ Return: box2d.b2Body
+ """
+ # NOTE: Box2D has a maximum poly vertex count, defined in Common/box2d.b2Settings.h (box2d.b2_maxPolygonVertices)
+ # We need to make sure, that we reach that by reducing the poly with increased tolerance
+ # Reduce Polygon
+ tolerance = 10 #5
+ v_new = vertices
+ while len(v_new) > box2d.b2_maxPolygonVertices:
+ tolerance += 1
+ v_new = tools_poly.reduce_poly(vertices, tolerance)
+
+ print "convexPoly: Polygon reduced from %i to %i vertices | tolerance: %i" % (len(vertices), len(v_new), tolerance)
+ vertices = v_new
+
+ # So poly should be alright now
+ # Continue reducing the vertecs
+ vertices_orig_reduced = vertices
+ vertices = tools_poly.poly_center_vertices(vertices)
+
+ vertices = tools_poly.convex_hull(vertices)
+
+ if len(vertices) < 3:
+ return
+
+ # Define the body
+ x, y = c = tools_poly.calc_center(vertices_orig_reduced)
return self.poly((x,y), vertices, dynamic, density, restitution, friction)
def to_b2vec(self,pt):
pt = self.parent.to_world(pt)
ptx, pty = pt
- ptx /= self.parent.ppm
+ ptx /= self.parent.ppm
pty /= self.parent.ppm
pt = box2d.b2Vec2(ptx, pty)
return pt
# Alex Levenson's added joint methods:
- def distanceJoint(self,b1,b2,p1,p2):
- # Distance Joint
- p1 = self.to_b2vec(p1)
- p2 = self.to_b2vec(p2)
-
- jointDef = box2d.b2DistanceJointDef()
- jointDef.Initialize(b1, b2, p1, p2)
- jointDef.collideConnected = True
+ def distanceJoint(self,b1,b2,p1,p2):
+ # Distance Joint
+ p1 = self.to_b2vec(p1)
+ p2 = self.to_b2vec(p2)
+
+ jointDef = box2d.b2DistanceJointDef()
+ jointDef.Initialize(b1, b2, p1, p2)
+ jointDef.collideConnected = True
self.parent.world.CreateJoint(jointDef)
def fixedJoint(self, *args):
if len(args) == 2:
- # Fixed Joint to the Background, don't assume the center of the body
- b1 = self.parent.world.GetGroundBody()
- b2 = args[0]
+ # Fixed Joint to the Background, don't assume the center of the body
+ b1 = self.parent.world.GetGroundBody()
+ b2 = args[0]
p1 = self.to_b2vec(args[1])
-
- jointDef = box2d.b2RevoluteJointDef()
+
+ jointDef = box2d.b2RevoluteJointDef()
+ jointDef.Initialize(b1, b2, p1)
+ self.parent.world.CreateJoint(jointDef)
+ elif len(args) == 1:
+ # Fixed Joint to the Background, assume the center of the body
+ b1 = self.parent.world.GetGroundBody()
+ b2 = args[0]
+ p1 = b2.GetWorldCenter()
+
+ jointDef = box2d.b2RevoluteJointDef()
jointDef.Initialize(b1, b2, p1)
- self.parent.world.CreateJoint(jointDef)
- elif len(args) == 1:
- # Fixed Joint to the Background, assume the center of the body
- b1 = self.parent.world.GetGroundBody()
- b2 = args[0]
- p1 = b2.GetWorldCenter()
-
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, b2, p1)
-
+
self.parent.world.CreateJoint(jointDef)
def revoluteJoint(self,b1,b2,p1):
- # revolute joint between to bodies
+ # revolute joint between to bodies
p1 = self.to_b2vec(p1)
-
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, b2, p1)
-
+
+ jointDef = box2d.b2RevoluteJointDef()
+ jointDef.Initialize(b1, b2, p1)
+
self.parent.world.CreateJoint(jointDef)
# prismatic joint + pully not fully functional at this point
@@ -522,16 +522,16 @@ class Add:
self.parent.world.CreateJoint(jointDef)
def motor(self, body,pt,torque=900,speed=-10):
- # Fixed Joint to the Background with a motor on it
- b1 = self.parent.world.GetGroundBody()
+ # Fixed Joint to the Background with a motor on it
+ b1 = self.parent.world.GetGroundBody()
pt = self.to_b2vec(pt)
-
- jointDef = box2d.b2RevoluteJointDef()
+
+ jointDef = box2d.b2RevoluteJointDef()
jointDef.Initialize(b1, body, pt)
jointDef.maxMotorTorque = torque
jointDef.motorSpeed = speed
jointDef.enableMotor = True
- self.parent.world.CreateJoint(jointDef)
+ self.parent.world.CreateJoint(jointDef)
#def jointMotor(self,b1,b2,p1,speed):
# p1 = self.tob2vec(p1)
# jointDef = box2d.b2RevoluteJointDef()
@@ -539,63 +539,63 @@ class Add:
# jointDef.
#
def joint(self, *args):
- print "* Add Joint:", args
-
- if len(args) == 4:
- # Distance Joint
- b1, b2, p1, p2 = args
-
- p1 = self.parent.to_world(p1)
- p2 = self.parent.to_world(p2)
-
- p1x, p1y = p1
- p2x, p2y = p2
-
- p1x /= self.parent.ppm
- p1y /= self.parent.ppm
- p2x /= self.parent.ppm
- p2y /= self.parent.ppm
-
- p1 = box2d.b2Vec2(p1x, p1y)
- p2 = box2d.b2Vec2(p2x, p2y)
-
- jointDef = box2d.b2DistanceJointDef()
- jointDef.Initialize(b1, b2, p1, p2)
- jointDef.collideConnected = True
-
- self.parent.world.CreateJoint(jointDef)
-
- elif len(args) == 3:
- # Revolute Joint
- pass
-
- elif len(args) == 1:
- # Fixed Joint to the Background, assume the center of the body
- b1 = self.parent.world.GetGroundBody()
- b2 = args[0]
- p1 = b2.GetWorldCenter()
-
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, b2, p1)
-
- self.parent.world.CreateJoint(jointDef)
-
- def mouseJoint(self, body, pos):
- pos = self.parent.to_world(pos)
- x, y = pos
- x /= self.parent.ppm
- y /= self.parent.ppm
-
- mj = box2d.b2MouseJointDef()
- mj.body1 = self.parent.world.GetGroundBody()
- mj.body2 = body
- mj.target = box2d.b2Vec2(x, y)
- mj.maxForce = 100.0 * body.GetMass() # give humans POWER!
- self.parent.mouseJoint = self.parent.world.CreateJoint(mj).getAsType()
- body.WakeUp()
-
- def remove_mouseJoint(self):
- if self.parent.mouseJoint:
- self.parent.world.DestroyJoint(self.parent.mouseJoint)
- self.parent.mouseJoint = None
-
+ print "* Add Joint:", args
+
+ if len(args) == 4:
+ # Distance Joint
+ b1, b2, p1, p2 = args
+
+ p1 = self.parent.to_world(p1)
+ p2 = self.parent.to_world(p2)
+
+ p1x, p1y = p1
+ p2x, p2y = p2
+
+ p1x /= self.parent.ppm
+ p1y /= self.parent.ppm
+ p2x /= self.parent.ppm
+ p2y /= self.parent.ppm
+
+ p1 = box2d.b2Vec2(p1x, p1y)
+ p2 = box2d.b2Vec2(p2x, p2y)
+
+ jointDef = box2d.b2DistanceJointDef()
+ jointDef.Initialize(b1, b2, p1, p2)
+ jointDef.collideConnected = True
+
+ self.parent.world.CreateJoint(jointDef)
+
+ elif len(args) == 3:
+ # Revolute Joint
+ pass
+
+ elif len(args) == 1:
+ # Fixed Joint to the Background, assume the center of the body
+ b1 = self.parent.world.GetGroundBody()
+ b2 = args[0]
+ p1 = b2.GetWorldCenter()
+
+ jointDef = box2d.b2RevoluteJointDef()
+ jointDef.Initialize(b1, b2, p1)
+
+ self.parent.world.CreateJoint(jointDef)
+
+ def mouseJoint(self, body, pos):
+ pos = self.parent.to_world(pos)
+ x, y = pos
+ x /= self.parent.ppm
+ y /= self.parent.ppm
+
+ mj = box2d.b2MouseJointDef()
+ mj.body1 = self.parent.world.GetGroundBody()
+ mj.body2 = body
+ mj.target = box2d.b2Vec2(x, y)
+ mj.maxForce = 100.0 * body.GetMass() # give humans POWER!
+ self.parent.mouseJoint = self.parent.world.CreateJoint(mj).getAsType()
+ body.WakeUp()
+
+ def remove_mouseJoint(self):
+ if self.parent.mouseJoint:
+ self.parent.world.DestroyJoint(self.parent.mouseJoint)
+ self.parent.mouseJoint = None
+
diff --git a/library/pippy/physics/tools_poly.py b/library/pippy/physics/tools_poly.py
index cd6c4c6..97a0cea 100755
--- a/library/pippy/physics/tools_poly.py
+++ b/library/pippy/physics/tools_poly.py
@@ -1,440 +1,440 @@
-"""
-This file is part of the 'Elements' Project
-Elements is a 2D Physics API for Python (supporting Box2D2)
-
-Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>
-
-Home: http://elements.linuxuser.at
-IRC: #elements on irc.freenode.org
-
-Code: http://www.assembla.com/wiki/show/elements
- svn co http://svn2.assembla.com/svn/elements
-
-License: GPLv3 | See LICENSE for the full text
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-"""
-from functools import partial
-
-from math import fabs
-from math import sqrt
-from math import atan
-from math import atan2
-from math import degrees
-from math import acos
-
-from locals import *
-from elements import box2d
-
-def ComputeCentroid(pd):
- count = pd.vertexCount
-
- if count < 3:
- return False
-
- c = box2d.b2Vec2(0, 0)
- area = 0.0
-
- # pRef is the reference point for forming triangles.
- # It's location doesn't change the result (except for rounding error).
- pRef = box2d.b2Vec2(0.0, 0.0)
-
- inv3 = 1.0 / 3.0
-
- for i in range(count):
- # Triangle vertices.
- p1 = pRef
- p2 = pd.getVertex(i)
- if i + 1 < count:
- p3 = pd.getVertex(i+1)
- else: p3 = pd.getVertex(0)
-
- e1 = p2 - p1
- e2 = p3 - p1
-
- D = box2d.b2Cross(e1, e2)
-
- triangleArea = 0.5 * D
- area += triangleArea
-
- # Area weighted centroid
- c += triangleArea * inv3 * (p1 + p2 + p3)
-
- # Centroid
- # if area < FLT_EPSILON:
- #raise ValueError, "ComputeCentroid: area < FLT_EPSILON"
-
- return c / area
-
-def checkDef(pd):
- """Check the polygon definition for invalid vertices, etc.
-
- Return: True if valid, False if invalid
- """
-
-# if pd.vertexCount < 3 or pd.vertexCount > box2d.b2_maxPolygonVertices:
- #raise ValueError, "Invalid vertexCount"
-
- threshold = FLT_EPSILON * FLT_EPSILON
- verts = pd.getVertices_b2Vec2()
- normals = []
- v0 = verts[0]
- for i in range(pd.vertexCount):
- if i == pd.vertexCount-1:
- v1 = verts[0]
- else: v1 = verts[i+1]
- edge=v1 - v0
-# if edge.LengthSquared() < threshold:
-# raise ValueError, "edge.LengthSquared < FLT_EPSILON**2"
- normals.append( box2d.b2Cross(edge, 1.0) )
- normals[-1].Normalize()
- v0=v1
-
- centroid = ComputeCentroid(pd)
-
- d=box2d.b2Vec2()
- for i in range(pd.vertexCount):
- i1 = i - 1
- if i1 < 0: i1 = pd.vertexCount - 1
- i2 = i
- n1 = normals[i1]
- n2 = normals[i2]
- v = verts[i] - centroid
-
- d.x = box2d.b2Dot(n1, v) - box2d.b2_toiSlop
- d.y = box2d.b2Dot(n2, v) - box2d.b2_toiSlop
-
- # Shifting the edge inward by b2_toiSlop should
- # not cause the plane to pass the centroid.
-
- # Your shape has a radius/extent less than b2_toiSlop.
-# if d.x < 0.0 or d.y <= 0.0:
-# raise ValueError, "Your shape has a radius/extent less than b2_toiSlop."
-
- A = box2d.b2Mat22()
- A.col1.x = n1.x; A.col2.x = n1.y
- A.col1.y = n2.x; A.col2.y = n2.y
- #coreVertices[i] = A.Solve(d) + m_centroid
-
- return True
-
-def calc_center(points):
- """ Calculate the center of a polygon
-
- Return: The center (x,y)
- """
- tot_x, tot_y = 0,0
- for p in points:
- tot_x += p[0]
- tot_y += p[1]
- n = len(points)
- return (tot_x/n, tot_y/n)
-
-def poly_center_vertices(pointlist):
- """ Rearranges vectors around the center
-
- Return: pointlist ([(x, y), ...])
- """
- poly_points_center = []
- center = cx, cy = calc_center(pointlist)
-
- for p in pointlist:
- x = p[0] - cx
- y = cy - p[1]
- poly_points_center.append((x, y))
-
- return poly_points_center
-
-def is_line(vertices, tolerance=25.0):
- """ Check if passed vertices are a line. Done by comparing
- the angles of all vectors and check tolerance.
-
- Parameters:
- vertices ... a list of vertices (x, y)
- tolerance .. how many degrees should be allowed max to be a line
-
- Returns: True if line, False if no line
- """
- if len(vertices) <= 2:
- return True
-
- # Step 1: Points -> Vectors
- p_old = vertices[0]
- alphas = []
-
-
- for p in vertices[1:]:
- x1, y1 = p_old
- x2, y2 = p
- p_old = p
-
- # Create Vector
- vx, vy = (x2-x1, y2-y1)
-
- # Check Length
- l = sqrt((vx*vx) + (vy*vy))
- if l == 0.0: continue
-
- # Normalize vector
- vx /= l
- vy /= l
-
- # Append angle
- if fabs(vx) < 0.2: alpha = 90.0
- else: alpha = degrees(atan(vy / vx))
-
- alphas.append(fabs(alpha))
-
- # Sort angles
- alphas.sort()
-
- # Get maximum difference
- alpha_diff = fabs(alphas[-1] - alphas[0])
- print "alpha difference:", alpha_diff
-
- if alpha_diff < tolerance:
- return True
- else:
- return False
-
-def reduce_poly_by_angle(vertices, tolerance=10.0, minlen=20):
- """ This function reduces a poly by the angles of the vectors (detect lines)
- If the angle difference from one vector to the last > tolerance: use last point
- If the angle is quite the same, it's on the line
-
- Parameters:
- vertices ... a list of vertices (x, y)
- tolerance .. how many degrees should be allowed max
-
- Returns: (1) New Pointlist, (2) Soft reduced pointlist (reduce_poly())
- """
- v_last = vertices[-1]
- vertices = vxx = reduce_poly(vertices, minlen)
-
- p_new = []
- p_new.append(vertices[0])
-
- dir = None
- is_convex = True
-
- for i in xrange(len(vertices)-1):
- if i == 0:
- p_old = vertices[i]
- continue
-
- x1, y1 = p_old
- x2, y2 = vertices[i]
- x3, y3 = vertices[i+1]
- p_old = vertices[i]
-
- # Create Vectors
- v1x = (x2 - x1) * 1.0
- v1y = (y2 - y1) * 1.0
-
- v2x = (x3 - x2) * 1.0
- v2y = (y3 - y2) * 1.0
-
- # Calculate angle
- a = ((v1x * v2x) + (v1y * v2y))
- b = sqrt((v1x*v1x) + (v1y*v1y))
- c = sqrt((v2x*v2x) + (v2y*v2y))
-
- # No Division by 0 :)
- if (b*c) == 0.0: continue
-
- # Get the current degrees
- # We have a bug here sometimes...
- try:
- angle = degrees(acos(a / (b*c)))
- except:
- # cos=1.0
- print "cos=", a/(b*c)
- continue
-
- # Check if inside tolerance
- if fabs(angle) > tolerance:
- p_new.append(vertices[i])
- # print "x", 180-angle, is_left(vertices[i-1], vertices[i], vertices[i+1])
-
- # Check if convex:
- if dir == None:
- dir = is_left(vertices[i-1], vertices[i], vertices[i+1])
- else:
- if dir != is_left(vertices[i-1], vertices[i], vertices[i+1]):
- is_convex = False
-
- # We also want to append the last point :)
- p_new.append(v_last)
-
- # Returns: (1) New Pointlist, (2) Soft reduced pointlist (reduce_poly())
- return p_new, is_convex
-
- """ OLD FUNCTION: """
- # Wipe all points too close to each other
- vxx = vertices = reduce_poly(vertices, minlen)
-
- # Create Output List
- p_new = []
- p_new.append(vertices[0])
-
- # Set the starting vertice
- p_old = vertices[0]
- alpha_old = None
-
- # For each vector, compare the angle difference to the last one
- for i in range(1, len(vertices)):
- x1, y1 = p_old
- x2, y2 = vertices[i]
- p_old = (x2, y2)
-
- # Make Vector
- vx, vy = (x2-x1, y2-y1)
-
- # Vector length
- l = sqrt((vx*vx) + (vy*vy))
-
- # normalize
- vx /= l
- vy /= l
-
- # Get Angle
- if fabs(vx) < 0.2:
- alpha = 90
- else:
- alpha = degrees(atan(vy * 1.0) / (vx*1.0))
-
- if alpha_old == None:
- alpha_old = alpha
- continue
-
- # Get difference to previous angle
- alpha_diff = fabs(alpha - alpha_old)
- alpha_old = alpha
-
- # If the new vector differs from the old one, we add the old point
- # to the output list, as the line changed it's way :)
- if alpha_diff > tolerance:
- #print ">",alpha_diff, "\t", vx, vy, l
- p_new.append(vertices[i-1])
-
- # We also want to append the last point :)
- p_new.append(vertices[-1])
-
- # Returns: (1) New Pointlist, (2) Soft reduced pointlist (reduce_poly())
- return p_new, vxx
-
-
-# The following functions is_left, reduce_poly and convex_hull are
-# from the pymunk project (http://code.google.com/p/pymunk/)
-def is_left(p0, p1, p2):
- """Test if p2 is left, on or right of the (infinite) line (p0,p1).
-
- :return: > 0 for p2 left of the line through p0 and p1
- = 0 for p2 on the line
- < 0 for p2 right of the line
- """
- sorting = (p1[0] - p0[0])*(p2[1]-p0[1]) - (p2[0]-p0[0])*(p1[1]-p0[1])
- if sorting > 0: return 1
- elif sorting < 0: return -1
- else: return 0
-
-def is_convex(points):
- """Test if a polygon (list of (x,y)) is strictly convex or not.
-
- :return: True if the polygon is convex, False otherwise
- """
- #assert len(points) > 2, "not enough points to form a polygon"
-
- p0 = points[0]
- p1 = points[1]
- p2 = points[2]
-
- xc, yc = 0, 0
- is_same_winding = is_left(p0, p1, p2)
- for p2 in points[2:] + [p0] + [p1]:
- if is_same_winding != is_left(p0, p1, p2):
- return False
- a = p1[0] - p0[0], p1[1] - p0[1] # p1-p0
- b = p2[0] - p1[0], p2[1] - p1[1] # p2-p1
- if sign(a[0]) != sign(b[0]): xc +=1
- if sign(a[1]) != sign(b[1]): yc +=1
- p0, p1 = p1, p2
-
- return xc <= 2 and yc <= 2
-
-def sign(x):
- if x < 0: return -1
- else: return 1
-
-
-def reduce_poly(points, tolerance=50):
- """Remove close points to simplify a polyline
- tolerance is the min distance between two points squared.
-
- :return: The reduced polygon as a list of (x,y)
- """
- curr_p = points[0]
- reduced_ps = [points[0]]
-
- for p in points[1:]:
- x1, y1 = curr_p
- x2, y2 = p
- dx = fabs(x2 - x1)
- dy = fabs(y2 - y1)
- l = sqrt((dx*dx) + (dy*dy))
- if l > tolerance:
- curr_p = p
- reduced_ps.append(p)
-
- return reduced_ps
-
-def convex_hull(points):
- """Create a convex hull from a list of points.
- This function uses the Graham Scan Algorithm.
-
- :return: Convex hull as a list of (x,y)
- """
- ### Find lowest rightmost point
- p0 = points[0]
- for p in points[1:]:
- if p[1] < p0[1]:
- p0 = p
- elif p[1] == p0[1] and p[0] > p0[0]:
- p0 = p
- points.remove(p0)
-
- ### Sort the points angularly about p0 as center
- f = partial(is_left, p0)
- points.sort(cmp = f)
- points.reverse()
- points.insert(0, p0)
-
- ### Find the hull points
- hull = [p0, points[1]]
-
- for p in points[2:]:
-
- pt1 = hull[-1]
- pt2 = hull[-2]
- l = is_left(pt2, pt1, p)
- if l > 0:
- hull.append(p)
- else:
- while l <= 0 and len(hull) > 2:
- hull.pop()
- pt1 = hull[-1]
- pt2 = hull[-2]
- l = is_left(pt2, pt1, p)
- hull.append(p)
- return hull
-
+"""
+This file is part of the 'Elements' Project
+Elements is a 2D Physics API for Python (supporting Box2D2)
+
+Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>
+
+Home: http://elements.linuxuser.at
+IRC: #elements on irc.freenode.org
+
+Code: http://www.assembla.com/wiki/show/elements
+ svn co http://svn2.assembla.com/svn/elements
+
+License: GPLv3 | See LICENSE for the full text
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+from functools import partial
+
+from math import fabs
+from math import sqrt
+from math import atan
+from math import atan2
+from math import degrees
+from math import acos
+
+from locals import *
+from elements import box2d
+
+def ComputeCentroid(pd):
+ count = pd.vertexCount
+
+ if count < 3:
+ return False
+
+ c = box2d.b2Vec2(0, 0)
+ area = 0.0
+
+ # pRef is the reference point for forming triangles.
+ # It's location doesn't change the result (except for rounding error).
+ pRef = box2d.b2Vec2(0.0, 0.0)
+
+ inv3 = 1.0 / 3.0
+
+ for i in range(count):
+ # Triangle vertices.
+ p1 = pRef
+ p2 = pd.getVertex(i)
+ if i + 1 < count:
+ p3 = pd.getVertex(i+1)
+ else: p3 = pd.getVertex(0)
+
+ e1 = p2 - p1
+ e2 = p3 - p1
+
+ D = box2d.b2Cross(e1, e2)
+
+ triangleArea = 0.5 * D
+ area += triangleArea
+
+ # Area weighted centroid
+ c += triangleArea * inv3 * (p1 + p2 + p3)
+
+ # Centroid
+ # if area < FLT_EPSILON:
+ #raise ValueError, "ComputeCentroid: area < FLT_EPSILON"
+
+ return c / area
+
+def checkDef(pd):
+ """Check the polygon definition for invalid vertices, etc.
+
+ Return: True if valid, False if invalid
+ """
+
+# if pd.vertexCount < 3 or pd.vertexCount > box2d.b2_maxPolygonVertices:
+ #raise ValueError, "Invalid vertexCount"
+
+ threshold = FLT_EPSILON * FLT_EPSILON
+ verts = pd.getVertices_b2Vec2()
+ normals = []
+ v0 = verts[0]
+ for i in range(pd.vertexCount):
+ if i == pd.vertexCount-1:
+ v1 = verts[0]
+ else: v1 = verts[i+1]
+ edge=v1 - v0
+# if edge.LengthSquared() < threshold:
+# raise ValueError, "edge.LengthSquared < FLT_EPSILON**2"
+ normals.append( box2d.b2Cross(edge, 1.0) )
+ normals[-1].Normalize()
+ v0=v1
+
+ centroid = ComputeCentroid(pd)
+
+ d=box2d.b2Vec2()
+ for i in range(pd.vertexCount):
+ i1 = i - 1
+ if i1 < 0: i1 = pd.vertexCount - 1
+ i2 = i
+ n1 = normals[i1]
+ n2 = normals[i2]
+ v = verts[i] - centroid
+
+ d.x = box2d.b2Dot(n1, v) - box2d.b2_toiSlop
+ d.y = box2d.b2Dot(n2, v) - box2d.b2_toiSlop
+
+ # Shifting the edge inward by b2_toiSlop should
+ # not cause the plane to pass the centroid.
+
+ # Your shape has a radius/extent less than b2_toiSlop.
+# if d.x < 0.0 or d.y <= 0.0:
+# raise ValueError, "Your shape has a radius/extent less than b2_toiSlop."
+
+ A = box2d.b2Mat22()
+ A.col1.x = n1.x; A.col2.x = n1.y
+ A.col1.y = n2.x; A.col2.y = n2.y
+ #coreVertices[i] = A.Solve(d) + m_centroid
+
+ return True
+
+def calc_center(points):
+ """ Calculate the center of a polygon
+
+ Return: The center (x,y)
+ """
+ tot_x, tot_y = 0,0
+ for p in points:
+ tot_x += p[0]
+ tot_y += p[1]
+ n = len(points)
+ return (tot_x/n, tot_y/n)
+
+def poly_center_vertices(pointlist):
+ """ Rearranges vectors around the center
+
+ Return: pointlist ([(x, y), ...])
+ """
+ poly_points_center = []
+ center = cx, cy = calc_center(pointlist)
+
+ for p in pointlist:
+ x = p[0] - cx
+ y = cy - p[1]
+ poly_points_center.append((x, y))
+
+ return poly_points_center
+
+def is_line(vertices, tolerance=25.0):
+ """ Check if passed vertices are a line. Done by comparing
+ the angles of all vectors and check tolerance.
+
+ Parameters:
+ vertices ... a list of vertices (x, y)
+ tolerance .. how many degrees should be allowed max to be a line
+
+ Returns: True if line, False if no line
+ """
+ if len(vertices) <= 2:
+ return True
+
+ # Step 1: Points -> Vectors
+ p_old = vertices[0]
+ alphas = []
+
+
+ for p in vertices[1:]:
+ x1, y1 = p_old
+ x2, y2 = p
+ p_old = p
+
+ # Create Vector
+ vx, vy = (x2-x1, y2-y1)
+
+ # Check Length
+ l = sqrt((vx*vx) + (vy*vy))
+ if l == 0.0: continue
+
+ # Normalize vector
+ vx /= l
+ vy /= l
+
+ # Append angle
+ if fabs(vx) < 0.2: alpha = 90.0
+ else: alpha = degrees(atan(vy / vx))
+
+ alphas.append(fabs(alpha))
+
+ # Sort angles
+ alphas.sort()
+
+ # Get maximum difference
+ alpha_diff = fabs(alphas[-1] - alphas[0])
+ print "alpha difference:", alpha_diff
+
+ if alpha_diff < tolerance:
+ return True
+ else:
+ return False
+
+def reduce_poly_by_angle(vertices, tolerance=10.0, minlen=20):
+ """ This function reduces a poly by the angles of the vectors (detect lines)
+ If the angle difference from one vector to the last > tolerance: use last point
+ If the angle is quite the same, it's on the line
+
+ Parameters:
+ vertices ... a list of vertices (x, y)
+ tolerance .. how many degrees should be allowed max
+
+ Returns: (1) New Pointlist, (2) Soft reduced pointlist (reduce_poly())
+ """
+ v_last = vertices[-1]
+ vertices = vxx = reduce_poly(vertices, minlen)
+
+ p_new = []
+ p_new.append(vertices[0])
+
+ dir = None
+ is_convex = True
+
+ for i in xrange(len(vertices)-1):
+ if i == 0:
+ p_old = vertices[i]
+ continue
+
+ x1, y1 = p_old
+ x2, y2 = vertices[i]
+ x3, y3 = vertices[i+1]
+ p_old = vertices[i]
+
+ # Create Vectors
+ v1x = (x2 - x1) * 1.0
+ v1y = (y2 - y1) * 1.0
+
+ v2x = (x3 - x2) * 1.0
+ v2y = (y3 - y2) * 1.0
+
+ # Calculate angle
+ a = ((v1x * v2x) + (v1y * v2y))
+ b = sqrt((v1x*v1x) + (v1y*v1y))
+ c = sqrt((v2x*v2x) + (v2y*v2y))
+
+ # No Division by 0 :)
+ if (b*c) == 0.0: continue
+
+ # Get the current degrees
+ # We have a bug here sometimes...
+ try:
+ angle = degrees(acos(a / (b*c)))
+ except:
+ # cos=1.0
+ print "cos=", a/(b*c)
+ continue
+
+ # Check if inside tolerance
+ if fabs(angle) > tolerance:
+ p_new.append(vertices[i])
+ # print "x", 180-angle, is_left(vertices[i-1], vertices[i], vertices[i+1])
+
+ # Check if convex:
+ if dir == None:
+ dir = is_left(vertices[i-1], vertices[i], vertices[i+1])
+ else:
+ if dir != is_left(vertices[i-1], vertices[i], vertices[i+1]):
+ is_convex = False
+
+ # We also want to append the last point :)
+ p_new.append(v_last)
+
+ # Returns: (1) New Pointlist, (2) Soft reduced pointlist (reduce_poly())
+ return p_new, is_convex
+
+ """ OLD FUNCTION: """
+ # Wipe all points too close to each other
+ vxx = vertices = reduce_poly(vertices, minlen)
+
+ # Create Output List
+ p_new = []
+ p_new.append(vertices[0])
+
+ # Set the starting vertice
+ p_old = vertices[0]
+ alpha_old = None
+
+ # For each vector, compare the angle difference to the last one
+ for i in range(1, len(vertices)):
+ x1, y1 = p_old
+ x2, y2 = vertices[i]
+ p_old = (x2, y2)
+
+ # Make Vector
+ vx, vy = (x2-x1, y2-y1)
+
+ # Vector length
+ l = sqrt((vx*vx) + (vy*vy))
+
+ # normalize
+ vx /= l
+ vy /= l
+
+ # Get Angle
+ if fabs(vx) < 0.2:
+ alpha = 90
+ else:
+ alpha = degrees(atan(vy * 1.0) / (vx*1.0))
+
+ if alpha_old == None:
+ alpha_old = alpha
+ continue
+
+ # Get difference to previous angle
+ alpha_diff = fabs(alpha - alpha_old)
+ alpha_old = alpha
+
+ # If the new vector differs from the old one, we add the old point
+ # to the output list, as the line changed it's way :)
+ if alpha_diff > tolerance:
+ #print ">",alpha_diff, "\t", vx, vy, l
+ p_new.append(vertices[i-1])
+
+ # We also want to append the last point :)
+ p_new.append(vertices[-1])
+
+ # Returns: (1) New Pointlist, (2) Soft reduced pointlist (reduce_poly())
+ return p_new, vxx
+
+
+# The following functions is_left, reduce_poly and convex_hull are
+# from the pymunk project (http://code.google.com/p/pymunk/)
+def is_left(p0, p1, p2):
+ """Test if p2 is left, on or right of the (infinite) line (p0,p1).
+
+ :return: > 0 for p2 left of the line through p0 and p1
+ = 0 for p2 on the line
+ < 0 for p2 right of the line
+ """
+ sorting = (p1[0] - p0[0])*(p2[1]-p0[1]) - (p2[0]-p0[0])*(p1[1]-p0[1])
+ if sorting > 0: return 1
+ elif sorting < 0: return -1
+ else: return 0
+
+def is_convex(points):
+ """Test if a polygon (list of (x,y)) is strictly convex or not.
+
+ :return: True if the polygon is convex, False otherwise
+ """
+ #assert len(points) > 2, "not enough points to form a polygon"
+
+ p0 = points[0]
+ p1 = points[1]
+ p2 = points[2]
+
+ xc, yc = 0, 0
+ is_same_winding = is_left(p0, p1, p2)
+ for p2 in points[2:] + [p0] + [p1]:
+ if is_same_winding != is_left(p0, p1, p2):
+ return False
+ a = p1[0] - p0[0], p1[1] - p0[1] # p1-p0
+ b = p2[0] - p1[0], p2[1] - p1[1] # p2-p1
+ if sign(a[0]) != sign(b[0]): xc +=1
+ if sign(a[1]) != sign(b[1]): yc +=1
+ p0, p1 = p1, p2
+
+ return xc <= 2 and yc <= 2
+
+def sign(x):
+ if x < 0: return -1
+ else: return 1
+
+
+def reduce_poly(points, tolerance=50):
+ """Remove close points to simplify a polyline
+ tolerance is the min distance between two points squared.
+
+ :return: The reduced polygon as a list of (x,y)
+ """
+ curr_p = points[0]
+ reduced_ps = [points[0]]
+
+ for p in points[1:]:
+ x1, y1 = curr_p
+ x2, y2 = p
+ dx = fabs(x2 - x1)
+ dy = fabs(y2 - y1)
+ l = sqrt((dx*dx) + (dy*dy))
+ if l > tolerance:
+ curr_p = p
+ reduced_ps.append(p)
+
+ return reduced_ps
+
+def convex_hull(points):
+ """Create a convex hull from a list of points.
+ This function uses the Graham Scan Algorithm.
+
+ :return: Convex hull as a list of (x,y)
+ """
+ ### Find lowest rightmost point
+ p0 = points[0]
+ for p in points[1:]:
+ if p[1] < p0[1]:
+ p0 = p
+ elif p[1] == p0[1] and p[0] > p0[0]:
+ p0 = p
+ points.remove(p0)
+
+ ### Sort the points angularly about p0 as center
+ f = partial(is_left, p0)
+ points.sort(cmp = f)
+ points.reverse()
+ points.insert(0, p0)
+
+ ### Find the hull points
+ hull = [p0, points[1]]
+
+ for p in points[2:]:
+
+ pt1 = hull[-1]
+ pt2 = hull[-2]
+ l = is_left(pt2, pt1, p)
+ if l > 0:
+ hull.append(p)
+ else:
+ while l <= 0 and len(hull) > 2:
+ hull.pop()
+ pt1 = hull[-1]
+ pt2 = hull[-2]
+ l = is_left(pt2, pt1, p)
+ hull.append(p)
+ return hull
+