Box2D/Box2D_shapes.i (317 lines of code) (raw):

/* * pybox2d -- http://pybox2d.googlecode.com * * Copyright (c) 2010 Ken Lauer / sirkne at gmail dot com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ /**** Shape ****/ %extend b2Shape { public: %pythoncode %{ __eq__ = b2ShapeCompare __ne__ = lambda self,other: not b2ShapeCompare(self,other) # Read-only type = property(__GetType, None) def getAsType(self): return self @property def childCount(self): """ Get the number of child primitives. """ return self.__GetChildCount() def getAABB(self, transform, childIndex): """ Given a transform, compute the associated axis aligned bounding box for a child shape. """ if childIndex >= self.childCount: raise ValueError('Child index should be at most childCount=%d' % self.childCount) aabb=b2AABB() self.__ComputeAABB(aabb, transform, childIndex) return aabb def getMass(self, density): """ Compute the mass properties of this shape using its dimensions and density. The inertia tensor is computed about the local origin. """ m=b2MassData() self.__ComputeMass(m, density) return m %} } %ignore b2Shape::m_type; %ignore b2Shape::Clone; %rename(radius) b2Shape::m_radius; %rename(__GetChildCount) b2Shape::GetChildCount; %rename(__GetType) b2Shape::GetType; %rename(__ComputeAABB) b2Shape::ComputeAABB; %rename(__ComputeMass) b2Shape::ComputeMass; /**** CircleShape ****/ %extend b2CircleShape { public: %pythoncode %{ %} } %rename (pos) b2CircleShape::m_p; %ignore b2CircleShape::GetVertexCount; %ignore b2CircleShape::GetVertex; %ignore b2CircleShape::GetSupport; %ignore b2CircleShape::GetSupportVertex; /**** PolygonShape ****/ %extend b2PolygonShape { public: PyObject* __get_vertices() { PyObject* ret=PyList_New($self->m_count); PyObject* vertex; for (int i=0; i < $self->m_count; i++) { vertex = PyTuple_New(2); PyTuple_SetItem(vertex, 0, SWIG_From_double((float32)$self->m_vertices[i].x)); PyTuple_SetItem(vertex, 1, SWIG_From_double((float32)$self->m_vertices[i].y)); PyList_SetItem(ret, i, vertex); } return ret; } PyObject* __get_normals() { PyObject* ret=PyList_New($self->m_count); PyObject* vertex; for (int i=0; i < $self->m_count; i++) { vertex = PyTuple_New(2); PyTuple_SetItem(vertex, 0, SWIG_From_double((float32)$self->m_normals[i].x)); PyTuple_SetItem(vertex, 1, SWIG_From_double((float32)$self->m_normals[i].y)); PyList_SetItem(ret, i, vertex); } return ret; } %pythoncode %{ def __repr__(self): return "b2PolygonShape(vertices: %s)" % (self.vertices) def __clear_vertices(self): self.vertexCount=0 for i in range(0, b2_maxPolygonVertices): self.set_vertex(i, 0, 0) def __set_vertices(self, values): if not values: self.__clear_vertices() else: if len(values) < 2 or len(values) > b2_maxPolygonVertices: raise ValueError('Expected tuple or list of length >= 2 and less than b2_maxPolygonVertices=%d, got length %d.' % (b2_maxPolygonVertices, len(values))) for i,value in enumerate(values): if isinstance(value, (tuple, list, b2Vec2)): if len(value) != 2: raise ValueError('Expected tuple or list of length 2, got length %d' % len(value)) self.set_vertex(i, *value) else: raise ValueError('Expected tuple, list, or b2Vec2, got %s' % type(value)) self.vertexCount=i+1 # follow along in case of an exception to indicate valid number set self.__set_vertices_internal() # calculates normals, centroid, etc. def __iter__(self): """ Iterates over the vertices in the polygon """ for v in self.vertices: yield v def __IsValid(self): return b2CheckPolygon(self) valid = property(__IsValid, None, doc="Checks the polygon to see if it can be properly created. Raises ValueError for invalid shapes.") vertices = property(__get_vertices, __set_vertices, doc="All of the vertices as a list of tuples [ (x1,y1), (x2,y2) ... (xN,yN) ]") normals = property(__get_normals, None, doc="All of the normals as a list of tuples [ (x1,y1), (x2,y2) ... (xN,yN) ]") box = property(None, lambda self, value: self.SetAsBox(*value), doc="Property replacement for running SetAsBox (Write-only)") %} const b2Vec2* __get_vertex(uint16 vnum) { if (vnum >= b2_maxPolygonVertices) return NULL; return &( $self->m_vertices[vnum] ); } const b2Vec2* __get_normal(uint16 vnum) { if (vnum >= b2_maxPolygonVertices) return NULL; return &( $self->m_normals[vnum] ); } void set_vertex(uint16 vnum, b2Vec2& value) { if (vnum < b2_maxPolygonVertices) $self->m_vertices[vnum].Set(value.x, value.y); } void set_vertex(uint16 vnum, float32 x, float32 y) { if (vnum < b2_maxPolygonVertices) $self->m_vertices[vnum].Set(x, y); } void __set_vertices_internal() { $self->Set($self->m_vertices, $self->m_count); } } %rename (centroid) b2PolygonShape::m_centroid; %rename (vertexCount) b2PolygonShape::m_count; %rename (__set_vertices_internal) b2PolygonShape::Set; %ignore b2PolygonShape::m_normals; %ignore b2PolygonShape::m_vertices; %ignore b2PolygonShape::GetVertex; %ignore b2PolygonShape::GetVertexCount; %ignore b2PolygonShape::vertices; %ignore b2PolygonShape::GetVertices; %ignore b2PolygonShape::GetNormals; /**** ChainShape ****/ %include "carrays.i" %array_class(b2Vec2, _b2Vec2Array); %extend b2ChainShape { public: PyObject* __get_vertices() { if (!$self->m_vertices) { Py_INCREF(Py_None); return Py_None; } PyObject* ret=PyList_New($self->m_count); PyObject* vertex; for (int i=0; i < $self->m_count; i++) { vertex = PyTuple_New(2); PyTuple_SetItem(vertex, 0, SWIG_From_double((float32)$self->m_vertices[i].x)); PyTuple_SetItem(vertex, 1, SWIG_From_double((float32)$self->m_vertices[i].y)); PyList_SetItem(ret, i, vertex); } return ret; } %pythoncode %{ def __repr__(self): return "b2ChainShape(vertices: %s)" % (self.vertices) def getChildEdge(self, index): if childIndex >= self.childCount: raise ValueError('Child index should be at most childCount=%d' % self.childCount) edge=b2EdgeShape() self.__GetChildEdge(edge, index) return edge @property def edges(self): return [self.getChildEdge(i) for i in range(self.childCount)] @property def vertexCount(self): return self.__get_count() def __get_vertices(self): """Returns all of the vertices as a list of tuples [ (x1,y1), (x2,y2) ... (xN,yN) ]""" return [ (self.__get_vertex(i).x, self.__get_vertex(i).y ) for i in range(0, self.vertexCount)] def __iter__(self): """ Iterates over the vertices in the Chain """ for v in self.vertices: yield v def __set_vertices(self, values, loop=True): if not values or not isinstance(values, (list, tuple)) or (len(values) < 2): raise ValueError('Expected tuple or list of length >= 2.') for i,value in enumerate(values): if isinstance(value, (tuple, list)): if len(value) != 2: raise ValueError('Expected tuple or list of length 2, got length %d' % len(value)) for j in value: if not isinstance(j, (int, float)): raise ValueError('Expected int or float values, got %s' % (type(j))) elif isinstance(value, b2Vec2): pass else: raise ValueError('Expected tuple, list, or b2Vec2, got %s' % type(value)) vecs=_b2Vec2Array(len(values)) for i, value in enumerate(values): if isinstance(value, b2Vec2): vecs[i]=value else: vecs[i]=b2Vec2(value) self.__create(vecs, len(values), loop) vertices = property(__get_vertices, __set_vertices) vertices_chain = property(__get_vertices, lambda self, v : self.__set_vertices(v, loop=False)) vertices_loop = vertices %} void __create(_b2Vec2Array* v, int c, bool loop) { if (v) { if (loop) $self->CreateLoop(v, c); else $self->CreateChain(v, c); } } const b2Vec2* __get_vertex(uint16 vnum) { if (vnum >= $self->m_count) return NULL; return &($self->m_vertices[vnum]); } int32 __get_count() { return $self->m_count; } } %rename (__GetVertices) b2ChainShape::GetVertices; %rename (__GetChildEdge) b2ChainShape::GetChildEdge; %ignore b2ChainShape::m_vertices; %ignore b2ChainShape::m_count; %ignore b2ChainShape::Create; /**** EdgeShape ****/ %extend b2EdgeShape { public: %pythoncode %{ def __repr__(self): return "b2EdgeShape(vertices: %s)" % (self.vertices) @property def all_vertices(self): """Returns all of the vertices as a list of tuples [ (x0,y0), (x1,y1), (x2,y2) (x3,y3) ] Note that the validity of vertices 0 and 4 depend on whether or not hasVertex0 and hasVertex3 are set. """ return [tuple(self.vertex0), tuple(self.vertex1), tuple(self.vertex2), tuple(self.vertex3)] def __get_vertices(self): """Returns the basic vertices as a list of tuples [ (x1,y1), (x2,y2) ] To include the supporting vertices, see 'all_vertices' If you want to set vertex3 but not vertex0, pass in None for vertex0. """ return [tuple(self.vertex1), tuple(self.vertex2)] def __set_vertices(self, vertices): if len(vertices)==2: self.vertex1, self.vertex2=vertices self.hasVertex0=False self.hasVertex3=False elif len(vertices)==3: self.vertex0, self.vertex1, self.vertex2=vertices self.hasVertex0=(vertices[0] != None) self.hasVertex3=False elif len(vertices)==4: self.vertex0, self.vertex1, self.vertex2, self.vertex3=vertices self.hasVertex0=(vertices[0] != None) self.hasVertex3=True else: raise ValueError('Expected from 2 to 4 vertices.') @property def vertexCount(self): """ Returns the number of valid vertices (as in, it counts whether or not hasVertex0 or hasVertex3 are set) """ if self.hasVertex0 and self.hasVertex3: return 4 elif self.hasVertex0 or self.hasVertex3: return 3 else: return 2 def __iter__(self): """ Iterates over the vertices in the Edge """ for v in self.vertices: yield v vertices=property(__get_vertices, __set_vertices) %} } %rename(radius) b2EdgeShape::m_radius; %rename(vertex0) b2EdgeShape::m_vertex0; %rename(vertex1) b2EdgeShape::m_vertex1; %rename(vertex2) b2EdgeShape::m_vertex2; %rename(vertex3) b2EdgeShape::m_vertex3; %rename(hasVertex0) b2EdgeShape::m_hasVertex0; %rename(hasVertex3) b2EdgeShape::m_hasVertex3; %rename(__Set) b2EdgeShape::Set;