qml-box2d/0000755000000000000000000000000012310410615007542 5ustar qml-box2d/box2dbody.h0000664000000000000000000001213312310072714011615 0ustar /* * box2dbody.h * Copyright (c) 2010-2011 Thorbjørn Lindeijer * Copyright (c) 2011 Daker Fernandes Pinheiro * Copyright (c) 2011 Tan Miaoqing * Copyright (c) 2011 Antonio Aloisio * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Antti Krats * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DBODY_H #define BOX2DBODY_H #include #include class Box2DFixture; class Box2DWorld; class b2Body; class b2BodyDef; class b2World; /** * The Box2D body, build up from a list of shapes. */ class Box2DBody : public QQuickItem { Q_OBJECT Q_ENUMS(BodyType) Q_PROPERTY(qreal linearDamping READ linearDamping WRITE setLinearDamping NOTIFY linearDampingChanged) Q_PROPERTY(qreal angularDamping READ angularDamping WRITE setAngularDamping NOTIFY angularDampingChanged) Q_PROPERTY(BodyType bodyType READ bodyType WRITE setBodyType NOTIFY bodyTypeChanged) Q_PROPERTY(bool bullet READ isBullet WRITE setBullet NOTIFY bulletChanged) Q_PROPERTY(bool sleepingAllowed READ sleepingAllowed WRITE setSleepingAllowed NOTIFY sleepingAllowedChanged) Q_PROPERTY(bool fixedRotation READ fixedRotation WRITE setFixedRotation NOTIFY fixedRotationChanged) Q_PROPERTY(bool active READ active WRITE setActive) Q_PROPERTY(bool awake READ awake WRITE setAwake) Q_PROPERTY(QPointF linearVelocity READ linearVelocity WRITE setLinearVelocity NOTIFY linearVelocityChanged) Q_PROPERTY(QQmlListProperty fixtures READ fixtures) Q_PROPERTY(qreal gravityScale READ gravityScale WRITE setGravityScale NOTIFY gravityScaleChanged) public: enum BodyType { Static = 0, Kinematic, Dynamic }; explicit Box2DBody(QQuickItem *parent = 0); ~Box2DBody(); qreal linearDamping() const; void setLinearDamping(qreal _linearDamping); qreal angularDamping() const; void setAngularDamping(qreal _angularDamping); BodyType bodyType() const; void setBodyType(BodyType _bodyType); bool isBullet() const; void setBullet(bool _bullet); bool sleepingAllowed() const; void setSleepingAllowed(bool allowed); bool fixedRotation() const; void setFixedRotation(bool _fixedRotation); bool active() const; void setActive(bool _active); bool awake() const; void setAwake(bool _awake); QPointF linearVelocity() const; void setLinearVelocity(const QPointF &_linearVelocity); qreal gravityScale() const; void setGravityScale(qreal _gravityScale); QQmlListProperty fixtures(); void initialize(b2World *world); void synchronize(); void cleanup(b2World *world); Q_INVOKABLE void applyForce(const QPointF &force,const QPointF &point); Q_INVOKABLE void applyTorque(qreal torque); Q_INVOKABLE void applyLinearImpulse(const QPointF &impulse, const QPointF &point); Q_INVOKABLE QPointF getWorldCenter() const; Q_INVOKABLE float getMass() const; Q_INVOKABLE float GetInertia() const; Q_INVOKABLE QPointF GetLinearVelocityFromWorldPoint(const QPointF &point); Q_INVOKABLE QPointF GetLinearVelocityFromLocalPoint (const QPointF &point); void componentComplete(); b2Body *body() const; b2World * world() const; protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); signals: void linearDampingChanged(); void angularDampingChanged(); void bodyTypeChanged(); void bulletChanged(); void sleepingAllowedChanged(); void fixedRotationChanged(); void linearVelocityChanged(); void bodyCreated(); void gravityScaleChanged(); private slots: void onRotationChanged(); private: b2Body *mBody; b2World *mWorld; b2BodyDef mBodyDef; bool mSynchronizing; bool mInitializePending; QList mFixtures; static void append_fixture(QQmlListProperty *list, Box2DFixture *fixture); static int count_fixture(QQmlListProperty *list); static Box2DFixture * at_fixture(QQmlListProperty *list,int index); qreal mGravityScale; }; #endif // BOX2DBODY_H qml-box2d/box2drevolutejoint.cpp0000664000000000000000000001413412310076376014137 0ustar /* * box2drevolutejoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2drevolutejoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DRevoluteJoint::Box2DRevoluteJoint(QObject *parent) : Box2DJoint(parent), mRevoluteJointDef(), mRevoluteJoint(0), anchorsAuto(true) { } Box2DRevoluteJoint::~Box2DRevoluteJoint() { cleanup(world()); } float Box2DRevoluteJoint::lowerAngle() const { return -mRevoluteJointDef.lowerAngle * 180 / b2_pi; } void Box2DRevoluteJoint::setLowerAngle(float lowerAngle) { float lowerAngleRad = lowerAngle * b2_pi / -180; if (qFuzzyCompare(mRevoluteJointDef.lowerAngle,lowerAngleRad)) return; mRevoluteJointDef.lowerAngle = lowerAngleRad; if (mRevoluteJoint) mRevoluteJoint->SetLimits(lowerAngleRad,mRevoluteJointDef.upperAngle); emit lowerAngleChanged(); } float Box2DRevoluteJoint::upperAngle() const { return -mRevoluteJointDef.upperAngle * 180 / b2_pi; } void Box2DRevoluteJoint::setUpperAngle(float upperAngle) { float upperAngleRad = upperAngle * b2_pi / -180; if (qFuzzyCompare(mRevoluteJointDef.upperAngle,upperAngleRad)) return; mRevoluteJointDef.upperAngle = upperAngleRad; if (mRevoluteJoint) mRevoluteJoint->SetLimits(mRevoluteJointDef.lowerAngle, upperAngleRad); emit upperAngleChanged(); } float Box2DRevoluteJoint::maxMotorTorque() const { return mRevoluteJointDef.maxMotorTorque; } void Box2DRevoluteJoint::setMaxMotorTorque(float maxMotorTorque) { if (qFuzzyCompare(mRevoluteJointDef.maxMotorTorque,maxMotorTorque)) return; mRevoluteJointDef.maxMotorTorque = maxMotorTorque; if (mRevoluteJoint) mRevoluteJoint->SetMaxMotorTorque(maxMotorTorque); emit maxMotorTorqueChanged(); } float Box2DRevoluteJoint::motorSpeed() const { return -mRevoluteJointDef.motorSpeed * 180 / b2_pi; } void Box2DRevoluteJoint::setMotorSpeed(float motorSpeed) { float motorSpeedRad = -motorSpeed * ( b2_pi / 180); if (qFuzzyCompare(mRevoluteJointDef.motorSpeed,motorSpeedRad)) return; mRevoluteJointDef.motorSpeed = motorSpeedRad; if (mRevoluteJoint) mRevoluteJoint->SetMotorSpeed(motorSpeedRad); emit motorSpeedChanged(); } bool Box2DRevoluteJoint::enableLimit() const { return mRevoluteJointDef.enableLimit; } void Box2DRevoluteJoint::setEnableLimit(bool enableLimit) { if (mRevoluteJointDef.enableLimit == enableLimit) return; mRevoluteJointDef.enableLimit = enableLimit; if (mRevoluteJoint) mRevoluteJoint->EnableLimit(enableLimit); emit enableLimitChanged(); } bool Box2DRevoluteJoint::enableMotor() const { return mRevoluteJointDef.enableMotor; } void Box2DRevoluteJoint::setEnableMotor(bool enableMotor) { if (mRevoluteJointDef.enableMotor == enableMotor) return; mRevoluteJointDef.enableMotor = enableMotor; if (mRevoluteJoint) mRevoluteJoint->EnableMotor(enableMotor); emit enableMotorChanged(); } QPointF Box2DRevoluteJoint::localAnchorA() const { return QPointF(mRevoluteJointDef.localAnchorA.x * scaleRatio, mRevoluteJointDef.localAnchorA.y * scaleRatio); } QPointF Box2DRevoluteJoint::localAnchorB() const { return QPointF(mRevoluteJointDef.localAnchorB.x * scaleRatio, mRevoluteJointDef.localAnchorB.y * scaleRatio); } void Box2DRevoluteJoint::setLocalAnchorA(const QPointF &localAnchorA) { mRevoluteJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio,-localAnchorA.y() / scaleRatio); anchorsAuto = false; emit localAnchorAChanged(); } void Box2DRevoluteJoint::setLocalAnchorB(const QPointF &localAnchorB) { mRevoluteJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio,-localAnchorB.y() / scaleRatio); anchorsAuto = false; emit localAnchorBChanged(); } void Box2DRevoluteJoint::nullifyJoint() { mRevoluteJoint = 0; } void Box2DRevoluteJoint::createJoint() { if(anchorsAuto) mRevoluteJointDef.Initialize(bodyA()->body(), bodyB()->body(), bodyA()->body()->GetWorldCenter()); else { mRevoluteJointDef.bodyA = bodyA()->body(); mRevoluteJointDef.bodyB = bodyB()->body(); } mRevoluteJointDef.collideConnected = collideConnected(); mRevoluteJoint = static_cast(world()->CreateJoint(&mRevoluteJointDef)); mRevoluteJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DRevoluteJoint::cleanup(b2World *world) { if(!world) { qWarning() << "RevoluteJoint: There is no world connected"; return; } if (mRevoluteJoint && bodyA() && bodyB()) { mRevoluteJoint->SetUserData(0); world->DestroyJoint(mRevoluteJoint); mRevoluteJoint = 0; } } b2Joint *Box2DRevoluteJoint::GetJoint() { return mRevoluteJoint; } float Box2DRevoluteJoint::getJointAngle() { if(mRevoluteJoint) return -mRevoluteJoint->GetJointAngle() * 180 / b2_pi; return 0.0; } float Box2DRevoluteJoint::getJointSpeed() { if(mRevoluteJoint) return mRevoluteJoint->GetJointSpeed(); return 0.0; } qml-box2d/box2ddistancejoint.cpp0000664000000000000000000001205512310076376014064 0ustar /* * box2ddistancejoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2ddistancejoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DDistanceJoint::Box2DDistanceJoint(QObject *parent) : Box2DJoint(parent), mDistanceJointDef(), mDistanceJoint(0), anchorsAuto(true) { } Box2DDistanceJoint::~Box2DDistanceJoint() { cleanup(world()); } float Box2DDistanceJoint::length() const { if(mDistanceJoint) return mDistanceJoint->GetLength(); return mDistanceJointDef.length; } void Box2DDistanceJoint::setLength(float _length) { if (qFuzzyCompare(length(),_length / scaleRatio)) return; mDistanceJointDef.length = _length / scaleRatio; if (mDistanceJoint) mDistanceJoint->SetLength(mDistanceJointDef.length); emit lengthChanged(); } float Box2DDistanceJoint::frequencyHz() const { if(mDistanceJoint) return mDistanceJoint->GetFrequency(); return mDistanceJointDef.frequencyHz; } void Box2DDistanceJoint::setFrequencyHz(float _frequencyHz) { if (frequencyHz() == _frequencyHz) return; mDistanceJointDef.frequencyHz = _frequencyHz; if (mDistanceJoint) mDistanceJoint->SetFrequency(_frequencyHz); emit frequencyHzChanged(); } float Box2DDistanceJoint::dampingRatio() const { if(mDistanceJoint) mDistanceJoint->GetDampingRatio(); return mDistanceJointDef.dampingRatio; } void Box2DDistanceJoint::setDampingRatio(float _dampingRatio) { if (dampingRatio() == _dampingRatio) return; mDistanceJointDef.dampingRatio = _dampingRatio; if (mDistanceJoint) mDistanceJoint->SetDampingRatio(_dampingRatio); emit dampingRatioChanged(); } QPointF Box2DDistanceJoint::localAnchorA() const { return QPointF(mDistanceJointDef.localAnchorA.x * scaleRatio, -mDistanceJointDef.localAnchorA.y * scaleRatio); } void Box2DDistanceJoint::setLocalAnchorA(const QPointF &localAnchorA) { mDistanceJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio, -localAnchorA.y() / scaleRatio); anchorsAuto = false; emit localAnchorBChanged(); } QPointF Box2DDistanceJoint::localAnchorB() const { return QPointF(mDistanceJointDef.localAnchorB.x * scaleRatio, -mDistanceJointDef.localAnchorB.y * scaleRatio); } void Box2DDistanceJoint::setLocalAnchorB(const QPointF &localAnchorB) { mDistanceJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio, -localAnchorB.y() / scaleRatio); anchorsAuto = false; emit localAnchorBChanged(); } void Box2DDistanceJoint::nullifyJoint() { mDistanceJoint = 0; } void Box2DDistanceJoint::createJoint() { if(anchorsAuto) mDistanceJointDef.Initialize(bodyA()->body(), bodyB()->body(), bodyA()->body()->GetWorldCenter(), bodyB()->body()->GetWorldCenter()); else { mDistanceJointDef.bodyA = bodyA()->body(); mDistanceJointDef.bodyB = bodyB()->body(); } mDistanceJointDef.collideConnected = collideConnected(); mDistanceJoint = static_cast (world()->CreateJoint(&mDistanceJointDef)); mDistanceJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DDistanceJoint::cleanup(b2World *world) { if(!world) { qWarning() << "DistanceJoint: There is no world connected"; return; } if (mDistanceJoint && bodyA() && bodyB()) { mDistanceJoint->SetUserData(0); world->DestroyJoint(mDistanceJoint); mDistanceJoint = 0; } } b2Joint *Box2DDistanceJoint::GetJoint() { return mDistanceJoint; } QPointF Box2DDistanceJoint::GetReactionForce(float32 inv_dt) const { if(mDistanceJoint) { b2Vec2 point = mDistanceJoint->GetReactionForce(inv_dt); return QPointF(point.x * scaleRatio,point.y * scaleRatio); } return QPointF(); } float Box2DDistanceJoint::GetReactionTorque(float32 inv_dt) const { if(mDistanceJoint) return mDistanceJoint->GetReactionTorque(inv_dt); return 0.0f; } qml-box2d/box2ddistancejoint.h0000664000000000000000000000532112310072714013517 0ustar /* * box2ddistancejoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DDISTANCEJOINT_H #define BOX2DDISTANCEJOINT_H #include "box2djoint.h" #include class b2World; class b2DistanceJoint; class b2DistanceJointDef; class Box2DDistanceJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float length READ length WRITE setLength NOTIFY lengthChanged) Q_PROPERTY(float frequencyHz READ frequencyHz WRITE setFrequencyHz NOTIFY frequencyHzChanged) Q_PROPERTY(float dampingRatio READ dampingRatio WRITE setDampingRatio NOTIFY dampingRatioChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DDistanceJoint(QObject *parent = 0); ~Box2DDistanceJoint(); float length() const; void setLength(float length); float frequencyHz() const; void setFrequencyHz(float frequencyHz); float dampingRatio() const; void setDampingRatio(float dampingRatio); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); Q_INVOKABLE QPointF GetReactionForce(float32 inv_dt) const; Q_INVOKABLE float GetReactionTorque(float32 inv_dt) const; signals: void lengthChanged(); void frequencyHzChanged(); void dampingRatioChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2DistanceJointDef mDistanceJointDef; b2DistanceJoint *mDistanceJoint; bool anchorsAuto; }; #endif // BOX2DDISTANCEJOINT_H qml-box2d/box2djoint.cpp0000664000000000000000000000653212310076376012354 0ustar /* * box2djoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2djoint.h" #include "box2dbody.h" #include "box2dworld.h" Box2DJoint::Box2DJoint(QObject *parent) : QObject(parent), mInitializePending(false), mWorld(0), mCollideConnected(false), mBodyA(0), mBodyB(0) { } bool Box2DJoint::collideConnected() const { return mCollideConnected; } void Box2DJoint::setCollideConnected(bool collideConnected) { if (mCollideConnected == collideConnected) return; mCollideConnected = collideConnected; emit collideConnectedChanged(); } Box2DWorld *Box2DJoint::box2DWorld() const { return mWorld; } void Box2DJoint::setWorld(Box2DWorld *world) { if (mWorld == world || world == NULL) return; mWorld = world; emit worldChanged(); initialize(); } Box2DBody *Box2DJoint::bodyA() const { return mBodyA; } void Box2DJoint::setBodyA(Box2DBody *bodyA) { if (mBodyA) return; if (bodyA->body() != NULL) { mBodyA = bodyA; emit bodyAChanged(); initialize(); } else connect(bodyA, SIGNAL(bodyCreated()), this, SLOT(bodyACreated())); } Box2DBody *Box2DJoint::bodyB() const { return mBodyB; } void Box2DJoint::setBodyB(Box2DBody *bodyB) { if (mBodyB) return; if (bodyB->body() != NULL) { mBodyB = bodyB; emit bodyBChanged(); initialize(); } else connect(bodyB, SIGNAL(bodyCreated()), this, SLOT(bodyBCreated())); } void Box2DJoint::initialize() { if (!mBodyA || !mBodyB) { // When components are created dynamically, they get their parent // assigned before they have been completely initialized. In that case // we need to delay initialization. mInitializePending = true; return; } if(mBodyA->world() != mBodyB->world()) qWarning() << "bodyA and bodyB from different worlds"; else createJoint(); } b2World *Box2DJoint::world() const { if(mWorld) return mWorld->world(); else if(mBodyA && mBodyA->world()) return mBodyA->world(); else if(mBodyB && mBodyB->world()) return mBodyB->world(); return NULL; } void Box2DJoint::bodyACreated() { mBodyA = static_cast(sender()); emit bodyAChanged(); initialize(); } void Box2DJoint::bodyBCreated() { mBodyB = static_cast(sender()); emit bodyBChanged(); initialize(); } qml-box2d/debian/0000775000000000000000000000000012310410576010774 5ustar qml-box2d/debian/compat0000664000000000000000000000000212310100035012154 0ustar 9 qml-box2d/debian/rules0000775000000000000000000000020012310100035012026 0ustar #!/usr/bin/make -f # -*- makefile -*- # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ --fail-missing qml-box2d/debian/copyright0000664000000000000000000000312112310100035012706 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: qml-box2d Source: https://github.com/kenvandine/qml-box2d Files: * Copyright: 2006-2011 Erin Catto http://www.box2d.org 2010-2011 Thorbjørn Lindeijer 2011 Alessandro Portale 2011 Antonio Aloisio 2011 Antti Krats 2011 Daker Fernandes Pinheiro 2011 Joonas Erkinheimo 2011 Markus Kivioja 2011 Tan Miaoqing 2012 Adriano Rezende License: zlib/libpng 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. qml-box2d/debian/changelog0000664000000000000000000000343512310410576012653 0ustar qml-box2d (0.1~git20140412) trusty; urgency=medium * New upstream snapshot - Updated to Box2D 2.3.0 - Added Edge and Chain shapes - Added FrictionJoint - Added GearJoint - Added MotorJoint - Added MouseJoint - Added PulleyJoint - Added RopeJoint - Added WeldJoint - Added WheelJoint - Fixed DebugDraw module for correct work in Qt5 - Corrected installation rules for Qt5 - Fixed RevoluteJoint (added localAnchorB, angular units changed to use degree) - Fixed RevoluteJoint (adjusted linear units to pixels), added OnInitialized event to World - Fixed PrismaticJoint (adjusted linear units to pixels), added anchor points properties - Added basic ability to scale fixtures - Fixed a fault caused to crash when Body is not direct child of World (for example, inside Repeater etc.) - Added some missed functions to Body - Added some missed functions/small improvements in Body, shapes etc. - Added some missed properties to Body - Changed the version to 1.1 due to incompatibility with previous version (metres/pixels, degrees/radians etc.) - Fixed a defect with parent losing if a Body is not direct child of world. Making world property of Joint is unnecessary - Revert "Fixed a defect with parent losing if a Body is not direct child of world. Making world property of Joint is unnecessary" - Fixed getJointAngle() returned value - Fixed world gravity value. * debian/control * Renamed plugin binary packaging to match upstream API version -- Ken VanDine Wed, 12 Mar 2014 10:58:27 -0400 qml-box2d (0.1~git20131115) trusty; urgency=low * New package -- Ken VanDine Thu, 14 Nov 2013 12:23:03 -0500 qml-box2d/debian/control0000664000000000000000000000114512310100035012362 0ustar Source: qml-box2d Priority: extra Maintainer: Ken VanDine Build-Depends: debhelper (>= 9), libbox2d-dev, pkg-config, qt5-default, qtbase5-dev, qtdeclarative5-dev, qtdeclarative5-qtquick2-plugin, Standards-Version: 3.9.5 Section: libs Homepage: https://github.com/bjorn/qml-box2d Package: qtdeclarative5-box2d1.1 Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, Description: QML Bindings for the Box2d physics engine QML Bindings for the Box2d physics engine qml-box2d/box2dplugin.cpp0000664000000000000000000000637612310072714012525 0ustar /* * box2dplugin.cpp * Copyright (c) 2010-2011 Thorbjørn Lindeijer * Copyright (c) 2011 Daker Fernandes Pinheiro * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2dplugin.h" #include "box2dworld.h" #include "box2dbody.h" #include "box2ddebugdraw.h" #include "box2dfixture.h" #include "box2djoint.h" #include "box2ddistancejoint.h" #include "box2dprismaticjoint.h" #include "box2drevolutejoint.h" #include "box2dmotorjoint.h" #include "box2dweldjoint.h" #include "box2dpulleyjoint.h" #include "box2dfrictionjoint.h" #include "box2dwheeljoint.h" #include "box2dmousejoint.h" #include "box2dgearjoint.h" #include "box2dropejoint.h" Box2DPlugin::Box2DPlugin(QObject *parent) : QQmlExtensionPlugin(parent) { } void Box2DPlugin::registerTypes(const char *uri) { Q_ASSERT(QLatin1String(uri) == QLatin1String("Box2D")); qmlRegisterType(uri, 1, 1, "World"); qmlRegisterType(uri, 1, 1, "Body"); qmlRegisterUncreatableType(uri, 1,0, "Fixture", QStringLiteral("Base type for Box, Circle etc.")); qmlRegisterType(uri, 1, 1, "Box"); qmlRegisterType(uri, 1, 1, "Circle"); qmlRegisterType(uri, 1, 1, "Polygon"); qmlRegisterType(uri, 1, 1, "Chain"); qmlRegisterType(uri, 1, 1, "Edge"); qmlRegisterType(uri, 1, 1, "DebugDraw"); qmlRegisterUncreatableType(uri, 1, 1, "Joint", QStringLiteral("Base type for DistanceJoint, RevoluteJoint etc.")); qmlRegisterType(uri, 1, 1, "DistanceJoint"); qmlRegisterType(uri, 1, 1, "PrismaticJoint"); qmlRegisterType(uri, 1, 1, "RevoluteJoint"); qmlRegisterType(uri, 1, 1, "MotorJoint"); qmlRegisterType(uri, 1, 1, "WeldJoint"); qmlRegisterType(uri, 1, 1, "PulleyJoint"); qmlRegisterType(uri, 1, 1, "FrictionJoint"); qmlRegisterType(uri, 1, 1, "WheelJoint"); qmlRegisterType(uri, 1, 1, "MouseJoint"); qmlRegisterType(uri, 1, 1, "GearJoint"); qmlRegisterType(uri, 1, 1, "RopeJoint"); } qml-box2d/README0000644000000000000000000000200412241175670010432 0ustar QML Box2D plugin ---------------- This plugin is meant to be installed to your Qt/imports directory, or shipped in a directory of which the parent is added as import path. The goal is to expose the functionality of Box2D as QML components, in order to make it easy to write physics based games in QML. INSTALLING qmake make make install (goes to Qt's import path, run with sudo if necessary) RUNNING THE EXAMPLE qmlviewer examples/boxes/boxes.qml DEPLOYMENT Support for deployment to mobile devices like the N900 and N8 is being worked on. USING QT CREATOR For running you can use a "Custom Executable" configuration set to run "qmlviewer" with the right parameters. When you have write permissions to Qt's import path, it can be convenient to add a deployment step to your run settings: * Go to Projects -> box2d -> Run Settings * Choose Add Deploy Step -> Make * Enter "install" under "Make arguments" This will make sure that before running, the version of the plugin is updated in Qt's import path. qml-box2d/box2dbody.cpp0000664000000000000000000002570012310072714012154 0ustar /* * box2dbody.cpp * Copyright (c) 2010-2011 Thorbjørn Lindeijer * Copyright (c) 2011 Daker Fernandes Pinheiro * Copyright (c) 2011 Tan Miaoqing * Copyright (c) 2011 Antonio Aloisio * Copyright (c) 2011 Alessandro Portale * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Antti Krats * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2dbody.h" #include "box2dfixture.h" #include "box2dworld.h" Box2DBody::Box2DBody(QQuickItem *parent) : QQuickItem(parent), mBody(0), mWorld(0), mBodyDef(), mSynchronizing(false), mInitializePending(false), mGravityScale(1.0) { setTransformOrigin(TopLeft); connect(this, SIGNAL(rotationChanged()), SLOT(onRotationChanged())); } Box2DBody::~Box2DBody() { cleanup(mWorld); } qreal Box2DBody::linearDamping() const { if(mBody) return mBody->GetLinearDamping(); return mBodyDef.linearDamping; } void Box2DBody::setLinearDamping(qreal _linearDamping) { if (linearDamping() == _linearDamping) return; if (mBody) mBody->SetLinearDamping(_linearDamping); else mBodyDef.linearDamping = _linearDamping; emit linearDampingChanged(); } qreal Box2DBody::angularDamping() const { if(mBody) return mBody->GetAngularDamping(); return mBodyDef.angularDamping; } void Box2DBody::setAngularDamping(qreal _angularDamping) { if (angularDamping() == _angularDamping) return; if (mBody) mBody->SetAngularDamping(_angularDamping); else mBodyDef.angularDamping = _angularDamping; emit angularDampingChanged(); } Box2DBody::BodyType Box2DBody::bodyType() const { if(mBody) mBody->GetType(); return static_cast(mBodyDef.type); } void Box2DBody::setBodyType(BodyType _bodyType) { if (bodyType() == _bodyType) return; if (mBody) mBody->SetType(static_cast(_bodyType)); else mBodyDef.type = static_cast(_bodyType); emit bodyTypeChanged(); } bool Box2DBody::isBullet() const { if(mBody) mBody->IsBullet(); return mBodyDef.bullet; } void Box2DBody::setBullet(bool _bullet) { if (isBullet() == _bullet) return; if (mBody) mBody->SetBullet(_bullet); else mBodyDef.bullet = _bullet; emit bulletChanged(); } bool Box2DBody::sleepingAllowed() const { if(mBody) mBody->IsSleepingAllowed(); return mBodyDef.allowSleep; } void Box2DBody::setSleepingAllowed(bool allowed) { if (sleepingAllowed() == allowed) return; if (mBody) mBody->SetSleepingAllowed(allowed); else mBodyDef.allowSleep = allowed; emit sleepingAllowedChanged(); } bool Box2DBody::fixedRotation() const { if(mBody) mBody->IsFixedRotation(); return mBodyDef.fixedRotation; } void Box2DBody::setFixedRotation(bool _fixedRotation) { if (fixedRotation() == _fixedRotation) return; if (mBody) mBody->SetFixedRotation(_fixedRotation); else mBodyDef.fixedRotation = _fixedRotation; emit fixedRotationChanged(); } bool Box2DBody::active() const { if(mBody) mBody->IsActive(); return mBodyDef.active; } void Box2DBody::setActive(bool _active) { if (active() == _active) return; if (mBody) mBody->SetActive(_active); else mBodyDef.active = _active; } bool Box2DBody::awake() const { if(mBody) mBody->IsAwake(); return mBodyDef.awake; } void Box2DBody::setAwake(bool _awake) { if (awake() == _awake) return; if (mBody) mBody->SetAwake(_awake); else mBodyDef.awake = _awake; } QPointF Box2DBody::linearVelocity() const { b2Vec2 point; if(mBody) point = mBody->GetLinearVelocity(); else point = mBodyDef.linearVelocity; return QPointF(point.x * scaleRatio,-point.y * scaleRatio); } void Box2DBody::setLinearVelocity(const QPointF &_linearVelocity) { if (linearVelocity() == _linearVelocity) return; b2Vec2 point(_linearVelocity.x() / scaleRatio, -_linearVelocity.y() / scaleRatio); if (mBody) mBody->SetLinearVelocity(point); else mBodyDef.linearVelocity = point; emit linearVelocityChanged(); } qreal Box2DBody::gravityScale() const { if(mBody) return mBody->GetGravityScale(); return mGravityScale; } void Box2DBody::setGravityScale(qreal _gravityScale) { if(qFuzzyCompare(gravityScale(),_gravityScale)) return; mGravityScale = _gravityScale; if(mBody) { mBody->SetGravityScale(_gravityScale); emit gravityScaleChanged(); } } QQmlListProperty Box2DBody::fixtures() { return QQmlListProperty(this, 0, &Box2DBody::append_fixture, &Box2DBody::count_fixture, &Box2DBody::at_fixture, 0); } void Box2DBody::append_fixture(QQmlListProperty *list, Box2DFixture *fixture) { Box2DBody *body = static_cast(list->object); fixture->setParentItem(body); body->mFixtures.append(fixture); } int Box2DBody::count_fixture(QQmlListProperty *list) { Box2DBody *body = static_cast(list->object); return body->mFixtures.length(); } Box2DFixture * Box2DBody::at_fixture(QQmlListProperty *list, int index) { Box2DBody *body = static_cast(list->object); if(index < 0 || index >= body->mFixtures.length()) return NULL; return body->mFixtures.at(index); } void Box2DBody::initialize(b2World *world) { mWorld = world; if (!isComponentComplete()) { // When components are created dynamically, they get their parent // assigned before they have been completely initialized. In that case // we need to delay initialization. mInitializePending = true; return; } mBodyDef.position.Set(x() / scaleRatio, -y() / scaleRatio); mBodyDef.angle = -(rotation() * (2 * b2_pi)) / 360.0; mBody = world->CreateBody(&mBodyDef); mInitializePending = false; if(mGravityScale != 1.0) mBody->SetGravityScale(mGravityScale); foreach (Box2DFixture *fixture, mFixtures) fixture->createFixture(mBody); mBody->SetUserData(this); emit bodyCreated(); } /** * Synchronizes the state of this body with the internal Box2D state. */ void Box2DBody::synchronize() { Q_ASSERT(mBody); mSynchronizing = true; const b2Vec2 position = mBody->GetPosition(); const float32 angle = mBody->GetAngle(); const qreal newX = position.x * scaleRatio; const qreal newY = -position.y * scaleRatio; const qreal newRotation = -(angle * 180.0) / b2_pi; if (!qFuzzyCompare(x(), newX)) setX(newX); if (!qFuzzyCompare(y(), newY)) setY(newY); if (!qFuzzyCompare(rotation(), newRotation)) setRotation(newRotation); mSynchronizing = false; } void Box2DBody::cleanup(b2World *world) { if(mBody) world->DestroyBody(mBody); mBody = 0; mWorld = 0; } void Box2DBody::componentComplete() { QQuickItem::componentComplete(); if (mInitializePending) initialize(mWorld); } b2Body *Box2DBody::body() const { return mBody; } b2World *Box2DBody::world() const { return mWorld; } void Box2DBody::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { if (!mSynchronizing && mBody) { if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y()) { mBody->SetTransform(b2Vec2(newGeometry.x() / scaleRatio,-newGeometry.y() / scaleRatio),mBody->GetAngle()); } } QQuickItem::geometryChanged(newGeometry, oldGeometry); } void Box2DBody::onRotationChanged() { if (!mSynchronizing && mBody) { mBody->SetTransform(mBody->GetPosition(), (rotation() * b2_pi) / -180.0); } } void Box2DBody::applyLinearImpulse(const QPointF &impulse, const QPointF &point) { if (mBody) { mBody->ApplyLinearImpulse(b2Vec2(impulse.x() / scaleRatio, -impulse.y() / scaleRatio), b2Vec2(point.x() / scaleRatio, -point.y() / scaleRatio),true); } } void Box2DBody::applyTorque(qreal torque) { if (mBody) mBody->ApplyTorque(torque,true); } QPointF Box2DBody::getWorldCenter() const { QPointF worldCenter; if (mBody) { const b2Vec2 ¢er = mBody->GetWorldCenter(); worldCenter.setX(center.x * scaleRatio); worldCenter.setY(-center.y * scaleRatio); } return worldCenter; } void Box2DBody::applyForce(const QPointF &force, const QPointF &point) { if (mBody) { mBody->ApplyForce(b2Vec2(force.x() / scaleRatio, -force.y() / scaleRatio), b2Vec2(point.x() / scaleRatio, -point.y() / scaleRatio),true); } } float Box2DBody::getMass() const { if (mBody) return mBody->GetMass() * scaleRatio; return 0.0; } float Box2DBody::GetInertia() const { if(mBody) return mBody->GetInertia(); return 0.0; } QPointF Box2DBody::GetLinearVelocityFromWorldPoint(const QPointF &point) { const b2Vec2 &b2Point = mBody->GetLinearVelocityFromWorldPoint(b2Vec2(point.x() / scaleRatio, -point.y() / scaleRatio)); return QPointF(b2Point.x * scaleRatio,-b2Point.y * scaleRatio); } QPointF Box2DBody::GetLinearVelocityFromLocalPoint(const QPointF &point) { const b2Vec2 &b2Point = mBody->GetLinearVelocityFromLocalPoint(b2Vec2(point.x() / scaleRatio, -point.y() / scaleRatio)); return QPointF(b2Point.x * scaleRatio,-b2Point.y * scaleRatio); } qml-box2d/box2ddestructionlistener.h0000644000000000000000000000273512241175670015006 0ustar /* * box2ddestructionlistener.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DDESTRUCTIONLISTENER_H #define BOX2DDESTRUCTIONLISTENER_H #include #include class Box2DFixture; class Box2DDestructionListener : public QObject, public b2DestructionListener { Q_OBJECT public: explicit Box2DDestructionListener(QObject *parent = 0); void SayGoodbye(b2Joint *joint); void SayGoodbye(b2Fixture *fixture); signals: void fixtureDestroyed(Box2DFixture *fixture); }; #endif // BOX2DDESTRUCTIONLISTENER_H qml-box2d/box2dweldjoint.h0000664000000000000000000000513712310072714012665 0ustar /* * box2ddistancejoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2WELDJOINT_H #define BOX2WELDJOINT_H #include "box2djoint.h" #include class b2World; class b2WeldJoint; class b2WeldJointDef; class Box2DWeldJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float referenceAngle READ referenceAngle WRITE setReferenceAngle NOTIFY referenceAngleChanged) Q_PROPERTY(float frequencyHz READ frequencyHz WRITE setFrequencyHz NOTIFY frequencyHzChanged) Q_PROPERTY(float dampingRatio READ dampingRatio WRITE setDampingRatio NOTIFY dampingRatioChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DWeldJoint(QObject *parent = 0); ~Box2DWeldJoint(); float referenceAngle() const; void setReferenceAngle(float referenceAngle); float frequencyHz() const; void setFrequencyHz(float frequencyHz); float dampingRatio() const; void setDampingRatio(float dampingRatio); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); signals: void referenceAngleChanged(); void frequencyHzChanged(); void dampingRatioChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2WeldJointDef mWeldJointDef; b2WeldJoint * mWeldJoint; bool anchorsAuto; }; #endif // BOX2WELDJOINT_H qml-box2d/box2dropejoint.cpp0000664000000000000000000000736412310076376013246 0ustar /* * box2drevolutejoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dropejoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DRopeJoint::Box2DRopeJoint(QObject *parent) : Box2DJoint(parent), mRopeJointDef(), mRopeJoint(0) { } Box2DRopeJoint::~Box2DRopeJoint() { cleanup(world()); } float Box2DRopeJoint::maxLength() const { if(mRopeJoint) return mRopeJoint->GetMaxLength() * scaleRatio; return mRopeJointDef.maxLength * scaleRatio; } void Box2DRopeJoint::setMaxLength(float _maxLength) { if(qFuzzyCompare(maxLength(),_maxLength)) return; mRopeJointDef.maxLength = _maxLength / scaleRatio; if(mRopeJoint) mRopeJoint->SetMaxLength(mRopeJointDef.maxLength); emit maxLengthChanged(); } QPointF Box2DRopeJoint::localAnchorA() const { return QPointF(mRopeJointDef.localAnchorA.x * scaleRatio, mRopeJointDef.localAnchorA.y * scaleRatio); } void Box2DRopeJoint::setLocalAnchorA(const QPointF &localAnchorA) { mRopeJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio, -localAnchorA.y() / scaleRatio); emit localAnchorAChanged(); } QPointF Box2DRopeJoint::localAnchorB() const { return QPointF(mRopeJointDef.localAnchorB.x * scaleRatio, mRopeJointDef.localAnchorB.y * scaleRatio); } void Box2DRopeJoint::setLocalAnchorB(const QPointF &localAnchorB) { mRopeJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio, -localAnchorB.y() / scaleRatio); emit localAnchorBChanged(); } void Box2DRopeJoint::nullifyJoint() { mRopeJoint = 0; } void Box2DRopeJoint::createJoint() { mRopeJointDef.bodyA = bodyA()->body(); mRopeJointDef.bodyB = bodyB()->body(); mRopeJointDef.collideConnected = collideConnected(); mRopeJoint = static_cast(world()->CreateJoint(&mRopeJointDef)); mRopeJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DRopeJoint::cleanup(b2World *world) { if(!world) { qWarning() << "RopeJoint: There is no world connected"; return; } if (mRopeJoint && bodyA() && bodyB()) { mRopeJoint->SetUserData(0); world->DestroyJoint(mRopeJoint); mRopeJoint = 0; } } b2Joint *Box2DRopeJoint::GetJoint() { return mRopeJoint; } QPointF Box2DRopeJoint::GetReactionForce(float32 inv_dt) const { if(mRopeJoint) { b2Vec2 point = mRopeJoint->GetReactionForce(inv_dt); return QPointF(point.x * scaleRatio,point.y * scaleRatio); } return QPointF(); } float Box2DRopeJoint::GetReactionTorque(float32 inv_dt) const { if(mRopeJoint) return mRopeJoint->GetReactionTorque(inv_dt); return 0.0f; } qml-box2d/box2djoint.h0000664000000000000000000000540112310072714012003 0ustar /* * box2djoint.h * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Thorbjørn Lindeijer * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DJOINT_H #define BOX2DJOINT_H #include #include #include class b2World; class Box2DBody; class Box2DWorld; class Box2DJoint : public QObject { Q_OBJECT Q_PROPERTY(bool collideConnected READ collideConnected WRITE setCollideConnected NOTIFY collideConnectedChanged) Q_PROPERTY(Box2DWorld *world READ box2DWorld WRITE setWorld NOTIFY worldChanged) Q_PROPERTY(Box2DBody *bodyA READ bodyA WRITE setBodyA NOTIFY bodyAChanged) Q_PROPERTY(Box2DBody *bodyB READ bodyB WRITE setBodyB NOTIFY bodyBChanged) public: explicit Box2DJoint(QObject *parent = 0); bool collideConnected() const; void setCollideConnected(bool collideConnected); Box2DWorld *box2DWorld() const; void setWorld(Box2DWorld *world); Box2DBody *bodyA() const; void setBodyA(Box2DBody *bodyA); Box2DBody *bodyB() const; void setBodyB(Box2DBody *bodyB); void initialize(); virtual void nullifyJoint() = 0; virtual void cleanup(b2World *world) = 0; virtual b2Joint * GetJoint() = 0; protected: virtual void createJoint() = 0; b2World *world() const; private slots: void bodyACreated(); void bodyBCreated(); signals: void collideConnectedChanged(); void worldChanged(); void bodyAChanged(); void bodyBChanged(); void created(); protected: bool mInitializePending; private: Box2DWorld *mWorld; bool mCollideConnected; Box2DBody *mBodyA; Box2DBody *mBodyB; }; /** * Convenience function to get the Box2DJoint wrapping a b2Joint. */ inline Box2DJoint *toBox2DJoint(b2Joint *joint) { if(!joint) return 0; return static_cast(joint->GetUserData()); } #endif // BOX2DJOINT_H qml-box2d/box2dplugin.h0000644000000000000000000000267412241175670012175 0ustar /* * box2dplugin.h * Copyright (c) 2010 Thorbjørn Lindeijer * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DPLUGIN_H #define BOX2DPLUGIN_H #include /** * A plugin that exposes Box2D to QML in the form of declarative items. */ class Box2DPlugin : public QQmlExtensionPlugin { Q_OBJECT #if !defined(STATIC_PLUGIN_BOX2D) Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") #endif public: explicit Box2DPlugin(QObject *parent = 0); void registerTypes(const char *uri); }; #endif // BOX2DPLUGIN_H qml-box2d/box2dpulleyjoint.cpp0000664000000000000000000001365312310076376013611 0ustar /* * box2dprismaticjoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dpulleyjoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DPulleyJoint::Box2DPulleyJoint(QObject *parent) : Box2DJoint(parent), mPulleyJointDef(), mPulleyJoint(0) { } Box2DPulleyJoint::~Box2DPulleyJoint() { cleanup(world()); } float Box2DPulleyJoint::lengthA() const { if(mPulleyJoint) return mPulleyJoint->GetLengthA() * scaleRatio; return mPulleyJointDef.lengthA * scaleRatio; } void Box2DPulleyJoint::setLengthA(float lengthA) { if(mPulleyJointDef.lengthA * scaleRatio == lengthA) return; mPulleyJointDef.lengthA = lengthA / scaleRatio; emit lengthAChanged(); } float Box2DPulleyJoint::lengthB() const { if(mPulleyJoint) return mPulleyJoint->GetLengthB() * scaleRatio; return mPulleyJointDef.lengthB * scaleRatio; } void Box2DPulleyJoint::setLengthB(float lengthB) { if(mPulleyJointDef.lengthB * scaleRatio == lengthB) return; mPulleyJointDef.lengthB = lengthB / scaleRatio; emit lengthBChanged(); } float Box2DPulleyJoint::ratio() const { if(mPulleyJoint) return mPulleyJoint->GetRatio(); return mPulleyJointDef.ratio; } void Box2DPulleyJoint::setRatio(float ratio) { if(mPulleyJointDef.ratio == ratio) return; mPulleyJointDef.ratio = ratio; emit ratioChanged(); } QPointF Box2DPulleyJoint::groundAnchorA() const { if(mPulleyJoint) QPointF(mPulleyJoint->GetGroundAnchorA().x * scaleRatio,-mPulleyJoint->GetGroundAnchorA().y * scaleRatio); return QPointF(mPulleyJointDef.groundAnchorA.x * scaleRatio, mPulleyJointDef.groundAnchorA.y * scaleRatio); } void Box2DPulleyJoint::setGroundAnchorA(const QPointF &groundAnchorA) { mPulleyJointDef.groundAnchorA = b2Vec2(groundAnchorA.x() / scaleRatio,-groundAnchorA.y() / scaleRatio); emit groundAnchorAChanged(); } QPointF Box2DPulleyJoint::groundAnchorB() const { if(mPulleyJoint) QPointF(mPulleyJoint->GetGroundAnchorB().x * scaleRatio,-mPulleyJoint->GetGroundAnchorB().y * scaleRatio); return QPointF(mPulleyJointDef.groundAnchorB.x * scaleRatio, mPulleyJointDef.groundAnchorB.y * scaleRatio); } void Box2DPulleyJoint::setGroundAnchorB(const QPointF &groundAnchorB) { mPulleyJointDef.groundAnchorB = b2Vec2(groundAnchorB.x() / scaleRatio,-groundAnchorB.y() / scaleRatio); emit groundAnchorBChanged(); } QPointF Box2DPulleyJoint::localAnchorA() const { if(mPulleyJoint) QPointF(mPulleyJoint->GetAnchorA().x * scaleRatio,-mPulleyJoint->GetAnchorA().y * scaleRatio); return QPointF(mPulleyJointDef.localAnchorA.x * scaleRatio, mPulleyJointDef.localAnchorA.y * scaleRatio); } void Box2DPulleyJoint::setLocalAnchorA(const QPointF &localAnchorA) { mPulleyJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio,-localAnchorA.y() / scaleRatio); emit localAnchorAChanged(); } QPointF Box2DPulleyJoint::localAnchorB() const { if(mPulleyJoint) QPointF(mPulleyJoint->GetAnchorB().x * scaleRatio,-mPulleyJoint->GetAnchorB().y * scaleRatio); return QPointF(mPulleyJointDef.localAnchorB.x * scaleRatio, mPulleyJointDef.localAnchorB.y * scaleRatio); } void Box2DPulleyJoint::setLocalAnchorB(const QPointF &localAnchorB) { mPulleyJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio,-localAnchorB.y() / scaleRatio); emit localAnchorBChanged(); } void Box2DPulleyJoint::nullifyJoint() { mPulleyJoint = 0; } void Box2DPulleyJoint::createJoint() { if(qFuzzyCompare(mPulleyJointDef.lengthA,0.0f) || qFuzzyCompare(mPulleyJointDef.lengthB,0.0f)) { qWarning() << "PulleyJoint: the joint length cannot be zero"; return; } mPulleyJointDef.bodyA = bodyA()->body(); mPulleyJointDef.bodyB = bodyB()->body(); mPulleyJointDef.collideConnected = collideConnected(); mPulleyJoint = static_cast(world()->CreateJoint(&mPulleyJointDef)); mPulleyJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DPulleyJoint::cleanup(b2World *world) { if(!world) { qWarning() << "PulleyJoint: There is no world connected"; return; } if (mPulleyJoint && bodyA() && bodyB()) { mPulleyJoint->SetUserData(0); world->DestroyJoint(mPulleyJoint); mPulleyJoint = 0; } } b2Joint *Box2DPulleyJoint::GetJoint() { return mPulleyJoint; } float Box2DPulleyJoint::GetCurrentLengthA() const { if(mPulleyJoint) return mPulleyJoint->GetCurrentLengthA() * scaleRatio; return 0.0f; } float Box2DPulleyJoint::GetCurrentLengthB() const { if(mPulleyJoint) return mPulleyJoint->GetCurrentLengthB() * scaleRatio; return 0.0f; } QPointF Box2DPulleyJoint::GetReactionForce(float32 inv_dt) const { if(mPulleyJoint) { b2Vec2 point = mPulleyJoint->GetReactionForce(inv_dt); return QPointF(point.x * scaleRatio,point.y * scaleRatio); } return QPointF(); } float Box2DPulleyJoint::GetReactionTorque(float32 inv_dt) const { if(mPulleyJoint) return mPulleyJoint->GetReactionTorque(inv_dt); return 0.0f; } qml-box2d/box2dworld.h0000664000000000000000000001020212310072714012002 0ustar /* * box2dworld.h * Copyright (c) 2010 Thorbjørn Lindeijer * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2012 Adriano Rezende * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DWORLD_H #define BOX2DWORLD_H #include #include #include class Box2DBody; class Box2DFixture; class Box2DJoint; class ContactListener; class Box2DDestructionListener; class b2World; // TODO: Maybe turn this into a property of the world, though it can't be // changed dynamically. static const float scaleRatio = 32.0f; // 32 pixels in one meter /** * Wrapper class around a Box2D world. */ class Box2DWorld : public QQuickItem { Q_OBJECT Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) Q_PROPERTY(float timeStep READ timeStep WRITE setTimeStep) Q_PROPERTY(int velocityIterations READ velocityIterations WRITE setVelocityIterations) Q_PROPERTY(int positionIterations READ positionIterations WRITE setPositionIterations) Q_PROPERTY(int frameTime READ frameTime WRITE setFrameTime) Q_PROPERTY(QPointF gravity READ gravity WRITE setGravity NOTIFY gravityChanged) public: explicit Box2DWorld(QQuickItem *parent = 0); ~Box2DWorld(); /** * The amount of time to step through each frame in seconds. * By default it is 1 / 60. */ float timeStep() const { return mTimeStep; } void setTimeStep(float timeStep) { mTimeStep = timeStep; } bool isRunning() const { return mIsRunning; } void setRunning(bool running); /** * The number of velocity iterations used to process one step. * 10 by default. */ int velocityIterations() const { return mVelocityIterations; } void setVelocityIterations(int iterations) { mVelocityIterations = iterations; } /** * The number of position iterations used to process one step. * 10 by default. */ int positionIterations() const { return mPositionIterations; } void setPositionIterations(int iterations) { mPositionIterations = iterations; } /** * The amount of time each frame takes in milliseconds. * By default it is 1000 / 60. */ int frameTime() const { return mFrameTime; } void setFrameTime(int frameTime) { mFrameTime = frameTime; } QPointF gravity() const { return mGravity; } void setGravity(const QPointF &gravity); void componentComplete(); void registerBody(Box2DBody *body); b2World *world() const { return mWorld; } private slots: void unregisterBody(); void fixtureDestroyed(Box2DFixture *fixture); signals: void gravityChanged(); void runningChanged(); void stepped(); void initialized(); protected: void timerEvent(QTimerEvent *); void itemChange(ItemChange, const ItemChangeData &); void GetAllBodies(QQuickItem * parent, QList &list); private: b2World *mWorld; ContactListener *mContactListener; Box2DDestructionListener *mDestructionListener; float mTimeStep; int mVelocityIterations; int mPositionIterations; int mFrameTime; QPointF mGravity; bool mIsRunning; QBasicTimer mTimer; QList mBodies; }; QML_DECLARE_TYPE(Box2DWorld) #endif // BOX2DWORLD_H qml-box2d/box2dwheeljoint.h0000664000000000000000000000676012310072714013041 0ustar /* * box2drevolutejoint.h * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DWHEELJOINT_H #define BOX2DWHEELJOINT_H #include "box2djoint.h" #include class b2World; class b2WheelJoint; class b2WheelJointDef; class Box2DWheelJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float dampingRatio READ dampingRatio WRITE setDampingRatio NOTIFY dampingRatioChanged) Q_PROPERTY(float frequencyHz READ frequencyHz WRITE setFrequencyHz NOTIFY frequencyHzChanged) Q_PROPERTY(float maxMotorTorque READ maxMotorTorque WRITE setMaxMotorTorque NOTIFY maxMotorTorqueChanged) Q_PROPERTY(float motorSpeed READ motorSpeed WRITE setMotorSpeed NOTIFY motorSpeedChanged) Q_PROPERTY(bool enableMotor READ enableMotor WRITE setEnableMotor NOTIFY enableMotorChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) Q_PROPERTY(QPointF localAxisA READ localAxisA WRITE setLocalAxisA NOTIFY localAxisAChanged) public: explicit Box2DWheelJoint(QObject *parent = 0); ~Box2DWheelJoint(); float dampingRatio() const; void setDampingRatio(float _dampingRatio); float frequencyHz() const; void setFrequencyHz(float _frequencyHz); float maxMotorTorque() const; void setMaxMotorTorque(float _maxMotorTorque); float motorSpeed() const; void setMotorSpeed(float _motorSpeed); bool enableMotor() const; void setEnableMotor(bool enableMotor); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); QPointF localAxisA() const; void setLocalAxisA(const QPointF &localAxisA); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); Q_INVOKABLE QPointF GetReactionForce(float32 inv_dt) const; Q_INVOKABLE float GetReactionTorque(float32 inv_dt) const; Q_INVOKABLE float GetJointTranslation() const; Q_INVOKABLE float GetJointSpeed() const; signals: void dampingRatioChanged(); void frequencyHzChanged(); void maxMotorTorqueChanged(); void motorSpeedChanged(); void enableMotorChanged(); void localAnchorAChanged(); void localAnchorBChanged(); void localAxisAChanged(); private: b2WheelJointDef mWheelJointDef; b2WheelJoint *mWheelJoint; bool anchorsAuto; }; #endif // BOX2DWHEELJOINT_H qml-box2d/box2dfixture.cpp0000664000000000000000000002441212310072714012704 0ustar /* * box2dfixture.cpp * Copyright (c) 2010-2011 Thorbjørn Lindeijer * Copyright (c) 2011 Daker Fernandes Pinheiro * Copyright (c) 2011 Alessandro Portale * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2dfixture.h" #include "box2dworld.h" #include #include "Common/b2Math.h" Box2DFixture::Box2DFixture(QQuickItem *parent) : QQuickItem(parent), mFixture(0), mFixtureDef(), factorWidth(1.0), factorHeight(1.0) { } float Box2DFixture::density() const { return mFixtureDef.density; } void Box2DFixture::setDensity(float density) { if (mFixtureDef.density == density) return; mFixtureDef.density = density; if (mFixture) mFixture->SetDensity(density); emit densityChanged(); } float Box2DFixture::friction() const { return mFixtureDef.friction; } void Box2DFixture::setFriction(float friction) { if (mFixtureDef.friction == friction) return; mFixtureDef.friction = friction; if (mFixture) mFixture->SetFriction(friction); emit frictionChanged(); } float Box2DFixture::restitution() const { return mFixtureDef.restitution; } void Box2DFixture::setRestitution(float restitution) { if (mFixtureDef.restitution == restitution) return; mFixtureDef.restitution = restitution; if (mFixture) mFixture->SetRestitution(restitution); emit restitutionChanged(); } bool Box2DFixture::isSensor() const { return mFixtureDef.isSensor; } void Box2DFixture::setSensor(bool sensor) { if (mFixtureDef.isSensor == sensor) return; mFixtureDef.isSensor = sensor; if (mFixture) mFixture->SetSensor(sensor); emit sensorChanged(); } Box2DFixture::CategoryFlags Box2DFixture::categories() const { return CategoryFlags(mFixtureDef.filter.categoryBits); } void Box2DFixture::setCategories(CategoryFlags layers) { if (mFixtureDef.filter.categoryBits == layers) return; mFixtureDef.filter.categoryBits = layers; emit categoriesChanged(); } Box2DFixture::CategoryFlags Box2DFixture::collidesWith() const { return CategoryFlags(mFixtureDef.filter.maskBits); } void Box2DFixture::setCollidesWith(CategoryFlags layers) { if (mFixtureDef.filter.maskBits == layers) return; mFixtureDef.filter.maskBits = layers; emit collidesWithChanged(); } int Box2DFixture::groupIndex() const { return mFixtureDef.filter.groupIndex; } void Box2DFixture::setGroupIndex(int groupIndex) { if (mFixtureDef.filter.groupIndex == groupIndex) return; mFixtureDef.filter.groupIndex = groupIndex; emit groupIndexChanged(); } void Box2DFixture::createFixture(b2Body *body) { b2Shape *shape = createShape(); if (!shape) return; mFixtureDef.shape = shape; mFixture = body->CreateFixture(&mFixtureDef); mFixture->SetUserData(this); mBody = body; delete shape; } Box2DBody *Box2DFixture::GetBody() const { return static_cast(mBody->GetUserData()); } void Box2DFixture::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { if(!isComponentComplete()) return; qreal nw = newGeometry.width(); qreal nh = newGeometry.height(); qreal ow = oldGeometry.width(); qreal oh = oldGeometry.height(); if( (nw != ow && !qFuzzyCompare(ow,0.0)) || (nh != oh && !qFuzzyCompare(oh,0.0)) ) { factorWidth = nw / ow; factorHeight = nh / oh; scale(); } } void Box2DFixture::emitBeginContact(Box2DFixture *other) { emit beginContact(other); } void Box2DFixture::emitContactChanged(Box2DFixture *other) { emit contactChanged(other); } void Box2DFixture::emitEndContact(Box2DFixture *other) { emit endContact(other); } void Box2DFixture::applyShape(b2Shape *shape) { if(mFixture) mBody->DestroyFixture(mFixture); mFixtureDef.shape = shape; mFixture = mBody->CreateFixture(&mFixtureDef); mFixture->SetUserData(this); delete shape; } b2Vec2 *Box2DVerticesShape::scaleVertices() { const int count = mVertices.length(); b2Vec2 * vertices = new b2Vec2[count]; for (int i = 0; i < count; ++i) { QPointF point = mVertices.at(i).toPointF(); point.setX(point.x() * factorWidth); point.setY(point.y() * factorHeight); mVertices.replace(i,point); vertices[i].Set(point.x() / scaleRatio, -point.y() / scaleRatio); } return vertices; } //=================== BOX ======================= b2Shape *Box2DBox::createShape() { const qreal _x = x() / scaleRatio; const qreal _y = -y() / scaleRatio; const qreal _width = width() / scaleRatio; const qreal _height = height() / scaleRatio; vertices[0].Set(_x, _y); vertices[1].Set(_x , _y - _height); vertices[2].Set(_x + _width , _y - _height); vertices[3].Set(_x + _width , _y ); for(int i = 1;i < 4;i ++) { if(i > 0) { if(b2DistanceSquared(vertices[i - 1], vertices[i]) <= b2_linearSlop * b2_linearSlop) { qWarning() << "Box: vertices are too close together"; return 0; } } } int32 count = 4; b2PolygonShape *shape = new b2PolygonShape; shape->Set(vertices, count); return shape; } void Box2DBox::scale() { if(mFixture) { b2Shape * shape = createShape(); applyShape(shape); } } //=================== CIRCLE ======================= b2Shape *Box2DCircle::createShape() { b2CircleShape *shape = new b2CircleShape; shape->m_radius = mRadius / scaleRatio; shape->m_p.Set(shape->m_radius, -shape->m_radius); if(height() == 0 || width() == 0) { this->setWidth(shape->m_radius); this->setHeight(shape->m_radius); } return shape; } void Box2DCircle::scale() { if(mFixture) { b2Shape * shape = createShape(); applyShape(shape); } } //=================== POLYGON ======================= b2Shape *Box2DPolygon::createShape() { const int count = mVertices.length(); if (count < 2 || count > b2_maxPolygonVertices) { qWarning() << "Polygon: Invalid number of vertices:" << count; return 0; } b2Vec2 *vertices = new b2Vec2[count]; for (int i = 0; i < count; ++i) { const QPointF &point = mVertices.at(i).toPointF(); vertices[i].Set(point.x() / scaleRatio, -point.y() / scaleRatio); if(i > 0) { if(b2DistanceSquared(vertices[i - 1], vertices[i]) <= b2_linearSlop * b2_linearSlop) { qWarning() << "Polygon: vertices are too close together"; return 0; } } } b2PolygonShape *shape = new b2PolygonShape; shape->Set(vertices, count); delete[] vertices; return shape; } void Box2DPolygon::scale() { if(mFixture) { b2Vec2 *vertices = scaleVertices(); b2PolygonShape *shape = new b2PolygonShape; shape->Set(vertices, mVertices.count()); delete[] vertices; applyShape(shape); } } //=================== CHAIN ======================= b2Shape *Box2DChain::createShape() { const int count = mVertices.length(); if (count < 2) { qWarning() << "Chain: Invalid number of vertices:" << count; return 0; } b2Vec2 *vertices = new b2Vec2[count]; for (int i = 0; i < count; ++i) { const QPointF &point = mVertices.at(i).toPointF(); vertices[i].Set(point.x() / scaleRatio, -point.y() / scaleRatio); if(i > 0) { if(b2DistanceSquared(vertices[i - 1], vertices[i]) <= b2_linearSlop * b2_linearSlop) { qWarning() << "Chain: vertices are too close together"; return 0; } } } b2ChainShape *shape = new b2ChainShape; if(mLoop) shape->CreateLoop(vertices, count); else shape->CreateChain(vertices, count); if(prevVertexFlag) shape->SetPrevVertex(b2Vec2(mPrevVertex.x() / scaleRatio,mPrevVertex.y() / scaleRatio)); if(nextVertexFlag) shape->SetNextVertex(b2Vec2(mNextVertex.x() / scaleRatio,mNextVertex.y() / scaleRatio)); delete[] vertices; return shape; } void Box2DChain::scale() { if(mFixture) { b2Vec2 *vertices = scaleVertices(); b2ChainShape *shape = new b2ChainShape; if(mLoop) shape->CreateLoop(vertices, mVertices.count()); else shape->CreateChain(vertices, mVertices.count()); delete[] vertices; applyShape(shape); } } //=================== EDGE ======================= b2Shape *Box2DEdge::createShape() { const int count = mVertices.length(); if (count != 2) { qWarning() << "Edge: Invalid number of vertices:" << count; return 0; } QPointF point1 = mVertices.at(0).toPointF(); QPointF point2 = mVertices.at(1).toPointF(); b2Vec2 vertex1(point1.x() / scaleRatio, -point1.y() / scaleRatio); b2Vec2 vertex2(point2.x() / scaleRatio, -point2.y() / scaleRatio); if(b2DistanceSquared(vertex1, vertex2) <= b2_linearSlop * b2_linearSlop) { qWarning() << "Edge: vertices are too close together"; return 0; } b2EdgeShape *shape = new b2EdgeShape; shape->Set(vertex1,vertex2); return shape; } void Box2DEdge::scale() { if(mFixture) { b2Vec2 *vertices = scaleVertices(); b2EdgeShape *shape = new b2EdgeShape; shape->Set(vertices[0],vertices[1]); delete[] vertices; applyShape(shape); } } qml-box2d/Box2D/0000755000000000000000000000000012310074311010457 5ustar qml-box2d/Box2D/Rope/0000755000000000000000000000000012241175670011401 5ustar qml-box2d/Box2D/Rope/b2Rope.cpp0000644000000000000000000001145012241175670013237 0ustar /* * Copyright (c) 2011 Erin Catto http://box2d.org * * 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. */ #include #include b2Rope::b2Rope() { m_count = 0; m_ps = NULL; m_p0s = NULL; m_vs = NULL; m_ims = NULL; m_Ls = NULL; m_as = NULL; m_gravity.SetZero(); m_k2 = 1.0f; m_k3 = 0.1f; } b2Rope::~b2Rope() { b2Free(m_ps); b2Free(m_p0s); b2Free(m_vs); b2Free(m_ims); b2Free(m_Ls); b2Free(m_as); } void b2Rope::Initialize(const b2RopeDef* def) { b2Assert(def->count >= 3); m_count = def->count; m_ps = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); m_p0s = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); m_vs = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); m_ims = (float32*)b2Alloc(m_count * sizeof(float32)); for (int32 i = 0; i < m_count; ++i) { m_ps[i] = def->vertices[i]; m_p0s[i] = def->vertices[i]; m_vs[i].SetZero(); float32 m = def->masses[i]; if (m > 0.0f) { m_ims[i] = 1.0f / m; } else { m_ims[i] = 0.0f; } } int32 count2 = m_count - 1; int32 count3 = m_count - 2; m_Ls = (float32*)b2Alloc(count2 * sizeof(float32)); m_as = (float32*)b2Alloc(count3 * sizeof(float32)); for (int32 i = 0; i < count2; ++i) { b2Vec2 p1 = m_ps[i]; b2Vec2 p2 = m_ps[i+1]; m_Ls[i] = b2Distance(p1, p2); } for (int32 i = 0; i < count3; ++i) { b2Vec2 p1 = m_ps[i]; b2Vec2 p2 = m_ps[i + 1]; b2Vec2 p3 = m_ps[i + 2]; b2Vec2 d1 = p2 - p1; b2Vec2 d2 = p3 - p2; float32 a = b2Cross(d1, d2); float32 b = b2Dot(d1, d2); m_as[i] = b2Atan2(a, b); } m_gravity = def->gravity; m_damping = def->damping; m_k2 = def->k2; m_k3 = def->k3; } void b2Rope::Step(float32 h, int32 iterations) { if (h == 0.0) { return; } float32 d = expf(- h * m_damping); for (int32 i = 0; i < m_count; ++i) { m_p0s[i] = m_ps[i]; if (m_ims[i] > 0.0f) { m_vs[i] += h * m_gravity; } m_vs[i] *= d; m_ps[i] += h * m_vs[i]; } for (int32 i = 0; i < iterations; ++i) { SolveC2(); SolveC3(); SolveC2(); } float32 inv_h = 1.0f / h; for (int32 i = 0; i < m_count; ++i) { m_vs[i] = inv_h * (m_ps[i] - m_p0s[i]); } } void b2Rope::SolveC2() { int32 count2 = m_count - 1; for (int32 i = 0; i < count2; ++i) { b2Vec2 p1 = m_ps[i]; b2Vec2 p2 = m_ps[i + 1]; b2Vec2 d = p2 - p1; float32 L = d.Normalize(); float32 im1 = m_ims[i]; float32 im2 = m_ims[i + 1]; if (im1 + im2 == 0.0f) { continue; } float32 s1 = im1 / (im1 + im2); float32 s2 = im2 / (im1 + im2); p1 -= m_k2 * s1 * (m_Ls[i] - L) * d; p2 += m_k2 * s2 * (m_Ls[i] - L) * d; m_ps[i] = p1; m_ps[i + 1] = p2; } } void b2Rope::SetAngle(float32 angle) { int32 count3 = m_count - 2; for (int32 i = 0; i < count3; ++i) { m_as[i] = angle; } } void b2Rope::SolveC3() { int32 count3 = m_count - 2; for (int32 i = 0; i < count3; ++i) { b2Vec2 p1 = m_ps[i]; b2Vec2 p2 = m_ps[i + 1]; b2Vec2 p3 = m_ps[i + 2]; float32 m1 = m_ims[i]; float32 m2 = m_ims[i + 1]; float32 m3 = m_ims[i + 2]; b2Vec2 d1 = p2 - p1; b2Vec2 d2 = p3 - p2; float32 L1sqr = d1.LengthSquared(); float32 L2sqr = d2.LengthSquared(); if (L1sqr * L2sqr == 0.0f) { continue; } float32 a = b2Cross(d1, d2); float32 b = b2Dot(d1, d2); float32 angle = b2Atan2(a, b); b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew(); b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew(); b2Vec2 J1 = -Jd1; b2Vec2 J2 = Jd1 - Jd2; b2Vec2 J3 = Jd2; float32 mass = m1 * b2Dot(J1, J1) + m2 * b2Dot(J2, J2) + m3 * b2Dot(J3, J3); if (mass == 0.0f) { continue; } mass = 1.0f / mass; float32 C = angle - m_as[i]; while (C > b2_pi) { angle -= 2 * b2_pi; C = angle - m_as[i]; } while (C < -b2_pi) { angle += 2.0f * b2_pi; C = angle - m_as[i]; } float32 impulse = - m_k3 * mass * C; p1 += (m1 * impulse) * J1; p2 += (m2 * impulse) * J2; p3 += (m3 * impulse) * J3; m_ps[i] = p1; m_ps[i + 1] = p2; m_ps[i + 2] = p3; } } void b2Rope::Draw(b2Draw* draw) const { b2Color c(0.4f, 0.5f, 0.7f); for (int32 i = 0; i < m_count - 1; ++i) { draw->DrawSegment(m_ps[i], m_ps[i+1], c); } } qml-box2d/Box2D/Rope/b2Rope.h0000644000000000000000000000366512241175670012715 0ustar /* * Copyright (c) 2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_ROPE_H #define B2_ROPE_H #include class b2Draw; /// struct b2RopeDef { b2RopeDef() { vertices = NULL; count = 0; masses = NULL; gravity.SetZero(); damping = 0.1f; k2 = 0.9f; k3 = 0.1f; } /// b2Vec2* vertices; /// int32 count; /// float32* masses; /// b2Vec2 gravity; /// float32 damping; /// Stretching stiffness float32 k2; /// Bending stiffness. Values above 0.5 can make the simulation blow up. float32 k3; }; /// class b2Rope { public: b2Rope(); ~b2Rope(); /// void Initialize(const b2RopeDef* def); /// void Step(float32 timeStep, int32 iterations); /// int32 GetVertexCount() const { return m_count; } /// const b2Vec2* GetVertices() const { return m_ps; } /// void Draw(b2Draw* draw) const; /// void SetAngle(float32 angle); private: void SolveC2(); void SolveC3(); int32 m_count; b2Vec2* m_ps; b2Vec2* m_p0s; b2Vec2* m_vs; float32* m_ims; float32* m_Ls; float32* m_as; b2Vec2 m_gravity; float32 m_damping; float32 m_k2; float32 m_k3; }; #endif qml-box2d/Box2D/Collision/0000755000000000000000000000000012310072714012417 5ustar qml-box2d/Box2D/Collision/b2BroadPhase.cpp0000664000000000000000000000601512310072714015363 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include b2BroadPhase::b2BroadPhase() { m_proxyCount = 0; m_pairCapacity = 16; m_pairCount = 0; m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair)); m_moveCapacity = 16; m_moveCount = 0; m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32)); } b2BroadPhase::~b2BroadPhase() { b2Free(m_moveBuffer); b2Free(m_pairBuffer); } int32 b2BroadPhase::CreateProxy(const b2AABB& aabb, void* userData) { int32 proxyId = m_tree.CreateProxy(aabb, userData); ++m_proxyCount; BufferMove(proxyId); return proxyId; } void b2BroadPhase::DestroyProxy(int32 proxyId) { UnBufferMove(proxyId); --m_proxyCount; m_tree.DestroyProxy(proxyId); } void b2BroadPhase::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement) { bool buffer = m_tree.MoveProxy(proxyId, aabb, displacement); if (buffer) { BufferMove(proxyId); } } void b2BroadPhase::TouchProxy(int32 proxyId) { BufferMove(proxyId); } void b2BroadPhase::BufferMove(int32 proxyId) { if (m_moveCount == m_moveCapacity) { int32* oldBuffer = m_moveBuffer; m_moveCapacity *= 2; m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32)); memcpy(m_moveBuffer, oldBuffer, m_moveCount * sizeof(int32)); b2Free(oldBuffer); } m_moveBuffer[m_moveCount] = proxyId; ++m_moveCount; } void b2BroadPhase::UnBufferMove(int32 proxyId) { for (int32 i = 0; i < m_moveCount; ++i) { if (m_moveBuffer[i] == proxyId) { m_moveBuffer[i] = e_nullProxy; } } } // This is called from b2DynamicTree::Query when we are gathering pairs. bool b2BroadPhase::QueryCallback(int32 proxyId) { // A proxy cannot form a pair with itself. if (proxyId == m_queryProxyId) { return true; } // Grow the pair buffer as needed. if (m_pairCount == m_pairCapacity) { b2Pair* oldBuffer = m_pairBuffer; m_pairCapacity *= 2; m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair)); memcpy(m_pairBuffer, oldBuffer, m_pairCount * sizeof(b2Pair)); b2Free(oldBuffer); } m_pairBuffer[m_pairCount].proxyIdA = b2Min(proxyId, m_queryProxyId); m_pairBuffer[m_pairCount].proxyIdB = b2Max(proxyId, m_queryProxyId); ++m_pairCount; return true; } qml-box2d/Box2D/Collision/b2CollideCircle.cpp0000664000000000000000000001040212310072714016043 0ustar /* * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include void b2CollideCircles( b2Manifold* manifold, const b2CircleShape* circleA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB) { manifold->pointCount = 0; b2Vec2 pA = b2Mul(xfA, circleA->m_p); b2Vec2 pB = b2Mul(xfB, circleB->m_p); b2Vec2 d = pB - pA; float32 distSqr = b2Dot(d, d); float32 rA = circleA->m_radius, rB = circleB->m_radius; float32 radius = rA + rB; if (distSqr > radius * radius) { return; } manifold->type = b2Manifold::e_circles; manifold->localPoint = circleA->m_p; manifold->localNormal.SetZero(); manifold->pointCount = 1; manifold->points[0].localPoint = circleB->m_p; manifold->points[0].id.key = 0; } void b2CollidePolygonAndCircle( b2Manifold* manifold, const b2PolygonShape* polygonA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB) { manifold->pointCount = 0; // Compute circle position in the frame of the polygon. b2Vec2 c = b2Mul(xfB, circleB->m_p); b2Vec2 cLocal = b2MulT(xfA, c); // Find the min separating edge. int32 normalIndex = 0; float32 separation = -b2_maxFloat; float32 radius = polygonA->m_radius + circleB->m_radius; int32 vertexCount = polygonA->m_count; const b2Vec2* vertices = polygonA->m_vertices; const b2Vec2* normals = polygonA->m_normals; for (int32 i = 0; i < vertexCount; ++i) { float32 s = b2Dot(normals[i], cLocal - vertices[i]); if (s > radius) { // Early out. return; } if (s > separation) { separation = s; normalIndex = i; } } // Vertices that subtend the incident face. int32 vertIndex1 = normalIndex; int32 vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; b2Vec2 v1 = vertices[vertIndex1]; b2Vec2 v2 = vertices[vertIndex2]; // If the center is inside the polygon ... if (separation < b2_epsilon) { manifold->pointCount = 1; manifold->type = b2Manifold::e_faceA; manifold->localNormal = normals[normalIndex]; manifold->localPoint = 0.5f * (v1 + v2); manifold->points[0].localPoint = circleB->m_p; manifold->points[0].id.key = 0; return; } // Compute barycentric coordinates float32 u1 = b2Dot(cLocal - v1, v2 - v1); float32 u2 = b2Dot(cLocal - v2, v1 - v2); if (u1 <= 0.0f) { if (b2DistanceSquared(cLocal, v1) > radius * radius) { return; } manifold->pointCount = 1; manifold->type = b2Manifold::e_faceA; manifold->localNormal = cLocal - v1; manifold->localNormal.Normalize(); manifold->localPoint = v1; manifold->points[0].localPoint = circleB->m_p; manifold->points[0].id.key = 0; } else if (u2 <= 0.0f) { if (b2DistanceSquared(cLocal, v2) > radius * radius) { return; } manifold->pointCount = 1; manifold->type = b2Manifold::e_faceA; manifold->localNormal = cLocal - v2; manifold->localNormal.Normalize(); manifold->localPoint = v2; manifold->points[0].localPoint = circleB->m_p; manifold->points[0].id.key = 0; } else { b2Vec2 faceCenter = 0.5f * (v1 + v2); float32 separation = b2Dot(cLocal - faceCenter, normals[vertIndex1]); if (separation > radius) { return; } manifold->pointCount = 1; manifold->type = b2Manifold::e_faceA; manifold->localNormal = normals[vertIndex1]; manifold->localPoint = faceCenter; manifold->points[0].localPoint = circleB->m_p; manifold->points[0].id.key = 0; } } qml-box2d/Box2D/Collision/b2DynamicTree.cpp0000664000000000000000000004074612310072714015570 0ustar /* * Copyright (c) 2009 Erin Catto http://www.box2d.org * * 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. */ #include #include b2DynamicTree::b2DynamicTree() { m_root = b2_nullNode; m_nodeCapacity = 16; m_nodeCount = 0; m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode)); memset(m_nodes, 0, m_nodeCapacity * sizeof(b2TreeNode)); // Build a linked list for the free list. for (int32 i = 0; i < m_nodeCapacity - 1; ++i) { m_nodes[i].next = i + 1; m_nodes[i].height = -1; } m_nodes[m_nodeCapacity-1].next = b2_nullNode; m_nodes[m_nodeCapacity-1].height = -1; m_freeList = 0; m_path = 0; m_insertionCount = 0; } b2DynamicTree::~b2DynamicTree() { // This frees the entire tree in one shot. b2Free(m_nodes); } // Allocate a node from the pool. Grow the pool if necessary. int32 b2DynamicTree::AllocateNode() { // Expand the node pool as needed. if (m_freeList == b2_nullNode) { b2Assert(m_nodeCount == m_nodeCapacity); // The free list is empty. Rebuild a bigger pool. b2TreeNode* oldNodes = m_nodes; m_nodeCapacity *= 2; m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode)); memcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2TreeNode)); b2Free(oldNodes); // Build a linked list for the free list. The parent // pointer becomes the "next" pointer. for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i) { m_nodes[i].next = i + 1; m_nodes[i].height = -1; } m_nodes[m_nodeCapacity-1].next = b2_nullNode; m_nodes[m_nodeCapacity-1].height = -1; m_freeList = m_nodeCount; } // Peel a node off the free list. int32 nodeId = m_freeList; m_freeList = m_nodes[nodeId].next; m_nodes[nodeId].parent = b2_nullNode; m_nodes[nodeId].child1 = b2_nullNode; m_nodes[nodeId].child2 = b2_nullNode; m_nodes[nodeId].height = 0; m_nodes[nodeId].userData = NULL; ++m_nodeCount; return nodeId; } // Return a node to the pool. void b2DynamicTree::FreeNode(int32 nodeId) { b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); b2Assert(0 < m_nodeCount); m_nodes[nodeId].next = m_freeList; m_nodes[nodeId].height = -1; m_freeList = nodeId; --m_nodeCount; } // Create a proxy in the tree as a leaf node. We return the index // of the node instead of a pointer so that we can grow // the node pool. int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData) { int32 proxyId = AllocateNode(); // Fatten the aabb. b2Vec2 r(b2_aabbExtension, b2_aabbExtension); m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r; m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r; m_nodes[proxyId].userData = userData; m_nodes[proxyId].height = 0; InsertLeaf(proxyId); return proxyId; } void b2DynamicTree::DestroyProxy(int32 proxyId) { b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); b2Assert(m_nodes[proxyId].IsLeaf()); RemoveLeaf(proxyId); FreeNode(proxyId); } bool b2DynamicTree::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement) { b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); b2Assert(m_nodes[proxyId].IsLeaf()); if (m_nodes[proxyId].aabb.Contains(aabb)) { return false; } RemoveLeaf(proxyId); // Extend AABB. b2AABB b = aabb; b2Vec2 r(b2_aabbExtension, b2_aabbExtension); b.lowerBound = b.lowerBound - r; b.upperBound = b.upperBound + r; // Predict AABB displacement. b2Vec2 d = b2_aabbMultiplier * displacement; if (d.x < 0.0f) { b.lowerBound.x += d.x; } else { b.upperBound.x += d.x; } if (d.y < 0.0f) { b.lowerBound.y += d.y; } else { b.upperBound.y += d.y; } m_nodes[proxyId].aabb = b; InsertLeaf(proxyId); return true; } void b2DynamicTree::InsertLeaf(int32 leaf) { ++m_insertionCount; if (m_root == b2_nullNode) { m_root = leaf; m_nodes[m_root].parent = b2_nullNode; return; } // Find the best sibling for this node b2AABB leafAABB = m_nodes[leaf].aabb; int32 index = m_root; while (m_nodes[index].IsLeaf() == false) { int32 child1 = m_nodes[index].child1; int32 child2 = m_nodes[index].child2; float32 area = m_nodes[index].aabb.GetPerimeter(); b2AABB combinedAABB; combinedAABB.Combine(m_nodes[index].aabb, leafAABB); float32 combinedArea = combinedAABB.GetPerimeter(); // Cost of creating a new parent for this node and the new leaf float32 cost = 2.0f * combinedArea; // Minimum cost of pushing the leaf further down the tree float32 inheritanceCost = 2.0f * (combinedArea - area); // Cost of descending into child1 float32 cost1; if (m_nodes[child1].IsLeaf()) { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child1].aabb); cost1 = aabb.GetPerimeter() + inheritanceCost; } else { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child1].aabb); float32 oldArea = m_nodes[child1].aabb.GetPerimeter(); float32 newArea = aabb.GetPerimeter(); cost1 = (newArea - oldArea) + inheritanceCost; } // Cost of descending into child2 float32 cost2; if (m_nodes[child2].IsLeaf()) { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child2].aabb); cost2 = aabb.GetPerimeter() + inheritanceCost; } else { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child2].aabb); float32 oldArea = m_nodes[child2].aabb.GetPerimeter(); float32 newArea = aabb.GetPerimeter(); cost2 = newArea - oldArea + inheritanceCost; } // Descend according to the minimum cost. if (cost < cost1 && cost < cost2) { break; } // Descend if (cost1 < cost2) { index = child1; } else { index = child2; } } int32 sibling = index; // Create a new parent. int32 oldParent = m_nodes[sibling].parent; int32 newParent = AllocateNode(); m_nodes[newParent].parent = oldParent; m_nodes[newParent].userData = NULL; m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb); m_nodes[newParent].height = m_nodes[sibling].height + 1; if (oldParent != b2_nullNode) { // The sibling was not the root. if (m_nodes[oldParent].child1 == sibling) { m_nodes[oldParent].child1 = newParent; } else { m_nodes[oldParent].child2 = newParent; } m_nodes[newParent].child1 = sibling; m_nodes[newParent].child2 = leaf; m_nodes[sibling].parent = newParent; m_nodes[leaf].parent = newParent; } else { // The sibling was the root. m_nodes[newParent].child1 = sibling; m_nodes[newParent].child2 = leaf; m_nodes[sibling].parent = newParent; m_nodes[leaf].parent = newParent; m_root = newParent; } // Walk back up the tree fixing heights and AABBs index = m_nodes[leaf].parent; while (index != b2_nullNode) { index = Balance(index); int32 child1 = m_nodes[index].child1; int32 child2 = m_nodes[index].child2; b2Assert(child1 != b2_nullNode); b2Assert(child2 != b2_nullNode); m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height); m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); index = m_nodes[index].parent; } //Validate(); } void b2DynamicTree::RemoveLeaf(int32 leaf) { if (leaf == m_root) { m_root = b2_nullNode; return; } int32 parent = m_nodes[leaf].parent; int32 grandParent = m_nodes[parent].parent; int32 sibling; if (m_nodes[parent].child1 == leaf) { sibling = m_nodes[parent].child2; } else { sibling = m_nodes[parent].child1; } if (grandParent != b2_nullNode) { // Destroy parent and connect sibling to grandParent. if (m_nodes[grandParent].child1 == parent) { m_nodes[grandParent].child1 = sibling; } else { m_nodes[grandParent].child2 = sibling; } m_nodes[sibling].parent = grandParent; FreeNode(parent); // Adjust ancestor bounds. int32 index = grandParent; while (index != b2_nullNode) { index = Balance(index); int32 child1 = m_nodes[index].child1; int32 child2 = m_nodes[index].child2; m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height); index = m_nodes[index].parent; } } else { m_root = sibling; m_nodes[sibling].parent = b2_nullNode; FreeNode(parent); } //Validate(); } // Perform a left or right rotation if node A is imbalanced. // Returns the new root index. int32 b2DynamicTree::Balance(int32 iA) { b2Assert(iA != b2_nullNode); b2TreeNode* A = m_nodes + iA; if (A->IsLeaf() || A->height < 2) { return iA; } int32 iB = A->child1; int32 iC = A->child2; b2Assert(0 <= iB && iB < m_nodeCapacity); b2Assert(0 <= iC && iC < m_nodeCapacity); b2TreeNode* B = m_nodes + iB; b2TreeNode* C = m_nodes + iC; int32 balance = C->height - B->height; // Rotate C up if (balance > 1) { int32 iF = C->child1; int32 iG = C->child2; b2TreeNode* F = m_nodes + iF; b2TreeNode* G = m_nodes + iG; b2Assert(0 <= iF && iF < m_nodeCapacity); b2Assert(0 <= iG && iG < m_nodeCapacity); // Swap A and C C->child1 = iA; C->parent = A->parent; A->parent = iC; // A's old parent should point to C if (C->parent != b2_nullNode) { if (m_nodes[C->parent].child1 == iA) { m_nodes[C->parent].child1 = iC; } else { b2Assert(m_nodes[C->parent].child2 == iA); m_nodes[C->parent].child2 = iC; } } else { m_root = iC; } // Rotate if (F->height > G->height) { C->child2 = iF; A->child2 = iG; G->parent = iA; A->aabb.Combine(B->aabb, G->aabb); C->aabb.Combine(A->aabb, F->aabb); A->height = 1 + b2Max(B->height, G->height); C->height = 1 + b2Max(A->height, F->height); } else { C->child2 = iG; A->child2 = iF; F->parent = iA; A->aabb.Combine(B->aabb, F->aabb); C->aabb.Combine(A->aabb, G->aabb); A->height = 1 + b2Max(B->height, F->height); C->height = 1 + b2Max(A->height, G->height); } return iC; } // Rotate B up if (balance < -1) { int32 iD = B->child1; int32 iE = B->child2; b2TreeNode* D = m_nodes + iD; b2TreeNode* E = m_nodes + iE; b2Assert(0 <= iD && iD < m_nodeCapacity); b2Assert(0 <= iE && iE < m_nodeCapacity); // Swap A and B B->child1 = iA; B->parent = A->parent; A->parent = iB; // A's old parent should point to B if (B->parent != b2_nullNode) { if (m_nodes[B->parent].child1 == iA) { m_nodes[B->parent].child1 = iB; } else { b2Assert(m_nodes[B->parent].child2 == iA); m_nodes[B->parent].child2 = iB; } } else { m_root = iB; } // Rotate if (D->height > E->height) { B->child2 = iD; A->child1 = iE; E->parent = iA; A->aabb.Combine(C->aabb, E->aabb); B->aabb.Combine(A->aabb, D->aabb); A->height = 1 + b2Max(C->height, E->height); B->height = 1 + b2Max(A->height, D->height); } else { B->child2 = iE; A->child1 = iD; D->parent = iA; A->aabb.Combine(C->aabb, D->aabb); B->aabb.Combine(A->aabb, E->aabb); A->height = 1 + b2Max(C->height, D->height); B->height = 1 + b2Max(A->height, E->height); } return iB; } return iA; } int32 b2DynamicTree::GetHeight() const { if (m_root == b2_nullNode) { return 0; } return m_nodes[m_root].height; } // float32 b2DynamicTree::GetAreaRatio() const { if (m_root == b2_nullNode) { return 0.0f; } const b2TreeNode* root = m_nodes + m_root; float32 rootArea = root->aabb.GetPerimeter(); float32 totalArea = 0.0f; for (int32 i = 0; i < m_nodeCapacity; ++i) { const b2TreeNode* node = m_nodes + i; if (node->height < 0) { // Free node in pool continue; } totalArea += node->aabb.GetPerimeter(); } return totalArea / rootArea; } // Compute the height of a sub-tree. int32 b2DynamicTree::ComputeHeight(int32 nodeId) const { b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); b2TreeNode* node = m_nodes + nodeId; if (node->IsLeaf()) { return 0; } int32 height1 = ComputeHeight(node->child1); int32 height2 = ComputeHeight(node->child2); return 1 + b2Max(height1, height2); } int32 b2DynamicTree::ComputeHeight() const { int32 height = ComputeHeight(m_root); return height; } void b2DynamicTree::ValidateStructure(int32 index) const { if (index == b2_nullNode) { return; } if (index == m_root) { b2Assert(m_nodes[index].parent == b2_nullNode); } const b2TreeNode* node = m_nodes + index; int32 child1 = node->child1; int32 child2 = node->child2; if (node->IsLeaf()) { b2Assert(child1 == b2_nullNode); b2Assert(child2 == b2_nullNode); b2Assert(node->height == 0); return; } b2Assert(0 <= child1 && child1 < m_nodeCapacity); b2Assert(0 <= child2 && child2 < m_nodeCapacity); b2Assert(m_nodes[child1].parent == index); b2Assert(m_nodes[child2].parent == index); ValidateStructure(child1); ValidateStructure(child2); } void b2DynamicTree::ValidateMetrics(int32 index) const { if (index == b2_nullNode) { return; } const b2TreeNode* node = m_nodes + index; int32 child1 = node->child1; int32 child2 = node->child2; if (node->IsLeaf()) { b2Assert(child1 == b2_nullNode); b2Assert(child2 == b2_nullNode); b2Assert(node->height == 0); return; } b2Assert(0 <= child1 && child1 < m_nodeCapacity); b2Assert(0 <= child2 && child2 < m_nodeCapacity); int32 height1 = m_nodes[child1].height; int32 height2 = m_nodes[child2].height; int32 height; height = 1 + b2Max(height1, height2); b2Assert(node->height == height); b2AABB aabb; aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); b2Assert(aabb.lowerBound == node->aabb.lowerBound); b2Assert(aabb.upperBound == node->aabb.upperBound); ValidateMetrics(child1); ValidateMetrics(child2); } void b2DynamicTree::Validate() const { ValidateStructure(m_root); ValidateMetrics(m_root); int32 freeCount = 0; int32 freeIndex = m_freeList; while (freeIndex != b2_nullNode) { b2Assert(0 <= freeIndex && freeIndex < m_nodeCapacity); freeIndex = m_nodes[freeIndex].next; ++freeCount; } b2Assert(GetHeight() == ComputeHeight()); b2Assert(m_nodeCount + freeCount == m_nodeCapacity); } int32 b2DynamicTree::GetMaxBalance() const { int32 maxBalance = 0; for (int32 i = 0; i < m_nodeCapacity; ++i) { const b2TreeNode* node = m_nodes + i; if (node->height <= 1) { continue; } b2Assert(node->IsLeaf() == false); int32 child1 = node->child1; int32 child2 = node->child2; int32 balance = b2Abs(m_nodes[child2].height - m_nodes[child1].height); maxBalance = b2Max(maxBalance, balance); } return maxBalance; } void b2DynamicTree::RebuildBottomUp() { int32* nodes = (int32*)b2Alloc(m_nodeCount * sizeof(int32)); int32 count = 0; // Build array of leaves. Free the rest. for (int32 i = 0; i < m_nodeCapacity; ++i) { if (m_nodes[i].height < 0) { // free node in pool continue; } if (m_nodes[i].IsLeaf()) { m_nodes[i].parent = b2_nullNode; nodes[count] = i; ++count; } else { FreeNode(i); } } while (count > 1) { float32 minCost = b2_maxFloat; int32 iMin = -1, jMin = -1; for (int32 i = 0; i < count; ++i) { b2AABB aabbi = m_nodes[nodes[i]].aabb; for (int32 j = i + 1; j < count; ++j) { b2AABB aabbj = m_nodes[nodes[j]].aabb; b2AABB b; b.Combine(aabbi, aabbj); float32 cost = b.GetPerimeter(); if (cost < minCost) { iMin = i; jMin = j; minCost = cost; } } } int32 index1 = nodes[iMin]; int32 index2 = nodes[jMin]; b2TreeNode* child1 = m_nodes + index1; b2TreeNode* child2 = m_nodes + index2; int32 parentIndex = AllocateNode(); b2TreeNode* parent = m_nodes + parentIndex; parent->child1 = index1; parent->child2 = index2; parent->height = 1 + b2Max(child1->height, child2->height); parent->aabb.Combine(child1->aabb, child2->aabb); parent->parent = b2_nullNode; child1->parent = parentIndex; child2->parent = parentIndex; nodes[jMin] = nodes[count-1]; nodes[iMin] = parentIndex; --count; } m_root = nodes[0]; b2Free(nodes); Validate(); } void b2DynamicTree::ShiftOrigin(const b2Vec2& newOrigin) { // Build array of leaves. Free the rest. for (int32 i = 0; i < m_nodeCapacity; ++i) { m_nodes[i].aabb.lowerBound -= newOrigin; m_nodes[i].aabb.upperBound -= newOrigin; } } qml-box2d/Box2D/Collision/b2DynamicTree.h0000664000000000000000000001677612310072714015243 0ustar /* * Copyright (c) 2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_DYNAMIC_TREE_H #define B2_DYNAMIC_TREE_H #include #include #define b2_nullNode (-1) /// A node in the dynamic tree. The client does not interact with this directly. struct b2TreeNode { bool IsLeaf() const { return child1 == b2_nullNode; } /// Enlarged AABB b2AABB aabb; void* userData; union { int32 parent; int32 next; }; int32 child1; int32 child2; // leaf = 0, free node = -1 int32 height; }; /// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt. /// A dynamic tree arranges data in a binary tree to accelerate /// queries such as volume queries and ray casts. Leafs are proxies /// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor /// so that the proxy AABB is bigger than the client object. This allows the client /// object to move by small amounts without triggering a tree update. /// /// Nodes are pooled and relocatable, so we use node indices rather than pointers. class b2DynamicTree { public: /// Constructing the tree initializes the node pool. b2DynamicTree(); /// Destroy the tree, freeing the node pool. ~b2DynamicTree(); /// Create a proxy. Provide a tight fitting AABB and a userData pointer. int32 CreateProxy(const b2AABB& aabb, void* userData); /// Destroy a proxy. This asserts if the id is invalid. void DestroyProxy(int32 proxyId); /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB, /// then the proxy is removed from the tree and re-inserted. Otherwise /// the function returns immediately. /// @return true if the proxy was re-inserted. bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement); /// Get proxy user data. /// @return the proxy user data or 0 if the id is invalid. void* GetUserData(int32 proxyId) const; /// Get the fat AABB for a proxy. const b2AABB& GetFatAABB(int32 proxyId) const; /// Query an AABB for overlapping proxies. The callback class /// is called for each proxy that overlaps the supplied AABB. template void Query(T* callback, const b2AABB& aabb) const; /// Ray-cast against the proxies in the tree. This relies on the callback /// to perform a exact ray-cast in the case were the proxy contains a shape. /// The callback also performs the any collision filtering. This has performance /// roughly equal to k * log(n), where k is the number of collisions and n is the /// number of proxies in the tree. /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). /// @param callback a callback class that is called for each proxy that is hit by the ray. template void RayCast(T* callback, const b2RayCastInput& input) const; /// Validate this tree. For testing. void Validate() const; /// Compute the height of the binary tree in O(N) time. Should not be /// called often. int32 GetHeight() const; /// Get the maximum balance of an node in the tree. The balance is the difference /// in height of the two children of a node. int32 GetMaxBalance() const; /// Get the ratio of the sum of the node areas to the root area. float32 GetAreaRatio() const; /// Build an optimal tree. Very expensive. For testing. void RebuildBottomUp(); /// Shift the world origin. Useful for large worlds. /// The shift formula is: position -= newOrigin /// @param newOrigin the new origin with respect to the old origin void ShiftOrigin(const b2Vec2& newOrigin); private: int32 AllocateNode(); void FreeNode(int32 node); void InsertLeaf(int32 node); void RemoveLeaf(int32 node); int32 Balance(int32 index); int32 ComputeHeight() const; int32 ComputeHeight(int32 nodeId) const; void ValidateStructure(int32 index) const; void ValidateMetrics(int32 index) const; int32 m_root; b2TreeNode* m_nodes; int32 m_nodeCount; int32 m_nodeCapacity; int32 m_freeList; /// This is used to incrementally traverse the tree for re-balancing. uint32 m_path; int32 m_insertionCount; }; inline void* b2DynamicTree::GetUserData(int32 proxyId) const { b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); return m_nodes[proxyId].userData; } inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const { b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); return m_nodes[proxyId].aabb; } template inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const { b2GrowableStack stack; stack.Push(m_root); while (stack.GetCount() > 0) { int32 nodeId = stack.Pop(); if (nodeId == b2_nullNode) { continue; } const b2TreeNode* node = m_nodes + nodeId; if (b2TestOverlap(node->aabb, aabb)) { if (node->IsLeaf()) { bool proceed = callback->QueryCallback(nodeId); if (proceed == false) { return; } } else { stack.Push(node->child1); stack.Push(node->child2); } } } } template inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const { b2Vec2 p1 = input.p1; b2Vec2 p2 = input.p2; b2Vec2 r = p2 - p1; b2Assert(r.LengthSquared() > 0.0f); r.Normalize(); // v is perpendicular to the segment. b2Vec2 v = b2Cross(1.0f, r); b2Vec2 abs_v = b2Abs(v); // Separating axis for segment (Gino, p80). // |dot(v, p1 - c)| > dot(|v|, h) float32 maxFraction = input.maxFraction; // Build a bounding box for the segment. b2AABB segmentAABB; { b2Vec2 t = p1 + maxFraction * (p2 - p1); segmentAABB.lowerBound = b2Min(p1, t); segmentAABB.upperBound = b2Max(p1, t); } b2GrowableStack stack; stack.Push(m_root); while (stack.GetCount() > 0) { int32 nodeId = stack.Pop(); if (nodeId == b2_nullNode) { continue; } const b2TreeNode* node = m_nodes + nodeId; if (b2TestOverlap(node->aabb, segmentAABB) == false) { continue; } // Separating axis for segment (Gino, p80). // |dot(v, p1 - c)| > dot(|v|, h) b2Vec2 c = node->aabb.GetCenter(); b2Vec2 h = node->aabb.GetExtents(); float32 separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h); if (separation > 0.0f) { continue; } if (node->IsLeaf()) { b2RayCastInput subInput; subInput.p1 = input.p1; subInput.p2 = input.p2; subInput.maxFraction = maxFraction; float32 value = callback->RayCastCallback(subInput, nodeId); if (value == 0.0f) { // The client has terminated the ray cast. return; } if (value > 0.0f) { // Update segment bounding box. maxFraction = value; b2Vec2 t = p1 + maxFraction * (p2 - p1); segmentAABB.lowerBound = b2Min(p1, t); segmentAABB.upperBound = b2Max(p1, t); } } else { stack.Push(node->child1); stack.Push(node->child2); } } } #endif qml-box2d/Box2D/Collision/b2CollideEdge.cpp0000664000000000000000000003636512310072714015526 0ustar /* * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include // Compute contact points for edge versus circle. // This accounts for edge connectivity. void b2CollideEdgeAndCircle(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB) { manifold->pointCount = 0; // Compute circle in frame of edge b2Vec2 Q = b2MulT(xfA, b2Mul(xfB, circleB->m_p)); b2Vec2 A = edgeA->m_vertex1, B = edgeA->m_vertex2; b2Vec2 e = B - A; // Barycentric coordinates float32 u = b2Dot(e, B - Q); float32 v = b2Dot(e, Q - A); float32 radius = edgeA->m_radius + circleB->m_radius; b2ContactFeature cf; cf.indexB = 0; cf.typeB = b2ContactFeature::e_vertex; // Region A if (v <= 0.0f) { b2Vec2 P = A; b2Vec2 d = Q - P; float32 dd = b2Dot(d, d); if (dd > radius * radius) { return; } // Is there an edge connected to A? if (edgeA->m_hasVertex0) { b2Vec2 A1 = edgeA->m_vertex0; b2Vec2 B1 = A; b2Vec2 e1 = B1 - A1; float32 u1 = b2Dot(e1, B1 - Q); // Is the circle in Region AB of the previous edge? if (u1 > 0.0f) { return; } } cf.indexA = 0; cf.typeA = b2ContactFeature::e_vertex; manifold->pointCount = 1; manifold->type = b2Manifold::e_circles; manifold->localNormal.SetZero(); manifold->localPoint = P; manifold->points[0].id.key = 0; manifold->points[0].id.cf = cf; manifold->points[0].localPoint = circleB->m_p; return; } // Region B if (u <= 0.0f) { b2Vec2 P = B; b2Vec2 d = Q - P; float32 dd = b2Dot(d, d); if (dd > radius * radius) { return; } // Is there an edge connected to B? if (edgeA->m_hasVertex3) { b2Vec2 B2 = edgeA->m_vertex3; b2Vec2 A2 = B; b2Vec2 e2 = B2 - A2; float32 v2 = b2Dot(e2, Q - A2); // Is the circle in Region AB of the next edge? if (v2 > 0.0f) { return; } } cf.indexA = 1; cf.typeA = b2ContactFeature::e_vertex; manifold->pointCount = 1; manifold->type = b2Manifold::e_circles; manifold->localNormal.SetZero(); manifold->localPoint = P; manifold->points[0].id.key = 0; manifold->points[0].id.cf = cf; manifold->points[0].localPoint = circleB->m_p; return; } // Region AB float32 den = b2Dot(e, e); b2Assert(den > 0.0f); b2Vec2 P = (1.0f / den) * (u * A + v * B); b2Vec2 d = Q - P; float32 dd = b2Dot(d, d); if (dd > radius * radius) { return; } b2Vec2 n(-e.y, e.x); if (b2Dot(n, Q - A) < 0.0f) { n.Set(-n.x, -n.y); } n.Normalize(); cf.indexA = 0; cf.typeA = b2ContactFeature::e_face; manifold->pointCount = 1; manifold->type = b2Manifold::e_faceA; manifold->localNormal = n; manifold->localPoint = A; manifold->points[0].id.key = 0; manifold->points[0].id.cf = cf; manifold->points[0].localPoint = circleB->m_p; } // This structure is used to keep track of the best separating axis. struct b2EPAxis { enum Type { e_unknown, e_edgeA, e_edgeB }; Type type; int32 index; float32 separation; }; // This holds polygon B expressed in frame A. struct b2TempPolygon { b2Vec2 vertices[b2_maxPolygonVertices]; b2Vec2 normals[b2_maxPolygonVertices]; int32 count; }; // Reference face used for clipping struct b2ReferenceFace { int32 i1, i2; b2Vec2 v1, v2; b2Vec2 normal; b2Vec2 sideNormal1; float32 sideOffset1; b2Vec2 sideNormal2; float32 sideOffset2; }; // This class collides and edge and a polygon, taking into account edge adjacency. struct b2EPCollider { void Collide(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, const b2PolygonShape* polygonB, const b2Transform& xfB); b2EPAxis ComputeEdgeSeparation(); b2EPAxis ComputePolygonSeparation(); enum VertexType { e_isolated, e_concave, e_convex }; b2TempPolygon m_polygonB; b2Transform m_xf; b2Vec2 m_centroidB; b2Vec2 m_v0, m_v1, m_v2, m_v3; b2Vec2 m_normal0, m_normal1, m_normal2; b2Vec2 m_normal; VertexType m_type1, m_type2; b2Vec2 m_lowerLimit, m_upperLimit; float32 m_radius; bool m_front; }; // Algorithm: // 1. Classify v1 and v2 // 2. Classify polygon centroid as front or back // 3. Flip normal if necessary // 4. Initialize normal range to [-pi, pi] about face normal // 5. Adjust normal range according to adjacent edges // 6. Visit each separating axes, only accept axes within the range // 7. Return if _any_ axis indicates separation // 8. Clip void b2EPCollider::Collide(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, const b2PolygonShape* polygonB, const b2Transform& xfB) { m_xf = b2MulT(xfA, xfB); m_centroidB = b2Mul(m_xf, polygonB->m_centroid); m_v0 = edgeA->m_vertex0; m_v1 = edgeA->m_vertex1; m_v2 = edgeA->m_vertex2; m_v3 = edgeA->m_vertex3; bool hasVertex0 = edgeA->m_hasVertex0; bool hasVertex3 = edgeA->m_hasVertex3; b2Vec2 edge1 = m_v2 - m_v1; edge1.Normalize(); m_normal1.Set(edge1.y, -edge1.x); float32 offset1 = b2Dot(m_normal1, m_centroidB - m_v1); float32 offset0 = 0.0f, offset2 = 0.0f; bool convex1 = false, convex2 = false; // Is there a preceding edge? if (hasVertex0) { b2Vec2 edge0 = m_v1 - m_v0; edge0.Normalize(); m_normal0.Set(edge0.y, -edge0.x); convex1 = b2Cross(edge0, edge1) >= 0.0f; offset0 = b2Dot(m_normal0, m_centroidB - m_v0); } // Is there a following edge? if (hasVertex3) { b2Vec2 edge2 = m_v3 - m_v2; edge2.Normalize(); m_normal2.Set(edge2.y, -edge2.x); convex2 = b2Cross(edge1, edge2) > 0.0f; offset2 = b2Dot(m_normal2, m_centroidB - m_v2); } // Determine front or back collision. Determine collision normal limits. if (hasVertex0 && hasVertex3) { if (convex1 && convex2) { m_front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = m_normal0; m_upperLimit = m_normal2; } else { m_normal = -m_normal1; m_lowerLimit = -m_normal1; m_upperLimit = -m_normal1; } } else if (convex1) { m_front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f); if (m_front) { m_normal = m_normal1; m_lowerLimit = m_normal0; m_upperLimit = m_normal1; } else { m_normal = -m_normal1; m_lowerLimit = -m_normal2; m_upperLimit = -m_normal1; } } else if (convex2) { m_front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f); if (m_front) { m_normal = m_normal1; m_lowerLimit = m_normal1; m_upperLimit = m_normal2; } else { m_normal = -m_normal1; m_lowerLimit = -m_normal1; m_upperLimit = -m_normal0; } } else { m_front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = m_normal1; m_upperLimit = m_normal1; } else { m_normal = -m_normal1; m_lowerLimit = -m_normal2; m_upperLimit = -m_normal0; } } } else if (hasVertex0) { if (convex1) { m_front = offset0 >= 0.0f || offset1 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = m_normal0; m_upperLimit = -m_normal1; } else { m_normal = -m_normal1; m_lowerLimit = m_normal1; m_upperLimit = -m_normal1; } } else { m_front = offset0 >= 0.0f && offset1 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = m_normal1; m_upperLimit = -m_normal1; } else { m_normal = -m_normal1; m_lowerLimit = m_normal1; m_upperLimit = -m_normal0; } } } else if (hasVertex3) { if (convex2) { m_front = offset1 >= 0.0f || offset2 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = -m_normal1; m_upperLimit = m_normal2; } else { m_normal = -m_normal1; m_lowerLimit = -m_normal1; m_upperLimit = m_normal1; } } else { m_front = offset1 >= 0.0f && offset2 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = -m_normal1; m_upperLimit = m_normal1; } else { m_normal = -m_normal1; m_lowerLimit = -m_normal2; m_upperLimit = m_normal1; } } } else { m_front = offset1 >= 0.0f; if (m_front) { m_normal = m_normal1; m_lowerLimit = -m_normal1; m_upperLimit = -m_normal1; } else { m_normal = -m_normal1; m_lowerLimit = m_normal1; m_upperLimit = m_normal1; } } // Get polygonB in frameA m_polygonB.count = polygonB->m_count; for (int32 i = 0; i < polygonB->m_count; ++i) { m_polygonB.vertices[i] = b2Mul(m_xf, polygonB->m_vertices[i]); m_polygonB.normals[i] = b2Mul(m_xf.q, polygonB->m_normals[i]); } m_radius = 2.0f * b2_polygonRadius; manifold->pointCount = 0; b2EPAxis edgeAxis = ComputeEdgeSeparation(); // If no valid normal can be found than this edge should not collide. if (edgeAxis.type == b2EPAxis::e_unknown) { return; } if (edgeAxis.separation > m_radius) { return; } b2EPAxis polygonAxis = ComputePolygonSeparation(); if (polygonAxis.type != b2EPAxis::e_unknown && polygonAxis.separation > m_radius) { return; } // Use hysteresis for jitter reduction. const float32 k_relativeTol = 0.98f; const float32 k_absoluteTol = 0.001f; b2EPAxis primaryAxis; if (polygonAxis.type == b2EPAxis::e_unknown) { primaryAxis = edgeAxis; } else if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) { primaryAxis = polygonAxis; } else { primaryAxis = edgeAxis; } b2ClipVertex ie[2]; b2ReferenceFace rf; if (primaryAxis.type == b2EPAxis::e_edgeA) { manifold->type = b2Manifold::e_faceA; // Search for the polygon normal that is most anti-parallel to the edge normal. int32 bestIndex = 0; float32 bestValue = b2Dot(m_normal, m_polygonB.normals[0]); for (int32 i = 1; i < m_polygonB.count; ++i) { float32 value = b2Dot(m_normal, m_polygonB.normals[i]); if (value < bestValue) { bestValue = value; bestIndex = i; } } int32 i1 = bestIndex; int32 i2 = i1 + 1 < m_polygonB.count ? i1 + 1 : 0; ie[0].v = m_polygonB.vertices[i1]; ie[0].id.cf.indexA = 0; ie[0].id.cf.indexB = static_cast(i1); ie[0].id.cf.typeA = b2ContactFeature::e_face; ie[0].id.cf.typeB = b2ContactFeature::e_vertex; ie[1].v = m_polygonB.vertices[i2]; ie[1].id.cf.indexA = 0; ie[1].id.cf.indexB = static_cast(i2); ie[1].id.cf.typeA = b2ContactFeature::e_face; ie[1].id.cf.typeB = b2ContactFeature::e_vertex; if (m_front) { rf.i1 = 0; rf.i2 = 1; rf.v1 = m_v1; rf.v2 = m_v2; rf.normal = m_normal1; } else { rf.i1 = 1; rf.i2 = 0; rf.v1 = m_v2; rf.v2 = m_v1; rf.normal = -m_normal1; } } else { manifold->type = b2Manifold::e_faceB; ie[0].v = m_v1; ie[0].id.cf.indexA = 0; ie[0].id.cf.indexB = static_cast(primaryAxis.index); ie[0].id.cf.typeA = b2ContactFeature::e_vertex; ie[0].id.cf.typeB = b2ContactFeature::e_face; ie[1].v = m_v2; ie[1].id.cf.indexA = 0; ie[1].id.cf.indexB = static_cast(primaryAxis.index); ie[1].id.cf.typeA = b2ContactFeature::e_vertex; ie[1].id.cf.typeB = b2ContactFeature::e_face; rf.i1 = primaryAxis.index; rf.i2 = rf.i1 + 1 < m_polygonB.count ? rf.i1 + 1 : 0; rf.v1 = m_polygonB.vertices[rf.i1]; rf.v2 = m_polygonB.vertices[rf.i2]; rf.normal = m_polygonB.normals[rf.i1]; } rf.sideNormal1.Set(rf.normal.y, -rf.normal.x); rf.sideNormal2 = -rf.sideNormal1; rf.sideOffset1 = b2Dot(rf.sideNormal1, rf.v1); rf.sideOffset2 = b2Dot(rf.sideNormal2, rf.v2); // Clip incident edge against extruded edge1 side edges. b2ClipVertex clipPoints1[2]; b2ClipVertex clipPoints2[2]; int32 np; // Clip to box side 1 np = b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1, rf.sideOffset1, rf.i1); if (np < b2_maxManifoldPoints) { return; } // Clip to negative box side 1 np = b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2, rf.sideOffset2, rf.i2); if (np < b2_maxManifoldPoints) { return; } // Now clipPoints2 contains the clipped points. if (primaryAxis.type == b2EPAxis::e_edgeA) { manifold->localNormal = rf.normal; manifold->localPoint = rf.v1; } else { manifold->localNormal = polygonB->m_normals[rf.i1]; manifold->localPoint = polygonB->m_vertices[rf.i1]; } int32 pointCount = 0; for (int32 i = 0; i < b2_maxManifoldPoints; ++i) { float32 separation; separation = b2Dot(rf.normal, clipPoints2[i].v - rf.v1); if (separation <= m_radius) { b2ManifoldPoint* cp = manifold->points + pointCount; if (primaryAxis.type == b2EPAxis::e_edgeA) { cp->localPoint = b2MulT(m_xf, clipPoints2[i].v); cp->id = clipPoints2[i].id; } else { cp->localPoint = clipPoints2[i].v; cp->id.cf.typeA = clipPoints2[i].id.cf.typeB; cp->id.cf.typeB = clipPoints2[i].id.cf.typeA; cp->id.cf.indexA = clipPoints2[i].id.cf.indexB; cp->id.cf.indexB = clipPoints2[i].id.cf.indexA; } ++pointCount; } } manifold->pointCount = pointCount; } b2EPAxis b2EPCollider::ComputeEdgeSeparation() { b2EPAxis axis; axis.type = b2EPAxis::e_edgeA; axis.index = m_front ? 0 : 1; axis.separation = FLT_MAX; for (int32 i = 0; i < m_polygonB.count; ++i) { float32 s = b2Dot(m_normal, m_polygonB.vertices[i] - m_v1); if (s < axis.separation) { axis.separation = s; } } return axis; } b2EPAxis b2EPCollider::ComputePolygonSeparation() { b2EPAxis axis; axis.type = b2EPAxis::e_unknown; axis.index = -1; axis.separation = -FLT_MAX; b2Vec2 perp(-m_normal.y, m_normal.x); for (int32 i = 0; i < m_polygonB.count; ++i) { b2Vec2 n = -m_polygonB.normals[i]; float32 s1 = b2Dot(n, m_polygonB.vertices[i] - m_v1); float32 s2 = b2Dot(n, m_polygonB.vertices[i] - m_v2); float32 s = b2Min(s1, s2); if (s > m_radius) { // No collision axis.type = b2EPAxis::e_edgeB; axis.index = i; axis.separation = s; return axis; } // Adjacency if (b2Dot(n, perp) >= 0.0f) { if (b2Dot(n - m_upperLimit, m_normal) < -b2_angularSlop) { continue; } } else { if (b2Dot(n - m_lowerLimit, m_normal) < -b2_angularSlop) { continue; } } if (s > axis.separation) { axis.type = b2EPAxis::e_edgeB; axis.index = i; axis.separation = s; } } return axis; } void b2CollideEdgeAndPolygon( b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, const b2PolygonShape* polygonB, const b2Transform& xfB) { b2EPCollider collider; collider.Collide(manifold, edgeA, xfA, polygonB, xfB); } qml-box2d/Box2D/Collision/b2Distance.cpp0000664000000000000000000003163212310072714015110 0ustar /* * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include // GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates. int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; void b2DistanceProxy::Set(const b2Shape* shape, int32 index) { switch (shape->GetType()) { case b2Shape::e_circle: { const b2CircleShape* circle = static_cast(shape); m_vertices = &circle->m_p; m_count = 1; m_radius = circle->m_radius; } break; case b2Shape::e_polygon: { const b2PolygonShape* polygon = static_cast(shape); m_vertices = polygon->m_vertices; m_count = polygon->m_count; m_radius = polygon->m_radius; } break; case b2Shape::e_chain: { const b2ChainShape* chain = static_cast(shape); b2Assert(0 <= index && index < chain->m_count); m_buffer[0] = chain->m_vertices[index]; if (index + 1 < chain->m_count) { m_buffer[1] = chain->m_vertices[index + 1]; } else { m_buffer[1] = chain->m_vertices[0]; } m_vertices = m_buffer; m_count = 2; m_radius = chain->m_radius; } break; case b2Shape::e_edge: { const b2EdgeShape* edge = static_cast(shape); m_vertices = &edge->m_vertex1; m_count = 2; m_radius = edge->m_radius; } break; default: b2Assert(false); } } struct b2SimplexVertex { b2Vec2 wA; // support point in proxyA b2Vec2 wB; // support point in proxyB b2Vec2 w; // wB - wA float32 a; // barycentric coordinate for closest point int32 indexA; // wA index int32 indexB; // wB index }; struct b2Simplex { void ReadCache( const b2SimplexCache* cache, const b2DistanceProxy* proxyA, const b2Transform& transformA, const b2DistanceProxy* proxyB, const b2Transform& transformB) { b2Assert(cache->count <= 3); // Copy data from cache. m_count = cache->count; b2SimplexVertex* vertices = &m_v1; for (int32 i = 0; i < m_count; ++i) { b2SimplexVertex* v = vertices + i; v->indexA = cache->indexA[i]; v->indexB = cache->indexB[i]; b2Vec2 wALocal = proxyA->GetVertex(v->indexA); b2Vec2 wBLocal = proxyB->GetVertex(v->indexB); v->wA = b2Mul(transformA, wALocal); v->wB = b2Mul(transformB, wBLocal); v->w = v->wB - v->wA; v->a = 0.0f; } // Compute the new simplex metric, if it is substantially different than // old metric then flush the simplex. if (m_count > 1) { float32 metric1 = cache->metric; float32 metric2 = GetMetric(); if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon) { // Reset the simplex. m_count = 0; } } // If the cache is empty or invalid ... if (m_count == 0) { b2SimplexVertex* v = vertices + 0; v->indexA = 0; v->indexB = 0; b2Vec2 wALocal = proxyA->GetVertex(0); b2Vec2 wBLocal = proxyB->GetVertex(0); v->wA = b2Mul(transformA, wALocal); v->wB = b2Mul(transformB, wBLocal); v->w = v->wB - v->wA; v->a = 1.0f; m_count = 1; } } void WriteCache(b2SimplexCache* cache) const { cache->metric = GetMetric(); cache->count = uint16(m_count); const b2SimplexVertex* vertices = &m_v1; for (int32 i = 0; i < m_count; ++i) { cache->indexA[i] = uint8(vertices[i].indexA); cache->indexB[i] = uint8(vertices[i].indexB); } } b2Vec2 GetSearchDirection() const { switch (m_count) { case 1: return -m_v1.w; case 2: { b2Vec2 e12 = m_v2.w - m_v1.w; float32 sgn = b2Cross(e12, -m_v1.w); if (sgn > 0.0f) { // Origin is left of e12. return b2Cross(1.0f, e12); } else { // Origin is right of e12. return b2Cross(e12, 1.0f); } } default: b2Assert(false); return b2Vec2_zero; } } b2Vec2 GetClosestPoint() const { switch (m_count) { case 0: b2Assert(false); return b2Vec2_zero; case 1: return m_v1.w; case 2: return m_v1.a * m_v1.w + m_v2.a * m_v2.w; case 3: return b2Vec2_zero; default: b2Assert(false); return b2Vec2_zero; } } void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const { switch (m_count) { case 0: b2Assert(false); break; case 1: *pA = m_v1.wA; *pB = m_v1.wB; break; case 2: *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA; *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB; break; case 3: *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA; *pB = *pA; break; default: b2Assert(false); break; } } float32 GetMetric() const { switch (m_count) { case 0: b2Assert(false); return 0.0f; case 1: return 0.0f; case 2: return b2Distance(m_v1.w, m_v2.w); case 3: return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w); default: b2Assert(false); return 0.0f; } } void Solve2(); void Solve3(); b2SimplexVertex m_v1, m_v2, m_v3; int32 m_count; }; // Solve a line segment using barycentric coordinates. // // p = a1 * w1 + a2 * w2 // a1 + a2 = 1 // // The vector from the origin to the closest point on the line is // perpendicular to the line. // e12 = w2 - w1 // dot(p, e) = 0 // a1 * dot(w1, e) + a2 * dot(w2, e) = 0 // // 2-by-2 linear system // [1 1 ][a1] = [1] // [w1.e12 w2.e12][a2] = [0] // // Define // d12_1 = dot(w2, e12) // d12_2 = -dot(w1, e12) // d12 = d12_1 + d12_2 // // Solution // a1 = d12_1 / d12 // a2 = d12_2 / d12 void b2Simplex::Solve2() { b2Vec2 w1 = m_v1.w; b2Vec2 w2 = m_v2.w; b2Vec2 e12 = w2 - w1; // w1 region float32 d12_2 = -b2Dot(w1, e12); if (d12_2 <= 0.0f) { // a2 <= 0, so we clamp it to 0 m_v1.a = 1.0f; m_count = 1; return; } // w2 region float32 d12_1 = b2Dot(w2, e12); if (d12_1 <= 0.0f) { // a1 <= 0, so we clamp it to 0 m_v2.a = 1.0f; m_count = 1; m_v1 = m_v2; return; } // Must be in e12 region. float32 inv_d12 = 1.0f / (d12_1 + d12_2); m_v1.a = d12_1 * inv_d12; m_v2.a = d12_2 * inv_d12; m_count = 2; } // Possible regions: // - points[2] // - edge points[0]-points[2] // - edge points[1]-points[2] // - inside the triangle void b2Simplex::Solve3() { b2Vec2 w1 = m_v1.w; b2Vec2 w2 = m_v2.w; b2Vec2 w3 = m_v3.w; // Edge12 // [1 1 ][a1] = [1] // [w1.e12 w2.e12][a2] = [0] // a3 = 0 b2Vec2 e12 = w2 - w1; float32 w1e12 = b2Dot(w1, e12); float32 w2e12 = b2Dot(w2, e12); float32 d12_1 = w2e12; float32 d12_2 = -w1e12; // Edge13 // [1 1 ][a1] = [1] // [w1.e13 w3.e13][a3] = [0] // a2 = 0 b2Vec2 e13 = w3 - w1; float32 w1e13 = b2Dot(w1, e13); float32 w3e13 = b2Dot(w3, e13); float32 d13_1 = w3e13; float32 d13_2 = -w1e13; // Edge23 // [1 1 ][a2] = [1] // [w2.e23 w3.e23][a3] = [0] // a1 = 0 b2Vec2 e23 = w3 - w2; float32 w2e23 = b2Dot(w2, e23); float32 w3e23 = b2Dot(w3, e23); float32 d23_1 = w3e23; float32 d23_2 = -w2e23; // Triangle123 float32 n123 = b2Cross(e12, e13); float32 d123_1 = n123 * b2Cross(w2, w3); float32 d123_2 = n123 * b2Cross(w3, w1); float32 d123_3 = n123 * b2Cross(w1, w2); // w1 region if (d12_2 <= 0.0f && d13_2 <= 0.0f) { m_v1.a = 1.0f; m_count = 1; return; } // e12 if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f) { float32 inv_d12 = 1.0f / (d12_1 + d12_2); m_v1.a = d12_1 * inv_d12; m_v2.a = d12_2 * inv_d12; m_count = 2; return; } // e13 if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f) { float32 inv_d13 = 1.0f / (d13_1 + d13_2); m_v1.a = d13_1 * inv_d13; m_v3.a = d13_2 * inv_d13; m_count = 2; m_v2 = m_v3; return; } // w2 region if (d12_1 <= 0.0f && d23_2 <= 0.0f) { m_v2.a = 1.0f; m_count = 1; m_v1 = m_v2; return; } // w3 region if (d13_1 <= 0.0f && d23_1 <= 0.0f) { m_v3.a = 1.0f; m_count = 1; m_v1 = m_v3; return; } // e23 if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f) { float32 inv_d23 = 1.0f / (d23_1 + d23_2); m_v2.a = d23_1 * inv_d23; m_v3.a = d23_2 * inv_d23; m_count = 2; m_v1 = m_v3; return; } // Must be in triangle123 float32 inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3); m_v1.a = d123_1 * inv_d123; m_v2.a = d123_2 * inv_d123; m_v3.a = d123_3 * inv_d123; m_count = 3; } void b2Distance(b2DistanceOutput* output, b2SimplexCache* cache, const b2DistanceInput* input) { ++b2_gjkCalls; const b2DistanceProxy* proxyA = &input->proxyA; const b2DistanceProxy* proxyB = &input->proxyB; b2Transform transformA = input->transformA; b2Transform transformB = input->transformB; // Initialize the simplex. b2Simplex simplex; simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB); // Get simplex vertices as an array. b2SimplexVertex* vertices = &simplex.m_v1; const int32 k_maxIters = 20; // These store the vertices of the last simplex so that we // can check for duplicates and prevent cycling. int32 saveA[3], saveB[3]; int32 saveCount = 0; float32 distanceSqr1 = b2_maxFloat; float32 distanceSqr2 = distanceSqr1; // Main iteration loop. int32 iter = 0; while (iter < k_maxIters) { // Copy simplex so we can identify duplicates. saveCount = simplex.m_count; for (int32 i = 0; i < saveCount; ++i) { saveA[i] = vertices[i].indexA; saveB[i] = vertices[i].indexB; } switch (simplex.m_count) { case 1: break; case 2: simplex.Solve2(); break; case 3: simplex.Solve3(); break; default: b2Assert(false); } // If we have 3 points, then the origin is in the corresponding triangle. if (simplex.m_count == 3) { break; } // Compute closest point. b2Vec2 p = simplex.GetClosestPoint(); distanceSqr2 = p.LengthSquared(); // Ensure progress if (distanceSqr2 >= distanceSqr1) { //break; } distanceSqr1 = distanceSqr2; // Get search direction. b2Vec2 d = simplex.GetSearchDirection(); // Ensure the search direction is numerically fit. if (d.LengthSquared() < b2_epsilon * b2_epsilon) { // The origin is probably contained by a line segment // or triangle. Thus the shapes are overlapped. // We can't return zero here even though there may be overlap. // In case the simplex is a point, segment, or triangle it is difficult // to determine if the origin is contained in the CSO or very close to it. break; } // Compute a tentative new simplex vertex using support points. b2SimplexVertex* vertex = vertices + simplex.m_count; vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d)); vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA)); b2Vec2 wBLocal; vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d)); vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB)); vertex->w = vertex->wB - vertex->wA; // Iteration count is equated to the number of support point calls. ++iter; ++b2_gjkIters; // Check for duplicate support points. This is the main termination criteria. bool duplicate = false; for (int32 i = 0; i < saveCount; ++i) { if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i]) { duplicate = true; break; } } // If we found a duplicate support point we must exit to avoid cycling. if (duplicate) { break; } // New vertex is ok and needed. ++simplex.m_count; } b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter); // Prepare output. simplex.GetWitnessPoints(&output->pointA, &output->pointB); output->distance = b2Distance(output->pointA, output->pointB); output->iterations = iter; // Cache the simplex. simplex.WriteCache(cache); // Apply radii if requested. if (input->useRadii) { float32 rA = proxyA->m_radius; float32 rB = proxyB->m_radius; if (output->distance > rA + rB && output->distance > b2_epsilon) { // Shapes are still no overlapped. // Move the witness points to the outer surface. output->distance -= rA + rB; b2Vec2 normal = output->pointB - output->pointA; normal.Normalize(); output->pointA += rA * normal; output->pointB -= rB * normal; } else { // Shapes are overlapped when radii are considered. // Move the witness points to the middle. b2Vec2 p = 0.5f * (output->pointA + output->pointB); output->pointA = p; output->pointB = p; output->distance = 0.0f; } } } qml-box2d/Box2D/Collision/b2CollidePolygon.cpp0000664000000000000000000001464212310072714016303 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include // Find the max separation between poly1 and poly2 using edge normals from poly1. static float32 b2FindMaxSeparation(int32* edgeIndex, const b2PolygonShape* poly1, const b2Transform& xf1, const b2PolygonShape* poly2, const b2Transform& xf2) { int32 count1 = poly1->m_count; int32 count2 = poly2->m_count; const b2Vec2* n1s = poly1->m_normals; const b2Vec2* v1s = poly1->m_vertices; const b2Vec2* v2s = poly2->m_vertices; b2Transform xf = b2MulT(xf2, xf1); int32 bestIndex = 0; float32 maxSeparation = -b2_maxFloat; for (int32 i = 0; i < count1; ++i) { // Get poly1 normal in frame2. b2Vec2 n = b2Mul(xf.q, n1s[i]); b2Vec2 v1 = b2Mul(xf, v1s[i]); // Find deepest point for normal i. float32 si = b2_maxFloat; for (int32 j = 0; j < count2; ++j) { float32 sij = b2Dot(n, v2s[j] - v1); if (sij < si) { si = sij; } } if (si > maxSeparation) { maxSeparation = si; bestIndex = i; } } *edgeIndex = bestIndex; return maxSeparation; } static void b2FindIncidentEdge(b2ClipVertex c[2], const b2PolygonShape* poly1, const b2Transform& xf1, int32 edge1, const b2PolygonShape* poly2, const b2Transform& xf2) { const b2Vec2* normals1 = poly1->m_normals; int32 count2 = poly2->m_count; const b2Vec2* vertices2 = poly2->m_vertices; const b2Vec2* normals2 = poly2->m_normals; b2Assert(0 <= edge1 && edge1 < poly1->m_count); // Get the normal of the reference edge in poly2's frame. b2Vec2 normal1 = b2MulT(xf2.q, b2Mul(xf1.q, normals1[edge1])); // Find the incident edge on poly2. int32 index = 0; float32 minDot = b2_maxFloat; for (int32 i = 0; i < count2; ++i) { float32 dot = b2Dot(normal1, normals2[i]); if (dot < minDot) { minDot = dot; index = i; } } // Build the clip vertices for the incident edge. int32 i1 = index; int32 i2 = i1 + 1 < count2 ? i1 + 1 : 0; c[0].v = b2Mul(xf2, vertices2[i1]); c[0].id.cf.indexA = (uint8)edge1; c[0].id.cf.indexB = (uint8)i1; c[0].id.cf.typeA = b2ContactFeature::e_face; c[0].id.cf.typeB = b2ContactFeature::e_vertex; c[1].v = b2Mul(xf2, vertices2[i2]); c[1].id.cf.indexA = (uint8)edge1; c[1].id.cf.indexB = (uint8)i2; c[1].id.cf.typeA = b2ContactFeature::e_face; c[1].id.cf.typeB = b2ContactFeature::e_vertex; } // Find edge normal of max separation on A - return if separating axis is found // Find edge normal of max separation on B - return if separation axis is found // Choose reference edge as min(minA, minB) // Find incident edge // Clip // The normal points from 1 to 2 void b2CollidePolygons(b2Manifold* manifold, const b2PolygonShape* polyA, const b2Transform& xfA, const b2PolygonShape* polyB, const b2Transform& xfB) { manifold->pointCount = 0; float32 totalRadius = polyA->m_radius + polyB->m_radius; int32 edgeA = 0; float32 separationA = b2FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB); if (separationA > totalRadius) return; int32 edgeB = 0; float32 separationB = b2FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA); if (separationB > totalRadius) return; const b2PolygonShape* poly1; // reference polygon const b2PolygonShape* poly2; // incident polygon b2Transform xf1, xf2; int32 edge1; // reference edge uint8 flip; const float32 k_tol = 0.1f * b2_linearSlop; if (separationB > separationA + k_tol) { poly1 = polyB; poly2 = polyA; xf1 = xfB; xf2 = xfA; edge1 = edgeB; manifold->type = b2Manifold::e_faceB; flip = 1; } else { poly1 = polyA; poly2 = polyB; xf1 = xfA; xf2 = xfB; edge1 = edgeA; manifold->type = b2Manifold::e_faceA; flip = 0; } b2ClipVertex incidentEdge[2]; b2FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2); int32 count1 = poly1->m_count; const b2Vec2* vertices1 = poly1->m_vertices; int32 iv1 = edge1; int32 iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0; b2Vec2 v11 = vertices1[iv1]; b2Vec2 v12 = vertices1[iv2]; b2Vec2 localTangent = v12 - v11; localTangent.Normalize(); b2Vec2 localNormal = b2Cross(localTangent, 1.0f); b2Vec2 planePoint = 0.5f * (v11 + v12); b2Vec2 tangent = b2Mul(xf1.q, localTangent); b2Vec2 normal = b2Cross(tangent, 1.0f); v11 = b2Mul(xf1, v11); v12 = b2Mul(xf1, v12); // Face offset. float32 frontOffset = b2Dot(normal, v11); // Side offsets, extended by polytope skin thickness. float32 sideOffset1 = -b2Dot(tangent, v11) + totalRadius; float32 sideOffset2 = b2Dot(tangent, v12) + totalRadius; // Clip incident edge against extruded edge1 side edges. b2ClipVertex clipPoints1[2]; b2ClipVertex clipPoints2[2]; int np; // Clip to box side 1 np = b2ClipSegmentToLine(clipPoints1, incidentEdge, -tangent, sideOffset1, iv1); if (np < 2) return; // Clip to negative box side 1 np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2); if (np < 2) { return; } // Now clipPoints2 contains the clipped points. manifold->localNormal = localNormal; manifold->localPoint = planePoint; int32 pointCount = 0; for (int32 i = 0; i < b2_maxManifoldPoints; ++i) { float32 separation = b2Dot(normal, clipPoints2[i].v) - frontOffset; if (separation <= totalRadius) { b2ManifoldPoint* cp = manifold->points + pointCount; cp->localPoint = b2MulT(xf2, clipPoints2[i].v); cp->id = clipPoints2[i].id; if (flip) { // Swap features b2ContactFeature cf = cp->id.cf; cp->id.cf.indexA = cf.indexB; cp->id.cf.indexB = cf.indexA; cp->id.cf.typeA = cf.typeB; cp->id.cf.typeB = cf.typeA; } ++pointCount; } } manifold->pointCount = pointCount; } qml-box2d/Box2D/Collision/b2Distance.h0000644000000000000000000000730112241175670014557 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_DISTANCE_H #define B2_DISTANCE_H #include class b2Shape; /// A distance proxy is used by the GJK algorithm. /// It encapsulates any shape. struct b2DistanceProxy { b2DistanceProxy() : m_vertices(NULL), m_count(0), m_radius(0.0f) {} /// Initialize the proxy using the given shape. The shape /// must remain in scope while the proxy is in use. void Set(const b2Shape* shape, int32 index); /// Get the supporting vertex index in the given direction. int32 GetSupport(const b2Vec2& d) const; /// Get the supporting vertex in the given direction. const b2Vec2& GetSupportVertex(const b2Vec2& d) const; /// Get the vertex count. int32 GetVertexCount() const; /// Get a vertex by index. Used by b2Distance. const b2Vec2& GetVertex(int32 index) const; b2Vec2 m_buffer[2]; const b2Vec2* m_vertices; int32 m_count; float32 m_radius; }; /// Used to warm start b2Distance. /// Set count to zero on first call. struct b2SimplexCache { float32 metric; ///< length or area uint16 count; uint8 indexA[3]; ///< vertices on shape A uint8 indexB[3]; ///< vertices on shape B }; /// Input for b2Distance. /// You have to option to use the shape radii /// in the computation. Even struct b2DistanceInput { b2DistanceProxy proxyA; b2DistanceProxy proxyB; b2Transform transformA; b2Transform transformB; bool useRadii; }; /// Output for b2Distance. struct b2DistanceOutput { b2Vec2 pointA; ///< closest point on shapeA b2Vec2 pointB; ///< closest point on shapeB float32 distance; int32 iterations; ///< number of GJK iterations used }; /// Compute the closest points between two shapes. Supports any combination of: /// b2CircleShape, b2PolygonShape, b2EdgeShape. The simplex cache is input/output. /// On the first call set b2SimplexCache.count to zero. void b2Distance(b2DistanceOutput* output, b2SimplexCache* cache, const b2DistanceInput* input); ////////////////////////////////////////////////////////////////////////// inline int32 b2DistanceProxy::GetVertexCount() const { return m_count; } inline const b2Vec2& b2DistanceProxy::GetVertex(int32 index) const { b2Assert(0 <= index && index < m_count); return m_vertices[index]; } inline int32 b2DistanceProxy::GetSupport(const b2Vec2& d) const { int32 bestIndex = 0; float32 bestValue = b2Dot(m_vertices[0], d); for (int32 i = 1; i < m_count; ++i) { float32 value = b2Dot(m_vertices[i], d); if (value > bestValue) { bestIndex = i; bestValue = value; } } return bestIndex; } inline const b2Vec2& b2DistanceProxy::GetSupportVertex(const b2Vec2& d) const { int32 bestIndex = 0; float32 bestValue = b2Dot(m_vertices[0], d); for (int32 i = 1; i < m_count; ++i) { float32 value = b2Dot(m_vertices[i], d); if (value > bestValue) { bestIndex = i; bestValue = value; } } return m_vertices[bestIndex]; } #endif qml-box2d/Box2D/Collision/Shapes/0000755000000000000000000000000012310072714013642 5ustar qml-box2d/Box2D/Collision/Shapes/b2CircleShape.cpp0000664000000000000000000000576212310072714016770 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include b2Shape* b2CircleShape::Clone(b2BlockAllocator* allocator) const { void* mem = allocator->Allocate(sizeof(b2CircleShape)); b2CircleShape* clone = new (mem) b2CircleShape; *clone = *this; return clone; } int32 b2CircleShape::GetChildCount() const { return 1; } bool b2CircleShape::TestPoint(const b2Transform& transform, const b2Vec2& p) const { b2Vec2 center = transform.p + b2Mul(transform.q, m_p); b2Vec2 d = p - center; return b2Dot(d, d) <= m_radius * m_radius; } // Collision Detection in Interactive 3D Environments by Gino van den Bergen // From Section 3.1.2 // x = s + a * r // norm(x) = radius bool b2CircleShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform, int32 childIndex) const { B2_NOT_USED(childIndex); b2Vec2 position = transform.p + b2Mul(transform.q, m_p); b2Vec2 s = input.p1 - position; float32 b = b2Dot(s, s) - m_radius * m_radius; // Solve quadratic equation. b2Vec2 r = input.p2 - input.p1; float32 c = b2Dot(s, r); float32 rr = b2Dot(r, r); float32 sigma = c * c - rr * b; // Check for negative discriminant and short segment. if (sigma < 0.0f || rr < b2_epsilon) { return false; } // Find the point of intersection of the line with the circle. float32 a = -(c + b2Sqrt(sigma)); // Is the intersection point on the segment? if (0.0f <= a && a <= input.maxFraction * rr) { a /= rr; output->fraction = a; output->normal = s + a * r; output->normal.Normalize(); return true; } return false; } void b2CircleShape::ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const { B2_NOT_USED(childIndex); b2Vec2 p = transform.p + b2Mul(transform.q, m_p); aabb->lowerBound.Set(p.x - m_radius, p.y - m_radius); aabb->upperBound.Set(p.x + m_radius, p.y + m_radius); } void b2CircleShape::ComputeMass(b2MassData* massData, float32 density) const { massData->mass = density * b2_pi * m_radius * m_radius; massData->center = m_p; // inertia about the local origin massData->I = massData->mass * (0.5f * m_radius * m_radius + b2Dot(m_p, m_p)); } qml-box2d/Box2D/Collision/Shapes/b2CircleShape.h0000644000000000000000000000474712241175670016445 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CIRCLE_SHAPE_H #define B2_CIRCLE_SHAPE_H #include /// A circle shape. class b2CircleShape : public b2Shape { public: b2CircleShape(); /// Implement b2Shape. b2Shape* Clone(b2BlockAllocator* allocator) const; /// @see b2Shape::GetChildCount int32 GetChildCount() const; /// Implement b2Shape. bool TestPoint(const b2Transform& transform, const b2Vec2& p) const; /// Implement b2Shape. bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeAABB void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeMass void ComputeMass(b2MassData* massData, float32 density) const; /// Get the supporting vertex index in the given direction. int32 GetSupport(const b2Vec2& d) const; /// Get the supporting vertex in the given direction. const b2Vec2& GetSupportVertex(const b2Vec2& d) const; /// Get the vertex count. int32 GetVertexCount() const { return 1; } /// Get a vertex by index. Used by b2Distance. const b2Vec2& GetVertex(int32 index) const; /// Position b2Vec2 m_p; }; inline b2CircleShape::b2CircleShape() { m_type = e_circle; m_radius = 0.0f; m_p.SetZero(); } inline int32 b2CircleShape::GetSupport(const b2Vec2 &d) const { B2_NOT_USED(d); return 0; } inline const b2Vec2& b2CircleShape::GetSupportVertex(const b2Vec2 &d) const { B2_NOT_USED(d); return m_p; } inline const b2Vec2& b2CircleShape::GetVertex(int32 index) const { B2_NOT_USED(index); b2Assert(index == 0); return m_p; } #endif qml-box2d/Box2D/Collision/Shapes/b2ChainShape.cpp0000664000000000000000000001142712310072714016604 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include b2ChainShape::~b2ChainShape() { b2Free(m_vertices); m_vertices = NULL; m_count = 0; } void b2ChainShape::CreateLoop(const b2Vec2* vertices, int32 count) { b2Assert(m_vertices == NULL && m_count == 0); b2Assert(count >= 3); for (int32 i = 1; i < count; ++i) { b2Vec2 v1 = vertices[i-1]; b2Vec2 v2 = vertices[i]; // If the code crashes here, it means your vertices are too close together. b2Assert(b2DistanceSquared(v1, v2) > b2_linearSlop * b2_linearSlop); } m_count = count + 1; m_vertices = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); memcpy(m_vertices, vertices, count * sizeof(b2Vec2)); m_vertices[count] = m_vertices[0]; m_prevVertex = m_vertices[m_count - 2]; m_nextVertex = m_vertices[1]; m_hasPrevVertex = true; m_hasNextVertex = true; } void b2ChainShape::CreateChain(const b2Vec2* vertices, int32 count) { b2Assert(m_vertices == NULL && m_count == 0); b2Assert(count >= 2); for (int32 i = 1; i < count; ++i) { b2Vec2 v1 = vertices[i-1]; b2Vec2 v2 = vertices[i]; // If the code crashes here, it means your vertices are too close together. b2Assert(b2DistanceSquared(v1, v2) > b2_linearSlop * b2_linearSlop); } m_count = count; m_vertices = (b2Vec2*)b2Alloc(count * sizeof(b2Vec2)); memcpy(m_vertices, vertices, m_count * sizeof(b2Vec2)); m_hasPrevVertex = false; m_hasNextVertex = false; m_prevVertex.SetZero(); m_nextVertex.SetZero(); } void b2ChainShape::SetPrevVertex(const b2Vec2& prevVertex) { m_prevVertex = prevVertex; m_hasPrevVertex = true; } void b2ChainShape::SetNextVertex(const b2Vec2& nextVertex) { m_nextVertex = nextVertex; m_hasNextVertex = true; } b2Shape* b2ChainShape::Clone(b2BlockAllocator* allocator) const { void* mem = allocator->Allocate(sizeof(b2ChainShape)); b2ChainShape* clone = new (mem) b2ChainShape; clone->CreateChain(m_vertices, m_count); clone->m_prevVertex = m_prevVertex; clone->m_nextVertex = m_nextVertex; clone->m_hasPrevVertex = m_hasPrevVertex; clone->m_hasNextVertex = m_hasNextVertex; return clone; } int32 b2ChainShape::GetChildCount() const { // edge count = vertex count - 1 return m_count - 1; } void b2ChainShape::GetChildEdge(b2EdgeShape* edge, int32 index) const { b2Assert(0 <= index && index < m_count - 1); edge->m_type = b2Shape::e_edge; edge->m_radius = m_radius; edge->m_vertex1 = m_vertices[index + 0]; edge->m_vertex2 = m_vertices[index + 1]; if (index > 0) { edge->m_vertex0 = m_vertices[index - 1]; edge->m_hasVertex0 = true; } else { edge->m_vertex0 = m_prevVertex; edge->m_hasVertex0 = m_hasPrevVertex; } if (index < m_count - 2) { edge->m_vertex3 = m_vertices[index + 2]; edge->m_hasVertex3 = true; } else { edge->m_vertex3 = m_nextVertex; edge->m_hasVertex3 = m_hasNextVertex; } } bool b2ChainShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const { B2_NOT_USED(xf); B2_NOT_USED(p); return false; } bool b2ChainShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& xf, int32 childIndex) const { b2Assert(childIndex < m_count); b2EdgeShape edgeShape; int32 i1 = childIndex; int32 i2 = childIndex + 1; if (i2 == m_count) { i2 = 0; } edgeShape.m_vertex1 = m_vertices[i1]; edgeShape.m_vertex2 = m_vertices[i2]; return edgeShape.RayCast(output, input, xf, 0); } void b2ChainShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const { b2Assert(childIndex < m_count); int32 i1 = childIndex; int32 i2 = childIndex + 1; if (i2 == m_count) { i2 = 0; } b2Vec2 v1 = b2Mul(xf, m_vertices[i1]); b2Vec2 v2 = b2Mul(xf, m_vertices[i2]); aabb->lowerBound = b2Min(v1, v2); aabb->upperBound = b2Max(v1, v2); } void b2ChainShape::ComputeMass(b2MassData* massData, float32 density) const { B2_NOT_USED(density); massData->mass = 0.0f; massData->center.SetZero(); massData->I = 0.0f; } qml-box2d/Box2D/Collision/Shapes/b2PolygonShape.h0000664000000000000000000000663312310072714016661 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_POLYGON_SHAPE_H #define B2_POLYGON_SHAPE_H #include /// A convex polygon. It is assumed that the interior of the polygon is to /// the left of each edge. /// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices. /// In most cases you should not need many vertices for a convex polygon. class b2PolygonShape : public b2Shape { public: b2PolygonShape(); /// Implement b2Shape. b2Shape* Clone(b2BlockAllocator* allocator) const; /// @see b2Shape::GetChildCount int32 GetChildCount() const; /// Create a convex hull from the given array of local points. /// The count must be in the range [3, b2_maxPolygonVertices]. /// @warning the points may be re-ordered, even if they form a convex polygon /// @warning collinear points are handled but not removed. Collinear points /// may lead to poor stacking behavior. void Set(const b2Vec2* points, int32 count); /// Build vertices to represent an axis-aligned box centered on the local origin. /// @param hx the half-width. /// @param hy the half-height. void SetAsBox(float32 hx, float32 hy); /// Build vertices to represent an oriented box. /// @param hx the half-width. /// @param hy the half-height. /// @param center the center of the box in local coordinates. /// @param angle the rotation of the box in local coordinates. void SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle); /// @see b2Shape::TestPoint bool TestPoint(const b2Transform& transform, const b2Vec2& p) const; /// Implement b2Shape. bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeAABB void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeMass void ComputeMass(b2MassData* massData, float32 density) const; /// Get the vertex count. int32 GetVertexCount() const { return m_count; } /// Get a vertex by index. const b2Vec2& GetVertex(int32 index) const; /// Validate convexity. This is a very time consuming operation. /// @returns true if valid bool Validate() const; b2Vec2 m_centroid; b2Vec2 m_vertices[b2_maxPolygonVertices]; b2Vec2 m_normals[b2_maxPolygonVertices]; int32 m_count; }; inline b2PolygonShape::b2PolygonShape() { m_type = e_polygon; m_radius = b2_polygonRadius; m_count = 0; m_centroid.SetZero(); } inline const b2Vec2& b2PolygonShape::GetVertex(int32 index) const { b2Assert(0 <= index && index < m_count); return m_vertices[index]; } #endif qml-box2d/Box2D/Collision/Shapes/b2ChainShape.h0000664000000000000000000000654012310072714016251 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CHAIN_SHAPE_H #define B2_CHAIN_SHAPE_H #include class b2EdgeShape; /// A chain shape is a free form sequence of line segments. /// The chain has two-sided collision, so you can use inside and outside collision. /// Therefore, you may use any winding order. /// Since there may be many vertices, they are allocated using b2Alloc. /// Connectivity information is used to create smooth collisions. /// WARNING: The chain will not collide properly if there are self-intersections. class b2ChainShape : public b2Shape { public: b2ChainShape(); /// The destructor frees the vertices using b2Free. ~b2ChainShape(); /// Create a loop. This automatically adjusts connectivity. /// @param vertices an array of vertices, these are copied /// @param count the vertex count void CreateLoop(const b2Vec2* vertices, int32 count); /// Create a chain with isolated end vertices. /// @param vertices an array of vertices, these are copied /// @param count the vertex count void CreateChain(const b2Vec2* vertices, int32 count); /// Establish connectivity to a vertex that precedes the first vertex. /// Don't call this for loops. void SetPrevVertex(const b2Vec2& prevVertex); /// Establish connectivity to a vertex that follows the last vertex. /// Don't call this for loops. void SetNextVertex(const b2Vec2& nextVertex); /// Implement b2Shape. Vertices are cloned using b2Alloc. b2Shape* Clone(b2BlockAllocator* allocator) const; /// @see b2Shape::GetChildCount int32 GetChildCount() const; /// Get a child edge. void GetChildEdge(b2EdgeShape* edge, int32 index) const; /// This always return false. /// @see b2Shape::TestPoint bool TestPoint(const b2Transform& transform, const b2Vec2& p) const; /// Implement b2Shape. bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeAABB void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const; /// Chains have zero mass. /// @see b2Shape::ComputeMass void ComputeMass(b2MassData* massData, float32 density) const; /// The vertices. Owned by this class. b2Vec2* m_vertices; /// The vertex count. int32 m_count; b2Vec2 m_prevVertex, m_nextVertex; bool m_hasPrevVertex, m_hasNextVertex; }; inline b2ChainShape::b2ChainShape() { m_type = e_chain; m_radius = b2_polygonRadius; m_vertices = NULL; m_count = 0; m_hasPrevVertex = false; m_hasNextVertex = false; } #endif qml-box2d/Box2D/Collision/Shapes/b2Shape.h0000644000000000000000000000665112241175670015317 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_SHAPE_H #define B2_SHAPE_H #include #include #include /// This holds the mass data computed for a shape. struct b2MassData { /// The mass of the shape, usually in kilograms. float32 mass; /// The position of the shape's centroid relative to the shape's origin. b2Vec2 center; /// The rotational inertia of the shape about the local origin. float32 I; }; /// A shape is used for collision detection. You can create a shape however you like. /// Shapes used for simulation in b2World are created automatically when a b2Fixture /// is created. Shapes may encapsulate a one or more child shapes. class b2Shape { public: enum Type { e_circle = 0, e_edge = 1, e_polygon = 2, e_chain = 3, e_typeCount = 4 }; virtual ~b2Shape() {} /// Clone the concrete shape using the provided allocator. virtual b2Shape* Clone(b2BlockAllocator* allocator) const = 0; /// Get the type of this shape. You can use this to down cast to the concrete shape. /// @return the shape type. Type GetType() const; /// Get the number of child primitives. virtual int32 GetChildCount() const = 0; /// Test a point for containment in this shape. This only works for convex shapes. /// @param xf the shape world transform. /// @param p a point in world coordinates. virtual bool TestPoint(const b2Transform& xf, const b2Vec2& p) const = 0; /// Cast a ray against a child shape. /// @param output the ray-cast results. /// @param input the ray-cast input parameters. /// @param transform the transform to be applied to the shape. /// @param childIndex the child shape index virtual bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform, int32 childIndex) const = 0; /// Given a transform, compute the associated axis aligned bounding box for a child shape. /// @param aabb returns the axis aligned box. /// @param xf the world transform of the shape. /// @param childIndex the child shape virtual void ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const = 0; /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin. /// @param massData returns the mass data for this shape. /// @param density the density in kilograms per meter squared. virtual void ComputeMass(b2MassData* massData, float32 density) const = 0; Type m_type; float32 m_radius; }; inline b2Shape::Type b2Shape::GetType() const { return m_type; } #endif qml-box2d/Box2D/Collision/Shapes/b2PolygonShape.cpp0000664000000000000000000002447412310072714017217 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include b2Shape* b2PolygonShape::Clone(b2BlockAllocator* allocator) const { void* mem = allocator->Allocate(sizeof(b2PolygonShape)); b2PolygonShape* clone = new (mem) b2PolygonShape; *clone = *this; return clone; } void b2PolygonShape::SetAsBox(float32 hx, float32 hy) { m_count = 4; m_vertices[0].Set(-hx, -hy); m_vertices[1].Set( hx, -hy); m_vertices[2].Set( hx, hy); m_vertices[3].Set(-hx, hy); m_normals[0].Set(0.0f, -1.0f); m_normals[1].Set(1.0f, 0.0f); m_normals[2].Set(0.0f, 1.0f); m_normals[3].Set(-1.0f, 0.0f); m_centroid.SetZero(); } void b2PolygonShape::SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle) { m_count = 4; m_vertices[0].Set(-hx, -hy); m_vertices[1].Set( hx, -hy); m_vertices[2].Set( hx, hy); m_vertices[3].Set(-hx, hy); m_normals[0].Set(0.0f, -1.0f); m_normals[1].Set(1.0f, 0.0f); m_normals[2].Set(0.0f, 1.0f); m_normals[3].Set(-1.0f, 0.0f); m_centroid = center; b2Transform xf; xf.p = center; xf.q.Set(angle); // Transform vertices and normals. for (int32 i = 0; i < m_count; ++i) { m_vertices[i] = b2Mul(xf, m_vertices[i]); m_normals[i] = b2Mul(xf.q, m_normals[i]); } } int32 b2PolygonShape::GetChildCount() const { return 1; } static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count) { b2Assert(count >= 3); b2Vec2 c; c.Set(0.0f, 0.0f); float32 area = 0.0f; // pRef is the reference point for forming triangles. // It's location doesn't change the result (except for rounding error). b2Vec2 pRef(0.0f, 0.0f); #if 0 // This code would put the reference point inside the polygon. for (int32 i = 0; i < count; ++i) { pRef += vs[i]; } pRef *= 1.0f / count; #endif const float32 inv3 = 1.0f / 3.0f; for (int32 i = 0; i < count; ++i) { // Triangle vertices. b2Vec2 p1 = pRef; b2Vec2 p2 = vs[i]; b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0]; b2Vec2 e1 = p2 - p1; b2Vec2 e2 = p3 - p1; float32 D = b2Cross(e1, e2); float32 triangleArea = 0.5f * D; area += triangleArea; // Area weighted centroid c += triangleArea * inv3 * (p1 + p2 + p3); } // Centroid b2Assert(area > b2_epsilon); c *= 1.0f / area; return c; } void b2PolygonShape::Set(const b2Vec2* vertices, int32 count) { b2Assert(3 <= count && count <= b2_maxPolygonVertices); if (count < 3) { SetAsBox(1.0f, 1.0f); return; } int32 n = b2Min(count, b2_maxPolygonVertices); // Perform welding and copy vertices into local buffer. b2Vec2 ps[b2_maxPolygonVertices]; int32 tempCount = 0; for (int32 i = 0; i < n; ++i) { b2Vec2 v = vertices[i]; bool unique = true; for (int32 j = 0; j < tempCount; ++j) { if (b2DistanceSquared(v, ps[j]) < 0.5f * b2_linearSlop) { unique = false; break; } } if (unique) { ps[tempCount++] = v; } } n = tempCount; if (n < 3) { // Polygon is degenerate. b2Assert(false); SetAsBox(1.0f, 1.0f); return; } // Create the convex hull using the Gift wrapping algorithm // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm // Find the right most point on the hull int32 i0 = 0; float32 x0 = ps[0].x; for (int32 i = 1; i < n; ++i) { float32 x = ps[i].x; if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) { i0 = i; x0 = x; } } int32 hull[b2_maxPolygonVertices]; int32 m = 0; int32 ih = i0; for (;;) { hull[m] = ih; int32 ie = 0; for (int32 j = 1; j < n; ++j) { if (ie == ih) { ie = j; continue; } b2Vec2 r = ps[ie] - ps[hull[m]]; b2Vec2 v = ps[j] - ps[hull[m]]; float32 c = b2Cross(r, v); if (c < 0.0f) { ie = j; } // Collinearity check if (c == 0.0f && v.LengthSquared() > r.LengthSquared()) { ie = j; } } ++m; ih = ie; if (ie == i0) { break; } } m_count = m; // Copy vertices. for (int32 i = 0; i < m; ++i) { m_vertices[i] = ps[hull[i]]; } // Compute normals. Ensure the edges have non-zero length. for (int32 i = 0; i < m; ++i) { int32 i1 = i; int32 i2 = i + 1 < m ? i + 1 : 0; b2Vec2 edge = m_vertices[i2] - m_vertices[i1]; b2Assert(edge.LengthSquared() > b2_epsilon * b2_epsilon); m_normals[i] = b2Cross(edge, 1.0f); m_normals[i].Normalize(); } // Compute the polygon centroid. m_centroid = ComputeCentroid(m_vertices, m); } bool b2PolygonShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const { b2Vec2 pLocal = b2MulT(xf.q, p - xf.p); for (int32 i = 0; i < m_count; ++i) { float32 dot = b2Dot(m_normals[i], pLocal - m_vertices[i]); if (dot > 0.0f) { return false; } } return true; } bool b2PolygonShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& xf, int32 childIndex) const { B2_NOT_USED(childIndex); // Put the ray into the polygon's frame of reference. b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p); b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p); b2Vec2 d = p2 - p1; float32 lower = 0.0f, upper = input.maxFraction; int32 index = -1; for (int32 i = 0; i < m_count; ++i) { // p = p1 + a * d // dot(normal, p - v) = 0 // dot(normal, p1 - v) + a * dot(normal, d) = 0 float32 numerator = b2Dot(m_normals[i], m_vertices[i] - p1); float32 denominator = b2Dot(m_normals[i], d); if (denominator == 0.0f) { if (numerator < 0.0f) { return false; } } else { // Note: we want this predicate without division: // lower < numerator / denominator, where denominator < 0 // Since denominator < 0, we have to flip the inequality: // lower < numerator / denominator <==> denominator * lower > numerator. if (denominator < 0.0f && numerator < lower * denominator) { // Increase lower. // The segment enters this half-space. lower = numerator / denominator; index = i; } else if (denominator > 0.0f && numerator < upper * denominator) { // Decrease upper. // The segment exits this half-space. upper = numerator / denominator; } } // The use of epsilon here causes the assert on lower to trip // in some cases. Apparently the use of epsilon was to make edge // shapes work, but now those are handled separately. //if (upper < lower - b2_epsilon) if (upper < lower) { return false; } } b2Assert(0.0f <= lower && lower <= input.maxFraction); if (index >= 0) { output->fraction = lower; output->normal = b2Mul(xf.q, m_normals[index]); return true; } return false; } void b2PolygonShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const { B2_NOT_USED(childIndex); b2Vec2 lower = b2Mul(xf, m_vertices[0]); b2Vec2 upper = lower; for (int32 i = 1; i < m_count; ++i) { b2Vec2 v = b2Mul(xf, m_vertices[i]); lower = b2Min(lower, v); upper = b2Max(upper, v); } b2Vec2 r(m_radius, m_radius); aabb->lowerBound = lower - r; aabb->upperBound = upper + r; } void b2PolygonShape::ComputeMass(b2MassData* massData, float32 density) const { // Polygon mass, centroid, and inertia. // Let rho be the polygon density in mass per unit area. // Then: // mass = rho * int(dA) // centroid.x = (1/mass) * rho * int(x * dA) // centroid.y = (1/mass) * rho * int(y * dA) // I = rho * int((x*x + y*y) * dA) // // We can compute these integrals by summing all the integrals // for each triangle of the polygon. To evaluate the integral // for a single triangle, we make a change of variables to // the (u,v) coordinates of the triangle: // x = x0 + e1x * u + e2x * v // y = y0 + e1y * u + e2y * v // where 0 <= u && 0 <= v && u + v <= 1. // // We integrate u from [0,1-v] and then v from [0,1]. // We also need to use the Jacobian of the transformation: // D = cross(e1, e2) // // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3) // // The rest of the derivation is handled by computer algebra. b2Assert(m_count >= 3); b2Vec2 center; center.Set(0.0f, 0.0f); float32 area = 0.0f; float32 I = 0.0f; // s is the reference point for forming triangles. // It's location doesn't change the result (except for rounding error). b2Vec2 s(0.0f, 0.0f); // This code would put the reference point inside the polygon. for (int32 i = 0; i < m_count; ++i) { s += m_vertices[i]; } s *= 1.0f / m_count; const float32 k_inv3 = 1.0f / 3.0f; for (int32 i = 0; i < m_count; ++i) { // Triangle vertices. b2Vec2 e1 = m_vertices[i] - s; b2Vec2 e2 = i + 1 < m_count ? m_vertices[i+1] - s : m_vertices[0] - s; float32 D = b2Cross(e1, e2); float32 triangleArea = 0.5f * D; area += triangleArea; // Area weighted centroid center += triangleArea * k_inv3 * (e1 + e2); float32 ex1 = e1.x, ey1 = e1.y; float32 ex2 = e2.x, ey2 = e2.y; float32 intx2 = ex1*ex1 + ex2*ex1 + ex2*ex2; float32 inty2 = ey1*ey1 + ey2*ey1 + ey2*ey2; I += (0.25f * k_inv3 * D) * (intx2 + inty2); } // Total mass massData->mass = density * area; // Center of mass b2Assert(area > b2_epsilon); center *= 1.0f / area; massData->center = center + s; // Inertia tensor relative to the local origin (point s). massData->I = density * I; // Shift to center of mass then to original body origin. massData->I += massData->mass * (b2Dot(massData->center, massData->center) - b2Dot(center, center)); } bool b2PolygonShape::Validate() const { for (int32 i = 0; i < m_count; ++i) { int32 i1 = i; int32 i2 = i < m_count - 1 ? i1 + 1 : 0; b2Vec2 p = m_vertices[i1]; b2Vec2 e = m_vertices[i2] - p; for (int32 j = 0; j < m_count; ++j) { if (j == i1 || j == i2) { continue; } b2Vec2 v = m_vertices[j] - p; float32 c = b2Cross(e, v); if (c < 0.0f) { return false; } } } return true; } qml-box2d/Box2D/Collision/Shapes/b2EdgeShape.cpp0000664000000000000000000000637312310072714016432 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #include #include void b2EdgeShape::Set(const b2Vec2& v1, const b2Vec2& v2) { m_vertex1 = v1; m_vertex2 = v2; m_hasVertex0 = false; m_hasVertex3 = false; } b2Shape* b2EdgeShape::Clone(b2BlockAllocator* allocator) const { void* mem = allocator->Allocate(sizeof(b2EdgeShape)); b2EdgeShape* clone = new (mem) b2EdgeShape; *clone = *this; return clone; } int32 b2EdgeShape::GetChildCount() const { return 1; } bool b2EdgeShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const { B2_NOT_USED(xf); B2_NOT_USED(p); return false; } // p = p1 + t * d // v = v1 + s * e // p1 + t * d = v1 + s * e // s * e - t * d = p1 - v1 bool b2EdgeShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& xf, int32 childIndex) const { B2_NOT_USED(childIndex); // Put the ray into the edge's frame of reference. b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p); b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p); b2Vec2 d = p2 - p1; b2Vec2 v1 = m_vertex1; b2Vec2 v2 = m_vertex2; b2Vec2 e = v2 - v1; b2Vec2 normal(e.y, -e.x); normal.Normalize(); // q = p1 + t * d // dot(normal, q - v1) = 0 // dot(normal, p1 - v1) + t * dot(normal, d) = 0 float32 numerator = b2Dot(normal, v1 - p1); float32 denominator = b2Dot(normal, d); if (denominator == 0.0f) { return false; } float32 t = numerator / denominator; if (t < 0.0f || input.maxFraction < t) { return false; } b2Vec2 q = p1 + t * d; // q = v1 + s * r // s = dot(q - v1, r) / dot(r, r) b2Vec2 r = v2 - v1; float32 rr = b2Dot(r, r); if (rr == 0.0f) { return false; } float32 s = b2Dot(q - v1, r) / rr; if (s < 0.0f || 1.0f < s) { return false; } output->fraction = t; if (numerator > 0.0f) { output->normal = -b2Mul(xf.q, normal); } else { output->normal = b2Mul(xf.q, normal); } return true; } void b2EdgeShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const { B2_NOT_USED(childIndex); b2Vec2 v1 = b2Mul(xf, m_vertex1); b2Vec2 v2 = b2Mul(xf, m_vertex2); b2Vec2 lower = b2Min(v1, v2); b2Vec2 upper = b2Max(v1, v2); b2Vec2 r(m_radius, m_radius); aabb->lowerBound = lower - r; aabb->upperBound = upper + r; } void b2EdgeShape::ComputeMass(b2MassData* massData, float32 density) const { B2_NOT_USED(density); massData->mass = 0.0f; massData->center = 0.5f * (m_vertex1 + m_vertex2); massData->I = 0.0f; } qml-box2d/Box2D/Collision/Shapes/b2EdgeShape.h0000644000000000000000000000445512241175670016104 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_EDGE_SHAPE_H #define B2_EDGE_SHAPE_H #include /// A line segment (edge) shape. These can be connected in chains or loops /// to other edge shapes. The connectivity information is used to ensure /// correct contact normals. class b2EdgeShape : public b2Shape { public: b2EdgeShape(); /// Set this as an isolated edge. void Set(const b2Vec2& v1, const b2Vec2& v2); /// Implement b2Shape. b2Shape* Clone(b2BlockAllocator* allocator) const; /// @see b2Shape::GetChildCount int32 GetChildCount() const; /// @see b2Shape::TestPoint bool TestPoint(const b2Transform& transform, const b2Vec2& p) const; /// Implement b2Shape. bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeAABB void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const; /// @see b2Shape::ComputeMass void ComputeMass(b2MassData* massData, float32 density) const; /// These are the edge vertices b2Vec2 m_vertex1, m_vertex2; /// Optional adjacent vertices. These are used for smooth collision. b2Vec2 m_vertex0, m_vertex3; bool m_hasVertex0, m_hasVertex3; }; inline b2EdgeShape::b2EdgeShape() { m_type = e_edge; m_radius = b2_polygonRadius; m_vertex0.x = 0.0f; m_vertex0.y = 0.0f; m_vertex3.x = 0.0f; m_vertex3.y = 0.0f; m_hasVertex0 = false; m_hasVertex3 = false; } #endif qml-box2d/Box2D/Collision/b2BroadPhase.h0000664000000000000000000001545412310072714015037 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_BROAD_PHASE_H #define B2_BROAD_PHASE_H #include #include #include #include struct b2Pair { int32 proxyIdA; int32 proxyIdB; }; /// The broad-phase is used for computing pairs and performing volume queries and ray casts. /// This broad-phase does not persist pairs. Instead, this reports potentially new pairs. /// It is up to the client to consume the new pairs and to track subsequent overlap. class b2BroadPhase { public: enum { e_nullProxy = -1 }; b2BroadPhase(); ~b2BroadPhase(); /// Create a proxy with an initial AABB. Pairs are not reported until /// UpdatePairs is called. int32 CreateProxy(const b2AABB& aabb, void* userData); /// Destroy a proxy. It is up to the client to remove any pairs. void DestroyProxy(int32 proxyId); /// Call MoveProxy as many times as you like, then when you are done /// call UpdatePairs to finalized the proxy pairs (for your time step). void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement); /// Call to trigger a re-processing of it's pairs on the next call to UpdatePairs. void TouchProxy(int32 proxyId); /// Get the fat AABB for a proxy. const b2AABB& GetFatAABB(int32 proxyId) const; /// Get user data from a proxy. Returns NULL if the id is invalid. void* GetUserData(int32 proxyId) const; /// Test overlap of fat AABBs. bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const; /// Get the number of proxies. int32 GetProxyCount() const; /// Update the pairs. This results in pair callbacks. This can only add pairs. template void UpdatePairs(T* callback); /// Query an AABB for overlapping proxies. The callback class /// is called for each proxy that overlaps the supplied AABB. template void Query(T* callback, const b2AABB& aabb) const; /// Ray-cast against the proxies in the tree. This relies on the callback /// to perform a exact ray-cast in the case were the proxy contains a shape. /// The callback also performs the any collision filtering. This has performance /// roughly equal to k * log(n), where k is the number of collisions and n is the /// number of proxies in the tree. /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). /// @param callback a callback class that is called for each proxy that is hit by the ray. template void RayCast(T* callback, const b2RayCastInput& input) const; /// Get the height of the embedded tree. int32 GetTreeHeight() const; /// Get the balance of the embedded tree. int32 GetTreeBalance() const; /// Get the quality metric of the embedded tree. float32 GetTreeQuality() const; /// Shift the world origin. Useful for large worlds. /// The shift formula is: position -= newOrigin /// @param newOrigin the new origin with respect to the old origin void ShiftOrigin(const b2Vec2& newOrigin); private: friend class b2DynamicTree; void BufferMove(int32 proxyId); void UnBufferMove(int32 proxyId); bool QueryCallback(int32 proxyId); b2DynamicTree m_tree; int32 m_proxyCount; int32* m_moveBuffer; int32 m_moveCapacity; int32 m_moveCount; b2Pair* m_pairBuffer; int32 m_pairCapacity; int32 m_pairCount; int32 m_queryProxyId; }; /// This is used to sort pairs. inline bool b2PairLessThan(const b2Pair& pair1, const b2Pair& pair2) { if (pair1.proxyIdA < pair2.proxyIdA) { return true; } if (pair1.proxyIdA == pair2.proxyIdA) { return pair1.proxyIdB < pair2.proxyIdB; } return false; } inline void* b2BroadPhase::GetUserData(int32 proxyId) const { return m_tree.GetUserData(proxyId); } inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const { const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA); const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB); return b2TestOverlap(aabbA, aabbB); } inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const { return m_tree.GetFatAABB(proxyId); } inline int32 b2BroadPhase::GetProxyCount() const { return m_proxyCount; } inline int32 b2BroadPhase::GetTreeHeight() const { return m_tree.GetHeight(); } inline int32 b2BroadPhase::GetTreeBalance() const { return m_tree.GetMaxBalance(); } inline float32 b2BroadPhase::GetTreeQuality() const { return m_tree.GetAreaRatio(); } template void b2BroadPhase::UpdatePairs(T* callback) { // Reset pair buffer m_pairCount = 0; // Perform tree queries for all moving proxies. for (int32 i = 0; i < m_moveCount; ++i) { m_queryProxyId = m_moveBuffer[i]; if (m_queryProxyId == e_nullProxy) { continue; } // We have to query the tree with the fat AABB so that // we don't fail to create a pair that may touch later. const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId); // Query tree, create pairs and add them pair buffer. m_tree.Query(this, fatAABB); } // Reset move buffer m_moveCount = 0; // Sort the pair buffer to expose duplicates. std::sort(m_pairBuffer, m_pairBuffer + m_pairCount, b2PairLessThan); // Send the pairs back to the client. int32 i = 0; while (i < m_pairCount) { b2Pair* primaryPair = m_pairBuffer + i; void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA); void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB); callback->AddPair(userDataA, userDataB); ++i; // Skip any duplicate pairs. while (i < m_pairCount) { b2Pair* pair = m_pairBuffer + i; if (pair->proxyIdA != primaryPair->proxyIdA || pair->proxyIdB != primaryPair->proxyIdB) { break; } ++i; } } // Try to keep the tree balanced. //m_tree.Rebalance(4); } template inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const { m_tree.Query(callback, aabb); } template inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const { m_tree.RayCast(callback, input); } inline void b2BroadPhase::ShiftOrigin(const b2Vec2& newOrigin) { m_tree.ShiftOrigin(newOrigin); } #endif qml-box2d/Box2D/Collision/b2TimeOfImpact.cpp0000664000000000000000000002664612310072714015710 0ustar /* * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include float32 b2_toiTime, b2_toiMaxTime; int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; int32 b2_toiRootIters, b2_toiMaxRootIters; // struct b2SeparationFunction { enum Type { e_points, e_faceA, e_faceB }; // TODO_ERIN might not need to return the separation float32 Initialize(const b2SimplexCache* cache, const b2DistanceProxy* proxyA, const b2Sweep& sweepA, const b2DistanceProxy* proxyB, const b2Sweep& sweepB, float32 t1) { m_proxyA = proxyA; m_proxyB = proxyB; int32 count = cache->count; b2Assert(0 < count && count < 3); m_sweepA = sweepA; m_sweepB = sweepB; b2Transform xfA, xfB; m_sweepA.GetTransform(&xfA, t1); m_sweepB.GetTransform(&xfB, t1); if (count == 1) { m_type = e_points; b2Vec2 localPointA = m_proxyA->GetVertex(cache->indexA[0]); b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]); b2Vec2 pointA = b2Mul(xfA, localPointA); b2Vec2 pointB = b2Mul(xfB, localPointB); m_axis = pointB - pointA; float32 s = m_axis.Normalize(); return s; } else if (cache->indexA[0] == cache->indexA[1]) { // Two points on B and one on A. m_type = e_faceB; b2Vec2 localPointB1 = proxyB->GetVertex(cache->indexB[0]); b2Vec2 localPointB2 = proxyB->GetVertex(cache->indexB[1]); m_axis = b2Cross(localPointB2 - localPointB1, 1.0f); m_axis.Normalize(); b2Vec2 normal = b2Mul(xfB.q, m_axis); m_localPoint = 0.5f * (localPointB1 + localPointB2); b2Vec2 pointB = b2Mul(xfB, m_localPoint); b2Vec2 localPointA = proxyA->GetVertex(cache->indexA[0]); b2Vec2 pointA = b2Mul(xfA, localPointA); float32 s = b2Dot(pointA - pointB, normal); if (s < 0.0f) { m_axis = -m_axis; s = -s; } return s; } else { // Two points on A and one or two points on B. m_type = e_faceA; b2Vec2 localPointA1 = m_proxyA->GetVertex(cache->indexA[0]); b2Vec2 localPointA2 = m_proxyA->GetVertex(cache->indexA[1]); m_axis = b2Cross(localPointA2 - localPointA1, 1.0f); m_axis.Normalize(); b2Vec2 normal = b2Mul(xfA.q, m_axis); m_localPoint = 0.5f * (localPointA1 + localPointA2); b2Vec2 pointA = b2Mul(xfA, m_localPoint); b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]); b2Vec2 pointB = b2Mul(xfB, localPointB); float32 s = b2Dot(pointB - pointA, normal); if (s < 0.0f) { m_axis = -m_axis; s = -s; } return s; } } // float32 FindMinSeparation(int32* indexA, int32* indexB, float32 t) const { b2Transform xfA, xfB; m_sweepA.GetTransform(&xfA, t); m_sweepB.GetTransform(&xfB, t); switch (m_type) { case e_points: { b2Vec2 axisA = b2MulT(xfA.q, m_axis); b2Vec2 axisB = b2MulT(xfB.q, -m_axis); *indexA = m_proxyA->GetSupport(axisA); *indexB = m_proxyB->GetSupport(axisB); b2Vec2 localPointA = m_proxyA->GetVertex(*indexA); b2Vec2 localPointB = m_proxyB->GetVertex(*indexB); b2Vec2 pointA = b2Mul(xfA, localPointA); b2Vec2 pointB = b2Mul(xfB, localPointB); float32 separation = b2Dot(pointB - pointA, m_axis); return separation; } case e_faceA: { b2Vec2 normal = b2Mul(xfA.q, m_axis); b2Vec2 pointA = b2Mul(xfA, m_localPoint); b2Vec2 axisB = b2MulT(xfB.q, -normal); *indexA = -1; *indexB = m_proxyB->GetSupport(axisB); b2Vec2 localPointB = m_proxyB->GetVertex(*indexB); b2Vec2 pointB = b2Mul(xfB, localPointB); float32 separation = b2Dot(pointB - pointA, normal); return separation; } case e_faceB: { b2Vec2 normal = b2Mul(xfB.q, m_axis); b2Vec2 pointB = b2Mul(xfB, m_localPoint); b2Vec2 axisA = b2MulT(xfA.q, -normal); *indexB = -1; *indexA = m_proxyA->GetSupport(axisA); b2Vec2 localPointA = m_proxyA->GetVertex(*indexA); b2Vec2 pointA = b2Mul(xfA, localPointA); float32 separation = b2Dot(pointA - pointB, normal); return separation; } default: b2Assert(false); *indexA = -1; *indexB = -1; return 0.0f; } } // float32 Evaluate(int32 indexA, int32 indexB, float32 t) const { b2Transform xfA, xfB; m_sweepA.GetTransform(&xfA, t); m_sweepB.GetTransform(&xfB, t); switch (m_type) { case e_points: { b2Vec2 localPointA = m_proxyA->GetVertex(indexA); b2Vec2 localPointB = m_proxyB->GetVertex(indexB); b2Vec2 pointA = b2Mul(xfA, localPointA); b2Vec2 pointB = b2Mul(xfB, localPointB); float32 separation = b2Dot(pointB - pointA, m_axis); return separation; } case e_faceA: { b2Vec2 normal = b2Mul(xfA.q, m_axis); b2Vec2 pointA = b2Mul(xfA, m_localPoint); b2Vec2 localPointB = m_proxyB->GetVertex(indexB); b2Vec2 pointB = b2Mul(xfB, localPointB); float32 separation = b2Dot(pointB - pointA, normal); return separation; } case e_faceB: { b2Vec2 normal = b2Mul(xfB.q, m_axis); b2Vec2 pointB = b2Mul(xfB, m_localPoint); b2Vec2 localPointA = m_proxyA->GetVertex(indexA); b2Vec2 pointA = b2Mul(xfA, localPointA); float32 separation = b2Dot(pointA - pointB, normal); return separation; } default: b2Assert(false); return 0.0f; } } const b2DistanceProxy* m_proxyA; const b2DistanceProxy* m_proxyB; b2Sweep m_sweepA, m_sweepB; Type m_type; b2Vec2 m_localPoint; b2Vec2 m_axis; }; // CCD via the local separating axis method. This seeks progression // by computing the largest time at which separation is maintained. void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input) { b2Timer timer; ++b2_toiCalls; output->state = b2TOIOutput::e_unknown; output->t = input->tMax; const b2DistanceProxy* proxyA = &input->proxyA; const b2DistanceProxy* proxyB = &input->proxyB; b2Sweep sweepA = input->sweepA; b2Sweep sweepB = input->sweepB; // Large rotations can make the root finder fail, so we normalize the // sweep angles. sweepA.Normalize(); sweepB.Normalize(); float32 tMax = input->tMax; float32 totalRadius = proxyA->m_radius + proxyB->m_radius; float32 target = b2Max(b2_linearSlop, totalRadius - 3.0f * b2_linearSlop); float32 tolerance = 0.25f * b2_linearSlop; b2Assert(target > tolerance); float32 t1 = 0.0f; const int32 k_maxIterations = 20; // TODO_ERIN b2Settings int32 iter = 0; // Prepare input for distance query. b2SimplexCache cache; cache.count = 0; b2DistanceInput distanceInput; distanceInput.proxyA = input->proxyA; distanceInput.proxyB = input->proxyB; distanceInput.useRadii = false; // The outer loop progressively attempts to compute new separating axes. // This loop terminates when an axis is repeated (no progress is made). for(;;) { b2Transform xfA, xfB; sweepA.GetTransform(&xfA, t1); sweepB.GetTransform(&xfB, t1); // Get the distance between shapes. We can also use the results // to get a separating axis. distanceInput.transformA = xfA; distanceInput.transformB = xfB; b2DistanceOutput distanceOutput; b2Distance(&distanceOutput, &cache, &distanceInput); // If the shapes are overlapped, we give up on continuous collision. if (distanceOutput.distance <= 0.0f) { // Failure! output->state = b2TOIOutput::e_overlapped; output->t = 0.0f; break; } if (distanceOutput.distance < target + tolerance) { // Victory! output->state = b2TOIOutput::e_touching; output->t = t1; break; } // Initialize the separating axis. b2SeparationFunction fcn; fcn.Initialize(&cache, proxyA, sweepA, proxyB, sweepB, t1); #if 0 // Dump the curve seen by the root finder { const int32 N = 100; float32 dx = 1.0f / N; float32 xs[N+1]; float32 fs[N+1]; float32 x = 0.0f; for (int32 i = 0; i <= N; ++i) { sweepA.GetTransform(&xfA, x); sweepB.GetTransform(&xfB, x); float32 f = fcn.Evaluate(xfA, xfB) - target; printf("%g %g\n", x, f); xs[i] = x; fs[i] = f; x += dx; } } #endif // Compute the TOI on the separating axis. We do this by successively // resolving the deepest point. This loop is bounded by the number of vertices. bool done = false; float32 t2 = tMax; int32 pushBackIter = 0; for (;;) { // Find the deepest point at t2. Store the witness point indices. int32 indexA, indexB; float32 s2 = fcn.FindMinSeparation(&indexA, &indexB, t2); // Is the final configuration separated? if (s2 > target + tolerance) { // Victory! output->state = b2TOIOutput::e_separated; output->t = tMax; done = true; break; } // Has the separation reached tolerance? if (s2 > target - tolerance) { // Advance the sweeps t1 = t2; break; } // Compute the initial separation of the witness points. float32 s1 = fcn.Evaluate(indexA, indexB, t1); // Check for initial overlap. This might happen if the root finder // runs out of iterations. if (s1 < target - tolerance) { output->state = b2TOIOutput::e_failed; output->t = t1; done = true; break; } // Check for touching if (s1 <= target + tolerance) { // Victory! t1 should hold the TOI (could be 0.0). output->state = b2TOIOutput::e_touching; output->t = t1; done = true; break; } // Compute 1D root of: f(x) - target = 0 int32 rootIterCount = 0; float32 a1 = t1, a2 = t2; for (;;) { // Use a mix of the secant rule and bisection. float32 t; if (rootIterCount & 1) { // Secant rule to improve convergence. t = a1 + (target - s1) * (a2 - a1) / (s2 - s1); } else { // Bisection to guarantee progress. t = 0.5f * (a1 + a2); } ++rootIterCount; ++b2_toiRootIters; float32 s = fcn.Evaluate(indexA, indexB, t); if (b2Abs(s - target) < tolerance) { // t2 holds a tentative value for t1 t2 = t; break; } // Ensure we continue to bracket the root. if (s > target) { a1 = t; s1 = s; } else { a2 = t; s2 = s; } if (rootIterCount == 50) { break; } } b2_toiMaxRootIters = b2Max(b2_toiMaxRootIters, rootIterCount); ++pushBackIter; if (pushBackIter == b2_maxPolygonVertices) { break; } } ++iter; ++b2_toiIters; if (done) { break; } if (iter == k_maxIterations) { // Root finder got stuck. Semi-victory. output->state = b2TOIOutput::e_failed; output->t = t1; break; } } b2_toiMaxIters = b2Max(b2_toiMaxIters, iter); float32 time = timer.GetMilliseconds(); b2_toiMaxTime = b2Max(b2_toiMaxTime, time); b2_toiTime += time; } qml-box2d/Box2D/Collision/b2Collision.h0000664000000000000000000002155612310072714014762 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_COLLISION_H #define B2_COLLISION_H #include #include /// @file /// Structures and functions used for computing contact points, distance /// queries, and TOI queries. class b2Shape; class b2CircleShape; class b2EdgeShape; class b2PolygonShape; const uint8 b2_nullFeature = UCHAR_MAX; /// The features that intersect to form the contact point /// This must be 4 bytes or less. struct b2ContactFeature { enum Type { e_vertex = 0, e_face = 1 }; uint8 indexA; ///< Feature index on shapeA uint8 indexB; ///< Feature index on shapeB uint8 typeA; ///< The feature type on shapeA uint8 typeB; ///< The feature type on shapeB }; /// Contact ids to facilitate warm starting. union b2ContactID { b2ContactFeature cf; uint32 key; ///< Used to quickly compare contact ids. }; /// A manifold point is a contact point belonging to a contact /// manifold. It holds details related to the geometry and dynamics /// of the contact points. /// The local point usage depends on the manifold type: /// -e_circles: the local center of circleB /// -e_faceA: the local center of cirlceB or the clip point of polygonB /// -e_faceB: the clip point of polygonA /// This structure is stored across time steps, so we keep it small. /// Note: the impulses are used for internal caching and may not /// provide reliable contact forces, especially for high speed collisions. struct b2ManifoldPoint { b2Vec2 localPoint; ///< usage depends on manifold type float32 normalImpulse; ///< the non-penetration impulse float32 tangentImpulse; ///< the friction impulse b2ContactID id; ///< uniquely identifies a contact point between two shapes }; /// A manifold for two touching convex shapes. /// Box2D supports multiple types of contact: /// - clip point versus plane with radius /// - point versus point with radius (circles) /// The local point usage depends on the manifold type: /// -e_circles: the local center of circleA /// -e_faceA: the center of faceA /// -e_faceB: the center of faceB /// Similarly the local normal usage: /// -e_circles: not used /// -e_faceA: the normal on polygonA /// -e_faceB: the normal on polygonB /// We store contacts in this way so that position correction can /// account for movement, which is critical for continuous physics. /// All contact scenarios must be expressed in one of these types. /// This structure is stored across time steps, so we keep it small. struct b2Manifold { enum Type { e_circles, e_faceA, e_faceB }; b2ManifoldPoint points[b2_maxManifoldPoints]; ///< the points of contact b2Vec2 localNormal; ///< not use for Type::e_points b2Vec2 localPoint; ///< usage depends on manifold type Type type; int32 pointCount; ///< the number of manifold points }; /// This is used to compute the current state of a contact manifold. struct b2WorldManifold { /// Evaluate the manifold with supplied transforms. This assumes /// modest motion from the original state. This does not change the /// point count, impulses, etc. The radii must come from the shapes /// that generated the manifold. void Initialize(const b2Manifold* manifold, const b2Transform& xfA, float32 radiusA, const b2Transform& xfB, float32 radiusB); b2Vec2 normal; ///< world vector pointing from A to B b2Vec2 points[b2_maxManifoldPoints]; ///< world contact point (point of intersection) float32 separations[b2_maxManifoldPoints]; ///< a negative value indicates overlap, in meters }; /// This is used for determining the state of contact points. enum b2PointState { b2_nullState, ///< point does not exist b2_addState, ///< point was added in the update b2_persistState, ///< point persisted across the update b2_removeState ///< point was removed in the update }; /// Compute the point states given two manifolds. The states pertain to the transition from manifold1 /// to manifold2. So state1 is either persist or remove while state2 is either add or persist. void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], const b2Manifold* manifold1, const b2Manifold* manifold2); /// Used for computing contact manifolds. struct b2ClipVertex { b2Vec2 v; b2ContactID id; }; /// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). struct b2RayCastInput { b2Vec2 p1, p2; float32 maxFraction; }; /// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2 /// come from b2RayCastInput. struct b2RayCastOutput { b2Vec2 normal; float32 fraction; }; /// An axis aligned bounding box. struct b2AABB { /// Verify that the bounds are sorted. bool IsValid() const; /// Get the center of the AABB. b2Vec2 GetCenter() const { return 0.5f * (lowerBound + upperBound); } /// Get the extents of the AABB (half-widths). b2Vec2 GetExtents() const { return 0.5f * (upperBound - lowerBound); } /// Get the perimeter length float32 GetPerimeter() const { float32 wx = upperBound.x - lowerBound.x; float32 wy = upperBound.y - lowerBound.y; return 2.0f * (wx + wy); } /// Combine an AABB into this one. void Combine(const b2AABB& aabb) { lowerBound = b2Min(lowerBound, aabb.lowerBound); upperBound = b2Max(upperBound, aabb.upperBound); } /// Combine two AABBs into this one. void Combine(const b2AABB& aabb1, const b2AABB& aabb2) { lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound); upperBound = b2Max(aabb1.upperBound, aabb2.upperBound); } /// Does this aabb contain the provided AABB. bool Contains(const b2AABB& aabb) const { bool result = true; result = result && lowerBound.x <= aabb.lowerBound.x; result = result && lowerBound.y <= aabb.lowerBound.y; result = result && aabb.upperBound.x <= upperBound.x; result = result && aabb.upperBound.y <= upperBound.y; return result; } bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const; b2Vec2 lowerBound; ///< the lower vertex b2Vec2 upperBound; ///< the upper vertex }; /// Compute the collision manifold between two circles. void b2CollideCircles(b2Manifold* manifold, const b2CircleShape* circleA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB); /// Compute the collision manifold between a polygon and a circle. void b2CollidePolygonAndCircle(b2Manifold* manifold, const b2PolygonShape* polygonA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB); /// Compute the collision manifold between two polygons. void b2CollidePolygons(b2Manifold* manifold, const b2PolygonShape* polygonA, const b2Transform& xfA, const b2PolygonShape* polygonB, const b2Transform& xfB); /// Compute the collision manifold between an edge and a circle. void b2CollideEdgeAndCircle(b2Manifold* manifold, const b2EdgeShape* polygonA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB); /// Compute the collision manifold between an edge and a circle. void b2CollideEdgeAndPolygon(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, const b2PolygonShape* circleB, const b2Transform& xfB); /// Clipping for contact manifolds. int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], const b2Vec2& normal, float32 offset, int32 vertexIndexA); /// Determine if two generic shapes overlap. bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, const b2Shape* shapeB, int32 indexB, const b2Transform& xfA, const b2Transform& xfB); // ---------------- Inline Functions ------------------------------------------ inline bool b2AABB::IsValid() const { b2Vec2 d = upperBound - lowerBound; bool valid = d.x >= 0.0f && d.y >= 0.0f; valid = valid && lowerBound.IsValid() && upperBound.IsValid(); return valid; } inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b) { b2Vec2 d1, d2; d1 = b.lowerBound - a.upperBound; d2 = a.lowerBound - b.upperBound; if (d1.x > 0.0f || d1.y > 0.0f) return false; if (d2.x > 0.0f || d2.y > 0.0f) return false; return true; } #endif qml-box2d/Box2D/Collision/b2Collision.cpp0000664000000000000000000001443312310072714015311 0ustar /* * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include void b2WorldManifold::Initialize(const b2Manifold* manifold, const b2Transform& xfA, float32 radiusA, const b2Transform& xfB, float32 radiusB) { if (manifold->pointCount == 0) { return; } switch (manifold->type) { case b2Manifold::e_circles: { normal.Set(1.0f, 0.0f); b2Vec2 pointA = b2Mul(xfA, manifold->localPoint); b2Vec2 pointB = b2Mul(xfB, manifold->points[0].localPoint); if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon) { normal = pointB - pointA; normal.Normalize(); } b2Vec2 cA = pointA + radiusA * normal; b2Vec2 cB = pointB - radiusB * normal; points[0] = 0.5f * (cA + cB); separations[0] = b2Dot(cB - cA, normal); } break; case b2Manifold::e_faceA: { normal = b2Mul(xfA.q, manifold->localNormal); b2Vec2 planePoint = b2Mul(xfA, manifold->localPoint); for (int32 i = 0; i < manifold->pointCount; ++i) { b2Vec2 clipPoint = b2Mul(xfB, manifold->points[i].localPoint); b2Vec2 cA = clipPoint + (radiusA - b2Dot(clipPoint - planePoint, normal)) * normal; b2Vec2 cB = clipPoint - radiusB * normal; points[i] = 0.5f * (cA + cB); separations[i] = b2Dot(cB - cA, normal); } } break; case b2Manifold::e_faceB: { normal = b2Mul(xfB.q, manifold->localNormal); b2Vec2 planePoint = b2Mul(xfB, manifold->localPoint); for (int32 i = 0; i < manifold->pointCount; ++i) { b2Vec2 clipPoint = b2Mul(xfA, manifold->points[i].localPoint); b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal; b2Vec2 cA = clipPoint - radiusA * normal; points[i] = 0.5f * (cA + cB); separations[i] = b2Dot(cA - cB, normal); } // Ensure normal points from A to B. normal = -normal; } break; } } void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], const b2Manifold* manifold1, const b2Manifold* manifold2) { for (int32 i = 0; i < b2_maxManifoldPoints; ++i) { state1[i] = b2_nullState; state2[i] = b2_nullState; } // Detect persists and removes. for (int32 i = 0; i < manifold1->pointCount; ++i) { b2ContactID id = manifold1->points[i].id; state1[i] = b2_removeState; for (int32 j = 0; j < manifold2->pointCount; ++j) { if (manifold2->points[j].id.key == id.key) { state1[i] = b2_persistState; break; } } } // Detect persists and adds. for (int32 i = 0; i < manifold2->pointCount; ++i) { b2ContactID id = manifold2->points[i].id; state2[i] = b2_addState; for (int32 j = 0; j < manifold1->pointCount; ++j) { if (manifold1->points[j].id.key == id.key) { state2[i] = b2_persistState; break; } } } } // From Real-time Collision Detection, p179. bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const { float32 tmin = -b2_maxFloat; float32 tmax = b2_maxFloat; b2Vec2 p = input.p1; b2Vec2 d = input.p2 - input.p1; b2Vec2 absD = b2Abs(d); b2Vec2 normal; for (int32 i = 0; i < 2; ++i) { if (absD(i) < b2_epsilon) { // Parallel. if (p(i) < lowerBound(i) || upperBound(i) < p(i)) { return false; } } else { float32 inv_d = 1.0f / d(i); float32 t1 = (lowerBound(i) - p(i)) * inv_d; float32 t2 = (upperBound(i) - p(i)) * inv_d; // Sign of the normal vector. float32 s = -1.0f; if (t1 > t2) { b2Swap(t1, t2); s = 1.0f; } // Push the min up if (t1 > tmin) { normal.SetZero(); normal(i) = s; tmin = t1; } // Pull the max down tmax = b2Min(tmax, t2); if (tmin > tmax) { return false; } } } // Does the ray start inside the box? // Does the ray intersect beyond the max fraction? if (tmin < 0.0f || input.maxFraction < tmin) { return false; } // Intersection. output->fraction = tmin; output->normal = normal; return true; } // Sutherland-Hodgman clipping. int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], const b2Vec2& normal, float32 offset, int32 vertexIndexA) { // Start with no output points int32 numOut = 0; // Calculate the distance of end points to the line float32 distance0 = b2Dot(normal, vIn[0].v) - offset; float32 distance1 = b2Dot(normal, vIn[1].v) - offset; // If the points are behind the plane if (distance0 <= 0.0f) vOut[numOut++] = vIn[0]; if (distance1 <= 0.0f) vOut[numOut++] = vIn[1]; // If the points are on different sides of the plane if (distance0 * distance1 < 0.0f) { // Find intersection point of edge and plane float32 interp = distance0 / (distance0 - distance1); vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v); // VertexA is hitting edgeB. vOut[numOut].id.cf.indexA = static_cast(vertexIndexA); vOut[numOut].id.cf.indexB = vIn[0].id.cf.indexB; vOut[numOut].id.cf.typeA = b2ContactFeature::e_vertex; vOut[numOut].id.cf.typeB = b2ContactFeature::e_face; ++numOut; } return numOut; } bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, const b2Shape* shapeB, int32 indexB, const b2Transform& xfA, const b2Transform& xfB) { b2DistanceInput input; input.proxyA.Set(shapeA, indexA); input.proxyB.Set(shapeB, indexB); input.transformA = xfA; input.transformB = xfB; input.useRadii = true; b2SimplexCache cache; cache.count = 0; b2DistanceOutput output; b2Distance(&output, &cache, &input); return output.distance < 10.0f * b2_epsilon; } qml-box2d/Box2D/Collision/b2TimeOfImpact.h0000644000000000000000000000350712241175670015352 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_TIME_OF_IMPACT_H #define B2_TIME_OF_IMPACT_H #include #include /// Input parameters for b2TimeOfImpact struct b2TOIInput { b2DistanceProxy proxyA; b2DistanceProxy proxyB; b2Sweep sweepA; b2Sweep sweepB; float32 tMax; // defines sweep interval [0, tMax] }; // Output parameters for b2TimeOfImpact. struct b2TOIOutput { enum State { e_unknown, e_failed, e_overlapped, e_touching, e_separated }; State state; float32 t; }; /// Compute the upper bound on time before two shapes penetrate. Time is represented as /// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate, /// non-tunneling collision. If you change the time interval, you should call this function /// again. /// Note: use b2Distance to compute the contact point and normal at the time of impact. void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input); #endif qml-box2d/Box2D/box2d.pri0000664000000000000000000000757312310072714012234 0ustar # Box2D sources INCLUDEPATH += $$PWD SOURCES += \ $$PWD/Collision/Shapes/b2PolygonShape.cpp \ $$PWD/Collision/Shapes/b2EdgeShape.cpp \ $$PWD/Collision/Shapes/b2CircleShape.cpp \ $$PWD/Collision/Shapes/b2ChainShape.cpp \ $$PWD/Collision/b2TimeOfImpact.cpp \ $$PWD/Collision/b2DynamicTree.cpp \ $$PWD/Collision/b2Distance.cpp \ $$PWD/Collision/b2Collision.cpp \ $$PWD/Collision/b2CollidePolygon.cpp \ $$PWD/Collision/b2CollideEdge.cpp \ $$PWD/Collision/b2CollideCircle.cpp \ $$PWD/Collision/b2BroadPhase.cpp \ $$PWD/Common/b2Timer.cpp \ $$PWD/Common/b2StackAllocator.cpp \ $$PWD/Common/b2Settings.cpp \ $$PWD/Common/b2Math.cpp \ $$PWD/Common/b2Draw.cpp \ $$PWD/Common/b2BlockAllocator.cpp \ $$PWD/Dynamics/Contacts/b2PolygonContact.cpp \ $$PWD/Dynamics/Contacts/b2PolygonAndCircleContact.cpp \ $$PWD/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp \ $$PWD/Dynamics/Contacts/b2EdgeAndCircleContact.cpp \ $$PWD/Dynamics/Contacts/b2ContactSolver.cpp \ $$PWD/Dynamics/Contacts/b2Contact.cpp \ $$PWD/Dynamics/Contacts/b2CircleContact.cpp \ $$PWD/Dynamics/Contacts/b2ChainAndPolygonContact.cpp \ $$PWD/Dynamics/Contacts/b2ChainAndCircleContact.cpp \ $$PWD/Dynamics/Joints/b2WheelJoint.cpp \ $$PWD/Dynamics/Joints/b2WeldJoint.cpp \ $$PWD/Dynamics/Joints/b2RopeJoint.cpp \ $$PWD/Dynamics/Joints/b2RevoluteJoint.cpp \ $$PWD/Dynamics/Joints/b2PulleyJoint.cpp \ $$PWD/Dynamics/Joints/b2PrismaticJoint.cpp \ $$PWD/Dynamics/Joints/b2MouseJoint.cpp \ $$PWD/Dynamics/Joints/b2Joint.cpp \ $$PWD/Dynamics/Joints/b2GearJoint.cpp \ $$PWD/Dynamics/Joints/b2FrictionJoint.cpp \ $$PWD/Dynamics/Joints/b2DistanceJoint.cpp \ $$PWD/Dynamics/b2WorldCallbacks.cpp \ $$PWD/Dynamics/b2World.cpp \ $$PWD/Dynamics/b2Island.cpp \ $$PWD/Dynamics/b2Fixture.cpp \ $$PWD/Dynamics/b2ContactManager.cpp \ $$PWD/Dynamics/b2Body.cpp \ $$PWD/Rope/b2Rope.cpp \ $$PWD/Dynamics/Joints/b2MotorJoint.cpp HEADERS += \ $$PWD/Box2D.h \ $$PWD/Collision/Shapes/b2Shape.h \ $$PWD/Collision/Shapes/b2PolygonShape.h \ $$PWD/Collision/Shapes/b2EdgeShape.h \ $$PWD/Collision/Shapes/b2CircleShape.h \ $$PWD/Collision/Shapes/b2ChainShape.h \ $$PWD/Collision/b2TimeOfImpact.h \ $$PWD/Collision/b2DynamicTree.h \ $$PWD/Collision/b2Distance.h \ $$PWD/Collision/b2Collision.h \ $$PWD/Collision/b2BroadPhase.h \ $$PWD/Common/b2Timer.h \ $$PWD/Common/b2StackAllocator.h \ $$PWD/Common/b2Settings.h \ $$PWD/Common/b2Math.h \ $$PWD/Common/b2GrowableStack.h \ $$PWD/Common/b2Draw.h \ $$PWD/Common/b2BlockAllocator.h \ $$PWD/Dynamics/Contacts/b2PolygonContact.h \ $$PWD/Dynamics/Contacts/b2PolygonAndCircleContact.h \ $$PWD/Dynamics/Contacts/b2EdgeAndPolygonContact.h \ $$PWD/Dynamics/Contacts/b2EdgeAndCircleContact.h \ $$PWD/Dynamics/Contacts/b2ContactSolver.h \ $$PWD/Dynamics/Contacts/b2Contact.h \ $$PWD/Dynamics/Contacts/b2CircleContact.h \ $$PWD/Dynamics/Contacts/b2ChainAndPolygonContact.h \ $$PWD/Dynamics/Contacts/b2ChainAndCircleContact.h \ $$PWD/Dynamics/Joints/b2WheelJoint.h \ $$PWD/Dynamics/Joints/b2WeldJoint.h \ $$PWD/Dynamics/Joints/b2RopeJoint.h \ $$PWD/Dynamics/Joints/b2RevoluteJoint.h \ $$PWD/Dynamics/Joints/b2PulleyJoint.h \ $$PWD/Dynamics/Joints/b2PrismaticJoint.h \ $$PWD/Dynamics/Joints/b2MouseJoint.h \ $$PWD/Dynamics/Joints/b2Joint.h \ $$PWD/Dynamics/Joints/b2GearJoint.h \ $$PWD/Dynamics/Joints/b2FrictionJoint.h \ $$PWD/Dynamics/Joints/b2DistanceJoint.h \ $$PWD/Dynamics/b2WorldCallbacks.h \ $$PWD/Dynamics/b2World.h \ $$PWD/Dynamics/b2TimeStep.h \ $$PWD/Dynamics/b2Island.h \ $$PWD/Dynamics/b2Fixture.h \ $$PWD/Dynamics/b2ContactManager.h \ $$PWD/Dynamics/b2Body.h \ $$PWD/Rope/b2Rope.h \ $$PWD/Dynamics/Joints/b2MotorJoint.h qml-box2d/Box2D/Dynamics/0000755000000000000000000000000012310114147012230 5ustar qml-box2d/Box2D/Dynamics/b2ContactManager.h0000644000000000000000000000300012241175670015517 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CONTACT_MANAGER_H #define B2_CONTACT_MANAGER_H #include class b2Contact; class b2ContactFilter; class b2ContactListener; class b2BlockAllocator; // Delegate of b2World. class b2ContactManager { public: b2ContactManager(); // Broad-phase callback. void AddPair(void* proxyUserDataA, void* proxyUserDataB); void FindNewContacts(); void Destroy(b2Contact* c); void Collide(); b2BroadPhase m_broadPhase; b2Contact* m_contactList; int32 m_contactCount; b2ContactFilter* m_contactFilter; b2ContactListener* m_contactListener; b2BlockAllocator* m_allocator; }; #endif qml-box2d/Box2D/Dynamics/b2WorldCallbacks.cpp0000644000000000000000000000307512241175670016067 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include // Return true if contact calculations should be performed between these two shapes. // If you implement your own collision filter you may want to build from this implementation. bool b2ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB) { const b2Filter& filterA = fixtureA->GetFilterData(); const b2Filter& filterB = fixtureB->GetFilterData(); if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) { return filterA.groupIndex > 0; } bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; return collide; } qml-box2d/Box2D/Dynamics/b2Fixture.cpp0000664000000000000000000002007312310072714014615 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include #include #include #include b2Fixture::b2Fixture() { m_userData = NULL; m_body = NULL; m_next = NULL; m_proxies = NULL; m_proxyCount = 0; m_shape = NULL; m_density = 0.0f; } void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def) { m_userData = def->userData; m_friction = def->friction; m_restitution = def->restitution; m_body = body; m_next = NULL; m_filter = def->filter; m_isSensor = def->isSensor; m_shape = def->shape->Clone(allocator); // Reserve proxy space int32 childCount = m_shape->GetChildCount(); m_proxies = (b2FixtureProxy*)allocator->Allocate(childCount * sizeof(b2FixtureProxy)); for (int32 i = 0; i < childCount; ++i) { m_proxies[i].fixture = NULL; m_proxies[i].proxyId = b2BroadPhase::e_nullProxy; } m_proxyCount = 0; m_density = def->density; } void b2Fixture::Destroy(b2BlockAllocator* allocator) { // The proxies must be destroyed before calling this. b2Assert(m_proxyCount == 0); // Free the proxy array. int32 childCount = m_shape->GetChildCount(); allocator->Free(m_proxies, childCount * sizeof(b2FixtureProxy)); m_proxies = NULL; // Free the child shape. switch (m_shape->m_type) { case b2Shape::e_circle: { b2CircleShape* s = (b2CircleShape*)m_shape; s->~b2CircleShape(); allocator->Free(s, sizeof(b2CircleShape)); } break; case b2Shape::e_edge: { b2EdgeShape* s = (b2EdgeShape*)m_shape; s->~b2EdgeShape(); allocator->Free(s, sizeof(b2EdgeShape)); } break; case b2Shape::e_polygon: { b2PolygonShape* s = (b2PolygonShape*)m_shape; s->~b2PolygonShape(); allocator->Free(s, sizeof(b2PolygonShape)); } break; case b2Shape::e_chain: { b2ChainShape* s = (b2ChainShape*)m_shape; s->~b2ChainShape(); allocator->Free(s, sizeof(b2ChainShape)); } break; default: b2Assert(false); break; } m_shape = NULL; } void b2Fixture::CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf) { b2Assert(m_proxyCount == 0); // Create proxies in the broad-phase. m_proxyCount = m_shape->GetChildCount(); for (int32 i = 0; i < m_proxyCount; ++i) { b2FixtureProxy* proxy = m_proxies + i; m_shape->ComputeAABB(&proxy->aabb, xf, i); proxy->proxyId = broadPhase->CreateProxy(proxy->aabb, proxy); proxy->fixture = this; proxy->childIndex = i; } } void b2Fixture::DestroyProxies(b2BroadPhase* broadPhase) { // Destroy proxies in the broad-phase. for (int32 i = 0; i < m_proxyCount; ++i) { b2FixtureProxy* proxy = m_proxies + i; broadPhase->DestroyProxy(proxy->proxyId); proxy->proxyId = b2BroadPhase::e_nullProxy; } m_proxyCount = 0; } void b2Fixture::Synchronize(b2BroadPhase* broadPhase, const b2Transform& transform1, const b2Transform& transform2) { if (m_proxyCount == 0) { return; } for (int32 i = 0; i < m_proxyCount; ++i) { b2FixtureProxy* proxy = m_proxies + i; // Compute an AABB that covers the swept shape (may miss some rotation effect). b2AABB aabb1, aabb2; m_shape->ComputeAABB(&aabb1, transform1, proxy->childIndex); m_shape->ComputeAABB(&aabb2, transform2, proxy->childIndex); proxy->aabb.Combine(aabb1, aabb2); b2Vec2 displacement = transform2.p - transform1.p; broadPhase->MoveProxy(proxy->proxyId, proxy->aabb, displacement); } } void b2Fixture::SetFilterData(const b2Filter& filter) { m_filter = filter; Refilter(); } void b2Fixture::Refilter() { if (m_body == NULL) { return; } // Flag associated contacts for filtering. b2ContactEdge* edge = m_body->GetContactList(); while (edge) { b2Contact* contact = edge->contact; b2Fixture* fixtureA = contact->GetFixtureA(); b2Fixture* fixtureB = contact->GetFixtureB(); if (fixtureA == this || fixtureB == this) { contact->FlagForFiltering(); } edge = edge->next; } b2World* world = m_body->GetWorld(); if (world == NULL) { return; } // Touch each proxy so that new pairs may be created b2BroadPhase* broadPhase = &world->m_contactManager.m_broadPhase; for (int32 i = 0; i < m_proxyCount; ++i) { broadPhase->TouchProxy(m_proxies[i].proxyId); } } void b2Fixture::SetSensor(bool sensor) { if (sensor != m_isSensor) { m_body->SetAwake(true); m_isSensor = sensor; } } void b2Fixture::Dump(int32 bodyIndex) { b2Log(" b2FixtureDef fd;\n"); b2Log(" fd.friction = %.15lef;\n", m_friction); b2Log(" fd.restitution = %.15lef;\n", m_restitution); b2Log(" fd.density = %.15lef;\n", m_density); b2Log(" fd.isSensor = bool(%d);\n", m_isSensor); b2Log(" fd.filter.categoryBits = uint16(%d);\n", m_filter.categoryBits); b2Log(" fd.filter.maskBits = uint16(%d);\n", m_filter.maskBits); b2Log(" fd.filter.groupIndex = int16(%d);\n", m_filter.groupIndex); switch (m_shape->m_type) { case b2Shape::e_circle: { b2CircleShape* s = (b2CircleShape*)m_shape; b2Log(" b2CircleShape shape;\n"); b2Log(" shape.m_radius = %.15lef;\n", s->m_radius); b2Log(" shape.m_p.Set(%.15lef, %.15lef);\n", s->m_p.x, s->m_p.y); } break; case b2Shape::e_edge: { b2EdgeShape* s = (b2EdgeShape*)m_shape; b2Log(" b2EdgeShape shape;\n"); b2Log(" shape.m_radius = %.15lef;\n", s->m_radius); b2Log(" shape.m_vertex0.Set(%.15lef, %.15lef);\n", s->m_vertex0.x, s->m_vertex0.y); b2Log(" shape.m_vertex1.Set(%.15lef, %.15lef);\n", s->m_vertex1.x, s->m_vertex1.y); b2Log(" shape.m_vertex2.Set(%.15lef, %.15lef);\n", s->m_vertex2.x, s->m_vertex2.y); b2Log(" shape.m_vertex3.Set(%.15lef, %.15lef);\n", s->m_vertex3.x, s->m_vertex3.y); b2Log(" shape.m_hasVertex0 = bool(%d);\n", s->m_hasVertex0); b2Log(" shape.m_hasVertex3 = bool(%d);\n", s->m_hasVertex3); } break; case b2Shape::e_polygon: { b2PolygonShape* s = (b2PolygonShape*)m_shape; b2Log(" b2PolygonShape shape;\n"); b2Log(" b2Vec2 vs[%d];\n", b2_maxPolygonVertices); for (int32 i = 0; i < s->m_count; ++i) { b2Log(" vs[%d].Set(%.15lef, %.15lef);\n", i, s->m_vertices[i].x, s->m_vertices[i].y); } b2Log(" shape.Set(vs, %d);\n", s->m_count); } break; case b2Shape::e_chain: { b2ChainShape* s = (b2ChainShape*)m_shape; b2Log(" b2ChainShape shape;\n"); b2Log(" b2Vec2 vs[%d];\n", s->m_count); for (int32 i = 0; i < s->m_count; ++i) { b2Log(" vs[%d].Set(%.15lef, %.15lef);\n", i, s->m_vertices[i].x, s->m_vertices[i].y); } b2Log(" shape.CreateChain(vs, %d);\n", s->m_count); b2Log(" shape.m_prevVertex.Set(%.15lef, %.15lef);\n", s->m_prevVertex.x, s->m_prevVertex.y); b2Log(" shape.m_nextVertex.Set(%.15lef, %.15lef);\n", s->m_nextVertex.x, s->m_nextVertex.y); b2Log(" shape.m_hasPrevVertex = bool(%d);\n", s->m_hasPrevVertex); b2Log(" shape.m_hasNextVertex = bool(%d);\n", s->m_hasNextVertex); } break; default: return; } b2Log("\n"); b2Log(" fd.shape = &shape;\n"); b2Log("\n"); b2Log(" bodies[%d]->CreateFixture(&fd);\n", bodyIndex); } qml-box2d/Box2D/Dynamics/b2World.cpp0000664000000000000000000007201012310072714014254 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include b2World::b2World(const b2Vec2& gravity) { m_destructionListener = NULL; m_debugDraw = NULL; m_bodyList = NULL; m_jointList = NULL; m_bodyCount = 0; m_jointCount = 0; m_warmStarting = true; m_continuousPhysics = true; m_subStepping = false; m_stepComplete = true; m_allowSleep = true; m_gravity = gravity; m_flags = e_clearForces; m_inv_dt0 = 0.0f; m_contactManager.m_allocator = &m_blockAllocator; memset(&m_profile, 0, sizeof(b2Profile)); } b2World::~b2World() { // Some shapes allocate using b2Alloc. b2Body* b = m_bodyList; while (b) { b2Body* bNext = b->m_next; b2Fixture* f = b->m_fixtureList; while (f) { b2Fixture* fNext = f->m_next; f->m_proxyCount = 0; f->Destroy(&m_blockAllocator); f = fNext; } b = bNext; } } void b2World::SetDestructionListener(b2DestructionListener* listener) { m_destructionListener = listener; } void b2World::SetContactFilter(b2ContactFilter* filter) { m_contactManager.m_contactFilter = filter; } void b2World::SetContactListener(b2ContactListener* listener) { m_contactManager.m_contactListener = listener; } void b2World::SetDebugDraw(b2Draw* debugDraw) { m_debugDraw = debugDraw; } b2Body* b2World::CreateBody(const b2BodyDef* def) { b2Assert(IsLocked() == false); if (IsLocked()) { return NULL; } void* mem = m_blockAllocator.Allocate(sizeof(b2Body)); b2Body* b = new (mem) b2Body(def, this); // Add to world doubly linked list. b->m_prev = NULL; b->m_next = m_bodyList; if (m_bodyList) { m_bodyList->m_prev = b; } m_bodyList = b; ++m_bodyCount; return b; } void b2World::DestroyBody(b2Body* b) { b2Assert(m_bodyCount > 0); b2Assert(IsLocked() == false); if (IsLocked()) { return; } // Delete the attached joints. b2JointEdge* je = b->m_jointList; while (je) { b2JointEdge* je0 = je; je = je->next; if (m_destructionListener) { m_destructionListener->SayGoodbye(je0->joint); } DestroyJoint(je0->joint); b->m_jointList = je; } b->m_jointList = NULL; // Delete the attached contacts. b2ContactEdge* ce = b->m_contactList; while (ce) { b2ContactEdge* ce0 = ce; ce = ce->next; m_contactManager.Destroy(ce0->contact); } b->m_contactList = NULL; // Delete the attached fixtures. This destroys broad-phase proxies. b2Fixture* f = b->m_fixtureList; while (f) { b2Fixture* f0 = f; f = f->m_next; if (m_destructionListener) { m_destructionListener->SayGoodbye(f0); } f0->DestroyProxies(&m_contactManager.m_broadPhase); f0->Destroy(&m_blockAllocator); f0->~b2Fixture(); m_blockAllocator.Free(f0, sizeof(b2Fixture)); b->m_fixtureList = f; b->m_fixtureCount -= 1; } b->m_fixtureList = NULL; b->m_fixtureCount = 0; // Remove world body list. if (b->m_prev) { b->m_prev->m_next = b->m_next; } if (b->m_next) { b->m_next->m_prev = b->m_prev; } if (b == m_bodyList) { m_bodyList = b->m_next; } --m_bodyCount; b->~b2Body(); m_blockAllocator.Free(b, sizeof(b2Body)); } b2Joint* b2World::CreateJoint(const b2JointDef* def) { b2Assert(IsLocked() == false); if (IsLocked()) { return NULL; } b2Joint* j = b2Joint::Create(def, &m_blockAllocator); // Connect to the world list. j->m_prev = NULL; j->m_next = m_jointList; if (m_jointList) { m_jointList->m_prev = j; } m_jointList = j; ++m_jointCount; // Connect to the bodies' doubly linked lists. j->m_edgeA.joint = j; j->m_edgeA.other = j->m_bodyB; j->m_edgeA.prev = NULL; j->m_edgeA.next = j->m_bodyA->m_jointList; if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA; j->m_bodyA->m_jointList = &j->m_edgeA; j->m_edgeB.joint = j; j->m_edgeB.other = j->m_bodyA; j->m_edgeB.prev = NULL; j->m_edgeB.next = j->m_bodyB->m_jointList; if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB; j->m_bodyB->m_jointList = &j->m_edgeB; b2Body* bodyA = def->bodyA; b2Body* bodyB = def->bodyB; // If the joint prevents collisions, then flag any contacts for filtering. if (def->collideConnected == false) { b2ContactEdge* edge = bodyB->GetContactList(); while (edge) { if (edge->other == bodyA) { // Flag the contact for filtering at the next time step (where either // body is awake). edge->contact->FlagForFiltering(); } edge = edge->next; } } // Note: creating a joint doesn't wake the bodies. return j; } void b2World::DestroyJoint(b2Joint* j) { b2Assert(IsLocked() == false); if (IsLocked()) { return; } bool collideConnected = j->m_collideConnected; // Remove from the doubly linked list. if (j->m_prev) { j->m_prev->m_next = j->m_next; } if (j->m_next) { j->m_next->m_prev = j->m_prev; } if (j == m_jointList) { m_jointList = j->m_next; } // Disconnect from island graph. b2Body* bodyA = j->m_bodyA; b2Body* bodyB = j->m_bodyB; // Wake up connected bodies. bodyA->SetAwake(true); bodyB->SetAwake(true); // Remove from body 1. if (j->m_edgeA.prev) { j->m_edgeA.prev->next = j->m_edgeA.next; } if (j->m_edgeA.next) { j->m_edgeA.next->prev = j->m_edgeA.prev; } if (&j->m_edgeA == bodyA->m_jointList) { bodyA->m_jointList = j->m_edgeA.next; } j->m_edgeA.prev = NULL; j->m_edgeA.next = NULL; // Remove from body 2 if (j->m_edgeB.prev) { j->m_edgeB.prev->next = j->m_edgeB.next; } if (j->m_edgeB.next) { j->m_edgeB.next->prev = j->m_edgeB.prev; } if (&j->m_edgeB == bodyB->m_jointList) { bodyB->m_jointList = j->m_edgeB.next; } j->m_edgeB.prev = NULL; j->m_edgeB.next = NULL; b2Joint::Destroy(j, &m_blockAllocator); b2Assert(m_jointCount > 0); --m_jointCount; // If the joint prevents collisions, then flag any contacts for filtering. if (collideConnected == false) { b2ContactEdge* edge = bodyB->GetContactList(); while (edge) { if (edge->other == bodyA) { // Flag the contact for filtering at the next time step (where either // body is awake). edge->contact->FlagForFiltering(); } edge = edge->next; } } } // void b2World::SetAllowSleeping(bool flag) { if (flag == m_allowSleep) { return; } m_allowSleep = flag; if (m_allowSleep == false) { for (b2Body* b = m_bodyList; b; b = b->m_next) { b->SetAwake(true); } } } // Find islands, integrate and solve constraints, solve position constraints void b2World::Solve(const b2TimeStep& step) { m_profile.solveInit = 0.0f; m_profile.solveVelocity = 0.0f; m_profile.solvePosition = 0.0f; // Size the island for the worst case. b2Island island(m_bodyCount, m_contactManager.m_contactCount, m_jointCount, &m_stackAllocator, m_contactManager.m_contactListener); // Clear all the island flags. for (b2Body* b = m_bodyList; b; b = b->m_next) { b->m_flags &= ~b2Body::e_islandFlag; } for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) { c->m_flags &= ~b2Contact::e_islandFlag; } for (b2Joint* j = m_jointList; j; j = j->m_next) { j->m_islandFlag = false; } // Build and simulate all awake islands. int32 stackSize = m_bodyCount; b2Body** stack = (b2Body**)m_stackAllocator.Allocate(stackSize * sizeof(b2Body*)); for (b2Body* seed = m_bodyList; seed; seed = seed->m_next) { if (seed->m_flags & b2Body::e_islandFlag) { continue; } if (seed->IsAwake() == false || seed->IsActive() == false) { continue; } // The seed can be dynamic or kinematic. if (seed->GetType() == b2_staticBody) { continue; } // Reset island and stack. island.Clear(); int32 stackCount = 0; stack[stackCount++] = seed; seed->m_flags |= b2Body::e_islandFlag; // Perform a depth first search (DFS) on the constraint graph. while (stackCount > 0) { // Grab the next body off the stack and add it to the island. b2Body* b = stack[--stackCount]; b2Assert(b->IsActive() == true); island.Add(b); // Make sure the body is awake. b->SetAwake(true); // To keep islands as small as possible, we don't // propagate islands across static bodies. if (b->GetType() == b2_staticBody) { continue; } // Search all contacts connected to this body. for (b2ContactEdge* ce = b->m_contactList; ce; ce = ce->next) { b2Contact* contact = ce->contact; // Has this contact already been added to an island? if (contact->m_flags & b2Contact::e_islandFlag) { continue; } // Is this contact solid and touching? if (contact->IsEnabled() == false || contact->IsTouching() == false) { continue; } // Skip sensors. bool sensorA = contact->m_fixtureA->m_isSensor; bool sensorB = contact->m_fixtureB->m_isSensor; if (sensorA || sensorB) { continue; } island.Add(contact); contact->m_flags |= b2Contact::e_islandFlag; b2Body* other = ce->other; // Was the other body already added to this island? if (other->m_flags & b2Body::e_islandFlag) { continue; } b2Assert(stackCount < stackSize); stack[stackCount++] = other; other->m_flags |= b2Body::e_islandFlag; } // Search all joints connect to this body. for (b2JointEdge* je = b->m_jointList; je; je = je->next) { if (je->joint->m_islandFlag == true) { continue; } b2Body* other = je->other; // Don't simulate joints connected to inactive bodies. if (other->IsActive() == false) { continue; } island.Add(je->joint); je->joint->m_islandFlag = true; if (other->m_flags & b2Body::e_islandFlag) { continue; } b2Assert(stackCount < stackSize); stack[stackCount++] = other; other->m_flags |= b2Body::e_islandFlag; } } b2Profile profile; island.Solve(&profile, step, m_gravity, m_allowSleep); m_profile.solveInit += profile.solveInit; m_profile.solveVelocity += profile.solveVelocity; m_profile.solvePosition += profile.solvePosition; // Post solve cleanup. for (int32 i = 0; i < island.m_bodyCount; ++i) { // Allow static bodies to participate in other islands. b2Body* b = island.m_bodies[i]; if (b->GetType() == b2_staticBody) { b->m_flags &= ~b2Body::e_islandFlag; } } } m_stackAllocator.Free(stack); { b2Timer timer; // Synchronize fixtures, check for out of range bodies. for (b2Body* b = m_bodyList; b; b = b->GetNext()) { // If a body was not in an island then it did not move. if ((b->m_flags & b2Body::e_islandFlag) == 0) { continue; } if (b->GetType() == b2_staticBody) { continue; } // Update fixtures (for broad-phase). b->SynchronizeFixtures(); } // Look for new contacts. m_contactManager.FindNewContacts(); m_profile.broadphase = timer.GetMilliseconds(); } } // Find TOI contacts and solve them. void b2World::SolveTOI(const b2TimeStep& step) { b2Island island(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, &m_stackAllocator, m_contactManager.m_contactListener); if (m_stepComplete) { for (b2Body* b = m_bodyList; b; b = b->m_next) { b->m_flags &= ~b2Body::e_islandFlag; b->m_sweep.alpha0 = 0.0f; } for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) { // Invalidate TOI c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag); c->m_toiCount = 0; c->m_toi = 1.0f; } } // Find TOI events and solve them. for (;;) { // Find the first TOI. b2Contact* minContact = NULL; float32 minAlpha = 1.0f; for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) { // Is this contact disabled? if (c->IsEnabled() == false) { continue; } // Prevent excessive sub-stepping. if (c->m_toiCount > b2_maxSubSteps) { continue; } float32 alpha = 1.0f; if (c->m_flags & b2Contact::e_toiFlag) { // This contact has a valid cached TOI. alpha = c->m_toi; } else { b2Fixture* fA = c->GetFixtureA(); b2Fixture* fB = c->GetFixtureB(); // Is there a sensor? if (fA->IsSensor() || fB->IsSensor()) { continue; } b2Body* bA = fA->GetBody(); b2Body* bB = fB->GetBody(); b2BodyType typeA = bA->m_type; b2BodyType typeB = bB->m_type; b2Assert(typeA == b2_dynamicBody || typeB == b2_dynamicBody); bool activeA = bA->IsAwake() && typeA != b2_staticBody; bool activeB = bB->IsAwake() && typeB != b2_staticBody; // Is at least one body active (awake and dynamic or kinematic)? if (activeA == false && activeB == false) { continue; } bool collideA = bA->IsBullet() || typeA != b2_dynamicBody; bool collideB = bB->IsBullet() || typeB != b2_dynamicBody; // Are these two non-bullet dynamic bodies? if (collideA == false && collideB == false) { continue; } // Compute the TOI for this contact. // Put the sweeps onto the same time interval. float32 alpha0 = bA->m_sweep.alpha0; if (bA->m_sweep.alpha0 < bB->m_sweep.alpha0) { alpha0 = bB->m_sweep.alpha0; bA->m_sweep.Advance(alpha0); } else if (bB->m_sweep.alpha0 < bA->m_sweep.alpha0) { alpha0 = bA->m_sweep.alpha0; bB->m_sweep.Advance(alpha0); } b2Assert(alpha0 < 1.0f); int32 indexA = c->GetChildIndexA(); int32 indexB = c->GetChildIndexB(); // Compute the time of impact in interval [0, minTOI] b2TOIInput input; input.proxyA.Set(fA->GetShape(), indexA); input.proxyB.Set(fB->GetShape(), indexB); input.sweepA = bA->m_sweep; input.sweepB = bB->m_sweep; input.tMax = 1.0f; b2TOIOutput output; b2TimeOfImpact(&output, &input); // Beta is the fraction of the remaining portion of the . float32 beta = output.t; if (output.state == b2TOIOutput::e_touching) { alpha = b2Min(alpha0 + (1.0f - alpha0) * beta, 1.0f); } else { alpha = 1.0f; } c->m_toi = alpha; c->m_flags |= b2Contact::e_toiFlag; } if (alpha < minAlpha) { // This is the minimum TOI found so far. minContact = c; minAlpha = alpha; } } if (minContact == NULL || 1.0f - 10.0f * b2_epsilon < minAlpha) { // No more TOI events. Done! m_stepComplete = true; break; } // Advance the bodies to the TOI. b2Fixture* fA = minContact->GetFixtureA(); b2Fixture* fB = minContact->GetFixtureB(); b2Body* bA = fA->GetBody(); b2Body* bB = fB->GetBody(); b2Sweep backup1 = bA->m_sweep; b2Sweep backup2 = bB->m_sweep; bA->Advance(minAlpha); bB->Advance(minAlpha); // The TOI contact likely has some new contact points. minContact->Update(m_contactManager.m_contactListener); minContact->m_flags &= ~b2Contact::e_toiFlag; ++minContact->m_toiCount; // Is the contact solid? if (minContact->IsEnabled() == false || minContact->IsTouching() == false) { // Restore the sweeps. minContact->SetEnabled(false); bA->m_sweep = backup1; bB->m_sweep = backup2; bA->SynchronizeTransform(); bB->SynchronizeTransform(); continue; } bA->SetAwake(true); bB->SetAwake(true); // Build the island island.Clear(); island.Add(bA); island.Add(bB); island.Add(minContact); bA->m_flags |= b2Body::e_islandFlag; bB->m_flags |= b2Body::e_islandFlag; minContact->m_flags |= b2Contact::e_islandFlag; // Get contacts on bodyA and bodyB. b2Body* bodies[2] = {bA, bB}; for (int32 i = 0; i < 2; ++i) { b2Body* body = bodies[i]; if (body->m_type == b2_dynamicBody) { for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next) { if (island.m_bodyCount == island.m_bodyCapacity) { break; } if (island.m_contactCount == island.m_contactCapacity) { break; } b2Contact* contact = ce->contact; // Has this contact already been added to the island? if (contact->m_flags & b2Contact::e_islandFlag) { continue; } // Only add static, kinematic, or bullet bodies. b2Body* other = ce->other; if (other->m_type == b2_dynamicBody && body->IsBullet() == false && other->IsBullet() == false) { continue; } // Skip sensors. bool sensorA = contact->m_fixtureA->m_isSensor; bool sensorB = contact->m_fixtureB->m_isSensor; if (sensorA || sensorB) { continue; } // Tentatively advance the body to the TOI. b2Sweep backup = other->m_sweep; if ((other->m_flags & b2Body::e_islandFlag) == 0) { other->Advance(minAlpha); } // Update the contact points contact->Update(m_contactManager.m_contactListener); // Was the contact disabled by the user? if (contact->IsEnabled() == false) { other->m_sweep = backup; other->SynchronizeTransform(); continue; } // Are there contact points? if (contact->IsTouching() == false) { other->m_sweep = backup; other->SynchronizeTransform(); continue; } // Add the contact to the island contact->m_flags |= b2Contact::e_islandFlag; island.Add(contact); // Has the other body already been added to the island? if (other->m_flags & b2Body::e_islandFlag) { continue; } // Add the other body to the island. other->m_flags |= b2Body::e_islandFlag; if (other->m_type != b2_staticBody) { other->SetAwake(true); } island.Add(other); } } } b2TimeStep subStep; subStep.dt = (1.0f - minAlpha) * step.dt; subStep.inv_dt = 1.0f / subStep.dt; subStep.dtRatio = 1.0f; subStep.positionIterations = 20; subStep.velocityIterations = step.velocityIterations; subStep.warmStarting = false; island.SolveTOI(subStep, bA->m_islandIndex, bB->m_islandIndex); // Reset island flags and synchronize broad-phase proxies. for (int32 i = 0; i < island.m_bodyCount; ++i) { b2Body* body = island.m_bodies[i]; body->m_flags &= ~b2Body::e_islandFlag; if (body->m_type != b2_dynamicBody) { continue; } body->SynchronizeFixtures(); // Invalidate all contact TOIs on this displaced body. for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next) { ce->contact->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag); } } // Commit fixture proxy movements to the broad-phase so that new contacts are created. // Also, some contacts can be destroyed. m_contactManager.FindNewContacts(); if (m_subStepping) { m_stepComplete = false; break; } } } void b2World::Step(float32 dt, int32 velocityIterations, int32 positionIterations) { b2Timer stepTimer; // If new fixtures were added, we need to find the new contacts. if (m_flags & e_newFixture) { m_contactManager.FindNewContacts(); m_flags &= ~e_newFixture; } m_flags |= e_locked; b2TimeStep step; step.dt = dt; step.velocityIterations = velocityIterations; step.positionIterations = positionIterations; if (dt > 0.0f) { step.inv_dt = 1.0f / dt; } else { step.inv_dt = 0.0f; } step.dtRatio = m_inv_dt0 * dt; step.warmStarting = m_warmStarting; // Update contacts. This is where some contacts are destroyed. { b2Timer timer; m_contactManager.Collide(); m_profile.collide = timer.GetMilliseconds(); } // Integrate velocities, solve velocity constraints, and integrate positions. if (m_stepComplete && step.dt > 0.0f) { b2Timer timer; Solve(step); m_profile.solve = timer.GetMilliseconds(); } // Handle TOI events. if (m_continuousPhysics && step.dt > 0.0f) { b2Timer timer; SolveTOI(step); m_profile.solveTOI = timer.GetMilliseconds(); } if (step.dt > 0.0f) { m_inv_dt0 = step.inv_dt; } if (m_flags & e_clearForces) { ClearForces(); } m_flags &= ~e_locked; m_profile.step = stepTimer.GetMilliseconds(); } void b2World::ClearForces() { for (b2Body* body = m_bodyList; body; body = body->GetNext()) { body->m_force.SetZero(); body->m_torque = 0.0f; } } struct b2WorldQueryWrapper { bool QueryCallback(int32 proxyId) { b2FixtureProxy* proxy = (b2FixtureProxy*)broadPhase->GetUserData(proxyId); return callback->ReportFixture(proxy->fixture); } const b2BroadPhase* broadPhase; b2QueryCallback* callback; }; void b2World::QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const { b2WorldQueryWrapper wrapper; wrapper.broadPhase = &m_contactManager.m_broadPhase; wrapper.callback = callback; m_contactManager.m_broadPhase.Query(&wrapper, aabb); } struct b2WorldRayCastWrapper { float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId) { void* userData = broadPhase->GetUserData(proxyId); b2FixtureProxy* proxy = (b2FixtureProxy*)userData; b2Fixture* fixture = proxy->fixture; int32 index = proxy->childIndex; b2RayCastOutput output; bool hit = fixture->RayCast(&output, input, index); if (hit) { float32 fraction = output.fraction; b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2; return callback->ReportFixture(fixture, point, output.normal, fraction); } return input.maxFraction; } const b2BroadPhase* broadPhase; b2RayCastCallback* callback; }; void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const { b2WorldRayCastWrapper wrapper; wrapper.broadPhase = &m_contactManager.m_broadPhase; wrapper.callback = callback; b2RayCastInput input; input.maxFraction = 1.0f; input.p1 = point1; input.p2 = point2; m_contactManager.m_broadPhase.RayCast(&wrapper, input); } void b2World::DrawShape(b2Fixture* fixture, const b2Transform& xf, const b2Color& color) { switch (fixture->GetType()) { case b2Shape::e_circle: { b2CircleShape* circle = (b2CircleShape*)fixture->GetShape(); b2Vec2 center = b2Mul(xf, circle->m_p); float32 radius = circle->m_radius; b2Vec2 axis = b2Mul(xf.q, b2Vec2(1.0f, 0.0f)); m_debugDraw->DrawSolidCircle(center, radius, axis, color); } break; case b2Shape::e_edge: { b2EdgeShape* edge = (b2EdgeShape*)fixture->GetShape(); b2Vec2 v1 = b2Mul(xf, edge->m_vertex1); b2Vec2 v2 = b2Mul(xf, edge->m_vertex2); m_debugDraw->DrawSegment(v1, v2, color); } break; case b2Shape::e_chain: { b2ChainShape* chain = (b2ChainShape*)fixture->GetShape(); int32 count = chain->m_count; const b2Vec2* vertices = chain->m_vertices; b2Vec2 v1 = b2Mul(xf, vertices[0]); for (int32 i = 1; i < count; ++i) { b2Vec2 v2 = b2Mul(xf, vertices[i]); m_debugDraw->DrawSegment(v1, v2, color); m_debugDraw->DrawCircle(v1, 0.05f, color); v1 = v2; } } break; case b2Shape::e_polygon: { b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape(); int32 vertexCount = poly->m_count; b2Assert(vertexCount <= b2_maxPolygonVertices); b2Vec2 vertices[b2_maxPolygonVertices]; for (int32 i = 0; i < vertexCount; ++i) { vertices[i] = b2Mul(xf, poly->m_vertices[i]); } m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color); } break; default: break; } } void b2World::DrawJoint(b2Joint* joint) { b2Body* bodyA = joint->GetBodyA(); b2Body* bodyB = joint->GetBodyB(); const b2Transform& xf1 = bodyA->GetTransform(); const b2Transform& xf2 = bodyB->GetTransform(); b2Vec2 x1 = xf1.p; b2Vec2 x2 = xf2.p; b2Vec2 p1 = joint->GetAnchorA(); b2Vec2 p2 = joint->GetAnchorB(); b2Color color(0.5f, 0.8f, 0.8f); switch (joint->GetType()) { case e_distanceJoint: m_debugDraw->DrawSegment(p1, p2, color); break; case e_pulleyJoint: { b2PulleyJoint* pulley = (b2PulleyJoint*)joint; b2Vec2 s1 = pulley->GetGroundAnchorA(); b2Vec2 s2 = pulley->GetGroundAnchorB(); m_debugDraw->DrawSegment(s1, p1, color); m_debugDraw->DrawSegment(s2, p2, color); m_debugDraw->DrawSegment(s1, s2, color); } break; case e_mouseJoint: // don't draw this break; default: m_debugDraw->DrawSegment(x1, p1, color); m_debugDraw->DrawSegment(p1, p2, color); m_debugDraw->DrawSegment(x2, p2, color); } } void b2World::DrawDebugData() { if (m_debugDraw == NULL) { return; } uint32 flags = m_debugDraw->GetFlags(); if (flags & b2Draw::e_shapeBit) { for (b2Body* b = m_bodyList; b; b = b->GetNext()) { const b2Transform& xf = b->GetTransform(); for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) { if (b->IsActive() == false) { DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.3f)); } else if (b->GetType() == b2_staticBody) { DrawShape(f, xf, b2Color(0.5f, 0.9f, 0.5f)); } else if (b->GetType() == b2_kinematicBody) { DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.9f)); } else if (b->IsAwake() == false) { DrawShape(f, xf, b2Color(0.6f, 0.6f, 0.6f)); } else { DrawShape(f, xf, b2Color(0.9f, 0.7f, 0.7f)); } } } } if (flags & b2Draw::e_jointBit) { for (b2Joint* j = m_jointList; j; j = j->GetNext()) { DrawJoint(j); } } if (flags & b2Draw::e_pairBit) { b2Color color(0.3f, 0.9f, 0.9f); for (b2Contact* c = m_contactManager.m_contactList; c; c = c->GetNext()) { //b2Fixture* fixtureA = c->GetFixtureA(); //b2Fixture* fixtureB = c->GetFixtureB(); //b2Vec2 cA = fixtureA->GetAABB().GetCenter(); //b2Vec2 cB = fixtureB->GetAABB().GetCenter(); //m_debugDraw->DrawSegment(cA, cB, color); } } if (flags & b2Draw::e_aabbBit) { b2Color color(0.9f, 0.3f, 0.9f); b2BroadPhase* bp = &m_contactManager.m_broadPhase; for (b2Body* b = m_bodyList; b; b = b->GetNext()) { if (b->IsActive() == false) { continue; } for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) { for (int32 i = 0; i < f->m_proxyCount; ++i) { b2FixtureProxy* proxy = f->m_proxies + i; b2AABB aabb = bp->GetFatAABB(proxy->proxyId); b2Vec2 vs[4]; vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y); vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y); vs[2].Set(aabb.upperBound.x, aabb.upperBound.y); vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y); m_debugDraw->DrawPolygon(vs, 4, color); } } } } if (flags & b2Draw::e_centerOfMassBit) { for (b2Body* b = m_bodyList; b; b = b->GetNext()) { b2Transform xf = b->GetTransform(); xf.p = b->GetWorldCenter(); m_debugDraw->DrawTransform(xf); } } } int32 b2World::GetProxyCount() const { return m_contactManager.m_broadPhase.GetProxyCount(); } int32 b2World::GetTreeHeight() const { return m_contactManager.m_broadPhase.GetTreeHeight(); } int32 b2World::GetTreeBalance() const { return m_contactManager.m_broadPhase.GetTreeBalance(); } float32 b2World::GetTreeQuality() const { return m_contactManager.m_broadPhase.GetTreeQuality(); } void b2World::ShiftOrigin(const b2Vec2& newOrigin) { b2Assert((m_flags & e_locked) == 0); if ((m_flags & e_locked) == e_locked) { return; } for (b2Body* b = m_bodyList; b; b = b->m_next) { b->m_xf.p -= newOrigin; b->m_sweep.c0 -= newOrigin; b->m_sweep.c -= newOrigin; } for (b2Joint* j = m_jointList; j; j = j->m_next) { j->ShiftOrigin(newOrigin); } m_contactManager.m_broadPhase.ShiftOrigin(newOrigin); } void b2World::Dump() { if ((m_flags & e_locked) == e_locked) { return; } b2Log("b2Vec2 g(%.15lef, %.15lef);\n", m_gravity.x, m_gravity.y); b2Log("m_world->SetGravity(g);\n"); b2Log("b2Body** bodies = (b2Body**)b2Alloc(%d * sizeof(b2Body*));\n", m_bodyCount); b2Log("b2Joint** joints = (b2Joint**)b2Alloc(%d * sizeof(b2Joint*));\n", m_jointCount); int32 i = 0; for (b2Body* b = m_bodyList; b; b = b->m_next) { b->m_islandIndex = i; b->Dump(); ++i; } i = 0; for (b2Joint* j = m_jointList; j; j = j->m_next) { j->m_index = i; ++i; } // First pass on joints, skip gear joints. for (b2Joint* j = m_jointList; j; j = j->m_next) { if (j->m_type == e_gearJoint) { continue; } b2Log("{\n"); j->Dump(); b2Log("}\n"); } // Second pass on joints, only gear joints. for (b2Joint* j = m_jointList; j; j = j->m_next) { if (j->m_type != e_gearJoint) { continue; } b2Log("{\n"); j->Dump(); b2Log("}\n"); } b2Log("b2Free(joints);\n"); b2Log("b2Free(bodies);\n"); b2Log("joints = NULL;\n"); b2Log("bodies = NULL;\n"); } qml-box2d/Box2D/Dynamics/b2Island.cpp0000664000000000000000000004032412310072714014402 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include #include #include #include /* Position Correction Notes ========================= I tried the several algorithms for position correction of the 2D revolute joint. I looked at these systems: - simple pendulum (1m diameter sphere on massless 5m stick) with initial angular velocity of 100 rad/s. - suspension bridge with 30 1m long planks of length 1m. - multi-link chain with 30 1m long links. Here are the algorithms: Baumgarte - A fraction of the position error is added to the velocity error. There is no separate position solver. Pseudo Velocities - After the velocity solver and position integration, the position error, Jacobian, and effective mass are recomputed. Then the velocity constraints are solved with pseudo velocities and a fraction of the position error is added to the pseudo velocity error. The pseudo velocities are initialized to zero and there is no warm-starting. After the position solver, the pseudo velocities are added to the positions. This is also called the First Order World method or the Position LCP method. Modified Nonlinear Gauss-Seidel (NGS) - Like Pseudo Velocities except the position error is re-computed for each constraint and the positions are updated after the constraint is solved. The radius vectors (aka Jacobians) are re-computed too (otherwise the algorithm has horrible instability). The pseudo velocity states are not needed because they are effectively zero at the beginning of each iteration. Since we have the current position error, we allow the iterations to terminate early if the error becomes smaller than b2_linearSlop. Full NGS or just NGS - Like Modified NGS except the effective mass are re-computed each time a constraint is solved. Here are the results: Baumgarte - this is the cheapest algorithm but it has some stability problems, especially with the bridge. The chain links separate easily close to the root and they jitter as they struggle to pull together. This is one of the most common methods in the field. The big drawback is that the position correction artificially affects the momentum, thus leading to instabilities and false bounce. I used a bias factor of 0.2. A larger bias factor makes the bridge less stable, a smaller factor makes joints and contacts more spongy. Pseudo Velocities - the is more stable than the Baumgarte method. The bridge is stable. However, joints still separate with large angular velocities. Drag the simple pendulum in a circle quickly and the joint will separate. The chain separates easily and does not recover. I used a bias factor of 0.2. A larger value lead to the bridge collapsing when a heavy cube drops on it. Modified NGS - this algorithm is better in some ways than Baumgarte and Pseudo Velocities, but in other ways it is worse. The bridge and chain are much more stable, but the simple pendulum goes unstable at high angular velocities. Full NGS - stable in all tests. The joints display good stiffness. The bridge still sags, but this is better than infinite forces. Recommendations Pseudo Velocities are not really worthwhile because the bridge and chain cannot recover from joint separation. In other cases the benefit over Baumgarte is small. Modified NGS is not a robust method for the revolute joint due to the violent instability seen in the simple pendulum. Perhaps it is viable with other constraint types, especially scalar constraints where the effective mass is a scalar. This leaves Baumgarte and Full NGS. Baumgarte has small, but manageable instabilities and is very fast. I don't think we can escape Baumgarte, especially in highly demanding cases where high constraint fidelity is not needed. Full NGS is robust and easy on the eyes. I recommend this as an option for higher fidelity simulation and certainly for suspension bridges and long chains. Full NGS might be a good choice for ragdolls, especially motorized ragdolls where joint separation can be problematic. The number of NGS iterations can be reduced for better performance without harming robustness much. Each joint in a can be handled differently in the position solver. So I recommend a system where the user can select the algorithm on a per joint basis. I would probably default to the slower Full NGS and let the user select the faster Baumgarte method in performance critical scenarios. */ /* Cache Performance The Box2D solvers are dominated by cache misses. Data structures are designed to increase the number of cache hits. Much of misses are due to random access to body data. The constraint structures are iterated over linearly, which leads to few cache misses. The bodies are not accessed during iteration. Instead read only data, such as the mass values are stored with the constraints. The mutable data are the constraint impulses and the bodies velocities/positions. The impulses are held inside the constraint structures. The body velocities/positions are held in compact, temporary arrays to increase the number of cache hits. Linear and angular velocity are stored in a single array since multiple arrays lead to multiple misses. */ /* 2D Rotation R = [cos(theta) -sin(theta)] [sin(theta) cos(theta) ] thetaDot = omega Let q1 = cos(theta), q2 = sin(theta). R = [q1 -q2] [q2 q1] q1Dot = -thetaDot * q2 q2Dot = thetaDot * q1 q1_new = q1_old - dt * w * q2 q2_new = q2_old + dt * w * q1 then normalize. This might be faster than computing sin+cos. However, we can compute sin+cos of the same angle fast. */ b2Island::b2Island( int32 bodyCapacity, int32 contactCapacity, int32 jointCapacity, b2StackAllocator* allocator, b2ContactListener* listener) { m_bodyCapacity = bodyCapacity; m_contactCapacity = contactCapacity; m_jointCapacity = jointCapacity; m_bodyCount = 0; m_contactCount = 0; m_jointCount = 0; m_allocator = allocator; m_listener = listener; m_bodies = (b2Body**)m_allocator->Allocate(bodyCapacity * sizeof(b2Body*)); m_contacts = (b2Contact**)m_allocator->Allocate(contactCapacity * sizeof(b2Contact*)); m_joints = (b2Joint**)m_allocator->Allocate(jointCapacity * sizeof(b2Joint*)); m_velocities = (b2Velocity*)m_allocator->Allocate(m_bodyCapacity * sizeof(b2Velocity)); m_positions = (b2Position*)m_allocator->Allocate(m_bodyCapacity * sizeof(b2Position)); } b2Island::~b2Island() { // Warning: the order should reverse the constructor order. m_allocator->Free(m_positions); m_allocator->Free(m_velocities); m_allocator->Free(m_joints); m_allocator->Free(m_contacts); m_allocator->Free(m_bodies); } void b2Island::Solve(b2Profile* profile, const b2TimeStep& step, const b2Vec2& gravity, bool allowSleep) { b2Timer timer; float32 h = step.dt; // Integrate velocities and apply damping. Initialize the body state. for (int32 i = 0; i < m_bodyCount; ++i) { b2Body* b = m_bodies[i]; b2Vec2 c = b->m_sweep.c; float32 a = b->m_sweep.a; b2Vec2 v = b->m_linearVelocity; float32 w = b->m_angularVelocity; // Store positions for continuous collision. b->m_sweep.c0 = b->m_sweep.c; b->m_sweep.a0 = b->m_sweep.a; if (b->m_type == b2_dynamicBody) { // Integrate velocities. v += h * (b->m_gravityScale * gravity + b->m_invMass * b->m_force); w += h * b->m_invI * b->m_torque; // Apply damping. // ODE: dv/dt + c * v = 0 // Solution: v(t) = v0 * exp(-c * t) // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) // v2 = exp(-c * dt) * v1 // Pade approximation: // v2 = v1 * 1 / (1 + c * dt) v *= 1.0f / (1.0f + h * b->m_linearDamping); w *= 1.0f / (1.0f + h * b->m_angularDamping); } m_positions[i].c = c; m_positions[i].a = a; m_velocities[i].v = v; m_velocities[i].w = w; } timer.Reset(); // Solver data b2SolverData solverData; solverData.step = step; solverData.positions = m_positions; solverData.velocities = m_velocities; // Initialize velocity constraints. b2ContactSolverDef contactSolverDef; contactSolverDef.step = step; contactSolverDef.contacts = m_contacts; contactSolverDef.count = m_contactCount; contactSolverDef.positions = m_positions; contactSolverDef.velocities = m_velocities; contactSolverDef.allocator = m_allocator; b2ContactSolver contactSolver(&contactSolverDef); contactSolver.InitializeVelocityConstraints(); if (step.warmStarting) { contactSolver.WarmStart(); } for (int32 i = 0; i < m_jointCount; ++i) { m_joints[i]->InitVelocityConstraints(solverData); } profile->solveInit = timer.GetMilliseconds(); // Solve velocity constraints timer.Reset(); for (int32 i = 0; i < step.velocityIterations; ++i) { for (int32 j = 0; j < m_jointCount; ++j) { m_joints[j]->SolveVelocityConstraints(solverData); } contactSolver.SolveVelocityConstraints(); } // Store impulses for warm starting contactSolver.StoreImpulses(); profile->solveVelocity = timer.GetMilliseconds(); // Integrate positions for (int32 i = 0; i < m_bodyCount; ++i) { b2Vec2 c = m_positions[i].c; float32 a = m_positions[i].a; b2Vec2 v = m_velocities[i].v; float32 w = m_velocities[i].w; // Check for large velocities b2Vec2 translation = h * v; if (b2Dot(translation, translation) > b2_maxTranslationSquared) { float32 ratio = b2_maxTranslation / translation.Length(); v *= ratio; } float32 rotation = h * w; if (rotation * rotation > b2_maxRotationSquared) { float32 ratio = b2_maxRotation / b2Abs(rotation); w *= ratio; } // Integrate c += h * v; a += h * w; m_positions[i].c = c; m_positions[i].a = a; m_velocities[i].v = v; m_velocities[i].w = w; } // Solve position constraints timer.Reset(); bool positionSolved = false; for (int32 i = 0; i < step.positionIterations; ++i) { bool contactsOkay = contactSolver.SolvePositionConstraints(); bool jointsOkay = true; for (int32 i = 0; i < m_jointCount; ++i) { bool jointOkay = m_joints[i]->SolvePositionConstraints(solverData); jointsOkay = jointsOkay && jointOkay; } if (contactsOkay && jointsOkay) { // Exit early if the position errors are small. positionSolved = true; break; } } // Copy state buffers back to the bodies for (int32 i = 0; i < m_bodyCount; ++i) { b2Body* body = m_bodies[i]; body->m_sweep.c = m_positions[i].c; body->m_sweep.a = m_positions[i].a; body->m_linearVelocity = m_velocities[i].v; body->m_angularVelocity = m_velocities[i].w; body->SynchronizeTransform(); } profile->solvePosition = timer.GetMilliseconds(); Report(contactSolver.m_velocityConstraints); if (allowSleep) { float32 minSleepTime = b2_maxFloat; const float32 linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance; const float32 angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance; for (int32 i = 0; i < m_bodyCount; ++i) { b2Body* b = m_bodies[i]; if (b->GetType() == b2_staticBody) { continue; } if ((b->m_flags & b2Body::e_autoSleepFlag) == 0 || b->m_angularVelocity * b->m_angularVelocity > angTolSqr || b2Dot(b->m_linearVelocity, b->m_linearVelocity) > linTolSqr) { b->m_sleepTime = 0.0f; minSleepTime = 0.0f; } else { b->m_sleepTime += h; minSleepTime = b2Min(minSleepTime, b->m_sleepTime); } } if (minSleepTime >= b2_timeToSleep && positionSolved) { for (int32 i = 0; i < m_bodyCount; ++i) { b2Body* b = m_bodies[i]; b->SetAwake(false); } } } } void b2Island::SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB) { b2Assert(toiIndexA < m_bodyCount); b2Assert(toiIndexB < m_bodyCount); // Initialize the body state. for (int32 i = 0; i < m_bodyCount; ++i) { b2Body* b = m_bodies[i]; m_positions[i].c = b->m_sweep.c; m_positions[i].a = b->m_sweep.a; m_velocities[i].v = b->m_linearVelocity; m_velocities[i].w = b->m_angularVelocity; } b2ContactSolverDef contactSolverDef; contactSolverDef.contacts = m_contacts; contactSolverDef.count = m_contactCount; contactSolverDef.allocator = m_allocator; contactSolverDef.step = subStep; contactSolverDef.positions = m_positions; contactSolverDef.velocities = m_velocities; b2ContactSolver contactSolver(&contactSolverDef); // Solve position constraints. for (int32 i = 0; i < subStep.positionIterations; ++i) { bool contactsOkay = contactSolver.SolveTOIPositionConstraints(toiIndexA, toiIndexB); if (contactsOkay) { break; } } #if 0 // Is the new position really safe? for (int32 i = 0; i < m_contactCount; ++i) { b2Contact* c = m_contacts[i]; b2Fixture* fA = c->GetFixtureA(); b2Fixture* fB = c->GetFixtureB(); b2Body* bA = fA->GetBody(); b2Body* bB = fB->GetBody(); int32 indexA = c->GetChildIndexA(); int32 indexB = c->GetChildIndexB(); b2DistanceInput input; input.proxyA.Set(fA->GetShape(), indexA); input.proxyB.Set(fB->GetShape(), indexB); input.transformA = bA->GetTransform(); input.transformB = bB->GetTransform(); input.useRadii = false; b2DistanceOutput output; b2SimplexCache cache; cache.count = 0; b2Distance(&output, &cache, &input); if (output.distance == 0 || cache.count == 3) { cache.count += 0; } } #endif // Leap of faith to new safe state. m_bodies[toiIndexA]->m_sweep.c0 = m_positions[toiIndexA].c; m_bodies[toiIndexA]->m_sweep.a0 = m_positions[toiIndexA].a; m_bodies[toiIndexB]->m_sweep.c0 = m_positions[toiIndexB].c; m_bodies[toiIndexB]->m_sweep.a0 = m_positions[toiIndexB].a; // No warm starting is needed for TOI events because warm // starting impulses were applied in the discrete solver. contactSolver.InitializeVelocityConstraints(); // Solve velocity constraints. for (int32 i = 0; i < subStep.velocityIterations; ++i) { contactSolver.SolveVelocityConstraints(); } // Don't store the TOI contact forces for warm starting // because they can be quite large. float32 h = subStep.dt; // Integrate positions for (int32 i = 0; i < m_bodyCount; ++i) { b2Vec2 c = m_positions[i].c; float32 a = m_positions[i].a; b2Vec2 v = m_velocities[i].v; float32 w = m_velocities[i].w; // Check for large velocities b2Vec2 translation = h * v; if (b2Dot(translation, translation) > b2_maxTranslationSquared) { float32 ratio = b2_maxTranslation / translation.Length(); v *= ratio; } float32 rotation = h * w; if (rotation * rotation > b2_maxRotationSquared) { float32 ratio = b2_maxRotation / b2Abs(rotation); w *= ratio; } // Integrate c += h * v; a += h * w; m_positions[i].c = c; m_positions[i].a = a; m_velocities[i].v = v; m_velocities[i].w = w; // Sync bodies b2Body* body = m_bodies[i]; body->m_sweep.c = c; body->m_sweep.a = a; body->m_linearVelocity = v; body->m_angularVelocity = w; body->SynchronizeTransform(); } Report(contactSolver.m_velocityConstraints); } void b2Island::Report(const b2ContactVelocityConstraint* constraints) { if (m_listener == NULL) { return; } for (int32 i = 0; i < m_contactCount; ++i) { b2Contact* c = m_contacts[i]; const b2ContactVelocityConstraint* vc = constraints + i; b2ContactImpulse impulse; impulse.count = vc->pointCount; for (int32 j = 0; j < vc->pointCount; ++j) { impulse.normalImpulses[j] = vc->points[j].normalImpulse; impulse.tangentImpulses[j] = vc->points[j].tangentImpulse; } m_listener->PostSolve(c, &impulse); } } qml-box2d/Box2D/Dynamics/b2Island.h0000644000000000000000000000461512241175670014060 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_ISLAND_H #define B2_ISLAND_H #include #include #include class b2Contact; class b2Joint; class b2StackAllocator; class b2ContactListener; struct b2ContactVelocityConstraint; struct b2Profile; /// This is an internal class. class b2Island { public: b2Island(int32 bodyCapacity, int32 contactCapacity, int32 jointCapacity, b2StackAllocator* allocator, b2ContactListener* listener); ~b2Island(); void Clear() { m_bodyCount = 0; m_contactCount = 0; m_jointCount = 0; } void Solve(b2Profile* profile, const b2TimeStep& step, const b2Vec2& gravity, bool allowSleep); void SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB); void Add(b2Body* body) { b2Assert(m_bodyCount < m_bodyCapacity); body->m_islandIndex = m_bodyCount; m_bodies[m_bodyCount] = body; ++m_bodyCount; } void Add(b2Contact* contact) { b2Assert(m_contactCount < m_contactCapacity); m_contacts[m_contactCount++] = contact; } void Add(b2Joint* joint) { b2Assert(m_jointCount < m_jointCapacity); m_joints[m_jointCount++] = joint; } void Report(const b2ContactVelocityConstraint* constraints); b2StackAllocator* m_allocator; b2ContactListener* m_listener; b2Body** m_bodies; b2Contact** m_contacts; b2Joint** m_joints; b2Position* m_positions; b2Velocity* m_velocities; int32 m_bodyCount; int32 m_jointCount; int32 m_contactCount; int32 m_bodyCapacity; int32 m_contactCapacity; int32 m_jointCapacity; }; #endif qml-box2d/Box2D/Dynamics/Contacts/0000755000000000000000000000000012310072714014011 5ustar qml-box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h0000644000000000000000000000301012241175670020741 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CHAIN_AND_POLYGON_CONTACT_H #define B2_CHAIN_AND_POLYGON_CONTACT_H #include class b2BlockAllocator; class b2ChainAndPolygonContact : public b2Contact { public: static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2ChainAndPolygonContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); ~b2ChainAndPolygonContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2ContactSolver.cpp0000664000000000000000000005436012310072714017541 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #define B2_DEBUG_SOLVER 0 struct b2ContactPositionConstraint { b2Vec2 localPoints[b2_maxManifoldPoints]; b2Vec2 localNormal; b2Vec2 localPoint; int32 indexA; int32 indexB; float32 invMassA, invMassB; b2Vec2 localCenterA, localCenterB; float32 invIA, invIB; b2Manifold::Type type; float32 radiusA, radiusB; int32 pointCount; }; b2ContactSolver::b2ContactSolver(b2ContactSolverDef* def) { m_step = def->step; m_allocator = def->allocator; m_count = def->count; m_positionConstraints = (b2ContactPositionConstraint*)m_allocator->Allocate(m_count * sizeof(b2ContactPositionConstraint)); m_velocityConstraints = (b2ContactVelocityConstraint*)m_allocator->Allocate(m_count * sizeof(b2ContactVelocityConstraint)); m_positions = def->positions; m_velocities = def->velocities; m_contacts = def->contacts; // Initialize position independent portions of the constraints. for (int32 i = 0; i < m_count; ++i) { b2Contact* contact = m_contacts[i]; b2Fixture* fixtureA = contact->m_fixtureA; b2Fixture* fixtureB = contact->m_fixtureB; b2Shape* shapeA = fixtureA->GetShape(); b2Shape* shapeB = fixtureB->GetShape(); float32 radiusA = shapeA->m_radius; float32 radiusB = shapeB->m_radius; b2Body* bodyA = fixtureA->GetBody(); b2Body* bodyB = fixtureB->GetBody(); b2Manifold* manifold = contact->GetManifold(); int32 pointCount = manifold->pointCount; b2Assert(pointCount > 0); b2ContactVelocityConstraint* vc = m_velocityConstraints + i; vc->friction = contact->m_friction; vc->restitution = contact->m_restitution; vc->tangentSpeed = contact->m_tangentSpeed; vc->indexA = bodyA->m_islandIndex; vc->indexB = bodyB->m_islandIndex; vc->invMassA = bodyA->m_invMass; vc->invMassB = bodyB->m_invMass; vc->invIA = bodyA->m_invI; vc->invIB = bodyB->m_invI; vc->contactIndex = i; vc->pointCount = pointCount; vc->K.SetZero(); vc->normalMass.SetZero(); b2ContactPositionConstraint* pc = m_positionConstraints + i; pc->indexA = bodyA->m_islandIndex; pc->indexB = bodyB->m_islandIndex; pc->invMassA = bodyA->m_invMass; pc->invMassB = bodyB->m_invMass; pc->localCenterA = bodyA->m_sweep.localCenter; pc->localCenterB = bodyB->m_sweep.localCenter; pc->invIA = bodyA->m_invI; pc->invIB = bodyB->m_invI; pc->localNormal = manifold->localNormal; pc->localPoint = manifold->localPoint; pc->pointCount = pointCount; pc->radiusA = radiusA; pc->radiusB = radiusB; pc->type = manifold->type; for (int32 j = 0; j < pointCount; ++j) { b2ManifoldPoint* cp = manifold->points + j; b2VelocityConstraintPoint* vcp = vc->points + j; if (m_step.warmStarting) { vcp->normalImpulse = m_step.dtRatio * cp->normalImpulse; vcp->tangentImpulse = m_step.dtRatio * cp->tangentImpulse; } else { vcp->normalImpulse = 0.0f; vcp->tangentImpulse = 0.0f; } vcp->rA.SetZero(); vcp->rB.SetZero(); vcp->normalMass = 0.0f; vcp->tangentMass = 0.0f; vcp->velocityBias = 0.0f; pc->localPoints[j] = cp->localPoint; } } } b2ContactSolver::~b2ContactSolver() { m_allocator->Free(m_velocityConstraints); m_allocator->Free(m_positionConstraints); } // Initialize position dependent portions of the velocity constraints. void b2ContactSolver::InitializeVelocityConstraints() { for (int32 i = 0; i < m_count; ++i) { b2ContactVelocityConstraint* vc = m_velocityConstraints + i; b2ContactPositionConstraint* pc = m_positionConstraints + i; float32 radiusA = pc->radiusA; float32 radiusB = pc->radiusB; b2Manifold* manifold = m_contacts[vc->contactIndex]->GetManifold(); int32 indexA = vc->indexA; int32 indexB = vc->indexB; float32 mA = vc->invMassA; float32 mB = vc->invMassB; float32 iA = vc->invIA; float32 iB = vc->invIB; b2Vec2 localCenterA = pc->localCenterA; b2Vec2 localCenterB = pc->localCenterB; b2Vec2 cA = m_positions[indexA].c; float32 aA = m_positions[indexA].a; b2Vec2 vA = m_velocities[indexA].v; float32 wA = m_velocities[indexA].w; b2Vec2 cB = m_positions[indexB].c; float32 aB = m_positions[indexB].a; b2Vec2 vB = m_velocities[indexB].v; float32 wB = m_velocities[indexB].w; b2Assert(manifold->pointCount > 0); b2Transform xfA, xfB; xfA.q.Set(aA); xfB.q.Set(aB); xfA.p = cA - b2Mul(xfA.q, localCenterA); xfB.p = cB - b2Mul(xfB.q, localCenterB); b2WorldManifold worldManifold; worldManifold.Initialize(manifold, xfA, radiusA, xfB, radiusB); vc->normal = worldManifold.normal; int32 pointCount = vc->pointCount; for (int32 j = 0; j < pointCount; ++j) { b2VelocityConstraintPoint* vcp = vc->points + j; vcp->rA = worldManifold.points[j] - cA; vcp->rB = worldManifold.points[j] - cB; float32 rnA = b2Cross(vcp->rA, vc->normal); float32 rnB = b2Cross(vcp->rB, vc->normal); float32 kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; vcp->normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f; b2Vec2 tangent = b2Cross(vc->normal, 1.0f); float32 rtA = b2Cross(vcp->rA, tangent); float32 rtB = b2Cross(vcp->rB, tangent); float32 kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; vcp->tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f; // Setup a velocity bias for restitution. vcp->velocityBias = 0.0f; float32 vRel = b2Dot(vc->normal, vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA)); if (vRel < -b2_velocityThreshold) { vcp->velocityBias = -vc->restitution * vRel; } } // If we have two points, then prepare the block solver. if (vc->pointCount == 2) { b2VelocityConstraintPoint* vcp1 = vc->points + 0; b2VelocityConstraintPoint* vcp2 = vc->points + 1; float32 rn1A = b2Cross(vcp1->rA, vc->normal); float32 rn1B = b2Cross(vcp1->rB, vc->normal); float32 rn2A = b2Cross(vcp2->rA, vc->normal); float32 rn2B = b2Cross(vcp2->rB, vc->normal); float32 k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B; float32 k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B; float32 k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B; // Ensure a reasonable condition number. const float32 k_maxConditionNumber = 1000.0f; if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { // K is safe to invert. vc->K.ex.Set(k11, k12); vc->K.ey.Set(k12, k22); vc->normalMass = vc->K.GetInverse(); } else { // The constraints are redundant, just use one. // TODO_ERIN use deepest? vc->pointCount = 1; } } } } void b2ContactSolver::WarmStart() { // Warm start. for (int32 i = 0; i < m_count; ++i) { b2ContactVelocityConstraint* vc = m_velocityConstraints + i; int32 indexA = vc->indexA; int32 indexB = vc->indexB; float32 mA = vc->invMassA; float32 iA = vc->invIA; float32 mB = vc->invMassB; float32 iB = vc->invIB; int32 pointCount = vc->pointCount; b2Vec2 vA = m_velocities[indexA].v; float32 wA = m_velocities[indexA].w; b2Vec2 vB = m_velocities[indexB].v; float32 wB = m_velocities[indexB].w; b2Vec2 normal = vc->normal; b2Vec2 tangent = b2Cross(normal, 1.0f); for (int32 j = 0; j < pointCount; ++j) { b2VelocityConstraintPoint* vcp = vc->points + j; b2Vec2 P = vcp->normalImpulse * normal + vcp->tangentImpulse * tangent; wA -= iA * b2Cross(vcp->rA, P); vA -= mA * P; wB += iB * b2Cross(vcp->rB, P); vB += mB * P; } m_velocities[indexA].v = vA; m_velocities[indexA].w = wA; m_velocities[indexB].v = vB; m_velocities[indexB].w = wB; } } void b2ContactSolver::SolveVelocityConstraints() { for (int32 i = 0; i < m_count; ++i) { b2ContactVelocityConstraint* vc = m_velocityConstraints + i; int32 indexA = vc->indexA; int32 indexB = vc->indexB; float32 mA = vc->invMassA; float32 iA = vc->invIA; float32 mB = vc->invMassB; float32 iB = vc->invIB; int32 pointCount = vc->pointCount; b2Vec2 vA = m_velocities[indexA].v; float32 wA = m_velocities[indexA].w; b2Vec2 vB = m_velocities[indexB].v; float32 wB = m_velocities[indexB].w; b2Vec2 normal = vc->normal; b2Vec2 tangent = b2Cross(normal, 1.0f); float32 friction = vc->friction; b2Assert(pointCount == 1 || pointCount == 2); // Solve tangent constraints first because non-penetration is more important // than friction. for (int32 j = 0; j < pointCount; ++j) { b2VelocityConstraintPoint* vcp = vc->points + j; // Relative velocity at contact b2Vec2 dv = vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA); // Compute tangent force float32 vt = b2Dot(dv, tangent) - vc->tangentSpeed; float32 lambda = vcp->tangentMass * (-vt); // b2Clamp the accumulated force float32 maxFriction = friction * vcp->normalImpulse; float32 newImpulse = b2Clamp(vcp->tangentImpulse + lambda, -maxFriction, maxFriction); lambda = newImpulse - vcp->tangentImpulse; vcp->tangentImpulse = newImpulse; // Apply contact impulse b2Vec2 P = lambda * tangent; vA -= mA * P; wA -= iA * b2Cross(vcp->rA, P); vB += mB * P; wB += iB * b2Cross(vcp->rB, P); } // Solve normal constraints if (vc->pointCount == 1) { b2VelocityConstraintPoint* vcp = vc->points + 0; // Relative velocity at contact b2Vec2 dv = vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA); // Compute normal impulse float32 vn = b2Dot(dv, normal); float32 lambda = -vcp->normalMass * (vn - vcp->velocityBias); // b2Clamp the accumulated impulse float32 newImpulse = b2Max(vcp->normalImpulse + lambda, 0.0f); lambda = newImpulse - vcp->normalImpulse; vcp->normalImpulse = newImpulse; // Apply contact impulse b2Vec2 P = lambda * normal; vA -= mA * P; wA -= iA * b2Cross(vcp->rA, P); vB += mB * P; wB += iB * b2Cross(vcp->rB, P); } else { // Block solver developed in collaboration with Dirk Gregorius (back in 01/07 on Box2D_Lite). // Build the mini LCP for this contact patch // // vn = A * x + b, vn >= 0, , vn >= 0, x >= 0 and vn_i * x_i = 0 with i = 1..2 // // A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n ) // b = vn0 - velocityBias // // The system is solved using the "Total enumeration method" (s. Murty). The complementary constraint vn_i * x_i // implies that we must have in any solution either vn_i = 0 or x_i = 0. So for the 2D contact problem the cases // vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and vn1 = 0 need to be tested. The first valid // solution that satisfies the problem is chosen. // // In order to account of the accumulated impulse 'a' (because of the iterative nature of the solver which only requires // that the accumulated impulse is clamped and not the incremental impulse) we change the impulse variable (x_i). // // Substitute: // // x = a + d // // a := old total impulse // x := new total impulse // d := incremental impulse // // For the current iteration we extend the formula for the incremental impulse // to compute the new total impulse: // // vn = A * d + b // = A * (x - a) + b // = A * x + b - A * a // = A * x + b' // b' = b - A * a; b2VelocityConstraintPoint* cp1 = vc->points + 0; b2VelocityConstraintPoint* cp2 = vc->points + 1; b2Vec2 a(cp1->normalImpulse, cp2->normalImpulse); b2Assert(a.x >= 0.0f && a.y >= 0.0f); // Relative velocity at contact b2Vec2 dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA); b2Vec2 dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA); // Compute normal velocity float32 vn1 = b2Dot(dv1, normal); float32 vn2 = b2Dot(dv2, normal); b2Vec2 b; b.x = vn1 - cp1->velocityBias; b.y = vn2 - cp2->velocityBias; // Compute b' b -= b2Mul(vc->K, a); const float32 k_errorTol = 1e-3f; B2_NOT_USED(k_errorTol); for (;;) { // // Case 1: vn = 0 // // 0 = A * x + b' // // Solve for x: // // x = - inv(A) * b' // b2Vec2 x = - b2Mul(vc->normalMass, b); if (x.x >= 0.0f && x.y >= 0.0f) { // Get the incremental impulse b2Vec2 d = x - a; // Apply incremental impulse b2Vec2 P1 = d.x * normal; b2Vec2 P2 = d.y * normal; vA -= mA * (P1 + P2); wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); vB += mB * (P1 + P2); wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); // Accumulate cp1->normalImpulse = x.x; cp2->normalImpulse = x.y; #if B2_DEBUG_SOLVER == 1 // Postconditions dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA); dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA); // Compute normal velocity vn1 = b2Dot(dv1, normal); vn2 = b2Dot(dv2, normal); b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol); b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol); #endif break; } // // Case 2: vn1 = 0 and x2 = 0 // // 0 = a11 * x1 + a12 * 0 + b1' // vn2 = a21 * x1 + a22 * 0 + b2' // x.x = - cp1->normalMass * b.x; x.y = 0.0f; vn1 = 0.0f; vn2 = vc->K.ex.y * x.x + b.y; if (x.x >= 0.0f && vn2 >= 0.0f) { // Get the incremental impulse b2Vec2 d = x - a; // Apply incremental impulse b2Vec2 P1 = d.x * normal; b2Vec2 P2 = d.y * normal; vA -= mA * (P1 + P2); wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); vB += mB * (P1 + P2); wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); // Accumulate cp1->normalImpulse = x.x; cp2->normalImpulse = x.y; #if B2_DEBUG_SOLVER == 1 // Postconditions dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA); // Compute normal velocity vn1 = b2Dot(dv1, normal); b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol); #endif break; } // // Case 3: vn2 = 0 and x1 = 0 // // vn1 = a11 * 0 + a12 * x2 + b1' // 0 = a21 * 0 + a22 * x2 + b2' // x.x = 0.0f; x.y = - cp2->normalMass * b.y; vn1 = vc->K.ey.x * x.y + b.x; vn2 = 0.0f; if (x.y >= 0.0f && vn1 >= 0.0f) { // Resubstitute for the incremental impulse b2Vec2 d = x - a; // Apply incremental impulse b2Vec2 P1 = d.x * normal; b2Vec2 P2 = d.y * normal; vA -= mA * (P1 + P2); wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); vB += mB * (P1 + P2); wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); // Accumulate cp1->normalImpulse = x.x; cp2->normalImpulse = x.y; #if B2_DEBUG_SOLVER == 1 // Postconditions dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA); // Compute normal velocity vn2 = b2Dot(dv2, normal); b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol); #endif break; } // // Case 4: x1 = 0 and x2 = 0 // // vn1 = b1 // vn2 = b2; x.x = 0.0f; x.y = 0.0f; vn1 = b.x; vn2 = b.y; if (vn1 >= 0.0f && vn2 >= 0.0f ) { // Resubstitute for the incremental impulse b2Vec2 d = x - a; // Apply incremental impulse b2Vec2 P1 = d.x * normal; b2Vec2 P2 = d.y * normal; vA -= mA * (P1 + P2); wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); vB += mB * (P1 + P2); wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); // Accumulate cp1->normalImpulse = x.x; cp2->normalImpulse = x.y; break; } // No solution, give up. This is hit sometimes, but it doesn't seem to matter. break; } } m_velocities[indexA].v = vA; m_velocities[indexA].w = wA; m_velocities[indexB].v = vB; m_velocities[indexB].w = wB; } } void b2ContactSolver::StoreImpulses() { for (int32 i = 0; i < m_count; ++i) { b2ContactVelocityConstraint* vc = m_velocityConstraints + i; b2Manifold* manifold = m_contacts[vc->contactIndex]->GetManifold(); for (int32 j = 0; j < vc->pointCount; ++j) { manifold->points[j].normalImpulse = vc->points[j].normalImpulse; manifold->points[j].tangentImpulse = vc->points[j].tangentImpulse; } } } struct b2PositionSolverManifold { void Initialize(b2ContactPositionConstraint* pc, const b2Transform& xfA, const b2Transform& xfB, int32 index) { b2Assert(pc->pointCount > 0); switch (pc->type) { case b2Manifold::e_circles: { b2Vec2 pointA = b2Mul(xfA, pc->localPoint); b2Vec2 pointB = b2Mul(xfB, pc->localPoints[0]); normal = pointB - pointA; normal.Normalize(); point = 0.5f * (pointA + pointB); separation = b2Dot(pointB - pointA, normal) - pc->radiusA - pc->radiusB; } break; case b2Manifold::e_faceA: { normal = b2Mul(xfA.q, pc->localNormal); b2Vec2 planePoint = b2Mul(xfA, pc->localPoint); b2Vec2 clipPoint = b2Mul(xfB, pc->localPoints[index]); separation = b2Dot(clipPoint - planePoint, normal) - pc->radiusA - pc->radiusB; point = clipPoint; } break; case b2Manifold::e_faceB: { normal = b2Mul(xfB.q, pc->localNormal); b2Vec2 planePoint = b2Mul(xfB, pc->localPoint); b2Vec2 clipPoint = b2Mul(xfA, pc->localPoints[index]); separation = b2Dot(clipPoint - planePoint, normal) - pc->radiusA - pc->radiusB; point = clipPoint; // Ensure normal points from A to B normal = -normal; } break; } } b2Vec2 normal; b2Vec2 point; float32 separation; }; // Sequential solver. bool b2ContactSolver::SolvePositionConstraints() { float32 minSeparation = 0.0f; for (int32 i = 0; i < m_count; ++i) { b2ContactPositionConstraint* pc = m_positionConstraints + i; int32 indexA = pc->indexA; int32 indexB = pc->indexB; b2Vec2 localCenterA = pc->localCenterA; float32 mA = pc->invMassA; float32 iA = pc->invIA; b2Vec2 localCenterB = pc->localCenterB; float32 mB = pc->invMassB; float32 iB = pc->invIB; int32 pointCount = pc->pointCount; b2Vec2 cA = m_positions[indexA].c; float32 aA = m_positions[indexA].a; b2Vec2 cB = m_positions[indexB].c; float32 aB = m_positions[indexB].a; // Solve normal constraints for (int32 j = 0; j < pointCount; ++j) { b2Transform xfA, xfB; xfA.q.Set(aA); xfB.q.Set(aB); xfA.p = cA - b2Mul(xfA.q, localCenterA); xfB.p = cB - b2Mul(xfB.q, localCenterB); b2PositionSolverManifold psm; psm.Initialize(pc, xfA, xfB, j); b2Vec2 normal = psm.normal; b2Vec2 point = psm.point; float32 separation = psm.separation; b2Vec2 rA = point - cA; b2Vec2 rB = point - cB; // Track max constraint error. minSeparation = b2Min(minSeparation, separation); // Prevent large corrections and allow slop. float32 C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f); // Compute the effective mass. float32 rnA = b2Cross(rA, normal); float32 rnB = b2Cross(rB, normal); float32 K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; // Compute normal impulse float32 impulse = K > 0.0f ? - C / K : 0.0f; b2Vec2 P = impulse * normal; cA -= mA * P; aA -= iA * b2Cross(rA, P); cB += mB * P; aB += iB * b2Cross(rB, P); } m_positions[indexA].c = cA; m_positions[indexA].a = aA; m_positions[indexB].c = cB; m_positions[indexB].a = aB; } // We can't expect minSpeparation >= -b2_linearSlop because we don't // push the separation above -b2_linearSlop. return minSeparation >= -3.0f * b2_linearSlop; } // Sequential position solver for position constraints. bool b2ContactSolver::SolveTOIPositionConstraints(int32 toiIndexA, int32 toiIndexB) { float32 minSeparation = 0.0f; for (int32 i = 0; i < m_count; ++i) { b2ContactPositionConstraint* pc = m_positionConstraints + i; int32 indexA = pc->indexA; int32 indexB = pc->indexB; b2Vec2 localCenterA = pc->localCenterA; b2Vec2 localCenterB = pc->localCenterB; int32 pointCount = pc->pointCount; float32 mA = 0.0f; float32 iA = 0.0f; if (indexA == toiIndexA || indexA == toiIndexB) { mA = pc->invMassA; iA = pc->invIA; } float32 mB = 0.0f; float32 iB = 0.; if (indexB == toiIndexA || indexB == toiIndexB) { mB = pc->invMassB; iB = pc->invIB; } b2Vec2 cA = m_positions[indexA].c; float32 aA = m_positions[indexA].a; b2Vec2 cB = m_positions[indexB].c; float32 aB = m_positions[indexB].a; // Solve normal constraints for (int32 j = 0; j < pointCount; ++j) { b2Transform xfA, xfB; xfA.q.Set(aA); xfB.q.Set(aB); xfA.p = cA - b2Mul(xfA.q, localCenterA); xfB.p = cB - b2Mul(xfB.q, localCenterB); b2PositionSolverManifold psm; psm.Initialize(pc, xfA, xfB, j); b2Vec2 normal = psm.normal; b2Vec2 point = psm.point; float32 separation = psm.separation; b2Vec2 rA = point - cA; b2Vec2 rB = point - cB; // Track max constraint error. minSeparation = b2Min(minSeparation, separation); // Prevent large corrections and allow slop. float32 C = b2Clamp(b2_toiBaugarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f); // Compute the effective mass. float32 rnA = b2Cross(rA, normal); float32 rnB = b2Cross(rB, normal); float32 K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; // Compute normal impulse float32 impulse = K > 0.0f ? - C / K : 0.0f; b2Vec2 P = impulse * normal; cA -= mA * P; aA -= iA * b2Cross(rA, P); cB += mB * P; aB += iB * b2Cross(rB, P); } m_positions[indexA].c = cA; m_positions[indexA].a = aA; m_positions[indexB].c = cB; m_positions[indexB].a = aB; } // We can't expect minSpeparation >= -b2_linearSlop because we don't // push the separation above -b2_linearSlop. return minSeparation >= -1.5f * b2_linearSlop; } qml-box2d/Box2D/Dynamics/Contacts/b2PolygonContact.cpp0000664000000000000000000000404012310072714017704 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include b2Contact* b2PolygonContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2PolygonContact)); return new (mem) b2PolygonContact(fixtureA, fixtureB); } void b2PolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2PolygonContact*)contact)->~b2PolygonContact(); allocator->Free(contact, sizeof(b2PolygonContact)); } b2PolygonContact::b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB) : b2Contact(fixtureA, 0, fixtureB, 0) { b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon); b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon); } void b2PolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2CollidePolygons( manifold, (b2PolygonShape*)m_fixtureA->GetShape(), xfA, (b2PolygonShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2Contact.cpp0000664000000000000000000001634012310072714016342 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include b2ContactRegister b2Contact::s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]; bool b2Contact::s_initialized = false; void b2Contact::InitializeRegisters() { AddType(b2CircleContact::Create, b2CircleContact::Destroy, b2Shape::e_circle, b2Shape::e_circle); AddType(b2PolygonAndCircleContact::Create, b2PolygonAndCircleContact::Destroy, b2Shape::e_polygon, b2Shape::e_circle); AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, b2Shape::e_polygon, b2Shape::e_polygon); AddType(b2EdgeAndCircleContact::Create, b2EdgeAndCircleContact::Destroy, b2Shape::e_edge, b2Shape::e_circle); AddType(b2EdgeAndPolygonContact::Create, b2EdgeAndPolygonContact::Destroy, b2Shape::e_edge, b2Shape::e_polygon); AddType(b2ChainAndCircleContact::Create, b2ChainAndCircleContact::Destroy, b2Shape::e_chain, b2Shape::e_circle); AddType(b2ChainAndPolygonContact::Create, b2ChainAndPolygonContact::Destroy, b2Shape::e_chain, b2Shape::e_polygon); } void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn, b2Shape::Type type1, b2Shape::Type type2) { b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount); b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount); s_registers[type1][type2].createFcn = createFcn; s_registers[type1][type2].destroyFcn = destoryFcn; s_registers[type1][type2].primary = true; if (type1 != type2) { s_registers[type2][type1].createFcn = createFcn; s_registers[type2][type1].destroyFcn = destoryFcn; s_registers[type2][type1].primary = false; } } b2Contact* b2Contact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator) { if (s_initialized == false) { InitializeRegisters(); s_initialized = true; } b2Shape::Type type1 = fixtureA->GetType(); b2Shape::Type type2 = fixtureB->GetType(); b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount); b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount); b2ContactCreateFcn* createFcn = s_registers[type1][type2].createFcn; if (createFcn) { if (s_registers[type1][type2].primary) { return createFcn(fixtureA, indexA, fixtureB, indexB, allocator); } else { return createFcn(fixtureB, indexB, fixtureA, indexA, allocator); } } else { return NULL; } } void b2Contact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { b2Assert(s_initialized == true); b2Fixture* fixtureA = contact->m_fixtureA; b2Fixture* fixtureB = contact->m_fixtureB; if (contact->m_manifold.pointCount > 0 && fixtureA->IsSensor() == false && fixtureB->IsSensor() == false) { fixtureA->GetBody()->SetAwake(true); fixtureB->GetBody()->SetAwake(true); } b2Shape::Type typeA = fixtureA->GetType(); b2Shape::Type typeB = fixtureB->GetType(); b2Assert(0 <= typeA && typeB < b2Shape::e_typeCount); b2Assert(0 <= typeA && typeB < b2Shape::e_typeCount); b2ContactDestroyFcn* destroyFcn = s_registers[typeA][typeB].destroyFcn; destroyFcn(contact, allocator); } b2Contact::b2Contact(b2Fixture* fA, int32 indexA, b2Fixture* fB, int32 indexB) { m_flags = e_enabledFlag; m_fixtureA = fA; m_fixtureB = fB; m_indexA = indexA; m_indexB = indexB; m_manifold.pointCount = 0; m_prev = NULL; m_next = NULL; m_nodeA.contact = NULL; m_nodeA.prev = NULL; m_nodeA.next = NULL; m_nodeA.other = NULL; m_nodeB.contact = NULL; m_nodeB.prev = NULL; m_nodeB.next = NULL; m_nodeB.other = NULL; m_toiCount = 0; m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); m_tangentSpeed = 0.0f; } // Update the contact manifold and touching status. // Note: do not assume the fixture AABBs are overlapping or are valid. void b2Contact::Update(b2ContactListener* listener) { b2Manifold oldManifold = m_manifold; // Re-enable this contact. m_flags |= e_enabledFlag; bool touching = false; bool wasTouching = (m_flags & e_touchingFlag) == e_touchingFlag; bool sensorA = m_fixtureA->IsSensor(); bool sensorB = m_fixtureB->IsSensor(); bool sensor = sensorA || sensorB; b2Body* bodyA = m_fixtureA->GetBody(); b2Body* bodyB = m_fixtureB->GetBody(); const b2Transform& xfA = bodyA->GetTransform(); const b2Transform& xfB = bodyB->GetTransform(); // Is this contact a sensor? if (sensor) { const b2Shape* shapeA = m_fixtureA->GetShape(); const b2Shape* shapeB = m_fixtureB->GetShape(); touching = b2TestOverlap(shapeA, m_indexA, shapeB, m_indexB, xfA, xfB); // Sensors don't generate manifolds. m_manifold.pointCount = 0; } else { Evaluate(&m_manifold, xfA, xfB); touching = m_manifold.pointCount > 0; // Match old contact ids to new contact ids and copy the // stored impulses to warm start the solver. for (int32 i = 0; i < m_manifold.pointCount; ++i) { b2ManifoldPoint* mp2 = m_manifold.points + i; mp2->normalImpulse = 0.0f; mp2->tangentImpulse = 0.0f; b2ContactID id2 = mp2->id; for (int32 j = 0; j < oldManifold.pointCount; ++j) { b2ManifoldPoint* mp1 = oldManifold.points + j; if (mp1->id.key == id2.key) { mp2->normalImpulse = mp1->normalImpulse; mp2->tangentImpulse = mp1->tangentImpulse; break; } } } if (touching != wasTouching) { bodyA->SetAwake(true); bodyB->SetAwake(true); } } if (touching) { m_flags |= e_touchingFlag; } else { m_flags &= ~e_touchingFlag; } if (wasTouching == false && touching == true && listener) { listener->BeginContact(this); } if (wasTouching == true && touching == false && listener) { listener->EndContact(this); } if (sensor == false && touching && listener) { listener->PreSolve(this, &oldManifold); } } qml-box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp0000664000000000000000000000436612310072714021305 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include b2Contact* b2ChainAndPolygonContact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2ChainAndPolygonContact)); return new (mem) b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB); } void b2ChainAndPolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2ChainAndPolygonContact*)contact)->~b2ChainAndPolygonContact(); allocator->Free(contact, sizeof(b2ChainAndPolygonContact)); } b2ChainAndPolygonContact::b2ChainAndPolygonContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB) : b2Contact(fixtureA, indexA, fixtureB, indexB) { b2Assert(m_fixtureA->GetType() == b2Shape::e_chain); b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon); } void b2ChainAndPolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2ChainShape* chain = (b2ChainShape*)m_fixtureA->GetShape(); b2EdgeShape edge; chain->GetChildEdge(&edge, m_indexA); b2CollideEdgeAndPolygon( manifold, &edge, xfA, (b2PolygonShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp0000664000000000000000000000402012310072714021447 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include b2Contact* b2PolygonAndCircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2PolygonAndCircleContact)); return new (mem) b2PolygonAndCircleContact(fixtureA, fixtureB); } void b2PolygonAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2PolygonAndCircleContact*)contact)->~b2PolygonAndCircleContact(); allocator->Free(contact, sizeof(b2PolygonAndCircleContact)); } b2PolygonAndCircleContact::b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB) : b2Contact(fixtureA, 0, fixtureB, 0) { b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon); b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); } void b2PolygonAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2CollidePolygonAndCircle( manifold, (b2PolygonShape*)m_fixtureA->GetShape(), xfA, (b2CircleShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2CircleContact.cpp0000664000000000000000000000401512310072714017460 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include b2Contact* b2CircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2CircleContact)); return new (mem) b2CircleContact(fixtureA, fixtureB); } void b2CircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2CircleContact*)contact)->~b2CircleContact(); allocator->Free(contact, sizeof(b2CircleContact)); } b2CircleContact::b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB) : b2Contact(fixtureA, 0, fixtureB, 0) { b2Assert(m_fixtureA->GetType() == b2Shape::e_circle); b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); } void b2CircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2CollideCircles(manifold, (b2CircleShape*)m_fixtureA->GetShape(), xfA, (b2CircleShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp0000664000000000000000000000376412310072714021130 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include b2Contact* b2EdgeAndPolygonContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2EdgeAndPolygonContact)); return new (mem) b2EdgeAndPolygonContact(fixtureA, fixtureB); } void b2EdgeAndPolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2EdgeAndPolygonContact*)contact)->~b2EdgeAndPolygonContact(); allocator->Free(contact, sizeof(b2EdgeAndPolygonContact)); } b2EdgeAndPolygonContact::b2EdgeAndPolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB) : b2Contact(fixtureA, 0, fixtureB, 0) { b2Assert(m_fixtureA->GetType() == b2Shape::e_edge); b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon); } void b2EdgeAndPolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2CollideEdgeAndPolygon( manifold, (b2EdgeShape*)m_fixtureA->GetShape(), xfA, (b2PolygonShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2ContactSolver.h0000664000000000000000000000456212310072714017205 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CONTACT_SOLVER_H #define B2_CONTACT_SOLVER_H #include #include #include class b2Contact; class b2Body; class b2StackAllocator; struct b2ContactPositionConstraint; struct b2VelocityConstraintPoint { b2Vec2 rA; b2Vec2 rB; float32 normalImpulse; float32 tangentImpulse; float32 normalMass; float32 tangentMass; float32 velocityBias; }; struct b2ContactVelocityConstraint { b2VelocityConstraintPoint points[b2_maxManifoldPoints]; b2Vec2 normal; b2Mat22 normalMass; b2Mat22 K; int32 indexA; int32 indexB; float32 invMassA, invMassB; float32 invIA, invIB; float32 friction; float32 restitution; float32 tangentSpeed; int32 pointCount; int32 contactIndex; }; struct b2ContactSolverDef { b2TimeStep step; b2Contact** contacts; int32 count; b2Position* positions; b2Velocity* velocities; b2StackAllocator* allocator; }; class b2ContactSolver { public: b2ContactSolver(b2ContactSolverDef* def); ~b2ContactSolver(); void InitializeVelocityConstraints(); void WarmStart(); void SolveVelocityConstraints(); void StoreImpulses(); bool SolvePositionConstraints(); bool SolveTOIPositionConstraints(int32 toiIndexA, int32 toiIndexB); b2TimeStep m_step; b2Position* m_positions; b2Velocity* m_velocities; b2StackAllocator* m_allocator; b2ContactPositionConstraint* m_positionConstraints; b2ContactVelocityConstraint* m_velocityConstraints; b2Contact** m_contacts; int m_count; }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp0000664000000000000000000000374612310072714020702 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include b2Contact* b2EdgeAndCircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2EdgeAndCircleContact)); return new (mem) b2EdgeAndCircleContact(fixtureA, fixtureB); } void b2EdgeAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2EdgeAndCircleContact*)contact)->~b2EdgeAndCircleContact(); allocator->Free(contact, sizeof(b2EdgeAndCircleContact)); } b2EdgeAndCircleContact::b2EdgeAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB) : b2Contact(fixtureA, 0, fixtureB, 0) { b2Assert(m_fixtureA->GetType() == b2Shape::e_edge); b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); } void b2EdgeAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2CollideEdgeAndCircle( manifold, (b2EdgeShape*)m_fixtureA->GetShape(), xfA, (b2CircleShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2CircleContact.h0000644000000000000000000000267312241175670017143 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CIRCLE_CONTACT_H #define B2_CIRCLE_CONTACT_H #include class b2BlockAllocator; class b2CircleContact : public b2Contact { public: static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB); ~b2CircleContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h0000644000000000000000000000275012241175670021132 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_POLYGON_AND_CIRCLE_CONTACT_H #define B2_POLYGON_AND_CIRCLE_CONTACT_H #include class b2BlockAllocator; class b2PolygonAndCircleContact : public b2Contact { public: static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB); ~b2PolygonAndCircleContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp0000664000000000000000000000434712310072714021056 0ustar /* * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include b2Contact* b2ChainAndCircleContact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator) { void* mem = allocator->Allocate(sizeof(b2ChainAndCircleContact)); return new (mem) b2ChainAndCircleContact(fixtureA, indexA, fixtureB, indexB); } void b2ChainAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) { ((b2ChainAndCircleContact*)contact)->~b2ChainAndCircleContact(); allocator->Free(contact, sizeof(b2ChainAndCircleContact)); } b2ChainAndCircleContact::b2ChainAndCircleContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB) : b2Contact(fixtureA, indexA, fixtureB, indexB) { b2Assert(m_fixtureA->GetType() == b2Shape::e_chain); b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); } void b2ChainAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) { b2ChainShape* chain = (b2ChainShape*)m_fixtureA->GetShape(); b2EdgeShape edge; chain->GetChildEdge(&edge, m_indexA); b2CollideEdgeAndCircle( manifold, &edge, xfA, (b2CircleShape*)m_fixtureB->GetShape(), xfB); } qml-box2d/Box2D/Dynamics/Contacts/b2PolygonContact.h0000644000000000000000000000270012241175670017360 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_POLYGON_CONTACT_H #define B2_POLYGON_CONTACT_H #include class b2BlockAllocator; class b2PolygonContact : public b2Contact { public: static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB); ~b2PolygonContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2Contact.h0000664000000000000000000002213612310072714016007 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CONTACT_H #define B2_CONTACT_H #include #include #include #include class b2Body; class b2Contact; class b2Fixture; class b2World; class b2BlockAllocator; class b2StackAllocator; class b2ContactListener; /// Friction mixing law. The idea is to allow either fixture to drive the restitution to zero. /// For example, anything slides on ice. inline float32 b2MixFriction(float32 friction1, float32 friction2) { return b2Sqrt(friction1 * friction2); } /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface. /// For example, a superball bounces on anything. inline float32 b2MixRestitution(float32 restitution1, float32 restitution2) { return restitution1 > restitution2 ? restitution1 : restitution2; } typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator); struct b2ContactRegister { b2ContactCreateFcn* createFcn; b2ContactDestroyFcn* destroyFcn; bool primary; }; /// A contact edge is used to connect bodies and contacts together /// in a contact graph where each body is a node and each contact /// is an edge. A contact edge belongs to a doubly linked list /// maintained in each attached body. Each contact has two contact /// nodes, one for each attached body. struct b2ContactEdge { b2Body* other; ///< provides quick access to the other body attached. b2Contact* contact; ///< the contact b2ContactEdge* prev; ///< the previous contact edge in the body's contact list b2ContactEdge* next; ///< the next contact edge in the body's contact list }; /// The class manages contact between two shapes. A contact exists for each overlapping /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist /// that has no contact points. class b2Contact { public: /// Get the contact manifold. Do not modify the manifold unless you understand the /// internals of Box2D. b2Manifold* GetManifold(); const b2Manifold* GetManifold() const; /// Get the world manifold. void GetWorldManifold(b2WorldManifold* worldManifold) const; /// Is this contact touching? bool IsTouching() const; /// Enable/disable this contact. This can be used inside the pre-solve /// contact listener. The contact is only disabled for the current /// time step (or sub-step in continuous collisions). void SetEnabled(bool flag); /// Has this contact been disabled? bool IsEnabled() const; /// Get the next contact in the world's contact list. b2Contact* GetNext(); const b2Contact* GetNext() const; /// Get fixture A in this contact. b2Fixture* GetFixtureA(); const b2Fixture* GetFixtureA() const; /// Get the child primitive index for fixture A. int32 GetChildIndexA() const; /// Get fixture B in this contact. b2Fixture* GetFixtureB(); const b2Fixture* GetFixtureB() const; /// Get the child primitive index for fixture B. int32 GetChildIndexB() const; /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve. /// This value persists until set or reset. void SetFriction(float32 friction); /// Get the friction. float32 GetFriction() const; /// Reset the friction mixture to the default value. void ResetFriction(); /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve. /// The value persists until you set or reset. void SetRestitution(float32 restitution); /// Get the restitution. float32 GetRestitution() const; /// Reset the restitution to the default value. void ResetRestitution(); /// Set the desired tangent speed for a conveyor belt behavior. In meters per second. void SetTangentSpeed(float32 speed); /// Get the desired tangent speed. In meters per second. float32 GetTangentSpeed() const; /// Evaluate this contact with your own manifold and transforms. virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0; protected: friend class b2ContactManager; friend class b2World; friend class b2ContactSolver; friend class b2Body; friend class b2Fixture; // Flags stored in m_flags enum { // Used when crawling contact graph when forming islands. e_islandFlag = 0x0001, // Set when the shapes are touching. e_touchingFlag = 0x0002, // This contact can be disabled (by user) e_enabledFlag = 0x0004, // This contact needs filtering because a fixture filter was changed. e_filterFlag = 0x0008, // This bullet contact had a TOI event e_bulletHitFlag = 0x0010, // This contact has a valid TOI in m_toi e_toiFlag = 0x0020 }; /// Flag this contact for filtering. Filtering will occur the next time step. void FlagForFiltering(); static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn, b2Shape::Type typeA, b2Shape::Type typeB); static void InitializeRegisters(); static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {} b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); virtual ~b2Contact() {} void Update(b2ContactListener* listener); static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]; static bool s_initialized; uint32 m_flags; // World pool and list pointers. b2Contact* m_prev; b2Contact* m_next; // Nodes for connecting bodies. b2ContactEdge m_nodeA; b2ContactEdge m_nodeB; b2Fixture* m_fixtureA; b2Fixture* m_fixtureB; int32 m_indexA; int32 m_indexB; b2Manifold m_manifold; int32 m_toiCount; float32 m_toi; float32 m_friction; float32 m_restitution; float32 m_tangentSpeed; }; inline b2Manifold* b2Contact::GetManifold() { return &m_manifold; } inline const b2Manifold* b2Contact::GetManifold() const { return &m_manifold; } inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const { const b2Body* bodyA = m_fixtureA->GetBody(); const b2Body* bodyB = m_fixtureB->GetBody(); const b2Shape* shapeA = m_fixtureA->GetShape(); const b2Shape* shapeB = m_fixtureB->GetShape(); worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius); } inline void b2Contact::SetEnabled(bool flag) { if (flag) { m_flags |= e_enabledFlag; } else { m_flags &= ~e_enabledFlag; } } inline bool b2Contact::IsEnabled() const { return (m_flags & e_enabledFlag) == e_enabledFlag; } inline bool b2Contact::IsTouching() const { return (m_flags & e_touchingFlag) == e_touchingFlag; } inline b2Contact* b2Contact::GetNext() { return m_next; } inline const b2Contact* b2Contact::GetNext() const { return m_next; } inline b2Fixture* b2Contact::GetFixtureA() { return m_fixtureA; } inline const b2Fixture* b2Contact::GetFixtureA() const { return m_fixtureA; } inline b2Fixture* b2Contact::GetFixtureB() { return m_fixtureB; } inline int32 b2Contact::GetChildIndexA() const { return m_indexA; } inline const b2Fixture* b2Contact::GetFixtureB() const { return m_fixtureB; } inline int32 b2Contact::GetChildIndexB() const { return m_indexB; } inline void b2Contact::FlagForFiltering() { m_flags |= e_filterFlag; } inline void b2Contact::SetFriction(float32 friction) { m_friction = friction; } inline float32 b2Contact::GetFriction() const { return m_friction; } inline void b2Contact::ResetFriction() { m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); } inline void b2Contact::SetRestitution(float32 restitution) { m_restitution = restitution; } inline float32 b2Contact::GetRestitution() const { return m_restitution; } inline void b2Contact::ResetRestitution() { m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); } inline void b2Contact::SetTangentSpeed(float32 speed) { m_tangentSpeed = speed; } inline float32 b2Contact::GetTangentSpeed() const { return m_tangentSpeed; } #endif qml-box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h0000644000000000000000000000274212241175670020350 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_EDGE_AND_CIRCLE_CONTACT_H #define B2_EDGE_AND_CIRCLE_CONTACT_H #include class b2BlockAllocator; class b2EdgeAndCircleContact : public b2Contact { public: static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2EdgeAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB); ~b2EdgeAndCircleContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h0000644000000000000000000000274712241175670020603 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_EDGE_AND_POLYGON_CONTACT_H #define B2_EDGE_AND_POLYGON_CONTACT_H #include class b2BlockAllocator; class b2EdgeAndPolygonContact : public b2Contact { public: static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2EdgeAndPolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB); ~b2EdgeAndPolygonContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h0000644000000000000000000000300312241175670020515 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_CHAIN_AND_CIRCLE_CONTACT_H #define B2_CHAIN_AND_CIRCLE_CONTACT_H #include class b2BlockAllocator; class b2ChainAndCircleContact : public b2Contact { public: static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); b2ChainAndCircleContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); ~b2ChainAndCircleContact() {} void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB); }; #endif qml-box2d/Box2D/Dynamics/b2ContactManager.cpp0000664000000000000000000001563012310072714016060 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include b2ContactFilter b2_defaultFilter; b2ContactListener b2_defaultListener; b2ContactManager::b2ContactManager() { m_contactList = NULL; m_contactCount = 0; m_contactFilter = &b2_defaultFilter; m_contactListener = &b2_defaultListener; m_allocator = NULL; } void b2ContactManager::Destroy(b2Contact* c) { b2Fixture* fixtureA = c->GetFixtureA(); b2Fixture* fixtureB = c->GetFixtureB(); b2Body* bodyA = fixtureA->GetBody(); b2Body* bodyB = fixtureB->GetBody(); if (m_contactListener && c->IsTouching()) { m_contactListener->EndContact(c); } // Remove from the world. if (c->m_prev) { c->m_prev->m_next = c->m_next; } if (c->m_next) { c->m_next->m_prev = c->m_prev; } if (c == m_contactList) { m_contactList = c->m_next; } // Remove from body 1 if (c->m_nodeA.prev) { c->m_nodeA.prev->next = c->m_nodeA.next; } if (c->m_nodeA.next) { c->m_nodeA.next->prev = c->m_nodeA.prev; } if (&c->m_nodeA == bodyA->m_contactList) { bodyA->m_contactList = c->m_nodeA.next; } // Remove from body 2 if (c->m_nodeB.prev) { c->m_nodeB.prev->next = c->m_nodeB.next; } if (c->m_nodeB.next) { c->m_nodeB.next->prev = c->m_nodeB.prev; } if (&c->m_nodeB == bodyB->m_contactList) { bodyB->m_contactList = c->m_nodeB.next; } // Call the factory. b2Contact::Destroy(c, m_allocator); --m_contactCount; } // This is the top level collision call for the time step. Here // all the narrow phase collision is processed for the world // contact list. void b2ContactManager::Collide() { // Update awake contacts. b2Contact* c = m_contactList; while (c) { b2Fixture* fixtureA = c->GetFixtureA(); b2Fixture* fixtureB = c->GetFixtureB(); int32 indexA = c->GetChildIndexA(); int32 indexB = c->GetChildIndexB(); b2Body* bodyA = fixtureA->GetBody(); b2Body* bodyB = fixtureB->GetBody(); // Is this contact flagged for filtering? if (c->m_flags & b2Contact::e_filterFlag) { // Should these bodies collide? if (bodyB->ShouldCollide(bodyA) == false) { b2Contact* cNuke = c; c = cNuke->GetNext(); Destroy(cNuke); continue; } // Check user filtering. if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) { b2Contact* cNuke = c; c = cNuke->GetNext(); Destroy(cNuke); continue; } // Clear the filtering flag. c->m_flags &= ~b2Contact::e_filterFlag; } bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody; bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody; // At least one body must be awake and it must be dynamic or kinematic. if (activeA == false && activeB == false) { c = c->GetNext(); continue; } int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId; int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId; bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB); // Here we destroy contacts that cease to overlap in the broad-phase. if (overlap == false) { b2Contact* cNuke = c; c = cNuke->GetNext(); Destroy(cNuke); continue; } // The contact persists. c->Update(m_contactListener); c = c->GetNext(); } } void b2ContactManager::FindNewContacts() { m_broadPhase.UpdatePairs(this); } void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB) { b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA; b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB; b2Fixture* fixtureA = proxyA->fixture; b2Fixture* fixtureB = proxyB->fixture; int32 indexA = proxyA->childIndex; int32 indexB = proxyB->childIndex; b2Body* bodyA = fixtureA->GetBody(); b2Body* bodyB = fixtureB->GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // TODO_ERIN use a hash table to remove a potential bottleneck when both // bodies have a lot of contacts. // Does a contact already exist? b2ContactEdge* edge = bodyB->GetContactList(); while (edge) { if (edge->other == bodyA) { b2Fixture* fA = edge->contact->GetFixtureA(); b2Fixture* fB = edge->contact->GetFixtureB(); int32 iA = edge->contact->GetChildIndexA(); int32 iB = edge->contact->GetChildIndexB(); if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) { // A contact already exists. return; } if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { // A contact already exists. return; } } edge = edge->next; } // Does a joint override collision? Is at least one body dynamic? if (bodyB->ShouldCollide(bodyA) == false) { return; } // Check user filtering. if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator); if (c == NULL) { return; } // Contact creation may swap fixtures. fixtureA = c->GetFixtureA(); fixtureB = c->GetFixtureB(); indexA = c->GetChildIndexA(); indexB = c->GetChildIndexB(); bodyA = fixtureA->GetBody(); bodyB = fixtureB->GetBody(); // Insert into the world. c->m_prev = NULL; c->m_next = m_contactList; if (m_contactList != NULL) { m_contactList->m_prev = c; } m_contactList = c; // Connect to island graph. // Connect to body A c->m_nodeA.contact = c; c->m_nodeA.other = bodyB; c->m_nodeA.prev = NULL; c->m_nodeA.next = bodyA->m_contactList; if (bodyA->m_contactList != NULL) { bodyA->m_contactList->prev = &c->m_nodeA; } bodyA->m_contactList = &c->m_nodeA; // Connect to body B c->m_nodeB.contact = c; c->m_nodeB.other = bodyA; c->m_nodeB.prev = NULL; c->m_nodeB.next = bodyB->m_contactList; if (bodyB->m_contactList != NULL) { bodyB->m_contactList->prev = &c->m_nodeB; } bodyB->m_contactList = &c->m_nodeB; // Wake up the bodies if (fixtureA->IsSensor() == false && fixtureB->IsSensor() == false) { bodyA->SetAwake(true); bodyB->SetAwake(true); } ++m_contactCount; } qml-box2d/Box2D/Dynamics/b2Fixture.h0000644000000000000000000002202212241175670014264 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_FIXTURE_H #define B2_FIXTURE_H #include #include #include class b2BlockAllocator; class b2Body; class b2BroadPhase; class b2Fixture; /// This holds contact filtering data. struct b2Filter { b2Filter() { categoryBits = 0x0001; maskBits = 0xFFFF; groupIndex = 0; } /// The collision category bits. Normally you would just set one bit. uint16 categoryBits; /// The collision mask bits. This states the categories that this /// shape would accept for collision. uint16 maskBits; /// Collision groups allow a certain group of objects to never collide (negative) /// or always collide (positive). Zero means no collision group. Non-zero group /// filtering always wins against the mask bits. int16 groupIndex; }; /// A fixture definition is used to create a fixture. This class defines an /// abstract fixture definition. You can reuse fixture definitions safely. struct b2FixtureDef { /// The constructor sets the default fixture definition values. b2FixtureDef() { shape = NULL; userData = NULL; friction = 0.2f; restitution = 0.0f; density = 0.0f; isSensor = false; } /// The shape, this must be set. The shape will be cloned, so you /// can create the shape on the stack. const b2Shape* shape; /// Use this to store application specific fixture data. void* userData; /// The friction coefficient, usually in the range [0,1]. float32 friction; /// The restitution (elasticity) usually in the range [0,1]. float32 restitution; /// The density, usually in kg/m^2. float32 density; /// A sensor shape collects contact information but never generates a collision /// response. bool isSensor; /// Contact filtering data. b2Filter filter; }; /// This proxy is used internally to connect fixtures to the broad-phase. struct b2FixtureProxy { b2AABB aabb; b2Fixture* fixture; int32 childIndex; int32 proxyId; }; /// A fixture is used to attach a shape to a body for collision detection. A fixture /// inherits its transform from its parent. Fixtures hold additional non-geometric data /// such as friction, collision filters, etc. /// Fixtures are created via b2Body::CreateFixture. /// @warning you cannot reuse fixtures. class b2Fixture { public: /// Get the type of the child shape. You can use this to down cast to the concrete shape. /// @return the shape type. b2Shape::Type GetType() const; /// Get the child shape. You can modify the child shape, however you should not change the /// number of vertices because this will crash some collision caching mechanisms. /// Manipulating the shape may lead to non-physical behavior. b2Shape* GetShape(); const b2Shape* GetShape() const; /// Set if this fixture is a sensor. void SetSensor(bool sensor); /// Is this fixture a sensor (non-solid)? /// @return the true if the shape is a sensor. bool IsSensor() const; /// Set the contact filtering data. This will not update contacts until the next time /// step when either parent body is active and awake. /// This automatically calls Refilter. void SetFilterData(const b2Filter& filter); /// Get the contact filtering data. const b2Filter& GetFilterData() const; /// Call this if you want to establish collision that was previously disabled by b2ContactFilter::ShouldCollide. void Refilter(); /// Get the parent body of this fixture. This is NULL if the fixture is not attached. /// @return the parent body. b2Body* GetBody(); const b2Body* GetBody() const; /// Get the next fixture in the parent body's fixture list. /// @return the next shape. b2Fixture* GetNext(); const b2Fixture* GetNext() const; /// Get the user data that was assigned in the fixture definition. Use this to /// store your application specific data. void* GetUserData() const; /// Set the user data. Use this to store your application specific data. void SetUserData(void* data); /// Test a point for containment in this fixture. /// @param p a point in world coordinates. bool TestPoint(const b2Vec2& p) const; /// Cast a ray against this shape. /// @param output the ray-cast results. /// @param input the ray-cast input parameters. bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const; /// Get the mass data for this fixture. The mass data is based on the density and /// the shape. The rotational inertia is about the shape's origin. This operation /// may be expensive. void GetMassData(b2MassData* massData) const; /// Set the density of this fixture. This will _not_ automatically adjust the mass /// of the body. You must call b2Body::ResetMassData to update the body's mass. void SetDensity(float32 density); /// Get the density of this fixture. float32 GetDensity() const; /// Get the coefficient of friction. float32 GetFriction() const; /// Set the coefficient of friction. This will _not_ change the friction of /// existing contacts. void SetFriction(float32 friction); /// Get the coefficient of restitution. float32 GetRestitution() const; /// Set the coefficient of restitution. This will _not_ change the restitution of /// existing contacts. void SetRestitution(float32 restitution); /// Get the fixture's AABB. This AABB may be enlarge and/or stale. /// If you need a more accurate AABB, compute it using the shape and /// the body transform. const b2AABB& GetAABB(int32 childIndex) const; /// Dump this fixture to the log file. void Dump(int32 bodyIndex); protected: friend class b2Body; friend class b2World; friend class b2Contact; friend class b2ContactManager; b2Fixture(); // We need separation create/destroy functions from the constructor/destructor because // the destructor cannot access the allocator (no destructor arguments allowed by C++). void Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def); void Destroy(b2BlockAllocator* allocator); // These support body activation/deactivation. void CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf); void DestroyProxies(b2BroadPhase* broadPhase); void Synchronize(b2BroadPhase* broadPhase, const b2Transform& xf1, const b2Transform& xf2); float32 m_density; b2Fixture* m_next; b2Body* m_body; b2Shape* m_shape; float32 m_friction; float32 m_restitution; b2FixtureProxy* m_proxies; int32 m_proxyCount; b2Filter m_filter; bool m_isSensor; void* m_userData; }; inline b2Shape::Type b2Fixture::GetType() const { return m_shape->GetType(); } inline b2Shape* b2Fixture::GetShape() { return m_shape; } inline const b2Shape* b2Fixture::GetShape() const { return m_shape; } inline bool b2Fixture::IsSensor() const { return m_isSensor; } inline const b2Filter& b2Fixture::GetFilterData() const { return m_filter; } inline void* b2Fixture::GetUserData() const { return m_userData; } inline void b2Fixture::SetUserData(void* data) { m_userData = data; } inline b2Body* b2Fixture::GetBody() { return m_body; } inline const b2Body* b2Fixture::GetBody() const { return m_body; } inline b2Fixture* b2Fixture::GetNext() { return m_next; } inline const b2Fixture* b2Fixture::GetNext() const { return m_next; } inline void b2Fixture::SetDensity(float32 density) { b2Assert(b2IsValid(density) && density >= 0.0f); m_density = density; } inline float32 b2Fixture::GetDensity() const { return m_density; } inline float32 b2Fixture::GetFriction() const { return m_friction; } inline void b2Fixture::SetFriction(float32 friction) { m_friction = friction; } inline float32 b2Fixture::GetRestitution() const { return m_restitution; } inline void b2Fixture::SetRestitution(float32 restitution) { m_restitution = restitution; } inline bool b2Fixture::TestPoint(const b2Vec2& p) const { return m_shape->TestPoint(m_body->GetTransform(), p); } inline bool b2Fixture::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const { return m_shape->RayCast(output, input, m_body->GetTransform(), childIndex); } inline void b2Fixture::GetMassData(b2MassData* massData) const { m_shape->ComputeMass(massData, m_density); } inline const b2AABB& b2Fixture::GetAABB(int32 childIndex) const { b2Assert(0 <= childIndex && childIndex < m_proxyCount); return m_proxies[childIndex].aabb; } #endif qml-box2d/Box2D/Dynamics/b2WorldCallbacks.h0000644000000000000000000001330412241175670015530 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_WORLD_CALLBACKS_H #define B2_WORLD_CALLBACKS_H #include struct b2Vec2; struct b2Transform; class b2Fixture; class b2Body; class b2Joint; class b2Contact; struct b2ContactResult; struct b2Manifold; /// Joints and fixtures are destroyed when their associated /// body is destroyed. Implement this listener so that you /// may nullify references to these joints and shapes. class b2DestructionListener { public: virtual ~b2DestructionListener() {} /// Called when any joint is about to be destroyed due /// to the destruction of one of its attached bodies. virtual void SayGoodbye(b2Joint* joint) = 0; /// Called when any fixture is about to be destroyed due /// to the destruction of its parent body. virtual void SayGoodbye(b2Fixture* fixture) = 0; }; /// Implement this class to provide collision filtering. In other words, you can implement /// this class if you want finer control over contact creation. class b2ContactFilter { public: virtual ~b2ContactFilter() {} /// Return true if contact calculations should be performed between these two shapes. /// @warning for performance reasons this is only called when the AABBs begin to overlap. virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB); }; /// Contact impulses for reporting. Impulses are used instead of forces because /// sub-step forces may approach infinity for rigid body collisions. These /// match up one-to-one with the contact points in b2Manifold. struct b2ContactImpulse { float32 normalImpulses[b2_maxManifoldPoints]; float32 tangentImpulses[b2_maxManifoldPoints]; int32 count; }; /// Implement this class to get contact information. You can use these results for /// things like sounds and game logic. You can also get contact results by /// traversing the contact lists after the time step. However, you might miss /// some contacts because continuous physics leads to sub-stepping. /// Additionally you may receive multiple callbacks for the same contact in a /// single time step. /// You should strive to make your callbacks efficient because there may be /// many callbacks per time step. /// @warning You cannot create/destroy Box2D entities inside these callbacks. class b2ContactListener { public: virtual ~b2ContactListener() {} /// Called when two fixtures begin to touch. virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); } /// Called when two fixtures cease to touch. virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); } /// This is called after a contact is updated. This allows you to inspect a /// contact before it goes to the solver. If you are careful, you can modify the /// contact manifold (e.g. disable contact). /// A copy of the old manifold is provided so that you can detect changes. /// Note: this is called only for awake bodies. /// Note: this is called even when the number of contact points is zero. /// Note: this is not called for sensors. /// Note: if you set the number of contact points to zero, you will not /// get an EndContact callback. However, you may get a BeginContact callback /// the next step. virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) { B2_NOT_USED(contact); B2_NOT_USED(oldManifold); } /// This lets you inspect a contact after the solver is finished. This is useful /// for inspecting impulses. /// Note: the contact manifold does not include time of impact impulses, which can be /// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly /// in a separate data structure. /// Note: this is only called for contacts that are touching, solid, and awake. virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) { B2_NOT_USED(contact); B2_NOT_USED(impulse); } }; /// Callback class for AABB queries. /// See b2World::Query class b2QueryCallback { public: virtual ~b2QueryCallback() {} /// Called for each fixture found in the query AABB. /// @return false to terminate the query. virtual bool ReportFixture(b2Fixture* fixture) = 0; }; /// Callback class for ray casts. /// See b2World::RayCast class b2RayCastCallback { public: virtual ~b2RayCastCallback() {} /// Called for each fixture found in the query. You control how the ray cast /// proceeds by returning a float: /// return -1: ignore this fixture and continue /// return 0: terminate the ray cast /// return fraction: clip the ray to this point /// return 1: don't clip the ray and continue /// @param fixture the fixture hit by the ray /// @param point the point of initial intersection /// @param normal the normal vector at the point of intersection /// @return -1 to filter, 0 to terminate, fraction to clip the ray for /// closest hit, 1 to continue virtual float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction) = 0; }; #endif qml-box2d/Box2D/Dynamics/b2Body.h0000664000000000000000000005431512310072714013537 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_BODY_H #define B2_BODY_H #include #include #include class b2Fixture; class b2Joint; class b2Contact; class b2Controller; class b2World; struct b2FixtureDef; struct b2JointEdge; struct b2ContactEdge; /// The body type. /// static: zero mass, zero velocity, may be manually moved /// kinematic: zero mass, non-zero velocity set by user, moved by solver /// dynamic: positive mass, non-zero velocity determined by forces, moved by solver enum b2BodyType { b2_staticBody = 0, b2_kinematicBody, b2_dynamicBody // TODO_ERIN //b2_bulletBody, }; /// A body definition holds all the data needed to construct a rigid body. /// You can safely re-use body definitions. Shapes are added to a body after construction. struct b2BodyDef { /// This constructor sets the body definition default values. b2BodyDef() { userData = NULL; position.Set(0.0f, 0.0f); angle = 0.0f; linearVelocity.Set(0.0f, 0.0f); angularVelocity = 0.0f; linearDamping = 0.0f; angularDamping = 0.0f; allowSleep = true; awake = true; fixedRotation = false; bullet = false; type = b2_staticBody; active = true; gravityScale = 1.0f; } /// The body type: static, kinematic, or dynamic. /// Note: if a dynamic body would have zero mass, the mass is set to one. b2BodyType type; /// The world position of the body. Avoid creating bodies at the origin /// since this can lead to many overlapping shapes. b2Vec2 position; /// The world angle of the body in radians. float32 angle; /// The linear velocity of the body's origin in world co-ordinates. b2Vec2 linearVelocity; /// The angular velocity of the body. float32 angularVelocity; /// Linear damping is use to reduce the linear velocity. The damping parameter /// can be larger than 1.0f but the damping effect becomes sensitive to the /// time step when the damping parameter is large. float32 linearDamping; /// Angular damping is use to reduce the angular velocity. The damping parameter /// can be larger than 1.0f but the damping effect becomes sensitive to the /// time step when the damping parameter is large. float32 angularDamping; /// Set this flag to false if this body should never fall asleep. Note that /// this increases CPU usage. bool allowSleep; /// Is this body initially awake or sleeping? bool awake; /// Should this body be prevented from rotating? Useful for characters. bool fixedRotation; /// Is this a fast moving body that should be prevented from tunneling through /// other moving bodies? Note that all bodies are prevented from tunneling through /// kinematic and static bodies. This setting is only considered on dynamic bodies. /// @warning You should use this flag sparingly since it increases processing time. bool bullet; /// Does this body start out active? bool active; /// Use this to store application specific body data. void* userData; /// Scale the gravity applied to this body. float32 gravityScale; }; /// A rigid body. These are created via b2World::CreateBody. class b2Body { public: /// Creates a fixture and attach it to this body. Use this function if you need /// to set some fixture parameters, like friction. Otherwise you can create the /// fixture directly from a shape. /// If the density is non-zero, this function automatically updates the mass of the body. /// Contacts are not created until the next time step. /// @param def the fixture definition. /// @warning This function is locked during callbacks. b2Fixture* CreateFixture(const b2FixtureDef* def); /// Creates a fixture from a shape and attach it to this body. /// This is a convenience function. Use b2FixtureDef if you need to set parameters /// like friction, restitution, user data, or filtering. /// If the density is non-zero, this function automatically updates the mass of the body. /// @param shape the shape to be cloned. /// @param density the shape density (set to zero for static bodies). /// @warning This function is locked during callbacks. b2Fixture* CreateFixture(const b2Shape* shape, float32 density); /// Destroy a fixture. This removes the fixture from the broad-phase and /// destroys all contacts associated with this fixture. This will /// automatically adjust the mass of the body if the body is dynamic and the /// fixture has positive density. /// All fixtures attached to a body are implicitly destroyed when the body is destroyed. /// @param fixture the fixture to be removed. /// @warning This function is locked during callbacks. void DestroyFixture(b2Fixture* fixture); /// Set the position of the body's origin and rotation. /// Manipulating a body's transform may cause non-physical behavior. /// Note: contacts are updated on the next call to b2World::Step. /// @param position the world position of the body's local origin. /// @param angle the world rotation in radians. void SetTransform(const b2Vec2& position, float32 angle); /// Get the body transform for the body's origin. /// @return the world transform of the body's origin. const b2Transform& GetTransform() const; /// Get the world body origin position. /// @return the world position of the body's origin. const b2Vec2& GetPosition() const; /// Get the angle in radians. /// @return the current world rotation angle in radians. float32 GetAngle() const; /// Get the world position of the center of mass. const b2Vec2& GetWorldCenter() const; /// Get the local position of the center of mass. const b2Vec2& GetLocalCenter() const; /// Set the linear velocity of the center of mass. /// @param v the new linear velocity of the center of mass. void SetLinearVelocity(const b2Vec2& v); /// Get the linear velocity of the center of mass. /// @return the linear velocity of the center of mass. const b2Vec2& GetLinearVelocity() const; /// Set the angular velocity. /// @param omega the new angular velocity in radians/second. void SetAngularVelocity(float32 omega); /// Get the angular velocity. /// @return the angular velocity in radians/second. float32 GetAngularVelocity() const; /// Apply a force at a world point. If the force is not /// applied at the center of mass, it will generate a torque and /// affect the angular velocity. This wakes up the body. /// @param force the world force vector, usually in Newtons (N). /// @param point the world position of the point of application. /// @param wake also wake up the body void ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake); /// Apply a force to the center of mass. This wakes up the body. /// @param force the world force vector, usually in Newtons (N). /// @param wake also wake up the body void ApplyForceToCenter(const b2Vec2& force, bool wake); /// Apply a torque. This affects the angular velocity /// without affecting the linear velocity of the center of mass. /// This wakes up the body. /// @param torque about the z-axis (out of the screen), usually in N-m. /// @param wake also wake up the body void ApplyTorque(float32 torque, bool wake); /// Apply an impulse at a point. This immediately modifies the velocity. /// It also modifies the angular velocity if the point of application /// is not at the center of mass. This wakes up the body. /// @param impulse the world impulse vector, usually in N-seconds or kg-m/s. /// @param point the world position of the point of application. /// @param wake also wake up the body void ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point, bool wake); /// Apply an angular impulse. /// @param impulse the angular impulse in units of kg*m*m/s /// @param wake also wake up the body void ApplyAngularImpulse(float32 impulse, bool wake); /// Get the total mass of the body. /// @return the mass, usually in kilograms (kg). float32 GetMass() const; /// Get the rotational inertia of the body about the local origin. /// @return the rotational inertia, usually in kg-m^2. float32 GetInertia() const; /// Get the mass data of the body. /// @return a struct containing the mass, inertia and center of the body. void GetMassData(b2MassData* data) const; /// Set the mass properties to override the mass properties of the fixtures. /// Note that this changes the center of mass position. /// Note that creating or destroying fixtures can also alter the mass. /// This function has no effect if the body isn't dynamic. /// @param massData the mass properties. void SetMassData(const b2MassData* data); /// This resets the mass properties to the sum of the mass properties of the fixtures. /// This normally does not need to be called unless you called SetMassData to override /// the mass and you later want to reset the mass. void ResetMassData(); /// Get the world coordinates of a point given the local coordinates. /// @param localPoint a point on the body measured relative the the body's origin. /// @return the same point expressed in world coordinates. b2Vec2 GetWorldPoint(const b2Vec2& localPoint) const; /// Get the world coordinates of a vector given the local coordinates. /// @param localVector a vector fixed in the body. /// @return the same vector expressed in world coordinates. b2Vec2 GetWorldVector(const b2Vec2& localVector) const; /// Gets a local point relative to the body's origin given a world point. /// @param a point in world coordinates. /// @return the corresponding local point relative to the body's origin. b2Vec2 GetLocalPoint(const b2Vec2& worldPoint) const; /// Gets a local vector given a world vector. /// @param a vector in world coordinates. /// @return the corresponding local vector. b2Vec2 GetLocalVector(const b2Vec2& worldVector) const; /// Get the world linear velocity of a world point attached to this body. /// @param a point in world coordinates. /// @return the world velocity of a point. b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const; /// Get the world velocity of a local point. /// @param a point in local coordinates. /// @return the world velocity of a point. b2Vec2 GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const; /// Get the linear damping of the body. float32 GetLinearDamping() const; /// Set the linear damping of the body. void SetLinearDamping(float32 linearDamping); /// Get the angular damping of the body. float32 GetAngularDamping() const; /// Set the angular damping of the body. void SetAngularDamping(float32 angularDamping); /// Get the gravity scale of the body. float32 GetGravityScale() const; /// Set the gravity scale of the body. void SetGravityScale(float32 scale); /// Set the type of this body. This may alter the mass and velocity. void SetType(b2BodyType type); /// Get the type of this body. b2BodyType GetType() const; /// Should this body be treated like a bullet for continuous collision detection? void SetBullet(bool flag); /// Is this body treated like a bullet for continuous collision detection? bool IsBullet() const; /// You can disable sleeping on this body. If you disable sleeping, the /// body will be woken. void SetSleepingAllowed(bool flag); /// Is this body allowed to sleep bool IsSleepingAllowed() const; /// Set the sleep state of the body. A sleeping body has very /// low CPU cost. /// @param flag set to true to wake the body, false to put it to sleep. void SetAwake(bool flag); /// Get the sleeping state of this body. /// @return true if the body is awake. bool IsAwake() const; /// Set the active state of the body. An inactive body is not /// simulated and cannot be collided with or woken up. /// If you pass a flag of true, all fixtures will be added to the /// broad-phase. /// If you pass a flag of false, all fixtures will be removed from /// the broad-phase and all contacts will be destroyed. /// Fixtures and joints are otherwise unaffected. You may continue /// to create/destroy fixtures and joints on inactive bodies. /// Fixtures on an inactive body are implicitly inactive and will /// not participate in collisions, ray-casts, or queries. /// Joints connected to an inactive body are implicitly inactive. /// An inactive body is still owned by a b2World object and remains /// in the body list. void SetActive(bool flag); /// Get the active state of the body. bool IsActive() const; /// Set this body to have fixed rotation. This causes the mass /// to be reset. void SetFixedRotation(bool flag); /// Does this body have fixed rotation? bool IsFixedRotation() const; /// Get the list of all fixtures attached to this body. b2Fixture* GetFixtureList(); const b2Fixture* GetFixtureList() const; /// Get the list of all joints attached to this body. b2JointEdge* GetJointList(); const b2JointEdge* GetJointList() const; /// Get the list of all contacts attached to this body. /// @warning this list changes during the time step and you may /// miss some collisions if you don't use b2ContactListener. b2ContactEdge* GetContactList(); const b2ContactEdge* GetContactList() const; /// Get the next body in the world's body list. b2Body* GetNext(); const b2Body* GetNext() const; /// Get the user data pointer that was provided in the body definition. void* GetUserData() const; /// Set the user data. Use this to store your application specific data. void SetUserData(void* data); /// Get the parent world of this body. b2World* GetWorld(); const b2World* GetWorld() const; /// Dump this body to a log file void Dump(); private: friend class b2World; friend class b2Island; friend class b2ContactManager; friend class b2ContactSolver; friend class b2Contact; friend class b2DistanceJoint; friend class b2FrictionJoint; friend class b2GearJoint; friend class b2MotorJoint; friend class b2MouseJoint; friend class b2PrismaticJoint; friend class b2PulleyJoint; friend class b2RevoluteJoint; friend class b2RopeJoint; friend class b2WeldJoint; friend class b2WheelJoint; // m_flags enum { e_islandFlag = 0x0001, e_awakeFlag = 0x0002, e_autoSleepFlag = 0x0004, e_bulletFlag = 0x0008, e_fixedRotationFlag = 0x0010, e_activeFlag = 0x0020, e_toiFlag = 0x0040 }; b2Body(const b2BodyDef* bd, b2World* world); ~b2Body(); void SynchronizeFixtures(); void SynchronizeTransform(); // This is used to prevent connected bodies from colliding. // It may lie, depending on the collideConnected flag. bool ShouldCollide(const b2Body* other) const; void Advance(float32 t); b2BodyType m_type; uint16 m_flags; int32 m_islandIndex; b2Transform m_xf; // the body origin transform b2Sweep m_sweep; // the swept motion for CCD b2Vec2 m_linearVelocity; float32 m_angularVelocity; b2Vec2 m_force; float32 m_torque; b2World* m_world; b2Body* m_prev; b2Body* m_next; b2Fixture* m_fixtureList; int32 m_fixtureCount; b2JointEdge* m_jointList; b2ContactEdge* m_contactList; float32 m_mass, m_invMass; // Rotational inertia about the center of mass. float32 m_I, m_invI; float32 m_linearDamping; float32 m_angularDamping; float32 m_gravityScale; float32 m_sleepTime; void* m_userData; }; inline b2BodyType b2Body::GetType() const { return m_type; } inline const b2Transform& b2Body::GetTransform() const { return m_xf; } inline const b2Vec2& b2Body::GetPosition() const { return m_xf.p; } inline float32 b2Body::GetAngle() const { return m_sweep.a; } inline const b2Vec2& b2Body::GetWorldCenter() const { return m_sweep.c; } inline const b2Vec2& b2Body::GetLocalCenter() const { return m_sweep.localCenter; } inline void b2Body::SetLinearVelocity(const b2Vec2& v) { if (m_type == b2_staticBody) { return; } if (b2Dot(v,v) > 0.0f) { SetAwake(true); } m_linearVelocity = v; } inline const b2Vec2& b2Body::GetLinearVelocity() const { return m_linearVelocity; } inline void b2Body::SetAngularVelocity(float32 w) { if (m_type == b2_staticBody) { return; } if (w * w > 0.0f) { SetAwake(true); } m_angularVelocity = w; } inline float32 b2Body::GetAngularVelocity() const { return m_angularVelocity; } inline float32 b2Body::GetMass() const { return m_mass; } inline float32 b2Body::GetInertia() const { return m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); } inline void b2Body::GetMassData(b2MassData* data) const { data->mass = m_mass; data->I = m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); data->center = m_sweep.localCenter; } inline b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint) const { return b2Mul(m_xf, localPoint); } inline b2Vec2 b2Body::GetWorldVector(const b2Vec2& localVector) const { return b2Mul(m_xf.q, localVector); } inline b2Vec2 b2Body::GetLocalPoint(const b2Vec2& worldPoint) const { return b2MulT(m_xf, worldPoint); } inline b2Vec2 b2Body::GetLocalVector(const b2Vec2& worldVector) const { return b2MulT(m_xf.q, worldVector); } inline b2Vec2 b2Body::GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const { return m_linearVelocity + b2Cross(m_angularVelocity, worldPoint - m_sweep.c); } inline b2Vec2 b2Body::GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const { return GetLinearVelocityFromWorldPoint(GetWorldPoint(localPoint)); } inline float32 b2Body::GetLinearDamping() const { return m_linearDamping; } inline void b2Body::SetLinearDamping(float32 linearDamping) { m_linearDamping = linearDamping; } inline float32 b2Body::GetAngularDamping() const { return m_angularDamping; } inline void b2Body::SetAngularDamping(float32 angularDamping) { m_angularDamping = angularDamping; } inline float32 b2Body::GetGravityScale() const { return m_gravityScale; } inline void b2Body::SetGravityScale(float32 scale) { m_gravityScale = scale; } inline void b2Body::SetBullet(bool flag) { if (flag) { m_flags |= e_bulletFlag; } else { m_flags &= ~e_bulletFlag; } } inline bool b2Body::IsBullet() const { return (m_flags & e_bulletFlag) == e_bulletFlag; } inline void b2Body::SetAwake(bool flag) { if (flag) { if ((m_flags & e_awakeFlag) == 0) { m_flags |= e_awakeFlag; m_sleepTime = 0.0f; } } else { m_flags &= ~e_awakeFlag; m_sleepTime = 0.0f; m_linearVelocity.SetZero(); m_angularVelocity = 0.0f; m_force.SetZero(); m_torque = 0.0f; } } inline bool b2Body::IsAwake() const { return (m_flags & e_awakeFlag) == e_awakeFlag; } inline bool b2Body::IsActive() const { return (m_flags & e_activeFlag) == e_activeFlag; } inline bool b2Body::IsFixedRotation() const { return (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag; } inline void b2Body::SetSleepingAllowed(bool flag) { if (flag) { m_flags |= e_autoSleepFlag; } else { m_flags &= ~e_autoSleepFlag; SetAwake(true); } } inline bool b2Body::IsSleepingAllowed() const { return (m_flags & e_autoSleepFlag) == e_autoSleepFlag; } inline b2Fixture* b2Body::GetFixtureList() { return m_fixtureList; } inline const b2Fixture* b2Body::GetFixtureList() const { return m_fixtureList; } inline b2JointEdge* b2Body::GetJointList() { return m_jointList; } inline const b2JointEdge* b2Body::GetJointList() const { return m_jointList; } inline b2ContactEdge* b2Body::GetContactList() { return m_contactList; } inline const b2ContactEdge* b2Body::GetContactList() const { return m_contactList; } inline b2Body* b2Body::GetNext() { return m_next; } inline const b2Body* b2Body::GetNext() const { return m_next; } inline void b2Body::SetUserData(void* data) { m_userData = data; } inline void* b2Body::GetUserData() const { return m_userData; } inline void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake) { if (m_type != b2_dynamicBody) { return; } if (wake && (m_flags & e_awakeFlag) == 0) { SetAwake(true); } // Don't accumulate a force if the body is sleeping. if (m_flags & e_awakeFlag) { m_force += force; m_torque += b2Cross(point - m_sweep.c, force); } } inline void b2Body::ApplyForceToCenter(const b2Vec2& force, bool wake) { if (m_type != b2_dynamicBody) { return; } if (wake && (m_flags & e_awakeFlag) == 0) { SetAwake(true); } // Don't accumulate a force if the body is sleeping if (m_flags & e_awakeFlag) { m_force += force; } } inline void b2Body::ApplyTorque(float32 torque, bool wake) { if (m_type != b2_dynamicBody) { return; } if (wake && (m_flags & e_awakeFlag) == 0) { SetAwake(true); } // Don't accumulate a force if the body is sleeping if (m_flags & e_awakeFlag) { m_torque += torque; } } inline void b2Body::ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point, bool wake) { if (m_type != b2_dynamicBody) { return; } if (wake && (m_flags & e_awakeFlag) == 0) { SetAwake(true); } // Don't accumulate velocity if the body is sleeping if (m_flags & e_awakeFlag) { m_linearVelocity += m_invMass * impulse; m_angularVelocity += m_invI * b2Cross(point - m_sweep.c, impulse); } } inline void b2Body::ApplyAngularImpulse(float32 impulse, bool wake) { if (m_type != b2_dynamicBody) { return; } if (wake && (m_flags & e_awakeFlag) == 0) { SetAwake(true); } // Don't accumulate velocity if the body is sleeping if (m_flags & e_awakeFlag) { m_angularVelocity += m_invI * impulse; } } inline void b2Body::SynchronizeTransform() { m_xf.q.Set(m_sweep.a); m_xf.p = m_sweep.c - b2Mul(m_xf.q, m_sweep.localCenter); } inline void b2Body::Advance(float32 alpha) { // Advance to the new safe time. This doesn't sync the broad-phase. m_sweep.Advance(alpha); m_sweep.c = m_sweep.c0; m_sweep.a = m_sweep.a0; m_xf.q.Set(m_sweep.a); m_xf.p = m_sweep.c - b2Mul(m_xf.q, m_sweep.localCenter); } inline b2World* b2Body::GetWorld() { return m_world; } inline const b2World* b2Body::GetWorld() const { return m_world; } #endif qml-box2d/Box2D/Dynamics/Joints/0000755000000000000000000000000012310072714013501 5ustar qml-box2d/Box2D/Dynamics/Joints/b2RopeJoint.h0000644000000000000000000000653712241175670016032 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_ROPE_JOINT_H #define B2_ROPE_JOINT_H #include /// Rope joint definition. This requires two body anchor points and /// a maximum lengths. /// Note: by default the connected objects will not collide. /// see collideConnected in b2JointDef. struct b2RopeJointDef : public b2JointDef { b2RopeJointDef() { type = e_ropeJoint; localAnchorA.Set(-1.0f, 0.0f); localAnchorB.Set(1.0f, 0.0f); maxLength = 0.0f; } /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The maximum length of the rope. /// Warning: this must be larger than b2_linearSlop or /// the joint will have no effect. float32 maxLength; }; /// A rope joint enforces a maximum distance between two points /// on two bodies. It has no other effect. /// Warning: if you attempt to change the maximum length during /// the simulation you will get some non-physical behavior. /// A model that would allow you to dynamically modify the length /// would have some sponginess, so I chose not to implement it /// that way. See b2DistanceJoint if you want to dynamically /// control length. class b2RopeJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// Set/Get the maximum length of the rope. void SetMaxLength(float32 length) { m_maxLength = length; } float32 GetMaxLength() const; b2LimitState GetLimitState() const; /// Dump joint to dmLog void Dump(); protected: friend class b2Joint; b2RopeJoint(const b2RopeJointDef* data); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; float32 m_maxLength; float32 m_length; float32 m_impulse; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_u; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; float32 m_mass; b2LimitState m_state; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2MotorJoint.cpp0000664000000000000000000001762712310072714016554 0ustar /* * Copyright (c) 2006-2012 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Point-to-point constraint // Cdot = v2 - v1 // = v2 + cross(w2, r2) - v1 - cross(w1, r1) // J = [-I -r1_skew I r2_skew ] // Identity used: // w k % (rx i + ry j) = w * (-ry i + rx j) // Angle constraint // Cdot = w2 - w1 // J = [0 0 -1 0 0 1] // K = invI1 + invI2 void b2MotorJointDef::Initialize(b2Body* bA, b2Body* bB) { bodyA = bA; bodyB = bB; b2Vec2 xB = bodyB->GetPosition(); linearOffset = bodyA->GetLocalPoint(xB); float32 angleA = bodyA->GetAngle(); float32 angleB = bodyB->GetAngle(); angularOffset = angleB - angleA; } b2MotorJoint::b2MotorJoint(const b2MotorJointDef* def) : b2Joint(def) { m_linearOffset = def->linearOffset; m_angularOffset = def->angularOffset; m_linearImpulse.SetZero(); m_angularImpulse = 0.0f; m_maxForce = def->maxForce; m_maxTorque = def->maxTorque; m_correctionFactor = def->correctionFactor; } void b2MotorJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); // Compute the effective mass matrix. m_rA = b2Mul(qA, -m_localCenterA); m_rB = b2Mul(qB, -m_localCenterB); // J = [-I -r1_skew I r2_skew] // [ 0 -1 0 1] // r_skew = [-ry; rx] // Matlab // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Mat22 K; K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y; K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y; K.ey.x = K.ex.y; K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x; m_linearMass = K.GetInverse(); m_angularMass = iA + iB; if (m_angularMass > 0.0f) { m_angularMass = 1.0f / m_angularMass; } m_linearError = cB + m_rB - cA - m_rA - b2Mul(qA, m_linearOffset); m_angularError = aB - aA - m_angularOffset; if (data.step.warmStarting) { // Scale impulses to support a variable time step. m_linearImpulse *= data.step.dtRatio; m_angularImpulse *= data.step.dtRatio; b2Vec2 P(m_linearImpulse.x, m_linearImpulse.y); vA -= mA * P; wA -= iA * (b2Cross(m_rA, P) + m_angularImpulse); vB += mB * P; wB += iB * (b2Cross(m_rB, P) + m_angularImpulse); } else { m_linearImpulse.SetZero(); m_angularImpulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2MotorJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; float32 h = data.step.dt; float32 inv_h = data.step.inv_dt; // Solve angular friction { float32 Cdot = wB - wA + inv_h * m_correctionFactor * m_angularError; float32 impulse = -m_angularMass * Cdot; float32 oldImpulse = m_angularImpulse; float32 maxImpulse = h * m_maxTorque; m_angularImpulse = b2Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse); impulse = m_angularImpulse - oldImpulse; wA -= iA * impulse; wB += iB * impulse; } // Solve linear friction { b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA) + inv_h * m_correctionFactor * m_linearError; b2Vec2 impulse = -b2Mul(m_linearMass, Cdot); b2Vec2 oldImpulse = m_linearImpulse; m_linearImpulse += impulse; float32 maxImpulse = h * m_maxForce; if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { m_linearImpulse.Normalize(); m_linearImpulse *= maxImpulse; } impulse = m_linearImpulse - oldImpulse; vA -= mA * impulse; wA -= iA * b2Cross(m_rA, impulse); vB += mB * impulse; wB += iB * b2Cross(m_rB, impulse); } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2MotorJoint::SolvePositionConstraints(const b2SolverData& data) { B2_NOT_USED(data); return true; } b2Vec2 b2MotorJoint::GetAnchorA() const { return m_bodyA->GetPosition(); } b2Vec2 b2MotorJoint::GetAnchorB() const { return m_bodyB->GetPosition(); } b2Vec2 b2MotorJoint::GetReactionForce(float32 inv_dt) const { return inv_dt * m_linearImpulse; } float32 b2MotorJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * m_angularImpulse; } void b2MotorJoint::SetMaxForce(float32 force) { b2Assert(b2IsValid(force) && force >= 0.0f); m_maxForce = force; } float32 b2MotorJoint::GetMaxForce() const { return m_maxForce; } void b2MotorJoint::SetMaxTorque(float32 torque) { b2Assert(b2IsValid(torque) && torque >= 0.0f); m_maxTorque = torque; } float32 b2MotorJoint::GetMaxTorque() const { return m_maxTorque; } void b2MotorJoint::SetCorrectionFactor(float32 factor) { b2Assert(b2IsValid(factor) && 0.0f <= factor && factor <= 1.0f); m_correctionFactor = factor; } float32 b2MotorJoint::GetCorrectionFactor() const { return m_correctionFactor; } void b2MotorJoint::SetLinearOffset(const b2Vec2& linearOffset) { if (linearOffset.x != m_linearOffset.x || linearOffset.y != m_linearOffset.y) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_linearOffset = linearOffset; } } const b2Vec2& b2MotorJoint::GetLinearOffset() const { return m_linearOffset; } void b2MotorJoint::SetAngularOffset(float32 angularOffset) { if (angularOffset != m_angularOffset) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_angularOffset = angularOffset; } } float32 b2MotorJoint::GetAngularOffset() const { return m_angularOffset; } void b2MotorJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2MotorJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.linearOffset.Set(%.15lef, %.15lef);\n", m_linearOffset.x, m_linearOffset.y); b2Log(" jd.angularOffset = %.15lef;\n", m_angularOffset); b2Log(" jd.maxForce = %.15lef;\n", m_maxForce); b2Log(" jd.maxTorque = %.15lef;\n", m_maxTorque); b2Log(" jd.correctionFactor = %.15lef;\n", m_correctionFactor); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2PulleyJoint.h0000664000000000000000000001053112310072714016356 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_PULLEY_JOINT_H #define B2_PULLEY_JOINT_H #include const float32 b2_minPulleyLength = 2.0f; /// Pulley joint definition. This requires two ground anchors, /// two dynamic body anchor points, and a pulley ratio. struct b2PulleyJointDef : public b2JointDef { b2PulleyJointDef() { type = e_pulleyJoint; groundAnchorA.Set(-1.0f, 1.0f); groundAnchorB.Set(1.0f, 1.0f); localAnchorA.Set(-1.0f, 0.0f); localAnchorB.Set(1.0f, 0.0f); lengthA = 0.0f; lengthB = 0.0f; ratio = 1.0f; collideConnected = true; } /// Initialize the bodies, anchors, lengths, max lengths, and ratio using the world anchors. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& groundAnchorA, const b2Vec2& groundAnchorB, const b2Vec2& anchorA, const b2Vec2& anchorB, float32 ratio); /// The first ground anchor in world coordinates. This point never moves. b2Vec2 groundAnchorA; /// The second ground anchor in world coordinates. This point never moves. b2Vec2 groundAnchorB; /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The a reference length for the segment attached to bodyA. float32 lengthA; /// The a reference length for the segment attached to bodyB. float32 lengthB; /// The pulley ratio, used to simulate a block-and-tackle. float32 ratio; }; /// The pulley joint is connected to two bodies and two fixed ground points. /// The pulley supports a ratio such that: /// length1 + ratio * length2 <= constant /// Yes, the force transmitted is scaled by the ratio. /// Warning: the pulley joint can get a bit squirrelly by itself. They often /// work better when combined with prismatic joints. You should also cover the /// the anchor points with static shapes to prevent one side from going to /// zero length. class b2PulleyJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// Get the first ground anchor. b2Vec2 GetGroundAnchorA() const; /// Get the second ground anchor. b2Vec2 GetGroundAnchorB() const; /// Get the current length of the segment attached to bodyA. float32 GetLengthA() const; /// Get the current length of the segment attached to bodyB. float32 GetLengthB() const; /// Get the pulley ratio. float32 GetRatio() const; /// Get the current length of the segment attached to bodyA. float32 GetCurrentLengthA() const; /// Get the current length of the segment attached to bodyB. float32 GetCurrentLengthB() const; /// Dump joint to dmLog void Dump(); /// Implement b2Joint::ShiftOrigin void ShiftOrigin(const b2Vec2& newOrigin); protected: friend class b2Joint; b2PulleyJoint(const b2PulleyJointDef* data); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); b2Vec2 m_groundAnchorA; b2Vec2 m_groundAnchorB; float32 m_lengthA; float32 m_lengthB; // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; float32 m_constant; float32 m_ratio; float32 m_impulse; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_uA; b2Vec2 m_uB; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; float32 m_mass; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2WheelJoint.h0000664000000000000000000001342712310072714016157 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_WHEEL_JOINT_H #define B2_WHEEL_JOINT_H #include /// Wheel joint definition. This requires defining a line of /// motion using an axis and an anchor point. The definition uses local /// anchor points and a local axis so that the initial configuration /// can violate the constraint slightly. The joint translation is zero /// when the local anchor points coincide in world space. Using local /// anchors and a local axis helps when saving and loading a game. struct b2WheelJointDef : public b2JointDef { b2WheelJointDef() { type = e_wheelJoint; localAnchorA.SetZero(); localAnchorB.SetZero(); localAxisA.Set(1.0f, 0.0f); enableMotor = false; maxMotorTorque = 0.0f; motorSpeed = 0.0f; frequencyHz = 2.0f; dampingRatio = 0.7f; } /// Initialize the bodies, anchors, axis, and reference angle using the world /// anchor and world axis. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor, const b2Vec2& axis); /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The local translation axis in bodyA. b2Vec2 localAxisA; /// Enable/disable the joint motor. bool enableMotor; /// The maximum motor torque, usually in N-m. float32 maxMotorTorque; /// The desired motor speed in radians per second. float32 motorSpeed; /// Suspension frequency, zero indicates no suspension float32 frequencyHz; /// Suspension damping ratio, one indicates critical damping float32 dampingRatio; }; /// A wheel joint. This joint provides two degrees of freedom: translation /// along an axis fixed in bodyA and rotation in the plane. You can use a /// joint limit to restrict the range of motion and a joint motor to drive /// the rotation or to model rotational friction. /// This joint is designed for vehicle suspensions. class b2WheelJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// The local joint axis relative to bodyA. const b2Vec2& GetLocalAxisA() const { return m_localXAxisA; } /// Get the current joint translation, usually in meters. float32 GetJointTranslation() const; /// Get the current joint translation speed, usually in meters per second. float32 GetJointSpeed() const; /// Is the joint motor enabled? bool IsMotorEnabled() const; /// Enable/disable the joint motor. void EnableMotor(bool flag); /// Set the motor speed, usually in radians per second. void SetMotorSpeed(float32 speed); /// Get the motor speed, usually in radians per second. float32 GetMotorSpeed() const; /// Set/Get the maximum motor force, usually in N-m. void SetMaxMotorTorque(float32 torque); float32 GetMaxMotorTorque() const; /// Get the current motor torque given the inverse time step, usually in N-m. float32 GetMotorTorque(float32 inv_dt) const; /// Set/Get the spring frequency in hertz. Setting the frequency to zero disables the spring. void SetSpringFrequencyHz(float32 hz); float32 GetSpringFrequencyHz() const; /// Set/Get the spring damping ratio void SetSpringDampingRatio(float32 ratio); float32 GetSpringDampingRatio() const; /// Dump to b2Log void Dump(); protected: friend class b2Joint; b2WheelJoint(const b2WheelJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); float32 m_frequencyHz; float32 m_dampingRatio; // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; b2Vec2 m_localXAxisA; b2Vec2 m_localYAxisA; float32 m_impulse; float32 m_motorImpulse; float32 m_springImpulse; float32 m_maxMotorTorque; float32 m_motorSpeed; bool m_enableMotor; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; b2Vec2 m_ax, m_ay; float32 m_sAx, m_sBx; float32 m_sAy, m_sBy; float32 m_mass; float32 m_motorMass; float32 m_springMass; float32 m_bias; float32 m_gamma; }; inline float32 b2WheelJoint::GetMotorSpeed() const { return m_motorSpeed; } inline float32 b2WheelJoint::GetMaxMotorTorque() const { return m_maxMotorTorque; } inline void b2WheelJoint::SetSpringFrequencyHz(float32 hz) { m_frequencyHz = hz; } inline float32 b2WheelJoint::GetSpringFrequencyHz() const { return m_frequencyHz; } inline void b2WheelJoint::SetSpringDampingRatio(float32 ratio) { m_dampingRatio = ratio; } inline float32 b2WheelJoint::GetSpringDampingRatio() const { return m_dampingRatio; } #endif qml-box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp0000664000000000000000000003144112310072714017247 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Point-to-point constraint // C = p2 - p1 // Cdot = v2 - v1 // = v2 + cross(w2, r2) - v1 - cross(w1, r1) // J = [-I -r1_skew I r2_skew ] // Identity used: // w k % (rx i + ry j) = w * (-ry i + rx j) // Motor constraint // Cdot = w2 - w1 // J = [0 0 -1 0 0 1] // K = invI1 + invI2 void b2RevoluteJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor) { bodyA = bA; bodyB = bB; localAnchorA = bodyA->GetLocalPoint(anchor); localAnchorB = bodyB->GetLocalPoint(anchor); referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); } b2RevoluteJoint::b2RevoluteJoint(const b2RevoluteJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_referenceAngle = def->referenceAngle; m_impulse.SetZero(); m_motorImpulse = 0.0f; m_lowerAngle = def->lowerAngle; m_upperAngle = def->upperAngle; m_maxMotorTorque = def->maxMotorTorque; m_motorSpeed = def->motorSpeed; m_enableLimit = def->enableLimit; m_enableMotor = def->enableMotor; m_limitState = e_inactiveLimit; } void b2RevoluteJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); // J = [-I -r1_skew I r2_skew] // [ 0 -1 0 1] // r_skew = [-ry; rx] // Matlab // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; bool fixedRotation = (iA + iB == 0.0f); m_mass.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB; m_mass.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB; m_mass.ez.x = -m_rA.y * iA - m_rB.y * iB; m_mass.ex.y = m_mass.ey.x; m_mass.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB; m_mass.ez.y = m_rA.x * iA + m_rB.x * iB; m_mass.ex.z = m_mass.ez.x; m_mass.ey.z = m_mass.ez.y; m_mass.ez.z = iA + iB; m_motorMass = iA + iB; if (m_motorMass > 0.0f) { m_motorMass = 1.0f / m_motorMass; } if (m_enableMotor == false || fixedRotation) { m_motorImpulse = 0.0f; } if (m_enableLimit && fixedRotation == false) { float32 jointAngle = aB - aA - m_referenceAngle; if (b2Abs(m_upperAngle - m_lowerAngle) < 2.0f * b2_angularSlop) { m_limitState = e_equalLimits; } else if (jointAngle <= m_lowerAngle) { if (m_limitState != e_atLowerLimit) { m_impulse.z = 0.0f; } m_limitState = e_atLowerLimit; } else if (jointAngle >= m_upperAngle) { if (m_limitState != e_atUpperLimit) { m_impulse.z = 0.0f; } m_limitState = e_atUpperLimit; } else { m_limitState = e_inactiveLimit; m_impulse.z = 0.0f; } } else { m_limitState = e_inactiveLimit; } if (data.step.warmStarting) { // Scale impulses to support a variable time step. m_impulse *= data.step.dtRatio; m_motorImpulse *= data.step.dtRatio; b2Vec2 P(m_impulse.x, m_impulse.y); vA -= mA * P; wA -= iA * (b2Cross(m_rA, P) + m_motorImpulse + m_impulse.z); vB += mB * P; wB += iB * (b2Cross(m_rB, P) + m_motorImpulse + m_impulse.z); } else { m_impulse.SetZero(); m_motorImpulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2RevoluteJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; bool fixedRotation = (iA + iB == 0.0f); // Solve motor constraint. if (m_enableMotor && m_limitState != e_equalLimits && fixedRotation == false) { float32 Cdot = wB - wA - m_motorSpeed; float32 impulse = -m_motorMass * Cdot; float32 oldImpulse = m_motorImpulse; float32 maxImpulse = data.step.dt * m_maxMotorTorque; m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); impulse = m_motorImpulse - oldImpulse; wA -= iA * impulse; wB += iB * impulse; } // Solve limit constraint. if (m_enableLimit && m_limitState != e_inactiveLimit && fixedRotation == false) { b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); float32 Cdot2 = wB - wA; b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2); b2Vec3 impulse = -m_mass.Solve33(Cdot); if (m_limitState == e_equalLimits) { m_impulse += impulse; } else if (m_limitState == e_atLowerLimit) { float32 newImpulse = m_impulse.z + impulse.z; if (newImpulse < 0.0f) { b2Vec2 rhs = -Cdot1 + m_impulse.z * b2Vec2(m_mass.ez.x, m_mass.ez.y); b2Vec2 reduced = m_mass.Solve22(rhs); impulse.x = reduced.x; impulse.y = reduced.y; impulse.z = -m_impulse.z; m_impulse.x += reduced.x; m_impulse.y += reduced.y; m_impulse.z = 0.0f; } else { m_impulse += impulse; } } else if (m_limitState == e_atUpperLimit) { float32 newImpulse = m_impulse.z + impulse.z; if (newImpulse > 0.0f) { b2Vec2 rhs = -Cdot1 + m_impulse.z * b2Vec2(m_mass.ez.x, m_mass.ez.y); b2Vec2 reduced = m_mass.Solve22(rhs); impulse.x = reduced.x; impulse.y = reduced.y; impulse.z = -m_impulse.z; m_impulse.x += reduced.x; m_impulse.y += reduced.y; m_impulse.z = 0.0f; } else { m_impulse += impulse; } } b2Vec2 P(impulse.x, impulse.y); vA -= mA * P; wA -= iA * (b2Cross(m_rA, P) + impulse.z); vB += mB * P; wB += iB * (b2Cross(m_rB, P) + impulse.z); } else { // Solve point-to-point constraint b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); b2Vec2 impulse = m_mass.Solve22(-Cdot); m_impulse.x += impulse.x; m_impulse.y += impulse.y; vA -= mA * impulse; wA -= iA * b2Cross(m_rA, impulse); vB += mB * impulse; wB += iB * b2Cross(m_rB, impulse); } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2RevoluteJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); float32 angularError = 0.0f; float32 positionError = 0.0f; bool fixedRotation = (m_invIA + m_invIB == 0.0f); // Solve angular limit constraint. if (m_enableLimit && m_limitState != e_inactiveLimit && fixedRotation == false) { float32 angle = aB - aA - m_referenceAngle; float32 limitImpulse = 0.0f; if (m_limitState == e_equalLimits) { // Prevent large angular corrections float32 C = b2Clamp(angle - m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); limitImpulse = -m_motorMass * C; angularError = b2Abs(C); } else if (m_limitState == e_atLowerLimit) { float32 C = angle - m_lowerAngle; angularError = -C; // Prevent large angular corrections and allow some slop. C = b2Clamp(C + b2_angularSlop, -b2_maxAngularCorrection, 0.0f); limitImpulse = -m_motorMass * C; } else if (m_limitState == e_atUpperLimit) { float32 C = angle - m_upperAngle; angularError = C; // Prevent large angular corrections and allow some slop. C = b2Clamp(C - b2_angularSlop, 0.0f, b2_maxAngularCorrection); limitImpulse = -m_motorMass * C; } aA -= m_invIA * limitImpulse; aB += m_invIB * limitImpulse; } // Solve point-to-point constraint. { qA.Set(aA); qB.Set(aB); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 C = cB + rB - cA - rA; positionError = C.Length(); float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Mat22 K; K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y; K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y; K.ey.x = K.ex.y; K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x; b2Vec2 impulse = -K.Solve(C); cA -= mA * impulse; aA -= iA * b2Cross(rA, impulse); cB += mB * impulse; aB += iB * b2Cross(rB, impulse); } data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return positionError <= b2_linearSlop && angularError <= b2_angularSlop; } b2Vec2 b2RevoluteJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2RevoluteJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2RevoluteJoint::GetReactionForce(float32 inv_dt) const { b2Vec2 P(m_impulse.x, m_impulse.y); return inv_dt * P; } float32 b2RevoluteJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * m_impulse.z; } float32 b2RevoluteJoint::GetJointAngle() const { b2Body* bA = m_bodyA; b2Body* bB = m_bodyB; return bB->m_sweep.a - bA->m_sweep.a - m_referenceAngle; } float32 b2RevoluteJoint::GetJointSpeed() const { b2Body* bA = m_bodyA; b2Body* bB = m_bodyB; return bB->m_angularVelocity - bA->m_angularVelocity; } bool b2RevoluteJoint::IsMotorEnabled() const { return m_enableMotor; } void b2RevoluteJoint::EnableMotor(bool flag) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_enableMotor = flag; } float32 b2RevoluteJoint::GetMotorTorque(float32 inv_dt) const { return inv_dt * m_motorImpulse; } void b2RevoluteJoint::SetMotorSpeed(float32 speed) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_motorSpeed = speed; } void b2RevoluteJoint::SetMaxMotorTorque(float32 torque) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_maxMotorTorque = torque; } bool b2RevoluteJoint::IsLimitEnabled() const { return m_enableLimit; } void b2RevoluteJoint::EnableLimit(bool flag) { if (flag != m_enableLimit) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_enableLimit = flag; m_impulse.z = 0.0f; } } float32 b2RevoluteJoint::GetLowerLimit() const { return m_lowerAngle; } float32 b2RevoluteJoint::GetUpperLimit() const { return m_upperAngle; } void b2RevoluteJoint::SetLimits(float32 lower, float32 upper) { b2Assert(lower <= upper); if (lower != m_lowerAngle || upper != m_upperAngle) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_impulse.z = 0.0f; m_lowerAngle = lower; m_upperAngle = upper; } } void b2RevoluteJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2RevoluteJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.referenceAngle = %.15lef;\n", m_referenceAngle); b2Log(" jd.enableLimit = bool(%d);\n", m_enableLimit); b2Log(" jd.lowerAngle = %.15lef;\n", m_lowerAngle); b2Log(" jd.upperAngle = %.15lef;\n", m_upperAngle); b2Log(" jd.enableMotor = bool(%d);\n", m_enableMotor); b2Log(" jd.motorSpeed = %.15lef;\n", m_motorSpeed); b2Log(" jd.maxMotorTorque = %.15lef;\n", m_maxMotorTorque); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2WeldJoint.h0000644000000000000000000000726312241175670016015 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_WELD_JOINT_H #define B2_WELD_JOINT_H #include /// Weld joint definition. You need to specify local anchor points /// where they are attached and the relative body angle. The position /// of the anchor points is important for computing the reaction torque. struct b2WeldJointDef : public b2JointDef { b2WeldJointDef() { type = e_weldJoint; localAnchorA.Set(0.0f, 0.0f); localAnchorB.Set(0.0f, 0.0f); referenceAngle = 0.0f; frequencyHz = 0.0f; dampingRatio = 0.0f; } /// Initialize the bodies, anchors, and reference angle using a world /// anchor point. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor); /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The bodyB angle minus bodyA angle in the reference state (radians). float32 referenceAngle; /// The mass-spring-damper frequency in Hertz. Rotation only. /// Disable softness with a value of 0. float32 frequencyHz; /// The damping ratio. 0 = no damping, 1 = critical damping. float32 dampingRatio; }; /// A weld joint essentially glues two bodies together. A weld joint may /// distort somewhat because the island constraint solver is approximate. class b2WeldJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// Get the reference angle. float32 GetReferenceAngle() const { return m_referenceAngle; } /// Set/get frequency in Hz. void SetFrequency(float32 hz) { m_frequencyHz = hz; } float32 GetFrequency() const { return m_frequencyHz; } /// Set/get damping ratio. void SetDampingRatio(float32 ratio) { m_dampingRatio = ratio; } float32 GetDampingRatio() const { return m_dampingRatio; } /// Dump to b2Log void Dump(); protected: friend class b2Joint; b2WeldJoint(const b2WeldJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); float32 m_frequencyHz; float32 m_dampingRatio; float32 m_bias; // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; float32 m_referenceAngle; float32 m_gamma; b2Vec3 m_impulse; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; b2Mat33 m_mass; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.h0000644000000000000000000001341512241175670017051 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_PRISMATIC_JOINT_H #define B2_PRISMATIC_JOINT_H #include /// Prismatic joint definition. This requires defining a line of /// motion using an axis and an anchor point. The definition uses local /// anchor points and a local axis so that the initial configuration /// can violate the constraint slightly. The joint translation is zero /// when the local anchor points coincide in world space. Using local /// anchors and a local axis helps when saving and loading a game. struct b2PrismaticJointDef : public b2JointDef { b2PrismaticJointDef() { type = e_prismaticJoint; localAnchorA.SetZero(); localAnchorB.SetZero(); localAxisA.Set(1.0f, 0.0f); referenceAngle = 0.0f; enableLimit = false; lowerTranslation = 0.0f; upperTranslation = 0.0f; enableMotor = false; maxMotorForce = 0.0f; motorSpeed = 0.0f; } /// Initialize the bodies, anchors, axis, and reference angle using the world /// anchor and unit world axis. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor, const b2Vec2& axis); /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The local translation unit axis in bodyA. b2Vec2 localAxisA; /// The constrained angle between the bodies: bodyB_angle - bodyA_angle. float32 referenceAngle; /// Enable/disable the joint limit. bool enableLimit; /// The lower translation limit, usually in meters. float32 lowerTranslation; /// The upper translation limit, usually in meters. float32 upperTranslation; /// Enable/disable the joint motor. bool enableMotor; /// The maximum motor torque, usually in N-m. float32 maxMotorForce; /// The desired motor speed in radians per second. float32 motorSpeed; }; /// A prismatic joint. This joint provides one degree of freedom: translation /// along an axis fixed in bodyA. Relative rotation is prevented. You can /// use a joint limit to restrict the range of motion and a joint motor to /// drive the motion or to model joint friction. class b2PrismaticJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// The local joint axis relative to bodyA. const b2Vec2& GetLocalAxisA() const { return m_localXAxisA; } /// Get the reference angle. float32 GetReferenceAngle() const { return m_referenceAngle; } /// Get the current joint translation, usually in meters. float32 GetJointTranslation() const; /// Get the current joint translation speed, usually in meters per second. float32 GetJointSpeed() const; /// Is the joint limit enabled? bool IsLimitEnabled() const; /// Enable/disable the joint limit. void EnableLimit(bool flag); /// Get the lower joint limit, usually in meters. float32 GetLowerLimit() const; /// Get the upper joint limit, usually in meters. float32 GetUpperLimit() const; /// Set the joint limits, usually in meters. void SetLimits(float32 lower, float32 upper); /// Is the joint motor enabled? bool IsMotorEnabled() const; /// Enable/disable the joint motor. void EnableMotor(bool flag); /// Set the motor speed, usually in meters per second. void SetMotorSpeed(float32 speed); /// Get the motor speed, usually in meters per second. float32 GetMotorSpeed() const; /// Set the maximum motor force, usually in N. void SetMaxMotorForce(float32 force); float32 GetMaxMotorForce() const { return m_maxMotorForce; } /// Get the current motor force given the inverse time step, usually in N. float32 GetMotorForce(float32 inv_dt) const; /// Dump to b2Log void Dump(); protected: friend class b2Joint; friend class b2GearJoint; b2PrismaticJoint(const b2PrismaticJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; b2Vec2 m_localXAxisA; b2Vec2 m_localYAxisA; float32 m_referenceAngle; b2Vec3 m_impulse; float32 m_motorImpulse; float32 m_lowerTranslation; float32 m_upperTranslation; float32 m_maxMotorForce; float32 m_motorSpeed; bool m_enableLimit; bool m_enableMotor; b2LimitState m_limitState; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; b2Vec2 m_axis, m_perp; float32 m_s1, m_s2; float32 m_a1, m_a2; b2Mat33 m_K; float32 m_motorMass; }; inline float32 b2PrismaticJoint::GetMotorSpeed() const { return m_motorSpeed; } #endif qml-box2d/Box2D/Dynamics/Joints/b2GearJoint.cpp0000664000000000000000000002652012310072714016322 0ustar /* * Copyright (c) 2007-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include // Gear Joint: // C0 = (coordinate1 + ratio * coordinate2)_initial // C = (coordinate1 + ratio * coordinate2) - C0 = 0 // J = [J1 ratio * J2] // K = J * invM * JT // = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T // // Revolute: // coordinate = rotation // Cdot = angularVelocity // J = [0 0 1] // K = J * invM * JT = invI // // Prismatic: // coordinate = dot(p - pg, ug) // Cdot = dot(v + cross(w, r), ug) // J = [ug cross(r, ug)] // K = J * invM * JT = invMass + invI * cross(r, ug)^2 b2GearJoint::b2GearJoint(const b2GearJointDef* def) : b2Joint(def) { m_joint1 = def->joint1; m_joint2 = def->joint2; m_typeA = m_joint1->GetType(); m_typeB = m_joint2->GetType(); b2Assert(m_typeA == e_revoluteJoint || m_typeA == e_prismaticJoint); b2Assert(m_typeB == e_revoluteJoint || m_typeB == e_prismaticJoint); float32 coordinateA, coordinateB; // TODO_ERIN there might be some problem with the joint edges in b2Joint. m_bodyC = m_joint1->GetBodyA(); m_bodyA = m_joint1->GetBodyB(); // Get geometry of joint1 b2Transform xfA = m_bodyA->m_xf; float32 aA = m_bodyA->m_sweep.a; b2Transform xfC = m_bodyC->m_xf; float32 aC = m_bodyC->m_sweep.a; if (m_typeA == e_revoluteJoint) { b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint1; m_localAnchorC = revolute->m_localAnchorA; m_localAnchorA = revolute->m_localAnchorB; m_referenceAngleA = revolute->m_referenceAngle; m_localAxisC.SetZero(); coordinateA = aA - aC - m_referenceAngleA; } else { b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint1; m_localAnchorC = prismatic->m_localAnchorA; m_localAnchorA = prismatic->m_localAnchorB; m_referenceAngleA = prismatic->m_referenceAngle; m_localAxisC = prismatic->m_localXAxisA; b2Vec2 pC = m_localAnchorC; b2Vec2 pA = b2MulT(xfC.q, b2Mul(xfA.q, m_localAnchorA) + (xfA.p - xfC.p)); coordinateA = b2Dot(pA - pC, m_localAxisC); } m_bodyD = m_joint2->GetBodyA(); m_bodyB = m_joint2->GetBodyB(); // Get geometry of joint2 b2Transform xfB = m_bodyB->m_xf; float32 aB = m_bodyB->m_sweep.a; b2Transform xfD = m_bodyD->m_xf; float32 aD = m_bodyD->m_sweep.a; if (m_typeB == e_revoluteJoint) { b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint2; m_localAnchorD = revolute->m_localAnchorA; m_localAnchorB = revolute->m_localAnchorB; m_referenceAngleB = revolute->m_referenceAngle; m_localAxisD.SetZero(); coordinateB = aB - aD - m_referenceAngleB; } else { b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint2; m_localAnchorD = prismatic->m_localAnchorA; m_localAnchorB = prismatic->m_localAnchorB; m_referenceAngleB = prismatic->m_referenceAngle; m_localAxisD = prismatic->m_localXAxisA; b2Vec2 pD = m_localAnchorD; b2Vec2 pB = b2MulT(xfD.q, b2Mul(xfB.q, m_localAnchorB) + (xfB.p - xfD.p)); coordinateB = b2Dot(pB - pD, m_localAxisD); } m_ratio = def->ratio; m_constant = coordinateA + m_ratio * coordinateB; m_impulse = 0.0f; } void b2GearJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_indexC = m_bodyC->m_islandIndex; m_indexD = m_bodyD->m_islandIndex; m_lcA = m_bodyA->m_sweep.localCenter; m_lcB = m_bodyB->m_sweep.localCenter; m_lcC = m_bodyC->m_sweep.localCenter; m_lcD = m_bodyD->m_sweep.localCenter; m_mA = m_bodyA->m_invMass; m_mB = m_bodyB->m_invMass; m_mC = m_bodyC->m_invMass; m_mD = m_bodyD->m_invMass; m_iA = m_bodyA->m_invI; m_iB = m_bodyB->m_invI; m_iC = m_bodyC->m_invI; m_iD = m_bodyD->m_invI; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; float32 aC = data.positions[m_indexC].a; b2Vec2 vC = data.velocities[m_indexC].v; float32 wC = data.velocities[m_indexC].w; float32 aD = data.positions[m_indexD].a; b2Vec2 vD = data.velocities[m_indexD].v; float32 wD = data.velocities[m_indexD].w; b2Rot qA(aA), qB(aB), qC(aC), qD(aD); m_mass = 0.0f; if (m_typeA == e_revoluteJoint) { m_JvAC.SetZero(); m_JwA = 1.0f; m_JwC = 1.0f; m_mass += m_iA + m_iC; } else { b2Vec2 u = b2Mul(qC, m_localAxisC); b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA); m_JvAC = u; m_JwC = b2Cross(rC, u); m_JwA = b2Cross(rA, u); m_mass += m_mC + m_mA + m_iC * m_JwC * m_JwC + m_iA * m_JwA * m_JwA; } if (m_typeB == e_revoluteJoint) { m_JvBD.SetZero(); m_JwB = m_ratio; m_JwD = m_ratio; m_mass += m_ratio * m_ratio * (m_iB + m_iD); } else { b2Vec2 u = b2Mul(qD, m_localAxisD); b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB); m_JvBD = m_ratio * u; m_JwD = m_ratio * b2Cross(rD, u); m_JwB = m_ratio * b2Cross(rB, u); m_mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * m_JwD * m_JwD + m_iB * m_JwB * m_JwB; } // Compute effective mass. m_mass = m_mass > 0.0f ? 1.0f / m_mass : 0.0f; if (data.step.warmStarting) { vA += (m_mA * m_impulse) * m_JvAC; wA += m_iA * m_impulse * m_JwA; vB += (m_mB * m_impulse) * m_JvBD; wB += m_iB * m_impulse * m_JwB; vC -= (m_mC * m_impulse) * m_JvAC; wC -= m_iC * m_impulse * m_JwC; vD -= (m_mD * m_impulse) * m_JvBD; wD -= m_iD * m_impulse * m_JwD; } else { m_impulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; data.velocities[m_indexC].v = vC; data.velocities[m_indexC].w = wC; data.velocities[m_indexD].v = vD; data.velocities[m_indexD].w = wD; } void b2GearJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Vec2 vC = data.velocities[m_indexC].v; float32 wC = data.velocities[m_indexC].w; b2Vec2 vD = data.velocities[m_indexD].v; float32 wD = data.velocities[m_indexD].w; float32 Cdot = b2Dot(m_JvAC, vA - vC) + b2Dot(m_JvBD, vB - vD); Cdot += (m_JwA * wA - m_JwC * wC) + (m_JwB * wB - m_JwD * wD); float32 impulse = -m_mass * Cdot; m_impulse += impulse; vA += (m_mA * impulse) * m_JvAC; wA += m_iA * impulse * m_JwA; vB += (m_mB * impulse) * m_JvBD; wB += m_iB * impulse * m_JwB; vC -= (m_mC * impulse) * m_JvAC; wC -= m_iC * impulse * m_JwC; vD -= (m_mD * impulse) * m_JvBD; wD -= m_iD * impulse * m_JwD; data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; data.velocities[m_indexC].v = vC; data.velocities[m_indexC].w = wC; data.velocities[m_indexD].v = vD; data.velocities[m_indexD].w = wD; } bool b2GearJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 cC = data.positions[m_indexC].c; float32 aC = data.positions[m_indexC].a; b2Vec2 cD = data.positions[m_indexD].c; float32 aD = data.positions[m_indexD].a; b2Rot qA(aA), qB(aB), qC(aC), qD(aD); float32 linearError = 0.0f; float32 coordinateA, coordinateB; b2Vec2 JvAC, JvBD; float32 JwA, JwB, JwC, JwD; float32 mass = 0.0f; if (m_typeA == e_revoluteJoint) { JvAC.SetZero(); JwA = 1.0f; JwC = 1.0f; mass += m_iA + m_iC; coordinateA = aA - aC - m_referenceAngleA; } else { b2Vec2 u = b2Mul(qC, m_localAxisC); b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA); JvAC = u; JwC = b2Cross(rC, u); JwA = b2Cross(rA, u); mass += m_mC + m_mA + m_iC * JwC * JwC + m_iA * JwA * JwA; b2Vec2 pC = m_localAnchorC - m_lcC; b2Vec2 pA = b2MulT(qC, rA + (cA - cC)); coordinateA = b2Dot(pA - pC, m_localAxisC); } if (m_typeB == e_revoluteJoint) { JvBD.SetZero(); JwB = m_ratio; JwD = m_ratio; mass += m_ratio * m_ratio * (m_iB + m_iD); coordinateB = aB - aD - m_referenceAngleB; } else { b2Vec2 u = b2Mul(qD, m_localAxisD); b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB); JvBD = m_ratio * u; JwD = m_ratio * b2Cross(rD, u); JwB = m_ratio * b2Cross(rB, u); mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * JwD * JwD + m_iB * JwB * JwB; b2Vec2 pD = m_localAnchorD - m_lcD; b2Vec2 pB = b2MulT(qD, rB + (cB - cD)); coordinateB = b2Dot(pB - pD, m_localAxisD); } float32 C = (coordinateA + m_ratio * coordinateB) - m_constant; float32 impulse = 0.0f; if (mass > 0.0f) { impulse = -C / mass; } cA += m_mA * impulse * JvAC; aA += m_iA * impulse * JwA; cB += m_mB * impulse * JvBD; aB += m_iB * impulse * JwB; cC -= m_mC * impulse * JvAC; aC -= m_iC * impulse * JwC; cD -= m_mD * impulse * JvBD; aD -= m_iD * impulse * JwD; data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; data.positions[m_indexC].c = cC; data.positions[m_indexC].a = aC; data.positions[m_indexD].c = cD; data.positions[m_indexD].a = aD; // TODO_ERIN not implemented return linearError < b2_linearSlop; } b2Vec2 b2GearJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2GearJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2GearJoint::GetReactionForce(float32 inv_dt) const { b2Vec2 P = m_impulse * m_JvAC; return inv_dt * P; } float32 b2GearJoint::GetReactionTorque(float32 inv_dt) const { float32 L = m_impulse * m_JwA; return inv_dt * L; } void b2GearJoint::SetRatio(float32 ratio) { b2Assert(b2IsValid(ratio)); m_ratio = ratio; } float32 b2GearJoint::GetRatio() const { return m_ratio; } void b2GearJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; int32 index1 = m_joint1->m_index; int32 index2 = m_joint2->m_index; b2Log(" b2GearJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.joint1 = joints[%d];\n", index1); b2Log(" jd.joint2 = joints[%d];\n", index2); b2Log(" jd.ratio = %.15lef;\n", m_ratio); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2Joint.h0000664000000000000000000001260312310072714015165 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_JOINT_H #define B2_JOINT_H #include class b2Body; class b2Joint; struct b2SolverData; class b2BlockAllocator; enum b2JointType { e_unknownJoint, e_revoluteJoint, e_prismaticJoint, e_distanceJoint, e_pulleyJoint, e_mouseJoint, e_gearJoint, e_wheelJoint, e_weldJoint, e_frictionJoint, e_ropeJoint, e_motorJoint }; enum b2LimitState { e_inactiveLimit, e_atLowerLimit, e_atUpperLimit, e_equalLimits }; struct b2Jacobian { b2Vec2 linear; float32 angularA; float32 angularB; }; /// A joint edge is used to connect bodies and joints together /// in a joint graph where each body is a node and each joint /// is an edge. A joint edge belongs to a doubly linked list /// maintained in each attached body. Each joint has two joint /// nodes, one for each attached body. struct b2JointEdge { b2Body* other; ///< provides quick access to the other body attached. b2Joint* joint; ///< the joint b2JointEdge* prev; ///< the previous joint edge in the body's joint list b2JointEdge* next; ///< the next joint edge in the body's joint list }; /// Joint definitions are used to construct joints. struct b2JointDef { b2JointDef() { type = e_unknownJoint; userData = NULL; bodyA = NULL; bodyB = NULL; collideConnected = false; } /// The joint type is set automatically for concrete joint types. b2JointType type; /// Use this to attach application specific data to your joints. void* userData; /// The first attached body. b2Body* bodyA; /// The second attached body. b2Body* bodyB; /// Set this flag to true if the attached bodies should collide. bool collideConnected; }; /// The base joint class. Joints are used to constraint two bodies together in /// various fashions. Some joints also feature limits and motors. class b2Joint { public: /// Get the type of the concrete joint. b2JointType GetType() const; /// Get the first body attached to this joint. b2Body* GetBodyA(); /// Get the second body attached to this joint. b2Body* GetBodyB(); /// Get the anchor point on bodyA in world coordinates. virtual b2Vec2 GetAnchorA() const = 0; /// Get the anchor point on bodyB in world coordinates. virtual b2Vec2 GetAnchorB() const = 0; /// Get the reaction force on bodyB at the joint anchor in Newtons. virtual b2Vec2 GetReactionForce(float32 inv_dt) const = 0; /// Get the reaction torque on bodyB in N*m. virtual float32 GetReactionTorque(float32 inv_dt) const = 0; /// Get the next joint the world joint list. b2Joint* GetNext(); const b2Joint* GetNext() const; /// Get the user data pointer. void* GetUserData() const; /// Set the user data pointer. void SetUserData(void* data); /// Short-cut function to determine if either body is inactive. bool IsActive() const; /// Get collide connected. /// Note: modifying the collide connect flag won't work correctly because /// the flag is only checked when fixture AABBs begin to overlap. bool GetCollideConnected() const; /// Dump this joint to the log file. virtual void Dump() { b2Log("// Dump is not supported for this joint type.\n"); } /// Shift the origin for any points stored in world coordinates. virtual void ShiftOrigin(const b2Vec2& newOrigin) { B2_NOT_USED(newOrigin); } protected: friend class b2World; friend class b2Body; friend class b2Island; friend class b2GearJoint; static b2Joint* Create(const b2JointDef* def, b2BlockAllocator* allocator); static void Destroy(b2Joint* joint, b2BlockAllocator* allocator); b2Joint(const b2JointDef* def); virtual ~b2Joint() {} virtual void InitVelocityConstraints(const b2SolverData& data) = 0; virtual void SolveVelocityConstraints(const b2SolverData& data) = 0; // This returns true if the position errors are within tolerance. virtual bool SolvePositionConstraints(const b2SolverData& data) = 0; b2JointType m_type; b2Joint* m_prev; b2Joint* m_next; b2JointEdge m_edgeA; b2JointEdge m_edgeB; b2Body* m_bodyA; b2Body* m_bodyB; int32 m_index; bool m_islandFlag; bool m_collideConnected; void* m_userData; }; inline b2JointType b2Joint::GetType() const { return m_type; } inline b2Body* b2Joint::GetBodyA() { return m_bodyA; } inline b2Body* b2Joint::GetBodyB() { return m_bodyB; } inline b2Joint* b2Joint::GetNext() { return m_next; } inline const b2Joint* b2Joint::GetNext() const { return m_next; } inline void* b2Joint::GetUserData() const { return m_userData; } inline void b2Joint::SetUserData(void* data) { m_userData = data; } inline bool b2Joint::GetCollideConnected() const { return m_collideConnected; } #endif qml-box2d/Box2D/Dynamics/Joints/b2DistanceJoint.cpp0000644000000000000000000001617712241175670017213 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // 1-D constrained system // m (v2 - v1) = lambda // v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass. // x2 = x1 + h * v2 // 1-D mass-damper-spring system // m (v2 - v1) + h * d * v2 + h * k * // C = norm(p2 - p1) - L // u = (p2 - p1) / norm(p2 - p1) // Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1)) // J = [-u -cross(r1, u) u cross(r2, u)] // K = J * invM * JT // = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2 void b2DistanceJointDef::Initialize(b2Body* b1, b2Body* b2, const b2Vec2& anchor1, const b2Vec2& anchor2) { bodyA = b1; bodyB = b2; localAnchorA = bodyA->GetLocalPoint(anchor1); localAnchorB = bodyB->GetLocalPoint(anchor2); b2Vec2 d = anchor2 - anchor1; length = d.Length(); } b2DistanceJoint::b2DistanceJoint(const b2DistanceJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_length = def->length; m_frequencyHz = def->frequencyHz; m_dampingRatio = def->dampingRatio; m_impulse = 0.0f; m_gamma = 0.0f; m_bias = 0.0f; } void b2DistanceJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); m_u = cB + m_rB - cA - m_rA; // Handle singularity. float32 length = m_u.Length(); if (length > b2_linearSlop) { m_u *= 1.0f / length; } else { m_u.Set(0.0f, 0.0f); } float32 crAu = b2Cross(m_rA, m_u); float32 crBu = b2Cross(m_rB, m_u); float32 invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu; // Compute the effective mass matrix. m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; if (m_frequencyHz > 0.0f) { float32 C = length - m_length; // Frequency float32 omega = 2.0f * b2_pi * m_frequencyHz; // Damping coefficient float32 d = 2.0f * m_mass * m_dampingRatio * omega; // Spring stiffness float32 k = m_mass * omega * omega; // magic formulas float32 h = data.step.dt; m_gamma = h * (d + h * k); m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f; m_bias = C * h * k * m_gamma; invMass += m_gamma; m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; } else { m_gamma = 0.0f; m_bias = 0.0f; } if (data.step.warmStarting) { // Scale the impulse to support a variable time step. m_impulse *= data.step.dtRatio; b2Vec2 P = m_impulse * m_u; vA -= m_invMassA * P; wA -= m_invIA * b2Cross(m_rA, P); vB += m_invMassB * P; wB += m_invIB * b2Cross(m_rB, P); } else { m_impulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2DistanceJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; // Cdot = dot(u, v + cross(w, r)) b2Vec2 vpA = vA + b2Cross(wA, m_rA); b2Vec2 vpB = vB + b2Cross(wB, m_rB); float32 Cdot = b2Dot(m_u, vpB - vpA); float32 impulse = -m_mass * (Cdot + m_bias + m_gamma * m_impulse); m_impulse += impulse; b2Vec2 P = impulse * m_u; vA -= m_invMassA * P; wA -= m_invIA * b2Cross(m_rA, P); vB += m_invMassB * P; wB += m_invIB * b2Cross(m_rB, P); data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2DistanceJoint::SolvePositionConstraints(const b2SolverData& data) { if (m_frequencyHz > 0.0f) { // There is no position correction for soft distance constraints. return true; } b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 u = cB + rB - cA - rA; float32 length = u.Normalize(); float32 C = length - m_length; C = b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection); float32 impulse = -m_mass * C; b2Vec2 P = impulse * u; cA -= m_invMassA * P; aA -= m_invIA * b2Cross(rA, P); cB += m_invMassB * P; aB += m_invIB * b2Cross(rB, P); data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return b2Abs(C) < b2_linearSlop; } b2Vec2 b2DistanceJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2DistanceJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2DistanceJoint::GetReactionForce(float32 inv_dt) const { b2Vec2 F = (inv_dt * m_impulse) * m_u; return F; } float32 b2DistanceJoint::GetReactionTorque(float32 inv_dt) const { B2_NOT_USED(inv_dt); return 0.0f; } void b2DistanceJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2DistanceJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.length = %.15lef;\n", m_length); b2Log(" jd.frequencyHz = %.15lef;\n", m_frequencyHz); b2Log(" jd.dampingRatio = %.15lef;\n", m_dampingRatio); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2FrictionJoint.cpp0000644000000000000000000001535512241175670017233 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Point-to-point constraint // Cdot = v2 - v1 // = v2 + cross(w2, r2) - v1 - cross(w1, r1) // J = [-I -r1_skew I r2_skew ] // Identity used: // w k % (rx i + ry j) = w * (-ry i + rx j) // Angle constraint // Cdot = w2 - w1 // J = [0 0 -1 0 0 1] // K = invI1 + invI2 void b2FrictionJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor) { bodyA = bA; bodyB = bB; localAnchorA = bodyA->GetLocalPoint(anchor); localAnchorB = bodyB->GetLocalPoint(anchor); } b2FrictionJoint::b2FrictionJoint(const b2FrictionJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_linearImpulse.SetZero(); m_angularImpulse = 0.0f; m_maxForce = def->maxForce; m_maxTorque = def->maxTorque; } void b2FrictionJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); // Compute the effective mass matrix. m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); // J = [-I -r1_skew I r2_skew] // [ 0 -1 0 1] // r_skew = [-ry; rx] // Matlab // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Mat22 K; K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y; K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y; K.ey.x = K.ex.y; K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x; m_linearMass = K.GetInverse(); m_angularMass = iA + iB; if (m_angularMass > 0.0f) { m_angularMass = 1.0f / m_angularMass; } if (data.step.warmStarting) { // Scale impulses to support a variable time step. m_linearImpulse *= data.step.dtRatio; m_angularImpulse *= data.step.dtRatio; b2Vec2 P(m_linearImpulse.x, m_linearImpulse.y); vA -= mA * P; wA -= iA * (b2Cross(m_rA, P) + m_angularImpulse); vB += mB * P; wB += iB * (b2Cross(m_rB, P) + m_angularImpulse); } else { m_linearImpulse.SetZero(); m_angularImpulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2FrictionJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; float32 h = data.step.dt; // Solve angular friction { float32 Cdot = wB - wA; float32 impulse = -m_angularMass * Cdot; float32 oldImpulse = m_angularImpulse; float32 maxImpulse = h * m_maxTorque; m_angularImpulse = b2Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse); impulse = m_angularImpulse - oldImpulse; wA -= iA * impulse; wB += iB * impulse; } // Solve linear friction { b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); b2Vec2 impulse = -b2Mul(m_linearMass, Cdot); b2Vec2 oldImpulse = m_linearImpulse; m_linearImpulse += impulse; float32 maxImpulse = h * m_maxForce; if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { m_linearImpulse.Normalize(); m_linearImpulse *= maxImpulse; } impulse = m_linearImpulse - oldImpulse; vA -= mA * impulse; wA -= iA * b2Cross(m_rA, impulse); vB += mB * impulse; wB += iB * b2Cross(m_rB, impulse); } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2FrictionJoint::SolvePositionConstraints(const b2SolverData& data) { B2_NOT_USED(data); return true; } b2Vec2 b2FrictionJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2FrictionJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2FrictionJoint::GetReactionForce(float32 inv_dt) const { return inv_dt * m_linearImpulse; } float32 b2FrictionJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * m_angularImpulse; } void b2FrictionJoint::SetMaxForce(float32 force) { b2Assert(b2IsValid(force) && force >= 0.0f); m_maxForce = force; } float32 b2FrictionJoint::GetMaxForce() const { return m_maxForce; } void b2FrictionJoint::SetMaxTorque(float32 torque) { b2Assert(b2IsValid(torque) && torque >= 0.0f); m_maxTorque = torque; } float32 b2FrictionJoint::GetMaxTorque() const { return m_maxTorque; } void b2FrictionJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2FrictionJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.maxForce = %.15lef;\n", m_maxForce); b2Log(" jd.maxTorque = %.15lef;\n", m_maxTorque); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2MouseJoint.h0000664000000000000000000000715112310072714016200 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_MOUSE_JOINT_H #define B2_MOUSE_JOINT_H #include /// Mouse joint definition. This requires a world target point, /// tuning parameters, and the time step. struct b2MouseJointDef : public b2JointDef { b2MouseJointDef() { type = e_mouseJoint; target.Set(0.0f, 0.0f); maxForce = 0.0f; frequencyHz = 5.0f; dampingRatio = 0.7f; } /// The initial world target point. This is assumed /// to coincide with the body anchor initially. b2Vec2 target; /// The maximum constraint force that can be exerted /// to move the candidate body. Usually you will express /// as some multiple of the weight (multiplier * mass * gravity). float32 maxForce; /// The response speed. float32 frequencyHz; /// The damping ratio. 0 = no damping, 1 = critical damping. float32 dampingRatio; }; /// A mouse joint is used to make a point on a body track a /// specified world point. This a soft constraint with a maximum /// force. This allows the constraint to stretch and without /// applying huge forces. /// NOTE: this joint is not documented in the manual because it was /// developed to be used in the testbed. If you want to learn how to /// use the mouse joint, look at the testbed. class b2MouseJoint : public b2Joint { public: /// Implements b2Joint. b2Vec2 GetAnchorA() const; /// Implements b2Joint. b2Vec2 GetAnchorB() const; /// Implements b2Joint. b2Vec2 GetReactionForce(float32 inv_dt) const; /// Implements b2Joint. float32 GetReactionTorque(float32 inv_dt) const; /// Use this to update the target point. void SetTarget(const b2Vec2& target); const b2Vec2& GetTarget() const; /// Set/get the maximum force in Newtons. void SetMaxForce(float32 force); float32 GetMaxForce() const; /// Set/get the frequency in Hertz. void SetFrequency(float32 hz); float32 GetFrequency() const; /// Set/get the damping ratio (dimensionless). void SetDampingRatio(float32 ratio); float32 GetDampingRatio() const; /// The mouse joint does not support dumping. void Dump() { b2Log("Mouse joint dumping is not supported.\n"); } /// Implement b2Joint::ShiftOrigin void ShiftOrigin(const b2Vec2& newOrigin); protected: friend class b2Joint; b2MouseJoint(const b2MouseJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); b2Vec2 m_localAnchorB; b2Vec2 m_targetA; float32 m_frequencyHz; float32 m_dampingRatio; float32 m_beta; // Solver shared b2Vec2 m_impulse; float32 m_maxForce; float32 m_gamma; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_rB; b2Vec2 m_localCenterB; float32 m_invMassB; float32 m_invIB; b2Mat22 m_mass; b2Vec2 m_C; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2FrictionJoint.h0000644000000000000000000000633112241175670016672 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_FRICTION_JOINT_H #define B2_FRICTION_JOINT_H #include /// Friction joint definition. struct b2FrictionJointDef : public b2JointDef { b2FrictionJointDef() { type = e_frictionJoint; localAnchorA.SetZero(); localAnchorB.SetZero(); maxForce = 0.0f; maxTorque = 0.0f; } /// Initialize the bodies, anchors, axis, and reference angle using the world /// anchor and world axis. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor); /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The maximum friction force in N. float32 maxForce; /// The maximum friction torque in N-m. float32 maxTorque; }; /// Friction joint. This is used for top-down friction. /// It provides 2D translational friction and angular friction. class b2FrictionJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// Set the maximum friction force in N. void SetMaxForce(float32 force); /// Get the maximum friction force in N. float32 GetMaxForce() const; /// Set the maximum friction torque in N*m. void SetMaxTorque(float32 torque); /// Get the maximum friction torque in N*m. float32 GetMaxTorque() const; /// Dump joint to dmLog void Dump(); protected: friend class b2Joint; b2FrictionJoint(const b2FrictionJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; // Solver shared b2Vec2 m_linearImpulse; float32 m_angularImpulse; float32 m_maxForce; float32 m_maxTorque; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; b2Mat22 m_linearMass; float32 m_angularMass; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2WeldJoint.cpp0000664000000000000000000002074512310072714016342 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Point-to-point constraint // C = p2 - p1 // Cdot = v2 - v1 // = v2 + cross(w2, r2) - v1 - cross(w1, r1) // J = [-I -r1_skew I r2_skew ] // Identity used: // w k % (rx i + ry j) = w * (-ry i + rx j) // Angle constraint // C = angle2 - angle1 - referenceAngle // Cdot = w2 - w1 // J = [0 0 -1 0 0 1] // K = invI1 + invI2 void b2WeldJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor) { bodyA = bA; bodyB = bB; localAnchorA = bodyA->GetLocalPoint(anchor); localAnchorB = bodyB->GetLocalPoint(anchor); referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); } b2WeldJoint::b2WeldJoint(const b2WeldJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_referenceAngle = def->referenceAngle; m_frequencyHz = def->frequencyHz; m_dampingRatio = def->dampingRatio; m_impulse.SetZero(); } void b2WeldJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); // J = [-I -r1_skew I r2_skew] // [ 0 -1 0 1] // r_skew = [-ry; rx] // Matlab // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Mat33 K; K.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB; K.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB; K.ez.x = -m_rA.y * iA - m_rB.y * iB; K.ex.y = K.ey.x; K.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB; K.ez.y = m_rA.x * iA + m_rB.x * iB; K.ex.z = K.ez.x; K.ey.z = K.ez.y; K.ez.z = iA + iB; if (m_frequencyHz > 0.0f) { K.GetInverse22(&m_mass); float32 invM = iA + iB; float32 m = invM > 0.0f ? 1.0f / invM : 0.0f; float32 C = aB - aA - m_referenceAngle; // Frequency float32 omega = 2.0f * b2_pi * m_frequencyHz; // Damping coefficient float32 d = 2.0f * m * m_dampingRatio * omega; // Spring stiffness float32 k = m * omega * omega; // magic formulas float32 h = data.step.dt; m_gamma = h * (d + h * k); m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f; m_bias = C * h * k * m_gamma; invM += m_gamma; m_mass.ez.z = invM != 0.0f ? 1.0f / invM : 0.0f; } else { K.GetSymInverse33(&m_mass); m_gamma = 0.0f; m_bias = 0.0f; } if (data.step.warmStarting) { // Scale impulses to support a variable time step. m_impulse *= data.step.dtRatio; b2Vec2 P(m_impulse.x, m_impulse.y); vA -= mA * P; wA -= iA * (b2Cross(m_rA, P) + m_impulse.z); vB += mB * P; wB += iB * (b2Cross(m_rB, P) + m_impulse.z); } else { m_impulse.SetZero(); } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2WeldJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; if (m_frequencyHz > 0.0f) { float32 Cdot2 = wB - wA; float32 impulse2 = -m_mass.ez.z * (Cdot2 + m_bias + m_gamma * m_impulse.z); m_impulse.z += impulse2; wA -= iA * impulse2; wB += iB * impulse2; b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); b2Vec2 impulse1 = -b2Mul22(m_mass, Cdot1); m_impulse.x += impulse1.x; m_impulse.y += impulse1.y; b2Vec2 P = impulse1; vA -= mA * P; wA -= iA * b2Cross(m_rA, P); vB += mB * P; wB += iB * b2Cross(m_rB, P); } else { b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); float32 Cdot2 = wB - wA; b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2); b2Vec3 impulse = -b2Mul(m_mass, Cdot); m_impulse += impulse; b2Vec2 P(impulse.x, impulse.y); vA -= mA * P; wA -= iA * (b2Cross(m_rA, P) + impulse.z); vB += mB * P; wB += iB * (b2Cross(m_rB, P) + impulse.z); } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2WeldJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); float32 positionError, angularError; b2Mat33 K; K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB; K.ez.x = -rA.y * iA - rB.y * iB; K.ex.y = K.ey.x; K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; K.ez.y = rA.x * iA + rB.x * iB; K.ex.z = K.ez.x; K.ey.z = K.ez.y; K.ez.z = iA + iB; if (m_frequencyHz > 0.0f) { b2Vec2 C1 = cB + rB - cA - rA; positionError = C1.Length(); angularError = 0.0f; b2Vec2 P = -K.Solve22(C1); cA -= mA * P; aA -= iA * b2Cross(rA, P); cB += mB * P; aB += iB * b2Cross(rB, P); } else { b2Vec2 C1 = cB + rB - cA - rA; float32 C2 = aB - aA - m_referenceAngle; positionError = C1.Length(); angularError = b2Abs(C2); b2Vec3 C(C1.x, C1.y, C2); b2Vec3 impulse = -K.Solve33(C); b2Vec2 P(impulse.x, impulse.y); cA -= mA * P; aA -= iA * (b2Cross(rA, P) + impulse.z); cB += mB * P; aB += iB * (b2Cross(rB, P) + impulse.z); } data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return positionError <= b2_linearSlop && angularError <= b2_angularSlop; } b2Vec2 b2WeldJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2WeldJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2WeldJoint::GetReactionForce(float32 inv_dt) const { b2Vec2 P(m_impulse.x, m_impulse.y); return inv_dt * P; } float32 b2WeldJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * m_impulse.z; } void b2WeldJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2WeldJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.referenceAngle = %.15lef;\n", m_referenceAngle); b2Log(" jd.frequencyHz = %.15lef;\n", m_frequencyHz); b2Log(" jd.dampingRatio = %.15lef;\n", m_dampingRatio); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2WheelJoint.cpp0000664000000000000000000002451312310072714016510 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Linear constraint (point-to-line) // d = pB - pA = xB + rB - xA - rA // C = dot(ay, d) // Cdot = dot(d, cross(wA, ay)) + dot(ay, vB + cross(wB, rB) - vA - cross(wA, rA)) // = -dot(ay, vA) - dot(cross(d + rA, ay), wA) + dot(ay, vB) + dot(cross(rB, ay), vB) // J = [-ay, -cross(d + rA, ay), ay, cross(rB, ay)] // Spring linear constraint // C = dot(ax, d) // Cdot = = -dot(ax, vA) - dot(cross(d + rA, ax), wA) + dot(ax, vB) + dot(cross(rB, ax), vB) // J = [-ax -cross(d+rA, ax) ax cross(rB, ax)] // Motor rotational constraint // Cdot = wB - wA // J = [0 0 -1 0 0 1] void b2WheelJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis) { bodyA = bA; bodyB = bB; localAnchorA = bodyA->GetLocalPoint(anchor); localAnchorB = bodyB->GetLocalPoint(anchor); localAxisA = bodyA->GetLocalVector(axis); } b2WheelJoint::b2WheelJoint(const b2WheelJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_localXAxisA = def->localAxisA; m_localYAxisA = b2Cross(1.0f, m_localXAxisA); m_mass = 0.0f; m_impulse = 0.0f; m_motorMass = 0.0f; m_motorImpulse = 0.0f; m_springMass = 0.0f; m_springImpulse = 0.0f; m_maxMotorTorque = def->maxMotorTorque; m_motorSpeed = def->motorSpeed; m_enableMotor = def->enableMotor; m_frequencyHz = def->frequencyHz; m_dampingRatio = def->dampingRatio; m_bias = 0.0f; m_gamma = 0.0f; m_ax.SetZero(); m_ay.SetZero(); } void b2WheelJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); // Compute the effective masses. b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 d = cB + rB - cA - rA; // Point to line constraint { m_ay = b2Mul(qA, m_localYAxisA); m_sAy = b2Cross(d + rA, m_ay); m_sBy = b2Cross(rB, m_ay); m_mass = mA + mB + iA * m_sAy * m_sAy + iB * m_sBy * m_sBy; if (m_mass > 0.0f) { m_mass = 1.0f / m_mass; } } // Spring constraint m_springMass = 0.0f; m_bias = 0.0f; m_gamma = 0.0f; if (m_frequencyHz > 0.0f) { m_ax = b2Mul(qA, m_localXAxisA); m_sAx = b2Cross(d + rA, m_ax); m_sBx = b2Cross(rB, m_ax); float32 invMass = mA + mB + iA * m_sAx * m_sAx + iB * m_sBx * m_sBx; if (invMass > 0.0f) { m_springMass = 1.0f / invMass; float32 C = b2Dot(d, m_ax); // Frequency float32 omega = 2.0f * b2_pi * m_frequencyHz; // Damping coefficient float32 d = 2.0f * m_springMass * m_dampingRatio * omega; // Spring stiffness float32 k = m_springMass * omega * omega; // magic formulas float32 h = data.step.dt; m_gamma = h * (d + h * k); if (m_gamma > 0.0f) { m_gamma = 1.0f / m_gamma; } m_bias = C * h * k * m_gamma; m_springMass = invMass + m_gamma; if (m_springMass > 0.0f) { m_springMass = 1.0f / m_springMass; } } } else { m_springImpulse = 0.0f; } // Rotational motor if (m_enableMotor) { m_motorMass = iA + iB; if (m_motorMass > 0.0f) { m_motorMass = 1.0f / m_motorMass; } } else { m_motorMass = 0.0f; m_motorImpulse = 0.0f; } if (data.step.warmStarting) { // Account for variable time step. m_impulse *= data.step.dtRatio; m_springImpulse *= data.step.dtRatio; m_motorImpulse *= data.step.dtRatio; b2Vec2 P = m_impulse * m_ay + m_springImpulse * m_ax; float32 LA = m_impulse * m_sAy + m_springImpulse * m_sAx + m_motorImpulse; float32 LB = m_impulse * m_sBy + m_springImpulse * m_sBx + m_motorImpulse; vA -= m_invMassA * P; wA -= m_invIA * LA; vB += m_invMassB * P; wB += m_invIB * LB; } else { m_impulse = 0.0f; m_springImpulse = 0.0f; m_motorImpulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2WheelJoint::SolveVelocityConstraints(const b2SolverData& data) { float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; // Solve spring constraint { float32 Cdot = b2Dot(m_ax, vB - vA) + m_sBx * wB - m_sAx * wA; float32 impulse = -m_springMass * (Cdot + m_bias + m_gamma * m_springImpulse); m_springImpulse += impulse; b2Vec2 P = impulse * m_ax; float32 LA = impulse * m_sAx; float32 LB = impulse * m_sBx; vA -= mA * P; wA -= iA * LA; vB += mB * P; wB += iB * LB; } // Solve rotational motor constraint { float32 Cdot = wB - wA - m_motorSpeed; float32 impulse = -m_motorMass * Cdot; float32 oldImpulse = m_motorImpulse; float32 maxImpulse = data.step.dt * m_maxMotorTorque; m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); impulse = m_motorImpulse - oldImpulse; wA -= iA * impulse; wB += iB * impulse; } // Solve point to line constraint { float32 Cdot = b2Dot(m_ay, vB - vA) + m_sBy * wB - m_sAy * wA; float32 impulse = -m_mass * Cdot; m_impulse += impulse; b2Vec2 P = impulse * m_ay; float32 LA = impulse * m_sAy; float32 LB = impulse * m_sBy; vA -= mA * P; wA -= iA * LA; vB += mB * P; wB += iB * LB; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2WheelJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 d = (cB - cA) + rB - rA; b2Vec2 ay = b2Mul(qA, m_localYAxisA); float32 sAy = b2Cross(d + rA, ay); float32 sBy = b2Cross(rB, ay); float32 C = b2Dot(d, ay); float32 k = m_invMassA + m_invMassB + m_invIA * m_sAy * m_sAy + m_invIB * m_sBy * m_sBy; float32 impulse; if (k != 0.0f) { impulse = - C / k; } else { impulse = 0.0f; } b2Vec2 P = impulse * ay; float32 LA = impulse * sAy; float32 LB = impulse * sBy; cA -= m_invMassA * P; aA -= m_invIA * LA; cB += m_invMassB * P; aB += m_invIB * LB; data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return b2Abs(C) <= b2_linearSlop; } b2Vec2 b2WheelJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2WheelJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2WheelJoint::GetReactionForce(float32 inv_dt) const { return inv_dt * (m_impulse * m_ay + m_springImpulse * m_ax); } float32 b2WheelJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * m_motorImpulse; } float32 b2WheelJoint::GetJointTranslation() const { b2Body* bA = m_bodyA; b2Body* bB = m_bodyB; b2Vec2 pA = bA->GetWorldPoint(m_localAnchorA); b2Vec2 pB = bB->GetWorldPoint(m_localAnchorB); b2Vec2 d = pB - pA; b2Vec2 axis = bA->GetWorldVector(m_localXAxisA); float32 translation = b2Dot(d, axis); return translation; } float32 b2WheelJoint::GetJointSpeed() const { float32 wA = m_bodyA->m_angularVelocity; float32 wB = m_bodyB->m_angularVelocity; return wB - wA; } bool b2WheelJoint::IsMotorEnabled() const { return m_enableMotor; } void b2WheelJoint::EnableMotor(bool flag) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_enableMotor = flag; } void b2WheelJoint::SetMotorSpeed(float32 speed) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_motorSpeed = speed; } void b2WheelJoint::SetMaxMotorTorque(float32 torque) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_maxMotorTorque = torque; } float32 b2WheelJoint::GetMotorTorque(float32 inv_dt) const { return inv_dt * m_motorImpulse; } void b2WheelJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2WheelJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.localAxisA.Set(%.15lef, %.15lef);\n", m_localXAxisA.x, m_localXAxisA.y); b2Log(" jd.enableMotor = bool(%d);\n", m_enableMotor); b2Log(" jd.motorSpeed = %.15lef;\n", m_motorSpeed); b2Log(" jd.maxMotorTorque = %.15lef;\n", m_maxMotorTorque); b2Log(" jd.frequencyHz = %.15lef;\n", m_frequencyHz); b2Log(" jd.dampingRatio = %.15lef;\n", m_dampingRatio); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2MouseJoint.cpp0000664000000000000000000001254012310072714016531 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // p = attached point, m = mouse point // C = p - m // Cdot = v // = v + cross(w, r) // J = [I r_skew] // Identity used: // w k % (rx i + ry j) = w * (-ry i + rx j) b2MouseJoint::b2MouseJoint(const b2MouseJointDef* def) : b2Joint(def) { b2Assert(def->target.IsValid()); b2Assert(b2IsValid(def->maxForce) && def->maxForce >= 0.0f); b2Assert(b2IsValid(def->frequencyHz) && def->frequencyHz >= 0.0f); b2Assert(b2IsValid(def->dampingRatio) && def->dampingRatio >= 0.0f); m_targetA = def->target; m_localAnchorB = b2MulT(m_bodyB->GetTransform(), m_targetA); m_maxForce = def->maxForce; m_impulse.SetZero(); m_frequencyHz = def->frequencyHz; m_dampingRatio = def->dampingRatio; m_beta = 0.0f; m_gamma = 0.0f; } void b2MouseJoint::SetTarget(const b2Vec2& target) { if (m_bodyB->IsAwake() == false) { m_bodyB->SetAwake(true); } m_targetA = target; } const b2Vec2& b2MouseJoint::GetTarget() const { return m_targetA; } void b2MouseJoint::SetMaxForce(float32 force) { m_maxForce = force; } float32 b2MouseJoint::GetMaxForce() const { return m_maxForce; } void b2MouseJoint::SetFrequency(float32 hz) { m_frequencyHz = hz; } float32 b2MouseJoint::GetFrequency() const { return m_frequencyHz; } void b2MouseJoint::SetDampingRatio(float32 ratio) { m_dampingRatio = ratio; } float32 b2MouseJoint::GetDampingRatio() const { return m_dampingRatio; } void b2MouseJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexB = m_bodyB->m_islandIndex; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassB = m_bodyB->m_invMass; m_invIB = m_bodyB->m_invI; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qB(aB); float32 mass = m_bodyB->GetMass(); // Frequency float32 omega = 2.0f * b2_pi * m_frequencyHz; // Damping coefficient float32 d = 2.0f * mass * m_dampingRatio * omega; // Spring stiffness float32 k = mass * (omega * omega); // magic formulas // gamma has units of inverse mass. // beta has units of inverse time. float32 h = data.step.dt; b2Assert(d + h * k > b2_epsilon); m_gamma = h * (d + h * k); if (m_gamma != 0.0f) { m_gamma = 1.0f / m_gamma; } m_beta = h * k * m_gamma; // Compute the effective mass matrix. m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)] // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y] // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x] b2Mat22 K; K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma; K.ex.y = -m_invIB * m_rB.x * m_rB.y; K.ey.x = K.ex.y; K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma; m_mass = K.GetInverse(); m_C = cB + m_rB - m_targetA; m_C *= m_beta; // Cheat with some damping wB *= 0.98f; if (data.step.warmStarting) { m_impulse *= data.step.dtRatio; vB += m_invMassB * m_impulse; wB += m_invIB * b2Cross(m_rB, m_impulse); } else { m_impulse.SetZero(); } data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2MouseJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; // Cdot = v + cross(w, r) b2Vec2 Cdot = vB + b2Cross(wB, m_rB); b2Vec2 impulse = b2Mul(m_mass, -(Cdot + m_C + m_gamma * m_impulse)); b2Vec2 oldImpulse = m_impulse; m_impulse += impulse; float32 maxImpulse = data.step.dt * m_maxForce; if (m_impulse.LengthSquared() > maxImpulse * maxImpulse) { m_impulse *= maxImpulse / m_impulse.Length(); } impulse = m_impulse - oldImpulse; vB += m_invMassB * impulse; wB += m_invIB * b2Cross(m_rB, impulse); data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2MouseJoint::SolvePositionConstraints(const b2SolverData& data) { B2_NOT_USED(data); return true; } b2Vec2 b2MouseJoint::GetAnchorA() const { return m_targetA; } b2Vec2 b2MouseJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2MouseJoint::GetReactionForce(float32 inv_dt) const { return inv_dt * m_impulse; } float32 b2MouseJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * 0.0f; } void b2MouseJoint::ShiftOrigin(const b2Vec2& newOrigin) { m_targetA -= newOrigin; } qml-box2d/Box2D/Dynamics/Joints/b2Joint.cpp0000664000000000000000000001235712310072714015526 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include b2Joint* b2Joint::Create(const b2JointDef* def, b2BlockAllocator* allocator) { b2Joint* joint = NULL; switch (def->type) { case e_distanceJoint: { void* mem = allocator->Allocate(sizeof(b2DistanceJoint)); joint = new (mem) b2DistanceJoint(static_cast(def)); } break; case e_mouseJoint: { void* mem = allocator->Allocate(sizeof(b2MouseJoint)); joint = new (mem) b2MouseJoint(static_cast(def)); } break; case e_prismaticJoint: { void* mem = allocator->Allocate(sizeof(b2PrismaticJoint)); joint = new (mem) b2PrismaticJoint(static_cast(def)); } break; case e_revoluteJoint: { void* mem = allocator->Allocate(sizeof(b2RevoluteJoint)); joint = new (mem) b2RevoluteJoint(static_cast(def)); } break; case e_pulleyJoint: { void* mem = allocator->Allocate(sizeof(b2PulleyJoint)); joint = new (mem) b2PulleyJoint(static_cast(def)); } break; case e_gearJoint: { void* mem = allocator->Allocate(sizeof(b2GearJoint)); joint = new (mem) b2GearJoint(static_cast(def)); } break; case e_wheelJoint: { void* mem = allocator->Allocate(sizeof(b2WheelJoint)); joint = new (mem) b2WheelJoint(static_cast(def)); } break; case e_weldJoint: { void* mem = allocator->Allocate(sizeof(b2WeldJoint)); joint = new (mem) b2WeldJoint(static_cast(def)); } break; case e_frictionJoint: { void* mem = allocator->Allocate(sizeof(b2FrictionJoint)); joint = new (mem) b2FrictionJoint(static_cast(def)); } break; case e_ropeJoint: { void* mem = allocator->Allocate(sizeof(b2RopeJoint)); joint = new (mem) b2RopeJoint(static_cast(def)); } break; case e_motorJoint: { void* mem = allocator->Allocate(sizeof(b2MotorJoint)); joint = new (mem) b2MotorJoint(static_cast(def)); } break; default: b2Assert(false); break; } return joint; } void b2Joint::Destroy(b2Joint* joint, b2BlockAllocator* allocator) { joint->~b2Joint(); switch (joint->m_type) { case e_distanceJoint: allocator->Free(joint, sizeof(b2DistanceJoint)); break; case e_mouseJoint: allocator->Free(joint, sizeof(b2MouseJoint)); break; case e_prismaticJoint: allocator->Free(joint, sizeof(b2PrismaticJoint)); break; case e_revoluteJoint: allocator->Free(joint, sizeof(b2RevoluteJoint)); break; case e_pulleyJoint: allocator->Free(joint, sizeof(b2PulleyJoint)); break; case e_gearJoint: allocator->Free(joint, sizeof(b2GearJoint)); break; case e_wheelJoint: allocator->Free(joint, sizeof(b2WheelJoint)); break; case e_weldJoint: allocator->Free(joint, sizeof(b2WeldJoint)); break; case e_frictionJoint: allocator->Free(joint, sizeof(b2FrictionJoint)); break; case e_ropeJoint: allocator->Free(joint, sizeof(b2RopeJoint)); break; case e_motorJoint: allocator->Free(joint, sizeof(b2MotorJoint)); break; default: b2Assert(false); break; } } b2Joint::b2Joint(const b2JointDef* def) { b2Assert(def->bodyA != def->bodyB); m_type = def->type; m_prev = NULL; m_next = NULL; m_bodyA = def->bodyA; m_bodyB = def->bodyB; m_index = 0; m_collideConnected = def->collideConnected; m_islandFlag = false; m_userData = def->userData; m_edgeA.joint = NULL; m_edgeA.other = NULL; m_edgeA.prev = NULL; m_edgeA.next = NULL; m_edgeB.joint = NULL; m_edgeB.other = NULL; m_edgeB.prev = NULL; m_edgeB.next = NULL; } bool b2Joint::IsActive() const { return m_bodyA->IsActive() && m_bodyB->IsActive(); } qml-box2d/Box2D/Dynamics/Joints/b2RopeJoint.cpp0000644000000000000000000001433212241175670016355 0ustar /* * Copyright (c) 2007-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Limit: // C = norm(pB - pA) - L // u = (pB - pA) / norm(pB - pA) // Cdot = dot(u, vB + cross(wB, rB) - vA - cross(wA, rA)) // J = [-u -cross(rA, u) u cross(rB, u)] // K = J * invM * JT // = invMassA + invIA * cross(rA, u)^2 + invMassB + invIB * cross(rB, u)^2 b2RopeJoint::b2RopeJoint(const b2RopeJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_maxLength = def->maxLength; m_mass = 0.0f; m_impulse = 0.0f; m_state = e_inactiveLimit; m_length = 0.0f; } void b2RopeJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); m_u = cB + m_rB - cA - m_rA; m_length = m_u.Length(); float32 C = m_length - m_maxLength; if (C > 0.0f) { m_state = e_atUpperLimit; } else { m_state = e_inactiveLimit; } if (m_length > b2_linearSlop) { m_u *= 1.0f / m_length; } else { m_u.SetZero(); m_mass = 0.0f; m_impulse = 0.0f; return; } // Compute effective mass. float32 crA = b2Cross(m_rA, m_u); float32 crB = b2Cross(m_rB, m_u); float32 invMass = m_invMassA + m_invIA * crA * crA + m_invMassB + m_invIB * crB * crB; m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; if (data.step.warmStarting) { // Scale the impulse to support a variable time step. m_impulse *= data.step.dtRatio; b2Vec2 P = m_impulse * m_u; vA -= m_invMassA * P; wA -= m_invIA * b2Cross(m_rA, P); vB += m_invMassB * P; wB += m_invIB * b2Cross(m_rB, P); } else { m_impulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2RopeJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; // Cdot = dot(u, v + cross(w, r)) b2Vec2 vpA = vA + b2Cross(wA, m_rA); b2Vec2 vpB = vB + b2Cross(wB, m_rB); float32 C = m_length - m_maxLength; float32 Cdot = b2Dot(m_u, vpB - vpA); // Predictive constraint. if (C < 0.0f) { Cdot += data.step.inv_dt * C; } float32 impulse = -m_mass * Cdot; float32 oldImpulse = m_impulse; m_impulse = b2Min(0.0f, m_impulse + impulse); impulse = m_impulse - oldImpulse; b2Vec2 P = impulse * m_u; vA -= m_invMassA * P; wA -= m_invIA * b2Cross(m_rA, P); vB += m_invMassB * P; wB += m_invIB * b2Cross(m_rB, P); data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2RopeJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 u = cB + rB - cA - rA; float32 length = u.Normalize(); float32 C = length - m_maxLength; C = b2Clamp(C, 0.0f, b2_maxLinearCorrection); float32 impulse = -m_mass * C; b2Vec2 P = impulse * u; cA -= m_invMassA * P; aA -= m_invIA * b2Cross(rA, P); cB += m_invMassB * P; aB += m_invIB * b2Cross(rB, P); data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return length - m_maxLength < b2_linearSlop; } b2Vec2 b2RopeJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2RopeJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2RopeJoint::GetReactionForce(float32 inv_dt) const { b2Vec2 F = (inv_dt * m_impulse) * m_u; return F; } float32 b2RopeJoint::GetReactionTorque(float32 inv_dt) const { B2_NOT_USED(inv_dt); return 0.0f; } float32 b2RopeJoint::GetMaxLength() const { return m_maxLength; } b2LimitState b2RopeJoint::GetLimitState() const { return m_state; } void b2RopeJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2RopeJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.maxLength = %.15lef;\n", m_maxLength); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/Joints/b2PulleyJoint.cpp0000664000000000000000000002115412310072714016714 0ustar /* * Copyright (c) 2007 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Pulley: // length1 = norm(p1 - s1) // length2 = norm(p2 - s2) // C0 = (length1 + ratio * length2)_initial // C = C0 - (length1 + ratio * length2) // u1 = (p1 - s1) / norm(p1 - s1) // u2 = (p2 - s2) / norm(p2 - s2) // Cdot = -dot(u1, v1 + cross(w1, r1)) - ratio * dot(u2, v2 + cross(w2, r2)) // J = -[u1 cross(r1, u1) ratio * u2 ratio * cross(r2, u2)] // K = J * invM * JT // = invMass1 + invI1 * cross(r1, u1)^2 + ratio^2 * (invMass2 + invI2 * cross(r2, u2)^2) void b2PulleyJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& groundA, const b2Vec2& groundB, const b2Vec2& anchorA, const b2Vec2& anchorB, float32 r) { bodyA = bA; bodyB = bB; groundAnchorA = groundA; groundAnchorB = groundB; localAnchorA = bodyA->GetLocalPoint(anchorA); localAnchorB = bodyB->GetLocalPoint(anchorB); b2Vec2 dA = anchorA - groundA; lengthA = dA.Length(); b2Vec2 dB = anchorB - groundB; lengthB = dB.Length(); ratio = r; b2Assert(ratio > b2_epsilon); } b2PulleyJoint::b2PulleyJoint(const b2PulleyJointDef* def) : b2Joint(def) { m_groundAnchorA = def->groundAnchorA; m_groundAnchorB = def->groundAnchorB; m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_lengthA = def->lengthA; m_lengthB = def->lengthB; b2Assert(def->ratio != 0.0f); m_ratio = def->ratio; m_constant = def->lengthA + m_ratio * def->lengthB; m_impulse = 0.0f; } void b2PulleyJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); // Get the pulley axes. m_uA = cA + m_rA - m_groundAnchorA; m_uB = cB + m_rB - m_groundAnchorB; float32 lengthA = m_uA.Length(); float32 lengthB = m_uB.Length(); if (lengthA > 10.0f * b2_linearSlop) { m_uA *= 1.0f / lengthA; } else { m_uA.SetZero(); } if (lengthB > 10.0f * b2_linearSlop) { m_uB *= 1.0f / lengthB; } else { m_uB.SetZero(); } // Compute effective mass. float32 ruA = b2Cross(m_rA, m_uA); float32 ruB = b2Cross(m_rB, m_uB); float32 mA = m_invMassA + m_invIA * ruA * ruA; float32 mB = m_invMassB + m_invIB * ruB * ruB; m_mass = mA + m_ratio * m_ratio * mB; if (m_mass > 0.0f) { m_mass = 1.0f / m_mass; } if (data.step.warmStarting) { // Scale impulses to support variable time steps. m_impulse *= data.step.dtRatio; // Warm starting. b2Vec2 PA = -(m_impulse) * m_uA; b2Vec2 PB = (-m_ratio * m_impulse) * m_uB; vA += m_invMassA * PA; wA += m_invIA * b2Cross(m_rA, PA); vB += m_invMassB * PB; wB += m_invIB * b2Cross(m_rB, PB); } else { m_impulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2PulleyJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Vec2 vpA = vA + b2Cross(wA, m_rA); b2Vec2 vpB = vB + b2Cross(wB, m_rB); float32 Cdot = -b2Dot(m_uA, vpA) - m_ratio * b2Dot(m_uB, vpB); float32 impulse = -m_mass * Cdot; m_impulse += impulse; b2Vec2 PA = -impulse * m_uA; b2Vec2 PB = -m_ratio * impulse * m_uB; vA += m_invMassA * PA; wA += m_invIA * b2Cross(m_rA, PA); vB += m_invMassB * PB; wB += m_invIB * b2Cross(m_rB, PB); data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2PulleyJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); // Get the pulley axes. b2Vec2 uA = cA + rA - m_groundAnchorA; b2Vec2 uB = cB + rB - m_groundAnchorB; float32 lengthA = uA.Length(); float32 lengthB = uB.Length(); if (lengthA > 10.0f * b2_linearSlop) { uA *= 1.0f / lengthA; } else { uA.SetZero(); } if (lengthB > 10.0f * b2_linearSlop) { uB *= 1.0f / lengthB; } else { uB.SetZero(); } // Compute effective mass. float32 ruA = b2Cross(rA, uA); float32 ruB = b2Cross(rB, uB); float32 mA = m_invMassA + m_invIA * ruA * ruA; float32 mB = m_invMassB + m_invIB * ruB * ruB; float32 mass = mA + m_ratio * m_ratio * mB; if (mass > 0.0f) { mass = 1.0f / mass; } float32 C = m_constant - lengthA - m_ratio * lengthB; float32 linearError = b2Abs(C); float32 impulse = -mass * C; b2Vec2 PA = -impulse * uA; b2Vec2 PB = -m_ratio * impulse * uB; cA += m_invMassA * PA; aA += m_invIA * b2Cross(rA, PA); cB += m_invMassB * PB; aB += m_invIB * b2Cross(rB, PB); data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return linearError < b2_linearSlop; } b2Vec2 b2PulleyJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2PulleyJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2PulleyJoint::GetReactionForce(float32 inv_dt) const { b2Vec2 P = m_impulse * m_uB; return inv_dt * P; } float32 b2PulleyJoint::GetReactionTorque(float32 inv_dt) const { B2_NOT_USED(inv_dt); return 0.0f; } b2Vec2 b2PulleyJoint::GetGroundAnchorA() const { return m_groundAnchorA; } b2Vec2 b2PulleyJoint::GetGroundAnchorB() const { return m_groundAnchorB; } float32 b2PulleyJoint::GetLengthA() const { return m_lengthA; } float32 b2PulleyJoint::GetLengthB() const { return m_lengthB; } float32 b2PulleyJoint::GetRatio() const { return m_ratio; } float32 b2PulleyJoint::GetCurrentLengthA() const { b2Vec2 p = m_bodyA->GetWorldPoint(m_localAnchorA); b2Vec2 s = m_groundAnchorA; b2Vec2 d = p - s; return d.Length(); } float32 b2PulleyJoint::GetCurrentLengthB() const { b2Vec2 p = m_bodyB->GetWorldPoint(m_localAnchorB); b2Vec2 s = m_groundAnchorB; b2Vec2 d = p - s; return d.Length(); } void b2PulleyJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2PulleyJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.groundAnchorA.Set(%.15lef, %.15lef);\n", m_groundAnchorA.x, m_groundAnchorA.y); b2Log(" jd.groundAnchorB.Set(%.15lef, %.15lef);\n", m_groundAnchorB.x, m_groundAnchorB.y); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.lengthA = %.15lef;\n", m_lengthA); b2Log(" jd.lengthB = %.15lef;\n", m_lengthB); b2Log(" jd.ratio = %.15lef;\n", m_ratio); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } void b2PulleyJoint::ShiftOrigin(const b2Vec2& newOrigin) { m_groundAnchorA -= newOrigin; m_groundAnchorB -= newOrigin; } qml-box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.h0000644000000000000000000001405212241175670016721 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_REVOLUTE_JOINT_H #define B2_REVOLUTE_JOINT_H #include /// Revolute joint definition. This requires defining an /// anchor point where the bodies are joined. The definition /// uses local anchor points so that the initial configuration /// can violate the constraint slightly. You also need to /// specify the initial relative angle for joint limits. This /// helps when saving and loading a game. /// The local anchor points are measured from the body's origin /// rather than the center of mass because: /// 1. you might not know where the center of mass will be. /// 2. if you add/remove shapes from a body and recompute the mass, /// the joints will be broken. struct b2RevoluteJointDef : public b2JointDef { b2RevoluteJointDef() { type = e_revoluteJoint; localAnchorA.Set(0.0f, 0.0f); localAnchorB.Set(0.0f, 0.0f); referenceAngle = 0.0f; lowerAngle = 0.0f; upperAngle = 0.0f; maxMotorTorque = 0.0f; motorSpeed = 0.0f; enableLimit = false; enableMotor = false; } /// Initialize the bodies, anchors, and reference angle using a world /// anchor point. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor); /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The bodyB angle minus bodyA angle in the reference state (radians). float32 referenceAngle; /// A flag to enable joint limits. bool enableLimit; /// The lower angle for the joint limit (radians). float32 lowerAngle; /// The upper angle for the joint limit (radians). float32 upperAngle; /// A flag to enable the joint motor. bool enableMotor; /// The desired motor speed. Usually in radians per second. float32 motorSpeed; /// The maximum motor torque used to achieve the desired motor speed. /// Usually in N-m. float32 maxMotorTorque; }; /// A revolute joint constrains two bodies to share a common point while they /// are free to rotate about the point. The relative rotation about the shared /// point is the joint angle. You can limit the relative rotation with /// a joint limit that specifies a lower and upper angle. You can use a motor /// to drive the relative rotation about the shared point. A maximum motor torque /// is provided so that infinite forces are not generated. class b2RevoluteJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// Get the reference angle. float32 GetReferenceAngle() const { return m_referenceAngle; } /// Get the current joint angle in radians. float32 GetJointAngle() const; /// Get the current joint angle speed in radians per second. float32 GetJointSpeed() const; /// Is the joint limit enabled? bool IsLimitEnabled() const; /// Enable/disable the joint limit. void EnableLimit(bool flag); /// Get the lower joint limit in radians. float32 GetLowerLimit() const; /// Get the upper joint limit in radians. float32 GetUpperLimit() const; /// Set the joint limits in radians. void SetLimits(float32 lower, float32 upper); /// Is the joint motor enabled? bool IsMotorEnabled() const; /// Enable/disable the joint motor. void EnableMotor(bool flag); /// Set the motor speed in radians per second. void SetMotorSpeed(float32 speed); /// Get the motor speed in radians per second. float32 GetMotorSpeed() const; /// Set the maximum motor torque, usually in N-m. void SetMaxMotorTorque(float32 torque); float32 GetMaxMotorTorque() const { return m_maxMotorTorque; } /// Get the reaction force given the inverse time step. /// Unit is N. b2Vec2 GetReactionForce(float32 inv_dt) const; /// Get the reaction torque due to the joint limit given the inverse time step. /// Unit is N*m. float32 GetReactionTorque(float32 inv_dt) const; /// Get the current motor torque given the inverse time step. /// Unit is N*m. float32 GetMotorTorque(float32 inv_dt) const; /// Dump to b2Log. void Dump(); protected: friend class b2Joint; friend class b2GearJoint; b2RevoluteJoint(const b2RevoluteJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; b2Vec3 m_impulse; float32 m_motorImpulse; bool m_enableMotor; float32 m_maxMotorTorque; float32 m_motorSpeed; bool m_enableLimit; float32 m_referenceAngle; float32 m_lowerAngle; float32 m_upperAngle; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; b2Mat33 m_mass; // effective mass for point-to-point constraint. float32 m_motorMass; // effective mass for motor/limit angular constraint. b2LimitState m_limitState; }; inline float32 b2RevoluteJoint::GetMotorSpeed() const { return m_motorSpeed; } #endif qml-box2d/Box2D/Dynamics/Joints/b2DistanceJoint.h0000644000000000000000000001075312241175670016652 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_DISTANCE_JOINT_H #define B2_DISTANCE_JOINT_H #include /// Distance joint definition. This requires defining an /// anchor point on both bodies and the non-zero length of the /// distance joint. The definition uses local anchor points /// so that the initial configuration can violate the constraint /// slightly. This helps when saving and loading a game. /// @warning Do not use a zero or short length. struct b2DistanceJointDef : public b2JointDef { b2DistanceJointDef() { type = e_distanceJoint; localAnchorA.Set(0.0f, 0.0f); localAnchorB.Set(0.0f, 0.0f); length = 1.0f; frequencyHz = 0.0f; dampingRatio = 0.0f; } /// Initialize the bodies, anchors, and length using the world /// anchors. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchorA, const b2Vec2& anchorB); /// The local anchor point relative to bodyA's origin. b2Vec2 localAnchorA; /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; /// The natural length between the anchor points. float32 length; /// The mass-spring-damper frequency in Hertz. A value of 0 /// disables softness. float32 frequencyHz; /// The damping ratio. 0 = no damping, 1 = critical damping. float32 dampingRatio; }; /// A distance joint constrains two points on two bodies /// to remain at a fixed distance from each other. You can view /// this as a massless, rigid rod. class b2DistanceJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; /// Get the reaction force given the inverse time step. /// Unit is N. b2Vec2 GetReactionForce(float32 inv_dt) const; /// Get the reaction torque given the inverse time step. /// Unit is N*m. This is always zero for a distance joint. float32 GetReactionTorque(float32 inv_dt) const; /// The local anchor point relative to bodyA's origin. const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } /// Set/get the natural length. /// Manipulating the length can lead to non-physical behavior when the frequency is zero. void SetLength(float32 length); float32 GetLength() const; /// Set/get frequency in Hz. void SetFrequency(float32 hz); float32 GetFrequency() const; /// Set/get damping ratio. void SetDampingRatio(float32 ratio); float32 GetDampingRatio() const; /// Dump joint to dmLog void Dump(); protected: friend class b2Joint; b2DistanceJoint(const b2DistanceJointDef* data); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); float32 m_frequencyHz; float32 m_dampingRatio; float32 m_bias; // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; float32 m_gamma; float32 m_impulse; float32 m_length; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_u; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; float32 m_mass; }; inline void b2DistanceJoint::SetLength(float32 length) { m_length = length; } inline float32 b2DistanceJoint::GetLength() const { return m_length; } inline void b2DistanceJoint::SetFrequency(float32 hz) { m_frequencyHz = hz; } inline float32 b2DistanceJoint::GetFrequency() const { return m_frequencyHz; } inline void b2DistanceJoint::SetDampingRatio(float32 ratio) { m_dampingRatio = ratio; } inline float32 b2DistanceJoint::GetDampingRatio() const { return m_dampingRatio; } #endif qml-box2d/Box2D/Dynamics/Joints/b2MotorJoint.h0000664000000000000000000000715712310072714016216 0ustar /* * Copyright (c) 2006-2012 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_MOTOR_JOINT_H #define B2_MOTOR_JOINT_H #include /// Motor joint definition. struct b2MotorJointDef : public b2JointDef { b2MotorJointDef() { type = e_motorJoint; linearOffset.SetZero(); angularOffset = 0.0f; maxForce = 1.0f; maxTorque = 1.0f; correctionFactor = 0.3f; } /// Initialize the bodies and offsets using the current transforms. void Initialize(b2Body* bodyA, b2Body* bodyB); /// Position of bodyB minus the position of bodyA, in bodyA's frame, in meters. b2Vec2 linearOffset; /// The bodyB angle minus bodyA angle in radians. float32 angularOffset; /// The maximum motor force in N. float32 maxForce; /// The maximum motor torque in N-m. float32 maxTorque; /// Position correction factor in the range [0,1]. float32 correctionFactor; }; /// A motor joint is used to control the relative motion /// between two bodies. A typical usage is to control the movement /// of a dynamic body with respect to the ground. class b2MotorJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// Set/get the target linear offset, in frame A, in meters. void SetLinearOffset(const b2Vec2& linearOffset); const b2Vec2& GetLinearOffset() const; /// Set/get the target angular offset, in radians. void SetAngularOffset(float32 angularOffset); float32 GetAngularOffset() const; /// Set the maximum friction force in N. void SetMaxForce(float32 force); /// Get the maximum friction force in N. float32 GetMaxForce() const; /// Set the maximum friction torque in N*m. void SetMaxTorque(float32 torque); /// Get the maximum friction torque in N*m. float32 GetMaxTorque() const; /// Set the position correction factor in the range [0,1]. void SetCorrectionFactor(float32 factor); /// Get the position correction factor in the range [0,1]. float32 GetCorrectionFactor() const; /// Dump to b2Log void Dump(); protected: friend class b2Joint; b2MotorJoint(const b2MotorJointDef* def); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); // Solver shared b2Vec2 m_linearOffset; float32 m_angularOffset; b2Vec2 m_linearImpulse; float32 m_angularImpulse; float32 m_maxForce; float32 m_maxTorque; float32 m_correctionFactor; // Solver temp int32 m_indexA; int32 m_indexB; b2Vec2 m_rA; b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; b2Vec2 m_linearError; float32 m_angularError; float32 m_invMassA; float32 m_invMassB; float32 m_invIA; float32 m_invIB; b2Mat22 m_linearMass; float32 m_angularMass; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2GearJoint.h0000644000000000000000000000660712241175670016001 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_GEAR_JOINT_H #define B2_GEAR_JOINT_H #include /// Gear joint definition. This definition requires two existing /// revolute or prismatic joints (any combination will work). struct b2GearJointDef : public b2JointDef { b2GearJointDef() { type = e_gearJoint; joint1 = NULL; joint2 = NULL; ratio = 1.0f; } /// The first revolute/prismatic joint attached to the gear joint. b2Joint* joint1; /// The second revolute/prismatic joint attached to the gear joint. b2Joint* joint2; /// The gear ratio. /// @see b2GearJoint for explanation. float32 ratio; }; /// A gear joint is used to connect two joints together. Either joint /// can be a revolute or prismatic joint. You specify a gear ratio /// to bind the motions together: /// coordinate1 + ratio * coordinate2 = constant /// The ratio can be negative or positive. If one joint is a revolute joint /// and the other joint is a prismatic joint, then the ratio will have units /// of length or units of 1/length. /// @warning You have to manually destroy the gear joint if joint1 or joint2 /// is destroyed. class b2GearJoint : public b2Joint { public: b2Vec2 GetAnchorA() const; b2Vec2 GetAnchorB() const; b2Vec2 GetReactionForce(float32 inv_dt) const; float32 GetReactionTorque(float32 inv_dt) const; /// Get the first joint. b2Joint* GetJoint1() { return m_joint1; } /// Get the second joint. b2Joint* GetJoint2() { return m_joint2; } /// Set/Get the gear ratio. void SetRatio(float32 ratio); float32 GetRatio() const; /// Dump joint to dmLog void Dump(); protected: friend class b2Joint; b2GearJoint(const b2GearJointDef* data); void InitVelocityConstraints(const b2SolverData& data); void SolveVelocityConstraints(const b2SolverData& data); bool SolvePositionConstraints(const b2SolverData& data); b2Joint* m_joint1; b2Joint* m_joint2; b2JointType m_typeA; b2JointType m_typeB; // Body A is connected to body C // Body B is connected to body D b2Body* m_bodyC; b2Body* m_bodyD; // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; b2Vec2 m_localAnchorC; b2Vec2 m_localAnchorD; b2Vec2 m_localAxisC; b2Vec2 m_localAxisD; float32 m_referenceAngleA; float32 m_referenceAngleB; float32 m_constant; float32 m_ratio; float32 m_impulse; // Solver temp int32 m_indexA, m_indexB, m_indexC, m_indexD; b2Vec2 m_lcA, m_lcB, m_lcC, m_lcD; float32 m_mA, m_mB, m_mC, m_mD; float32 m_iA, m_iB, m_iC, m_iD; b2Vec2 m_JvAC, m_JvBD; float32 m_JwA, m_JwB, m_JwC, m_JwD; float32 m_mass; }; #endif qml-box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp0000664000000000000000000004072112310072714017376 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #include #include #include // Linear constraint (point-to-line) // d = p2 - p1 = x2 + r2 - x1 - r1 // C = dot(perp, d) // Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1)) // = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2) // J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)] // // Angular constraint // C = a2 - a1 + a_initial // Cdot = w2 - w1 // J = [0 0 -1 0 0 1] // // K = J * invM * JT // // J = [-a -s1 a s2] // [0 -1 0 1] // a = perp // s1 = cross(d + r1, a) = cross(p2 - x1, a) // s2 = cross(r2, a) = cross(p2 - x2, a) // Motor/Limit linear constraint // C = dot(ax1, d) // Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2) // J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)] // Block Solver // We develop a block solver that includes the joint limit. This makes the limit stiff (inelastic) even // when the mass has poor distribution (leading to large torques about the joint anchor points). // // The Jacobian has 3 rows: // J = [-uT -s1 uT s2] // linear // [0 -1 0 1] // angular // [-vT -a1 vT a2] // limit // // u = perp // v = axis // s1 = cross(d + r1, u), s2 = cross(r2, u) // a1 = cross(d + r1, v), a2 = cross(r2, v) // M * (v2 - v1) = JT * df // J * v2 = bias // // v2 = v1 + invM * JT * df // J * (v1 + invM * JT * df) = bias // K * df = bias - J * v1 = -Cdot // K = J * invM * JT // Cdot = J * v1 - bias // // Now solve for f2. // df = f2 - f1 // K * (f2 - f1) = -Cdot // f2 = invK * (-Cdot) + f1 // // Clamp accumulated limit impulse. // lower: f2(3) = max(f2(3), 0) // upper: f2(3) = min(f2(3), 0) // // Solve for correct f2(1:2) // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:3) * f1 // = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:2) * f1(1:2) + K(1:2,3) * f1(3) // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3)) + K(1:2,1:2) * f1(1:2) // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2) // // Now compute impulse to be applied: // df = f2 - f1 void b2PrismaticJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis) { bodyA = bA; bodyB = bB; localAnchorA = bodyA->GetLocalPoint(anchor); localAnchorB = bodyB->GetLocalPoint(anchor); localAxisA = bodyA->GetLocalVector(axis); referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); } b2PrismaticJoint::b2PrismaticJoint(const b2PrismaticJointDef* def) : b2Joint(def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; m_localXAxisA = def->localAxisA; m_localXAxisA.Normalize(); m_localYAxisA = b2Cross(1.0f, m_localXAxisA); m_referenceAngle = def->referenceAngle; m_impulse.SetZero(); m_motorMass = 0.0f; m_motorImpulse = 0.0f; m_lowerTranslation = def->lowerTranslation; m_upperTranslation = def->upperTranslation; m_maxMotorForce = def->maxMotorForce; m_motorSpeed = def->motorSpeed; m_enableLimit = def->enableLimit; m_enableMotor = def->enableMotor; m_limitState = e_inactiveLimit; m_axis.SetZero(); m_perp.SetZero(); } void b2PrismaticJoint::InitVelocityConstraints(const b2SolverData& data) { m_indexA = m_bodyA->m_islandIndex; m_indexB = m_bodyB->m_islandIndex; m_localCenterA = m_bodyA->m_sweep.localCenter; m_localCenterB = m_bodyB->m_sweep.localCenter; m_invMassA = m_bodyA->m_invMass; m_invMassB = m_bodyB->m_invMass; m_invIA = m_bodyA->m_invI; m_invIB = m_bodyB->m_invI; b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; b2Rot qA(aA), qB(aB); // Compute the effective masses. b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 d = (cB - cA) + rB - rA; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; // Compute motor Jacobian and effective mass. { m_axis = b2Mul(qA, m_localXAxisA); m_a1 = b2Cross(d + rA, m_axis); m_a2 = b2Cross(rB, m_axis); m_motorMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2; if (m_motorMass > 0.0f) { m_motorMass = 1.0f / m_motorMass; } } // Prismatic constraint. { m_perp = b2Mul(qA, m_localYAxisA); m_s1 = b2Cross(d + rA, m_perp); m_s2 = b2Cross(rB, m_perp); float32 k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2; float32 k12 = iA * m_s1 + iB * m_s2; float32 k13 = iA * m_s1 * m_a1 + iB * m_s2 * m_a2; float32 k22 = iA + iB; if (k22 == 0.0f) { // For bodies with fixed rotation. k22 = 1.0f; } float32 k23 = iA * m_a1 + iB * m_a2; float32 k33 = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2; m_K.ex.Set(k11, k12, k13); m_K.ey.Set(k12, k22, k23); m_K.ez.Set(k13, k23, k33); } // Compute motor and limit terms. if (m_enableLimit) { float32 jointTranslation = b2Dot(m_axis, d); if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop) { m_limitState = e_equalLimits; } else if (jointTranslation <= m_lowerTranslation) { if (m_limitState != e_atLowerLimit) { m_limitState = e_atLowerLimit; m_impulse.z = 0.0f; } } else if (jointTranslation >= m_upperTranslation) { if (m_limitState != e_atUpperLimit) { m_limitState = e_atUpperLimit; m_impulse.z = 0.0f; } } else { m_limitState = e_inactiveLimit; m_impulse.z = 0.0f; } } else { m_limitState = e_inactiveLimit; m_impulse.z = 0.0f; } if (m_enableMotor == false) { m_motorImpulse = 0.0f; } if (data.step.warmStarting) { // Account for variable time step. m_impulse *= data.step.dtRatio; m_motorImpulse *= data.step.dtRatio; b2Vec2 P = m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis; float32 LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1; float32 LB = m_impulse.x * m_s2 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a2; vA -= mA * P; wA -= iA * LA; vB += mB * P; wB += iB * LB; } else { m_impulse.SetZero(); m_motorImpulse = 0.0f; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } void b2PrismaticJoint::SolveVelocityConstraints(const b2SolverData& data) { b2Vec2 vA = data.velocities[m_indexA].v; float32 wA = data.velocities[m_indexA].w; b2Vec2 vB = data.velocities[m_indexB].v; float32 wB = data.velocities[m_indexB].w; float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; // Solve linear motor constraint. if (m_enableMotor && m_limitState != e_equalLimits) { float32 Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA; float32 impulse = m_motorMass * (m_motorSpeed - Cdot); float32 oldImpulse = m_motorImpulse; float32 maxImpulse = data.step.dt * m_maxMotorForce; m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); impulse = m_motorImpulse - oldImpulse; b2Vec2 P = impulse * m_axis; float32 LA = impulse * m_a1; float32 LB = impulse * m_a2; vA -= mA * P; wA -= iA * LA; vB += mB * P; wB += iB * LB; } b2Vec2 Cdot1; Cdot1.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA; Cdot1.y = wB - wA; if (m_enableLimit && m_limitState != e_inactiveLimit) { // Solve prismatic and limit constraint in block form. float32 Cdot2; Cdot2 = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA; b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2); b2Vec3 f1 = m_impulse; b2Vec3 df = m_K.Solve33(-Cdot); m_impulse += df; if (m_limitState == e_atLowerLimit) { m_impulse.z = b2Max(m_impulse.z, 0.0f); } else if (m_limitState == e_atUpperLimit) { m_impulse.z = b2Min(m_impulse.z, 0.0f); } // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2) b2Vec2 b = -Cdot1 - (m_impulse.z - f1.z) * b2Vec2(m_K.ez.x, m_K.ez.y); b2Vec2 f2r = m_K.Solve22(b) + b2Vec2(f1.x, f1.y); m_impulse.x = f2r.x; m_impulse.y = f2r.y; df = m_impulse - f1; b2Vec2 P = df.x * m_perp + df.z * m_axis; float32 LA = df.x * m_s1 + df.y + df.z * m_a1; float32 LB = df.x * m_s2 + df.y + df.z * m_a2; vA -= mA * P; wA -= iA * LA; vB += mB * P; wB += iB * LB; } else { // Limit is inactive, just solve the prismatic constraint in block form. b2Vec2 df = m_K.Solve22(-Cdot1); m_impulse.x += df.x; m_impulse.y += df.y; b2Vec2 P = df.x * m_perp; float32 LA = df.x * m_s1 + df.y; float32 LB = df.x * m_s2 + df.y; vA -= mA * P; wA -= iA * LA; vB += mB * P; wB += iB * LB; } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; data.velocities[m_indexB].v = vB; data.velocities[m_indexB].w = wB; } bool b2PrismaticJoint::SolvePositionConstraints(const b2SolverData& data) { b2Vec2 cA = data.positions[m_indexA].c; float32 aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; float32 aB = data.positions[m_indexB].a; b2Rot qA(aA), qB(aB); float32 mA = m_invMassA, mB = m_invMassB; float32 iA = m_invIA, iB = m_invIB; // Compute fresh Jacobians b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); b2Vec2 d = cB + rB - cA - rA; b2Vec2 axis = b2Mul(qA, m_localXAxisA); float32 a1 = b2Cross(d + rA, axis); float32 a2 = b2Cross(rB, axis); b2Vec2 perp = b2Mul(qA, m_localYAxisA); float32 s1 = b2Cross(d + rA, perp); float32 s2 = b2Cross(rB, perp); b2Vec3 impulse; b2Vec2 C1; C1.x = b2Dot(perp, d); C1.y = aB - aA - m_referenceAngle; float32 linearError = b2Abs(C1.x); float32 angularError = b2Abs(C1.y); bool active = false; float32 C2 = 0.0f; if (m_enableLimit) { float32 translation = b2Dot(axis, d); if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop) { // Prevent large angular corrections C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection); linearError = b2Max(linearError, b2Abs(translation)); active = true; } else if (translation <= m_lowerTranslation) { // Prevent large linear corrections and allow some slop. C2 = b2Clamp(translation - m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0.0f); linearError = b2Max(linearError, m_lowerTranslation - translation); active = true; } else if (translation >= m_upperTranslation) { // Prevent large linear corrections and allow some slop. C2 = b2Clamp(translation - m_upperTranslation - b2_linearSlop, 0.0f, b2_maxLinearCorrection); linearError = b2Max(linearError, translation - m_upperTranslation); active = true; } } if (active) { float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; float32 k12 = iA * s1 + iB * s2; float32 k13 = iA * s1 * a1 + iB * s2 * a2; float32 k22 = iA + iB; if (k22 == 0.0f) { // For fixed rotation k22 = 1.0f; } float32 k23 = iA * a1 + iB * a2; float32 k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; b2Mat33 K; K.ex.Set(k11, k12, k13); K.ey.Set(k12, k22, k23); K.ez.Set(k13, k23, k33); b2Vec3 C; C.x = C1.x; C.y = C1.y; C.z = C2; impulse = K.Solve33(-C); } else { float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; float32 k12 = iA * s1 + iB * s2; float32 k22 = iA + iB; if (k22 == 0.0f) { k22 = 1.0f; } b2Mat22 K; K.ex.Set(k11, k12); K.ey.Set(k12, k22); b2Vec2 impulse1 = K.Solve(-C1); impulse.x = impulse1.x; impulse.y = impulse1.y; impulse.z = 0.0f; } b2Vec2 P = impulse.x * perp + impulse.z * axis; float32 LA = impulse.x * s1 + impulse.y + impulse.z * a1; float32 LB = impulse.x * s2 + impulse.y + impulse.z * a2; cA -= mA * P; aA -= iA * LA; cB += mB * P; aB += iB * LB; data.positions[m_indexA].c = cA; data.positions[m_indexA].a = aA; data.positions[m_indexB].c = cB; data.positions[m_indexB].a = aB; return linearError <= b2_linearSlop && angularError <= b2_angularSlop; } b2Vec2 b2PrismaticJoint::GetAnchorA() const { return m_bodyA->GetWorldPoint(m_localAnchorA); } b2Vec2 b2PrismaticJoint::GetAnchorB() const { return m_bodyB->GetWorldPoint(m_localAnchorB); } b2Vec2 b2PrismaticJoint::GetReactionForce(float32 inv_dt) const { return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis); } float32 b2PrismaticJoint::GetReactionTorque(float32 inv_dt) const { return inv_dt * m_impulse.y; } float32 b2PrismaticJoint::GetJointTranslation() const { b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA); b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB); b2Vec2 d = pB - pA; b2Vec2 axis = m_bodyA->GetWorldVector(m_localXAxisA); float32 translation = b2Dot(d, axis); return translation; } float32 b2PrismaticJoint::GetJointSpeed() const { b2Body* bA = m_bodyA; b2Body* bB = m_bodyB; b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter); b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter); b2Vec2 p1 = bA->m_sweep.c + rA; b2Vec2 p2 = bB->m_sweep.c + rB; b2Vec2 d = p2 - p1; b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA); b2Vec2 vA = bA->m_linearVelocity; b2Vec2 vB = bB->m_linearVelocity; float32 wA = bA->m_angularVelocity; float32 wB = bB->m_angularVelocity; float32 speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA)); return speed; } bool b2PrismaticJoint::IsLimitEnabled() const { return m_enableLimit; } void b2PrismaticJoint::EnableLimit(bool flag) { if (flag != m_enableLimit) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_enableLimit = flag; m_impulse.z = 0.0f; } } float32 b2PrismaticJoint::GetLowerLimit() const { return m_lowerTranslation; } float32 b2PrismaticJoint::GetUpperLimit() const { return m_upperTranslation; } void b2PrismaticJoint::SetLimits(float32 lower, float32 upper) { b2Assert(lower <= upper); if (lower != m_lowerTranslation || upper != m_upperTranslation) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_lowerTranslation = lower; m_upperTranslation = upper; m_impulse.z = 0.0f; } } bool b2PrismaticJoint::IsMotorEnabled() const { return m_enableMotor; } void b2PrismaticJoint::EnableMotor(bool flag) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_enableMotor = flag; } void b2PrismaticJoint::SetMotorSpeed(float32 speed) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_motorSpeed = speed; } void b2PrismaticJoint::SetMaxMotorForce(float32 force) { m_bodyA->SetAwake(true); m_bodyB->SetAwake(true); m_maxMotorForce = force; } float32 b2PrismaticJoint::GetMotorForce(float32 inv_dt) const { return inv_dt * m_motorImpulse; } void b2PrismaticJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; int32 indexB = m_bodyB->m_islandIndex; b2Log(" b2PrismaticJointDef jd;\n"); b2Log(" jd.bodyA = bodies[%d];\n", indexA); b2Log(" jd.bodyB = bodies[%d];\n", indexB); b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); b2Log(" jd.localAxisA.Set(%.15lef, %.15lef);\n", m_localXAxisA.x, m_localXAxisA.y); b2Log(" jd.referenceAngle = %.15lef;\n", m_referenceAngle); b2Log(" jd.enableLimit = bool(%d);\n", m_enableLimit); b2Log(" jd.lowerTranslation = %.15lef;\n", m_lowerTranslation); b2Log(" jd.upperTranslation = %.15lef;\n", m_upperTranslation); b2Log(" jd.enableMotor = bool(%d);\n", m_enableMotor); b2Log(" jd.motorSpeed = %.15lef;\n", m_motorSpeed); b2Log(" jd.maxMotorForce = %.15lef;\n", m_maxMotorForce); b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } qml-box2d/Box2D/Dynamics/b2TimeStep.h0000644000000000000000000000331012241175670014367 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_TIME_STEP_H #define B2_TIME_STEP_H #include /// Profiling data. Times are in milliseconds. struct b2Profile { float32 step; float32 collide; float32 solve; float32 solveInit; float32 solveVelocity; float32 solvePosition; float32 broadphase; float32 solveTOI; }; /// This is an internal structure. struct b2TimeStep { float32 dt; // time step float32 inv_dt; // inverse time step (0 if dt == 0). float32 dtRatio; // dt * inv_dt0 int32 velocityIterations; int32 positionIterations; bool warmStarting; }; /// This is an internal structure. struct b2Position { b2Vec2 c; float32 a; }; /// This is an internal structure. struct b2Velocity { b2Vec2 v; float32 w; }; /// Solver Data struct b2SolverData { b2TimeStep step; b2Position* positions; b2Velocity* velocities; }; #endif qml-box2d/Box2D/Dynamics/b2World.h0000664000000000000000000002515712310072714013733 0ustar /* * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_WORLD_H #define B2_WORLD_H #include #include #include #include #include #include struct b2AABB; struct b2BodyDef; struct b2Color; struct b2JointDef; class b2Body; class b2Draw; class b2Fixture; class b2Joint; /// The world class manages all physics entities, dynamic simulation, /// and asynchronous queries. The world also contains efficient memory /// management facilities. class b2World { public: /// Construct a world object. /// @param gravity the world gravity vector. b2World(const b2Vec2& gravity); /// Destruct the world. All physics entities are destroyed and all heap memory is released. ~b2World(); /// Register a destruction listener. The listener is owned by you and must /// remain in scope. void SetDestructionListener(b2DestructionListener* listener); /// Register a contact filter to provide specific control over collision. /// Otherwise the default filter is used (b2_defaultFilter). The listener is /// owned by you and must remain in scope. void SetContactFilter(b2ContactFilter* filter); /// Register a contact event listener. The listener is owned by you and must /// remain in scope. void SetContactListener(b2ContactListener* listener); /// Register a routine for debug drawing. The debug draw functions are called /// inside with b2World::DrawDebugData method. The debug draw object is owned /// by you and must remain in scope. void SetDebugDraw(b2Draw* debugDraw); /// Create a rigid body given a definition. No reference to the definition /// is retained. /// @warning This function is locked during callbacks. b2Body* CreateBody(const b2BodyDef* def); /// Destroy a rigid body given a definition. No reference to the definition /// is retained. This function is locked during callbacks. /// @warning This automatically deletes all associated shapes and joints. /// @warning This function is locked during callbacks. void DestroyBody(b2Body* body); /// Create a joint to constrain bodies together. No reference to the definition /// is retained. This may cause the connected bodies to cease colliding. /// @warning This function is locked during callbacks. b2Joint* CreateJoint(const b2JointDef* def); /// Destroy a joint. This may cause the connected bodies to begin colliding. /// @warning This function is locked during callbacks. void DestroyJoint(b2Joint* joint); /// Take a time step. This performs collision detection, integration, /// and constraint solution. /// @param timeStep the amount of time to simulate, this should not vary. /// @param velocityIterations for the velocity constraint solver. /// @param positionIterations for the position constraint solver. void Step( float32 timeStep, int32 velocityIterations, int32 positionIterations); /// Manually clear the force buffer on all bodies. By default, forces are cleared automatically /// after each call to Step. The default behavior is modified by calling SetAutoClearForces. /// The purpose of this function is to support sub-stepping. Sub-stepping is often used to maintain /// a fixed sized time step under a variable frame-rate. /// When you perform sub-stepping you will disable auto clearing of forces and instead call /// ClearForces after all sub-steps are complete in one pass of your game loop. /// @see SetAutoClearForces void ClearForces(); /// Call this to draw shapes and other debug draw data. This is intentionally non-const. void DrawDebugData(); /// Query the world for all fixtures that potentially overlap the /// provided AABB. /// @param callback a user implemented callback class. /// @param aabb the query box. void QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const; /// Ray-cast the world for all fixtures in the path of the ray. Your callback /// controls whether you get the closest point, any point, or n-points. /// The ray-cast ignores shapes that contain the starting point. /// @param callback a user implemented callback class. /// @param point1 the ray starting point /// @param point2 the ray ending point void RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const; /// Get the world body list. With the returned body, use b2Body::GetNext to get /// the next body in the world list. A NULL body indicates the end of the list. /// @return the head of the world body list. b2Body* GetBodyList(); const b2Body* GetBodyList() const; /// Get the world joint list. With the returned joint, use b2Joint::GetNext to get /// the next joint in the world list. A NULL joint indicates the end of the list. /// @return the head of the world joint list. b2Joint* GetJointList(); const b2Joint* GetJointList() const; /// Get the world contact list. With the returned contact, use b2Contact::GetNext to get /// the next contact in the world list. A NULL contact indicates the end of the list. /// @return the head of the world contact list. /// @warning contacts are created and destroyed in the middle of a time step. /// Use b2ContactListener to avoid missing contacts. b2Contact* GetContactList(); const b2Contact* GetContactList() const; /// Enable/disable sleep. void SetAllowSleeping(bool flag); bool GetAllowSleeping() const { return m_allowSleep; } /// Enable/disable warm starting. For testing. void SetWarmStarting(bool flag) { m_warmStarting = flag; } bool GetWarmStarting() const { return m_warmStarting; } /// Enable/disable continuous physics. For testing. void SetContinuousPhysics(bool flag) { m_continuousPhysics = flag; } bool GetContinuousPhysics() const { return m_continuousPhysics; } /// Enable/disable single stepped continuous physics. For testing. void SetSubStepping(bool flag) { m_subStepping = flag; } bool GetSubStepping() const { return m_subStepping; } /// Get the number of broad-phase proxies. int32 GetProxyCount() const; /// Get the number of bodies. int32 GetBodyCount() const; /// Get the number of joints. int32 GetJointCount() const; /// Get the number of contacts (each may have 0 or more contact points). int32 GetContactCount() const; /// Get the height of the dynamic tree. int32 GetTreeHeight() const; /// Get the balance of the dynamic tree. int32 GetTreeBalance() const; /// Get the quality metric of the dynamic tree. The smaller the better. /// The minimum is 1. float32 GetTreeQuality() const; /// Change the global gravity vector. void SetGravity(const b2Vec2& gravity); /// Get the global gravity vector. b2Vec2 GetGravity() const; /// Is the world locked (in the middle of a time step). bool IsLocked() const; /// Set flag to control automatic clearing of forces after each time step. void SetAutoClearForces(bool flag); /// Get the flag that controls automatic clearing of forces after each time step. bool GetAutoClearForces() const; /// Shift the world origin. Useful for large worlds. /// The body shift formula is: position -= newOrigin /// @param newOrigin the new origin with respect to the old origin void ShiftOrigin(const b2Vec2& newOrigin); /// Get the contact manager for testing. const b2ContactManager& GetContactManager() const; /// Get the current profile. const b2Profile& GetProfile() const; /// Dump the world into the log file. /// @warning this should be called outside of a time step. void Dump(); private: // m_flags enum { e_newFixture = 0x0001, e_locked = 0x0002, e_clearForces = 0x0004 }; friend class b2Body; friend class b2Fixture; friend class b2ContactManager; friend class b2Controller; void Solve(const b2TimeStep& step); void SolveTOI(const b2TimeStep& step); void DrawJoint(b2Joint* joint); void DrawShape(b2Fixture* shape, const b2Transform& xf, const b2Color& color); b2BlockAllocator m_blockAllocator; b2StackAllocator m_stackAllocator; int32 m_flags; b2ContactManager m_contactManager; b2Body* m_bodyList; b2Joint* m_jointList; int32 m_bodyCount; int32 m_jointCount; b2Vec2 m_gravity; bool m_allowSleep; b2DestructionListener* m_destructionListener; b2Draw* m_debugDraw; // This is used to compute the time step ratio to // support a variable time step. float32 m_inv_dt0; // These are for debugging the solver. bool m_warmStarting; bool m_continuousPhysics; bool m_subStepping; bool m_stepComplete; b2Profile m_profile; }; inline b2Body* b2World::GetBodyList() { return m_bodyList; } inline const b2Body* b2World::GetBodyList() const { return m_bodyList; } inline b2Joint* b2World::GetJointList() { return m_jointList; } inline const b2Joint* b2World::GetJointList() const { return m_jointList; } inline b2Contact* b2World::GetContactList() { return m_contactManager.m_contactList; } inline const b2Contact* b2World::GetContactList() const { return m_contactManager.m_contactList; } inline int32 b2World::GetBodyCount() const { return m_bodyCount; } inline int32 b2World::GetJointCount() const { return m_jointCount; } inline int32 b2World::GetContactCount() const { return m_contactManager.m_contactCount; } inline void b2World::SetGravity(const b2Vec2& gravity) { m_gravity = gravity; } inline b2Vec2 b2World::GetGravity() const { return m_gravity; } inline bool b2World::IsLocked() const { return (m_flags & e_locked) == e_locked; } inline void b2World::SetAutoClearForces(bool flag) { if (flag) { m_flags |= e_clearForces; } else { m_flags &= ~e_clearForces; } } /// Get the flag that controls automatic clearing of forces after each time step. inline bool b2World::GetAutoClearForces() const { return (m_flags & e_clearForces) == e_clearForces; } inline const b2ContactManager& b2World::GetContactManager() const { return m_contactManager; } inline const b2Profile& b2World::GetProfile() const { return m_profile; } #endif qml-box2d/Box2D/Dynamics/b2Body.cpp0000664000000000000000000002724112310072714014070 0ustar /* * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include #include b2Body::b2Body(const b2BodyDef* bd, b2World* world) { b2Assert(bd->position.IsValid()); b2Assert(bd->linearVelocity.IsValid()); b2Assert(b2IsValid(bd->angle)); b2Assert(b2IsValid(bd->angularVelocity)); b2Assert(b2IsValid(bd->angularDamping) && bd->angularDamping >= 0.0f); b2Assert(b2IsValid(bd->linearDamping) && bd->linearDamping >= 0.0f); m_flags = 0; if (bd->bullet) { m_flags |= e_bulletFlag; } if (bd->fixedRotation) { m_flags |= e_fixedRotationFlag; } if (bd->allowSleep) { m_flags |= e_autoSleepFlag; } if (bd->awake) { m_flags |= e_awakeFlag; } if (bd->active) { m_flags |= e_activeFlag; } m_world = world; m_xf.p = bd->position; m_xf.q.Set(bd->angle); m_sweep.localCenter.SetZero(); m_sweep.c0 = m_xf.p; m_sweep.c = m_xf.p; m_sweep.a0 = bd->angle; m_sweep.a = bd->angle; m_sweep.alpha0 = 0.0f; m_jointList = NULL; m_contactList = NULL; m_prev = NULL; m_next = NULL; m_linearVelocity = bd->linearVelocity; m_angularVelocity = bd->angularVelocity; m_linearDamping = bd->linearDamping; m_angularDamping = bd->angularDamping; m_gravityScale = bd->gravityScale; m_force.SetZero(); m_torque = 0.0f; m_sleepTime = 0.0f; m_type = bd->type; if (m_type == b2_dynamicBody) { m_mass = 1.0f; m_invMass = 1.0f; } else { m_mass = 0.0f; m_invMass = 0.0f; } m_I = 0.0f; m_invI = 0.0f; m_userData = bd->userData; m_fixtureList = NULL; m_fixtureCount = 0; } b2Body::~b2Body() { // shapes and joints are destroyed in b2World::Destroy } void b2Body::SetType(b2BodyType type) { b2Assert(m_world->IsLocked() == false); if (m_world->IsLocked() == true) { return; } if (m_type == type) { return; } m_type = type; ResetMassData(); if (m_type == b2_staticBody) { m_linearVelocity.SetZero(); m_angularVelocity = 0.0f; m_sweep.a0 = m_sweep.a; m_sweep.c0 = m_sweep.c; SynchronizeFixtures(); } SetAwake(true); m_force.SetZero(); m_torque = 0.0f; // Delete the attached contacts. b2ContactEdge* ce = m_contactList; while (ce) { b2ContactEdge* ce0 = ce; ce = ce->next; m_world->m_contactManager.Destroy(ce0->contact); } m_contactList = NULL; // Touch the proxies so that new contacts will be created (when appropriate) b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { int32 proxyCount = f->m_proxyCount; for (int32 i = 0; i < proxyCount; ++i) { broadPhase->TouchProxy(f->m_proxies[i].proxyId); } } } b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def) { b2Assert(m_world->IsLocked() == false); if (m_world->IsLocked() == true) { return NULL; } b2BlockAllocator* allocator = &m_world->m_blockAllocator; void* memory = allocator->Allocate(sizeof(b2Fixture)); b2Fixture* fixture = new (memory) b2Fixture; fixture->Create(allocator, this, def); if (m_flags & e_activeFlag) { b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; fixture->CreateProxies(broadPhase, m_xf); } fixture->m_next = m_fixtureList; m_fixtureList = fixture; ++m_fixtureCount; fixture->m_body = this; // Adjust mass properties if needed. if (fixture->m_density > 0.0f) { ResetMassData(); } // Let the world know we have a new fixture. This will cause new contacts // to be created at the beginning of the next time step. m_world->m_flags |= b2World::e_newFixture; return fixture; } b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float32 density) { b2FixtureDef def; def.shape = shape; def.density = density; return CreateFixture(&def); } void b2Body::DestroyFixture(b2Fixture* fixture) { b2Assert(m_world->IsLocked() == false); if (m_world->IsLocked() == true) { return; } b2Assert(fixture->m_body == this); // Remove the fixture from this body's singly linked list. b2Assert(m_fixtureCount > 0); b2Fixture** node = &m_fixtureList; bool found = false; while (*node != NULL) { if (*node == fixture) { *node = fixture->m_next; found = true; break; } node = &(*node)->m_next; } // You tried to remove a shape that is not attached to this body. b2Assert(found); // Destroy any contacts associated with the fixture. b2ContactEdge* edge = m_contactList; while (edge) { b2Contact* c = edge->contact; edge = edge->next; b2Fixture* fixtureA = c->GetFixtureA(); b2Fixture* fixtureB = c->GetFixtureB(); if (fixture == fixtureA || fixture == fixtureB) { // This destroys the contact and removes it from // this body's contact list. m_world->m_contactManager.Destroy(c); } } b2BlockAllocator* allocator = &m_world->m_blockAllocator; if (m_flags & e_activeFlag) { b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; fixture->DestroyProxies(broadPhase); } fixture->Destroy(allocator); fixture->m_body = NULL; fixture->m_next = NULL; fixture->~b2Fixture(); allocator->Free(fixture, sizeof(b2Fixture)); --m_fixtureCount; // Reset the mass data. ResetMassData(); } void b2Body::ResetMassData() { // Compute mass data from shapes. Each shape has its own density. m_mass = 0.0f; m_invMass = 0.0f; m_I = 0.0f; m_invI = 0.0f; m_sweep.localCenter.SetZero(); // Static and kinematic bodies have zero mass. if (m_type == b2_staticBody || m_type == b2_kinematicBody) { m_sweep.c0 = m_xf.p; m_sweep.c = m_xf.p; m_sweep.a0 = m_sweep.a; return; } b2Assert(m_type == b2_dynamicBody); // Accumulate mass over all fixtures. b2Vec2 localCenter = b2Vec2_zero; for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { if (f->m_density == 0.0f) { continue; } b2MassData massData; f->GetMassData(&massData); m_mass += massData.mass; localCenter += massData.mass * massData.center; m_I += massData.I; } // Compute center of mass. if (m_mass > 0.0f) { m_invMass = 1.0f / m_mass; localCenter *= m_invMass; } else { // Force all dynamic bodies to have a positive mass. m_mass = 1.0f; m_invMass = 1.0f; } if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0) { // Center the inertia about the center of mass. m_I -= m_mass * b2Dot(localCenter, localCenter); b2Assert(m_I > 0.0f); m_invI = 1.0f / m_I; } else { m_I = 0.0f; m_invI = 0.0f; } // Move center of mass. b2Vec2 oldCenter = m_sweep.c; m_sweep.localCenter = localCenter; m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter); // Update center of mass velocity. m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter); } void b2Body::SetMassData(const b2MassData* massData) { b2Assert(m_world->IsLocked() == false); if (m_world->IsLocked() == true) { return; } if (m_type != b2_dynamicBody) { return; } m_invMass = 0.0f; m_I = 0.0f; m_invI = 0.0f; m_mass = massData->mass; if (m_mass <= 0.0f) { m_mass = 1.0f; } m_invMass = 1.0f / m_mass; if (massData->I > 0.0f && (m_flags & b2Body::e_fixedRotationFlag) == 0) { m_I = massData->I - m_mass * b2Dot(massData->center, massData->center); b2Assert(m_I > 0.0f); m_invI = 1.0f / m_I; } // Move center of mass. b2Vec2 oldCenter = m_sweep.c; m_sweep.localCenter = massData->center; m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter); // Update center of mass velocity. m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter); } bool b2Body::ShouldCollide(const b2Body* other) const { // At least one body should be dynamic. if (m_type != b2_dynamicBody && other->m_type != b2_dynamicBody) { return false; } // Does a joint prevent collision? for (b2JointEdge* jn = m_jointList; jn; jn = jn->next) { if (jn->other == other) { if (jn->joint->m_collideConnected == false) { return false; } } } return true; } void b2Body::SetTransform(const b2Vec2& position, float32 angle) { b2Assert(m_world->IsLocked() == false); if (m_world->IsLocked() == true) { return; } m_xf.q.Set(angle); m_xf.p = position; m_sweep.c = b2Mul(m_xf, m_sweep.localCenter); m_sweep.a = angle; m_sweep.c0 = m_sweep.c; m_sweep.a0 = angle; b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { f->Synchronize(broadPhase, m_xf, m_xf); } } void b2Body::SynchronizeFixtures() { b2Transform xf1; xf1.q.Set(m_sweep.a0); xf1.p = m_sweep.c0 - b2Mul(xf1.q, m_sweep.localCenter); b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { f->Synchronize(broadPhase, xf1, m_xf); } } void b2Body::SetActive(bool flag) { b2Assert(m_world->IsLocked() == false); if (flag == IsActive()) { return; } if (flag) { m_flags |= e_activeFlag; // Create all proxies. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { f->CreateProxies(broadPhase, m_xf); } // Contacts are created the next time step. } else { m_flags &= ~e_activeFlag; // Destroy all proxies. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { f->DestroyProxies(broadPhase); } // Destroy the attached contacts. b2ContactEdge* ce = m_contactList; while (ce) { b2ContactEdge* ce0 = ce; ce = ce->next; m_world->m_contactManager.Destroy(ce0->contact); } m_contactList = NULL; } } void b2Body::SetFixedRotation(bool flag) { bool status = (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag; if (status == flag) { return; } if (flag) { m_flags |= e_fixedRotationFlag; } else { m_flags &= ~e_fixedRotationFlag; } m_angularVelocity = 0.0f; ResetMassData(); } void b2Body::Dump() { int32 bodyIndex = m_islandIndex; b2Log("{\n"); b2Log(" b2BodyDef bd;\n"); b2Log(" bd.type = b2BodyType(%d);\n", m_type); b2Log(" bd.position.Set(%.15lef, %.15lef);\n", m_xf.p.x, m_xf.p.y); b2Log(" bd.angle = %.15lef;\n", m_sweep.a); b2Log(" bd.linearVelocity.Set(%.15lef, %.15lef);\n", m_linearVelocity.x, m_linearVelocity.y); b2Log(" bd.angularVelocity = %.15lef;\n", m_angularVelocity); b2Log(" bd.linearDamping = %.15lef;\n", m_linearDamping); b2Log(" bd.angularDamping = %.15lef;\n", m_angularDamping); b2Log(" bd.allowSleep = bool(%d);\n", m_flags & e_autoSleepFlag); b2Log(" bd.awake = bool(%d);\n", m_flags & e_awakeFlag); b2Log(" bd.fixedRotation = bool(%d);\n", m_flags & e_fixedRotationFlag); b2Log(" bd.bullet = bool(%d);\n", m_flags & e_bulletFlag); b2Log(" bd.active = bool(%d);\n", m_flags & e_activeFlag); b2Log(" bd.gravityScale = %.15lef;\n", m_gravityScale); b2Log(" bodies[%d] = m_world->CreateBody(&bd);\n", m_islandIndex); b2Log("\n"); for (b2Fixture* f = m_fixtureList; f; f = f->m_next) { b2Log(" {\n"); f->Dump(bodyIndex); b2Log(" }\n"); } b2Log("}\n"); } qml-box2d/Box2D/Box2D.h0000664000000000000000000000461412310072714011562 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef BOX2D_H #define BOX2D_H /** \mainpage Box2D API Documentation \section intro_sec Getting Started For documentation please see http://box2d.org/documentation.html For discussion please visit http://box2d.org/forum */ // These include files constitute the main Box2D API #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif qml-box2d/Box2D/Common/0000755000000000000000000000000012310072714011714 5ustar qml-box2d/Box2D/Common/b2GrowableStack.h0000664000000000000000000000361712310072714015052 0ustar /* * Copyright (c) 2010 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_GROWABLE_STACK_H #define B2_GROWABLE_STACK_H #include #include /// This is a growable LIFO stack with an initial capacity of N. /// If the stack size exceeds the initial capacity, the heap is used /// to increase the size of the stack. template class b2GrowableStack { public: b2GrowableStack() { m_stack = m_array; m_count = 0; m_capacity = N; } ~b2GrowableStack() { if (m_stack != m_array) { b2Free(m_stack); m_stack = NULL; } } void Push(const T& element) { if (m_count == m_capacity) { T* old = m_stack; m_capacity *= 2; m_stack = (T*)b2Alloc(m_capacity * sizeof(T)); memcpy(m_stack, old, m_count * sizeof(T)); if (old != m_array) { b2Free(old); } } m_stack[m_count] = element; ++m_count; } T Pop() { b2Assert(m_count > 0); --m_count; return m_stack[m_count]; } int32 GetCount() { return m_count; } private: T* m_stack; T m_array[N]; int32 m_count; int32 m_capacity; }; #endif qml-box2d/Box2D/Common/b2Settings.h0000664000000000000000000001222112310072714014111 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_SETTINGS_H #define B2_SETTINGS_H #include #include #include #define B2_NOT_USED(x) ((void)(x)) #define b2Assert(A) assert(A) typedef signed char int8; typedef signed short int16; typedef signed int int32; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef float float32; typedef double float64; #define b2_maxFloat FLT_MAX #define b2_epsilon FLT_EPSILON #define b2_pi 3.14159265359f /// @file /// Global tuning constants based on meters-kilograms-seconds (MKS) units. /// // Collision /// The maximum number of contact points between two convex shapes. Do /// not change this value. #define b2_maxManifoldPoints 2 /// The maximum number of vertices on a convex polygon. You cannot increase /// this too much because b2BlockAllocator has a maximum object size. #define b2_maxPolygonVertices 8 /// This is used to fatten AABBs in the dynamic tree. This allows proxies /// to move by a small amount without triggering a tree adjustment. /// This is in meters. #define b2_aabbExtension 0.1f /// This is used to fatten AABBs in the dynamic tree. This is used to predict /// the future position based on the current displacement. /// This is a dimensionless multiplier. #define b2_aabbMultiplier 2.0f /// A small length used as a collision and constraint tolerance. Usually it is /// chosen to be numerically significant, but visually insignificant. #define b2_linearSlop 0.005f /// A small angle used as a collision and constraint tolerance. Usually it is /// chosen to be numerically significant, but visually insignificant. #define b2_angularSlop (2.0f / 180.0f * b2_pi) /// The radius of the polygon/edge shape skin. This should not be modified. Making /// this smaller means polygons will have an insufficient buffer for continuous collision. /// Making it larger may create artifacts for vertex collision. #define b2_polygonRadius (2.0f * b2_linearSlop) /// Maximum number of sub-steps per contact in continuous physics simulation. #define b2_maxSubSteps 8 // Dynamics /// Maximum number of contacts to be handled to solve a TOI impact. #define b2_maxTOIContacts 32 /// A velocity threshold for elastic collisions. Any collision with a relative linear /// velocity below this threshold will be treated as inelastic. #define b2_velocityThreshold 1.0f /// The maximum linear position correction used when solving constraints. This helps to /// prevent overshoot. #define b2_maxLinearCorrection 0.2f /// The maximum angular position correction used when solving constraints. This helps to /// prevent overshoot. #define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi) /// The maximum linear velocity of a body. This limit is very large and is used /// to prevent numerical problems. You shouldn't need to adjust this. #define b2_maxTranslation 2.0f #define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation) /// The maximum angular velocity of a body. This limit is very large and is used /// to prevent numerical problems. You shouldn't need to adjust this. #define b2_maxRotation (0.5f * b2_pi) #define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation) /// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so /// that overlap is removed in one time step. However using values close to 1 often lead /// to overshoot. #define b2_baumgarte 0.2f #define b2_toiBaugarte 0.75f // Sleep /// The time that a body must be still before it will go to sleep. #define b2_timeToSleep 0.5f /// A body cannot sleep if its linear velocity is above this tolerance. #define b2_linearSleepTolerance 0.01f /// A body cannot sleep if its angular velocity is above this tolerance. #define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi) // Memory Allocation /// Implement this function to use your own memory allocator. void* b2Alloc(int32 size); /// If you implement b2Alloc, you should also implement this function. void b2Free(void* mem); /// Logging function. void b2Log(const char* string, ...); /// Version numbering scheme. /// See http://en.wikipedia.org/wiki/Software_versioning struct b2Version { int32 major; ///< significant changes int32 minor; ///< incremental changes int32 revision; ///< bug fixes }; /// Current version. extern b2Version b2_version; #endif qml-box2d/Box2D/Common/b2StackAllocator.cpp0000644000000000000000000000400112241175670015555 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include b2StackAllocator::b2StackAllocator() { m_index = 0; m_allocation = 0; m_maxAllocation = 0; m_entryCount = 0; } b2StackAllocator::~b2StackAllocator() { b2Assert(m_index == 0); b2Assert(m_entryCount == 0); } void* b2StackAllocator::Allocate(int32 size) { b2Assert(m_entryCount < b2_maxStackEntries); b2StackEntry* entry = m_entries + m_entryCount; entry->size = size; if (m_index + size > b2_stackSize) { entry->data = (char*)b2Alloc(size); entry->usedMalloc = true; } else { entry->data = m_data + m_index; entry->usedMalloc = false; m_index += size; } m_allocation += size; m_maxAllocation = b2Max(m_maxAllocation, m_allocation); ++m_entryCount; return entry->data; } void b2StackAllocator::Free(void* p) { b2Assert(m_entryCount > 0); b2StackEntry* entry = m_entries + m_entryCount - 1; b2Assert(p == entry->data); if (entry->usedMalloc) { b2Free(p); } else { m_index -= entry->size; } m_allocation -= entry->size; --m_entryCount; p = NULL; } int32 b2StackAllocator::GetMaxAllocation() const { return m_maxAllocation; } qml-box2d/Box2D/Common/b2Draw.h0000664000000000000000000000535212310072714013215 0ustar /* * Copyright (c) 2011 Erin Catto http://box2d.org * * 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. */ #ifndef B2_DRAW_H #define B2_DRAW_H #include /// Color for debug drawing. Each value has the range [0,1]. struct b2Color { b2Color() {} b2Color(float32 r, float32 g, float32 b) : r(r), g(g), b(b) {} void Set(float32 ri, float32 gi, float32 bi) { r = ri; g = gi; b = bi; } float32 r, g, b; }; /// Implement and register this class with a b2World to provide debug drawing of physics /// entities in your game. class b2Draw { public: b2Draw(); virtual ~b2Draw() {} enum { e_shapeBit = 0x0001, ///< draw shapes e_jointBit = 0x0002, ///< draw joint connections e_aabbBit = 0x0004, ///< draw axis aligned bounding boxes e_pairBit = 0x0008, ///< draw broad-phase pairs e_centerOfMassBit = 0x0010 ///< draw center of mass frame }; /// Set the drawing flags. void SetFlags(uint32 flags); /// Get the drawing flags. uint32 GetFlags() const; /// Append flags to the current flags. void AppendFlags(uint32 flags); /// Clear flags from the current flags. void ClearFlags(uint32 flags); /// Draw a closed polygon provided in CCW order. virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0; /// Draw a solid closed polygon provided in CCW order. virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0; /// Draw a circle. virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) = 0; /// Draw a solid circle. virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) = 0; /// Draw a line segment. virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0; /// Draw a transform. Choose your own length scale. /// @param xf a transform. virtual void DrawTransform(const b2Transform& xf) = 0; protected: uint32 m_drawFlags; }; #endif qml-box2d/Box2D/Common/b2StackAllocator.h0000644000000000000000000000321012241175670015223 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_STACK_ALLOCATOR_H #define B2_STACK_ALLOCATOR_H #include const int32 b2_stackSize = 100 * 1024; // 100k const int32 b2_maxStackEntries = 32; struct b2StackEntry { char* data; int32 size; bool usedMalloc; }; // This is a stack allocator used for fast per step allocations. // You must nest allocate/free pairs. The code will assert // if you try to interleave multiple allocate/free pairs. class b2StackAllocator { public: b2StackAllocator(); ~b2StackAllocator(); void* Allocate(int32 size); void Free(void* p); int32 GetMaxAllocation() const; private: char m_data[b2_stackSize]; int32 m_index; int32 m_allocation; int32 m_maxAllocation; b2StackEntry m_entries[b2_maxStackEntries]; int32 m_entryCount; }; #endif qml-box2d/Box2D/Common/b2Timer.h0000664000000000000000000000265212310072714013400 0ustar /* * Copyright (c) 2011 Erin Catto http://box2d.org * * 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. */ #ifndef B2_TIMER_H #define B2_TIMER_H #include /// Timer for profiling. This has platform specific code and may /// not work on every platform. class b2Timer { public: /// Constructor b2Timer(); /// Reset the timer. void Reset(); /// Get the time since construction or the last reset. float32 GetMilliseconds() const; private: #if defined(_WIN32) float64 m_start; static float64 s_invFrequency; #elif defined(__linux__) || defined (__APPLE__) unsigned long m_start_sec; unsigned long m_start_usec; #endif }; #endif qml-box2d/Box2D/Common/b2BlockAllocator.cpp0000664000000000000000000001137512310072714015550 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include int32 b2BlockAllocator::s_blockSizes[b2_blockSizes] = { 16, // 0 32, // 1 64, // 2 96, // 3 128, // 4 160, // 5 192, // 6 224, // 7 256, // 8 320, // 9 384, // 10 448, // 11 512, // 12 640, // 13 }; uint8 b2BlockAllocator::s_blockSizeLookup[b2_maxBlockSize + 1]; bool b2BlockAllocator::s_blockSizeLookupInitialized; struct b2Chunk { int32 blockSize; b2Block* blocks; }; struct b2Block { b2Block* next; }; b2BlockAllocator::b2BlockAllocator() { b2Assert(b2_blockSizes < UCHAR_MAX); m_chunkSpace = b2_chunkArrayIncrement; m_chunkCount = 0; m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk)); memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk)); memset(m_freeLists, 0, sizeof(m_freeLists)); if (s_blockSizeLookupInitialized == false) { int32 j = 0; for (int32 i = 1; i <= b2_maxBlockSize; ++i) { b2Assert(j < b2_blockSizes); if (i <= s_blockSizes[j]) { s_blockSizeLookup[i] = (uint8)j; } else { ++j; s_blockSizeLookup[i] = (uint8)j; } } s_blockSizeLookupInitialized = true; } } b2BlockAllocator::~b2BlockAllocator() { for (int32 i = 0; i < m_chunkCount; ++i) { b2Free(m_chunks[i].blocks); } b2Free(m_chunks); } void* b2BlockAllocator::Allocate(int32 size) { if (size == 0) return NULL; b2Assert(0 < size); if (size > b2_maxBlockSize) { return b2Alloc(size); } int32 index = s_blockSizeLookup[size]; b2Assert(0 <= index && index < b2_blockSizes); if (m_freeLists[index]) { b2Block* block = m_freeLists[index]; m_freeLists[index] = block->next; return block; } else { if (m_chunkCount == m_chunkSpace) { b2Chunk* oldChunks = m_chunks; m_chunkSpace += b2_chunkArrayIncrement; m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk)); memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk)); memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk)); b2Free(oldChunks); } b2Chunk* chunk = m_chunks + m_chunkCount; chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize); #if defined(_DEBUG) memset(chunk->blocks, 0xcd, b2_chunkSize); #endif int32 blockSize = s_blockSizes[index]; chunk->blockSize = blockSize; int32 blockCount = b2_chunkSize / blockSize; b2Assert(blockCount * blockSize <= b2_chunkSize); for (int32 i = 0; i < blockCount - 1; ++i) { b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i); b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1)); block->next = next; } b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1)); last->next = NULL; m_freeLists[index] = chunk->blocks->next; ++m_chunkCount; return chunk->blocks; } } void b2BlockAllocator::Free(void* p, int32 size) { if (size == 0) { return; } b2Assert(0 < size); if (size > b2_maxBlockSize) { b2Free(p); return; } int32 index = s_blockSizeLookup[size]; b2Assert(0 <= index && index < b2_blockSizes); #ifdef _DEBUG // Verify the memory address and size is valid. int32 blockSize = s_blockSizes[index]; bool found = false; for (int32 i = 0; i < m_chunkCount; ++i) { b2Chunk* chunk = m_chunks + i; if (chunk->blockSize != blockSize) { b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks || (int8*)chunk->blocks + b2_chunkSize <= (int8*)p); } else { if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize) { found = true; } } } b2Assert(found); memset(p, 0xfd, blockSize); #endif b2Block* block = (b2Block*)p; block->next = m_freeLists[index]; m_freeLists[index] = block; } void b2BlockAllocator::Clear() { for (int32 i = 0; i < m_chunkCount; ++i) { b2Free(m_chunks[i].blocks); } m_chunkCount = 0; memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk)); memset(m_freeLists, 0, sizeof(m_freeLists)); } qml-box2d/Box2D/Common/b2Timer.cpp0000664000000000000000000000436612310072714013737 0ustar /* * Copyright (c) 2011 Erin Catto http://box2d.org * * 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. */ #include #if defined(_WIN32) float64 b2Timer::s_invFrequency = 0.0f; #define WIN32_LEAN_AND_MEAN #include b2Timer::b2Timer() { LARGE_INTEGER largeInteger; if (s_invFrequency == 0.0f) { QueryPerformanceFrequency(&largeInteger); s_invFrequency = float64(largeInteger.QuadPart); if (s_invFrequency > 0.0f) { s_invFrequency = 1000.0f / s_invFrequency; } } QueryPerformanceCounter(&largeInteger); m_start = float64(largeInteger.QuadPart); } void b2Timer::Reset() { LARGE_INTEGER largeInteger; QueryPerformanceCounter(&largeInteger); m_start = float64(largeInteger.QuadPart); } float32 b2Timer::GetMilliseconds() const { LARGE_INTEGER largeInteger; QueryPerformanceCounter(&largeInteger); float64 count = float64(largeInteger.QuadPart); float32 ms = float32(s_invFrequency * (count - m_start)); return ms; } #elif defined(__linux__) || defined (__APPLE__) #include b2Timer::b2Timer() { Reset(); } void b2Timer::Reset() { timeval t; gettimeofday(&t, 0); m_start_sec = t.tv_sec; m_start_usec = t.tv_usec; } float32 b2Timer::GetMilliseconds() const { timeval t; gettimeofday(&t, 0); return 1000.0f * (t.tv_sec - m_start_sec) + 0.001f * (t.tv_usec - m_start_usec); } #else b2Timer::b2Timer() { } void b2Timer::Reset() { } float32 b2Timer::GetMilliseconds() const { return 0.0f; } #endif qml-box2d/Box2D/Common/b2BlockAllocator.h0000644000000000000000000000364412241175670015223 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_BLOCK_ALLOCATOR_H #define B2_BLOCK_ALLOCATOR_H #include const int32 b2_chunkSize = 16 * 1024; const int32 b2_maxBlockSize = 640; const int32 b2_blockSizes = 14; const int32 b2_chunkArrayIncrement = 128; struct b2Block; struct b2Chunk; /// This is a small object allocator used for allocating small /// objects that persist for more than one time step. /// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp class b2BlockAllocator { public: b2BlockAllocator(); ~b2BlockAllocator(); /// Allocate memory. This will use b2Alloc if the size is larger than b2_maxBlockSize. void* Allocate(int32 size); /// Free memory. This will use b2Free if the size is larger than b2_maxBlockSize. void Free(void* p, int32 size); void Clear(); private: b2Chunk* m_chunks; int32 m_chunkCount; int32 m_chunkSpace; b2Block* m_freeLists[b2_blockSizes]; static int32 s_blockSizes[b2_blockSizes]; static uint8 s_blockSizeLookup[b2_maxBlockSize + 1]; static bool s_blockSizeLookupInitialized; }; #endif qml-box2d/Box2D/Common/b2Draw.cpp0000644000000000000000000000230112241175670013545 0ustar /* * Copyright (c) 2011 Erin Catto http://box2d.org * * 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. */ #include b2Draw::b2Draw() { m_drawFlags = 0; } void b2Draw::SetFlags(uint32 flags) { m_drawFlags = flags; } uint32 b2Draw::GetFlags() const { return m_drawFlags; } void b2Draw::AppendFlags(uint32 flags) { m_drawFlags |= flags; } void b2Draw::ClearFlags(uint32 flags) { m_drawFlags &= ~flags; } qml-box2d/Box2D/Common/b2Math.cpp0000644000000000000000000000524112241175670013547 0ustar /* * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org * * 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. */ #include const b2Vec2 b2Vec2_zero(0.0f, 0.0f); /// Solve A * x = b, where b is a column vector. This is more efficient /// than computing the inverse in one-shot cases. b2Vec3 b2Mat33::Solve33(const b2Vec3& b) const { float32 det = b2Dot(ex, b2Cross(ey, ez)); if (det != 0.0f) { det = 1.0f / det; } b2Vec3 x; x.x = det * b2Dot(b, b2Cross(ey, ez)); x.y = det * b2Dot(ex, b2Cross(b, ez)); x.z = det * b2Dot(ex, b2Cross(ey, b)); return x; } /// Solve A * x = b, where b is a column vector. This is more efficient /// than computing the inverse in one-shot cases. b2Vec2 b2Mat33::Solve22(const b2Vec2& b) const { float32 a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y; float32 det = a11 * a22 - a12 * a21; if (det != 0.0f) { det = 1.0f / det; } b2Vec2 x; x.x = det * (a22 * b.x - a12 * b.y); x.y = det * (a11 * b.y - a21 * b.x); return x; } /// void b2Mat33::GetInverse22(b2Mat33* M) const { float32 a = ex.x, b = ey.x, c = ex.y, d = ey.y; float32 det = a * d - b * c; if (det != 0.0f) { det = 1.0f / det; } M->ex.x = det * d; M->ey.x = -det * b; M->ex.z = 0.0f; M->ex.y = -det * c; M->ey.y = det * a; M->ey.z = 0.0f; M->ez.x = 0.0f; M->ez.y = 0.0f; M->ez.z = 0.0f; } /// Returns the zero matrix if singular. void b2Mat33::GetSymInverse33(b2Mat33* M) const { float32 det = b2Dot(ex, b2Cross(ey, ez)); if (det != 0.0f) { det = 1.0f / det; } float32 a11 = ex.x, a12 = ey.x, a13 = ez.x; float32 a22 = ey.y, a23 = ez.y; float32 a33 = ez.z; M->ex.x = det * (a22 * a33 - a23 * a23); M->ex.y = det * (a13 * a23 - a12 * a33); M->ex.z = det * (a12 * a23 - a13 * a22); M->ey.x = M->ex.y; M->ey.y = det * (a11 * a33 - a13 * a13); M->ey.z = det * (a13 * a12 - a11 * a23); M->ez.x = M->ex.z; M->ez.y = M->ey.z; M->ez.z = det * (a11 * a22 - a12 * a12); } qml-box2d/Box2D/Common/b2Settings.cpp0000664000000000000000000000251512310072714014451 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #include #include #include #include b2Version b2_version = {2, 3, 0}; // Memory allocators. Modify these to use your own allocator. void* b2Alloc(int32 size) { return malloc(size); } void b2Free(void* mem) { free(mem); } // You can modify this to use your logging facility. void b2Log(const char* string, ...) { va_list args; va_start(args, string); vprintf(string, args); va_end(args); } qml-box2d/Box2D/Common/b2Math.h0000664000000000000000000004003512310072714013206 0ustar /* * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org * * 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. */ #ifndef B2_MATH_H #define B2_MATH_H #include #include /// This function is used to ensure that a floating point number is not a NaN or infinity. inline bool b2IsValid(float32 x) { int32 ix = *reinterpret_cast(&x); return (ix & 0x7f800000) != 0x7f800000; } /// This is a approximate yet fast inverse square-root. inline float32 b2InvSqrt(float32 x) { union { float32 x; int32 i; } convert; convert.x = x; float32 xhalf = 0.5f * x; convert.i = 0x5f3759df - (convert.i >> 1); x = convert.x; x = x * (1.5f - xhalf * x * x); return x; } #define b2Sqrt(x) sqrtf(x) #define b2Atan2(y, x) atan2f(y, x) /// A 2D column vector. struct b2Vec2 { /// Default constructor does nothing (for performance). b2Vec2() {} /// Construct using coordinates. b2Vec2(float32 x, float32 y) : x(x), y(y) {} /// Set this vector to all zeros. void SetZero() { x = 0.0f; y = 0.0f; } /// Set this vector to some specified coordinates. void Set(float32 x_, float32 y_) { x = x_; y = y_; } /// Negate this vector. b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; } /// Read from and indexed element. float32 operator () (int32 i) const { return (&x)[i]; } /// Write to an indexed element. float32& operator () (int32 i) { return (&x)[i]; } /// Add a vector to this vector. void operator += (const b2Vec2& v) { x += v.x; y += v.y; } /// Subtract a vector from this vector. void operator -= (const b2Vec2& v) { x -= v.x; y -= v.y; } /// Multiply this vector by a scalar. void operator *= (float32 a) { x *= a; y *= a; } /// Get the length of this vector (the norm). float32 Length() const { return b2Sqrt(x * x + y * y); } /// Get the length squared. For performance, use this instead of /// b2Vec2::Length (if possible). float32 LengthSquared() const { return x * x + y * y; } /// Convert this vector into a unit vector. Returns the length. float32 Normalize() { float32 length = Length(); if (length < b2_epsilon) { return 0.0f; } float32 invLength = 1.0f / length; x *= invLength; y *= invLength; return length; } /// Does this vector contain finite coordinates? bool IsValid() const { return b2IsValid(x) && b2IsValid(y); } /// Get the skew vector such that dot(skew_vec, other) == cross(vec, other) b2Vec2 Skew() const { return b2Vec2(-y, x); } float32 x, y; }; /// A 2D column vector with 3 elements. struct b2Vec3 { /// Default constructor does nothing (for performance). b2Vec3() {} /// Construct using coordinates. b2Vec3(float32 x, float32 y, float32 z) : x(x), y(y), z(z) {} /// Set this vector to all zeros. void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; } /// Set this vector to some specified coordinates. void Set(float32 x_, float32 y_, float32 z_) { x = x_; y = y_; z = z_; } /// Negate this vector. b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; } /// Add a vector to this vector. void operator += (const b2Vec3& v) { x += v.x; y += v.y; z += v.z; } /// Subtract a vector from this vector. void operator -= (const b2Vec3& v) { x -= v.x; y -= v.y; z -= v.z; } /// Multiply this vector by a scalar. void operator *= (float32 s) { x *= s; y *= s; z *= s; } float32 x, y, z; }; /// A 2-by-2 matrix. Stored in column-major order. struct b2Mat22 { /// The default constructor does nothing (for performance). b2Mat22() {} /// Construct this matrix using columns. b2Mat22(const b2Vec2& c1, const b2Vec2& c2) { ex = c1; ey = c2; } /// Construct this matrix using scalars. b2Mat22(float32 a11, float32 a12, float32 a21, float32 a22) { ex.x = a11; ex.y = a21; ey.x = a12; ey.y = a22; } /// Initialize this matrix using columns. void Set(const b2Vec2& c1, const b2Vec2& c2) { ex = c1; ey = c2; } /// Set this to the identity matrix. void SetIdentity() { ex.x = 1.0f; ey.x = 0.0f; ex.y = 0.0f; ey.y = 1.0f; } /// Set this matrix to all zeros. void SetZero() { ex.x = 0.0f; ey.x = 0.0f; ex.y = 0.0f; ey.y = 0.0f; } b2Mat22 GetInverse() const { float32 a = ex.x, b = ey.x, c = ex.y, d = ey.y; b2Mat22 B; float32 det = a * d - b * c; if (det != 0.0f) { det = 1.0f / det; } B.ex.x = det * d; B.ey.x = -det * b; B.ex.y = -det * c; B.ey.y = det * a; return B; } /// Solve A * x = b, where b is a column vector. This is more efficient /// than computing the inverse in one-shot cases. b2Vec2 Solve(const b2Vec2& b) const { float32 a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y; float32 det = a11 * a22 - a12 * a21; if (det != 0.0f) { det = 1.0f / det; } b2Vec2 x; x.x = det * (a22 * b.x - a12 * b.y); x.y = det * (a11 * b.y - a21 * b.x); return x; } b2Vec2 ex, ey; }; /// A 3-by-3 matrix. Stored in column-major order. struct b2Mat33 { /// The default constructor does nothing (for performance). b2Mat33() {} /// Construct this matrix using columns. b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3) { ex = c1; ey = c2; ez = c3; } /// Set this matrix to all zeros. void SetZero() { ex.SetZero(); ey.SetZero(); ez.SetZero(); } /// Solve A * x = b, where b is a column vector. This is more efficient /// than computing the inverse in one-shot cases. b2Vec3 Solve33(const b2Vec3& b) const; /// Solve A * x = b, where b is a column vector. This is more efficient /// than computing the inverse in one-shot cases. Solve only the upper /// 2-by-2 matrix equation. b2Vec2 Solve22(const b2Vec2& b) const; /// Get the inverse of this matrix as a 2-by-2. /// Returns the zero matrix if singular. void GetInverse22(b2Mat33* M) const; /// Get the symmetric inverse of this matrix as a 3-by-3. /// Returns the zero matrix if singular. void GetSymInverse33(b2Mat33* M) const; b2Vec3 ex, ey, ez; }; /// Rotation struct b2Rot { b2Rot() {} /// Initialize from an angle in radians explicit b2Rot(float32 angle) { /// TODO_ERIN optimize s = sinf(angle); c = cosf(angle); } /// Set using an angle in radians. void Set(float32 angle) { /// TODO_ERIN optimize s = sinf(angle); c = cosf(angle); } /// Set to the identity rotation void SetIdentity() { s = 0.0f; c = 1.0f; } /// Get the angle in radians float32 GetAngle() const { return b2Atan2(s, c); } /// Get the x-axis b2Vec2 GetXAxis() const { return b2Vec2(c, s); } /// Get the u-axis b2Vec2 GetYAxis() const { return b2Vec2(-s, c); } /// Sine and cosine float32 s, c; }; /// A transform contains translation and rotation. It is used to represent /// the position and orientation of rigid frames. struct b2Transform { /// The default constructor does nothing. b2Transform() {} /// Initialize using a position vector and a rotation. b2Transform(const b2Vec2& position, const b2Rot& rotation) : p(position), q(rotation) {} /// Set this to the identity transform. void SetIdentity() { p.SetZero(); q.SetIdentity(); } /// Set this based on the position and angle. void Set(const b2Vec2& position, float32 angle) { p = position; q.Set(angle); } b2Vec2 p; b2Rot q; }; /// This describes the motion of a body/shape for TOI computation. /// Shapes are defined with respect to the body origin, which may /// no coincide with the center of mass. However, to support dynamics /// we must interpolate the center of mass position. struct b2Sweep { /// Get the interpolated transform at a specific time. /// @param beta is a factor in [0,1], where 0 indicates alpha0. void GetTransform(b2Transform* xfb, float32 beta) const; /// Advance the sweep forward, yielding a new initial state. /// @param alpha the new initial time. void Advance(float32 alpha); /// Normalize the angles. void Normalize(); b2Vec2 localCenter; ///< local center of mass position b2Vec2 c0, c; ///< center world positions float32 a0, a; ///< world angles /// Fraction of the current time step in the range [0,1] /// c0 and a0 are the positions at alpha0. float32 alpha0; }; /// Useful constant extern const b2Vec2 b2Vec2_zero; /// Perform the dot product on two vectors. inline float32 b2Dot(const b2Vec2& a, const b2Vec2& b) { return a.x * b.x + a.y * b.y; } /// Perform the cross product on two vectors. In 2D this produces a scalar. inline float32 b2Cross(const b2Vec2& a, const b2Vec2& b) { return a.x * b.y - a.y * b.x; } /// Perform the cross product on a vector and a scalar. In 2D this produces /// a vector. inline b2Vec2 b2Cross(const b2Vec2& a, float32 s) { return b2Vec2(s * a.y, -s * a.x); } /// Perform the cross product on a scalar and a vector. In 2D this produces /// a vector. inline b2Vec2 b2Cross(float32 s, const b2Vec2& a) { return b2Vec2(-s * a.y, s * a.x); } /// Multiply a matrix times a vector. If a rotation matrix is provided, /// then this transforms the vector from one frame to another. inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v) { return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y); } /// Multiply a matrix transpose times a vector. If a rotation matrix is provided, /// then this transforms the vector from one frame to another (inverse transform). inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v) { return b2Vec2(b2Dot(v, A.ex), b2Dot(v, A.ey)); } /// Add two vectors component-wise. inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b) { return b2Vec2(a.x + b.x, a.y + b.y); } /// Subtract two vectors component-wise. inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b) { return b2Vec2(a.x - b.x, a.y - b.y); } inline b2Vec2 operator * (float32 s, const b2Vec2& a) { return b2Vec2(s * a.x, s * a.y); } inline bool operator == (const b2Vec2& a, const b2Vec2& b) { return a.x == b.x && a.y == b.y; } inline float32 b2Distance(const b2Vec2& a, const b2Vec2& b) { b2Vec2 c = a - b; return c.Length(); } inline float32 b2DistanceSquared(const b2Vec2& a, const b2Vec2& b) { b2Vec2 c = a - b; return b2Dot(c, c); } inline b2Vec3 operator * (float32 s, const b2Vec3& a) { return b2Vec3(s * a.x, s * a.y, s * a.z); } /// Add two vectors component-wise. inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b) { return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z); } /// Subtract two vectors component-wise. inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b) { return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z); } /// Perform the dot product on two vectors. inline float32 b2Dot(const b2Vec3& a, const b2Vec3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; } /// Perform the cross product on two vectors. inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b) { return b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); } inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B) { return b2Mat22(A.ex + B.ex, A.ey + B.ey); } // A * B inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B) { return b2Mat22(b2Mul(A, B.ex), b2Mul(A, B.ey)); } // A^T * B inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B) { b2Vec2 c1(b2Dot(A.ex, B.ex), b2Dot(A.ey, B.ex)); b2Vec2 c2(b2Dot(A.ex, B.ey), b2Dot(A.ey, B.ey)); return b2Mat22(c1, c2); } /// Multiply a matrix times a vector. inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v) { return v.x * A.ex + v.y * A.ey + v.z * A.ez; } /// Multiply a matrix times a vector. inline b2Vec2 b2Mul22(const b2Mat33& A, const b2Vec2& v) { return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y); } /// Multiply two rotations: q * r inline b2Rot b2Mul(const b2Rot& q, const b2Rot& r) { // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc] // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc] // s = qs * rc + qc * rs // c = qc * rc - qs * rs b2Rot qr; qr.s = q.s * r.c + q.c * r.s; qr.c = q.c * r.c - q.s * r.s; return qr; } /// Transpose multiply two rotations: qT * r inline b2Rot b2MulT(const b2Rot& q, const b2Rot& r) { // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc] // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc] // s = qc * rs - qs * rc // c = qc * rc + qs * rs b2Rot qr; qr.s = q.c * r.s - q.s * r.c; qr.c = q.c * r.c + q.s * r.s; return qr; } /// Rotate a vector inline b2Vec2 b2Mul(const b2Rot& q, const b2Vec2& v) { return b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y); } /// Inverse rotate a vector inline b2Vec2 b2MulT(const b2Rot& q, const b2Vec2& v) { return b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y); } inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v) { float32 x = (T.q.c * v.x - T.q.s * v.y) + T.p.x; float32 y = (T.q.s * v.x + T.q.c * v.y) + T.p.y; return b2Vec2(x, y); } inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v) { float32 px = v.x - T.p.x; float32 py = v.y - T.p.y; float32 x = (T.q.c * px + T.q.s * py); float32 y = (-T.q.s * px + T.q.c * py); return b2Vec2(x, y); } // v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p // = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p inline b2Transform b2Mul(const b2Transform& A, const b2Transform& B) { b2Transform C; C.q = b2Mul(A.q, B.q); C.p = b2Mul(A.q, B.p) + A.p; return C; } // v2 = A.q' * (B.q * v1 + B.p - A.p) // = A.q' * B.q * v1 + A.q' * (B.p - A.p) inline b2Transform b2MulT(const b2Transform& A, const b2Transform& B) { b2Transform C; C.q = b2MulT(A.q, B.q); C.p = b2MulT(A.q, B.p - A.p); return C; } template inline T b2Abs(T a) { return a > T(0) ? a : -a; } inline b2Vec2 b2Abs(const b2Vec2& a) { return b2Vec2(b2Abs(a.x), b2Abs(a.y)); } inline b2Mat22 b2Abs(const b2Mat22& A) { return b2Mat22(b2Abs(A.ex), b2Abs(A.ey)); } template inline T b2Min(T a, T b) { return a < b ? a : b; } inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b) { return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)); } template inline T b2Max(T a, T b) { return a > b ? a : b; } inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b) { return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)); } template inline T b2Clamp(T a, T low, T high) { return b2Max(low, b2Min(a, high)); } inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high) { return b2Max(low, b2Min(a, high)); } template inline void b2Swap(T& a, T& b) { T tmp = a; a = b; b = tmp; } /// "Next Largest Power of 2 /// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm /// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with /// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next /// largest power of 2. For a 32-bit value:" inline uint32 b2NextPowerOfTwo(uint32 x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); return x + 1; } inline bool b2IsPowerOfTwo(uint32 x) { bool result = x > 0 && (x & (x - 1)) == 0; return result; } inline void b2Sweep::GetTransform(b2Transform* xf, float32 beta) const { xf->p = (1.0f - beta) * c0 + beta * c; float32 angle = (1.0f - beta) * a0 + beta * a; xf->q.Set(angle); // Shift to origin xf->p -= b2Mul(xf->q, localCenter); } inline void b2Sweep::Advance(float32 alpha) { b2Assert(alpha0 < 1.0f); float32 beta = (alpha - alpha0) / (1.0f - alpha0); c0 += beta * (c - c0); a0 += beta * (a - a0); alpha0 = alpha; } /// Normalize an angle in radians to be between -pi and pi inline void b2Sweep::Normalize() { float32 twoPi = 2.0f * b2_pi; float32 d = twoPi * floorf(a0 / twoPi); a0 -= d; a -= d; } #endif qml-box2d/Box2D/License.txt0000644000000000000000000000154412241175670012623 0ustar Copyright (c) 2006-2010 Erin Catto http://www.gphysics.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. qml-box2d/box2dmotorjoint.h0000664000000000000000000000521112310072714013063 0ustar #ifndef BOX2DMOTORJOINT_H #define BOX2DMOTORJOINT_H /* * box2dmotorjoint.h * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2djoint.h" #include class b2World; class b2MotorJoint; class b2MotorJointDef; class Box2DMotorJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(QPointF linearOffset READ linearOffset WRITE setLinearOffset NOTIFY linearOffsetChanged) Q_PROPERTY(float angularOffset READ angularOffset WRITE setAngularOffset NOTIFY angularOffsetChanged) Q_PROPERTY(float maxForce READ maxForce WRITE setMaxForce NOTIFY maxForceChanged) Q_PROPERTY(float maxTorque READ maxTorque WRITE setMaxTorque NOTIFY maxTorqueChanged) Q_PROPERTY(float correctionFactor READ correctionFactor WRITE setCorrectionFactor NOTIFY correctionFactorChanged) public: explicit Box2DMotorJoint(QObject *parent = 0); ~Box2DMotorJoint(); QPointF linearOffset() const; void setLinearOffset(const QPointF & linearOffset); float angularOffset() const; void setAngularOffset(const float angularOffset); float maxForce() const; void setMaxForce(const float maxForce); float maxTorque() const; void setMaxTorque(const float maxTorque); float correctionFactor() const; void setCorrectionFactor(const float correctionFactor); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); signals: void linearOffsetChanged(); void angularOffsetChanged(); void maxForceChanged(); void maxTorqueChanged(); void correctionFactorChanged(); private: b2MotorJointDef mMotorJointDef; b2MotorJoint *mMotorJoint; }; #endif // BOX2DMOTORJOINT_H qml-box2d/box2dfixture.h0000664000000000000000000001657412310072714012363 0ustar /* * box2dfixture.h * Copyright (c) 2010-2011 Thorbjørn Lindeijer * Copyright (c) 2011 Daker Fernandes Pinheiro * Copyright (c) 2011 Alessandro Portale * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DFIXTURE_H #define BOX2DFIXTURE_H #include #include #include #include "box2dfixture.h" class b2Body; class b2Fixture; struct b2FixtureDef; class b2Shape; class Box2DBody; class Box2DFixture : public QQuickItem { Q_OBJECT Q_PROPERTY(float density READ density WRITE setDensity NOTIFY densityChanged) Q_PROPERTY(float friction READ friction WRITE setFriction NOTIFY frictionChanged) Q_PROPERTY(float restitution READ restitution WRITE setRestitution NOTIFY restitutionChanged) Q_PROPERTY(bool sensor READ isSensor WRITE setSensor NOTIFY sensorChanged) Q_PROPERTY(CategoryFlags categories READ categories WRITE setCategories NOTIFY categoriesChanged) Q_PROPERTY(CategoryFlags collidesWith READ collidesWith WRITE setCollidesWith NOTIFY collidesWithChanged) Q_PROPERTY(int groupIndex READ groupIndex WRITE setGroupIndex NOTIFY groupIndexChanged) Q_ENUMS(CategoryFlag) Q_FLAGS(CategoryFlags) public: explicit Box2DFixture(QQuickItem *parent = 0); enum CategoryFlag {Category1 = 0x0001, Category2 = 0x0002, Category3 = 0x0004, Category4 = 0x0008, Category5 = 0x0010, Category6 = 0x0020, Category7 = 0x0040, Category8 = 0x0080, Category9 = 0x0100, Category10 = 0x0200, Category11 = 0x0400, Category12 = 0x0800, Category13 = 0x1000, Category14 = 0x2000, Category15 = 0x4000, Category16 = 0x8000, All = 0xFFFF, None=0x0000}; Q_DECLARE_FLAGS(CategoryFlags, CategoryFlag) float density() const; void setDensity(float density); float friction() const; void setFriction(float friction); float restitution() const; void setRestitution(float restitution); bool isSensor() const; void setSensor(bool sensor); CategoryFlags categories() const; void setCategories(CategoryFlags layers); CategoryFlags collidesWith() const; void setCollidesWith(CategoryFlags layers); int groupIndex() const; void setGroupIndex(int groupIndex); void createFixture(b2Body *body); virtual void scale(){} Q_INVOKABLE Box2DBody * GetBody() const; protected: b2Fixture *mFixture; b2FixtureDef mFixtureDef; b2Body * mBody; float factorWidth; float factorHeight; virtual b2Shape *createShape() = 0; void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry); void applyShape(b2Shape * shape); signals: void densityChanged(); void frictionChanged(); void restitutionChanged(); void sensorChanged(); void categoriesChanged(); void collidesWithChanged(); void groupIndexChanged(); void beginContact(Box2DFixture *other); void contactChanged(Box2DFixture *other); void endContact(Box2DFixture *other); private: friend class Box2DWorld; void emitBeginContact(Box2DFixture *other); void emitContactChanged(Box2DFixture *other); void emitEndContact(Box2DFixture *other); }; Q_DECLARE_OPERATORS_FOR_FLAGS(Box2DFixture::CategoryFlags) class Box2DBox : public Box2DFixture { Q_OBJECT public: explicit Box2DBox(QQuickItem *parent = 0) : Box2DFixture(parent) { } void scale(); protected: b2Shape *createShape(); b2Vec2 vertices[4]; }; class Box2DCircle : public Box2DFixture { Q_OBJECT Q_PROPERTY(float radius READ radius WRITE setRadius NOTIFY radiusChanged) public: explicit Box2DCircle(QQuickItem *parent = 0) : Box2DFixture(parent) { } float radius() const { return mRadius; } void setRadius(float radius) { if (mRadius == radius) return; mRadius = radius; scale(); emit radiusChanged(); } void scale(); signals: void radiusChanged(); protected: b2Shape *createShape(); private: float mRadius; }; class Box2DVerticesShape : public Box2DFixture { Q_OBJECT Q_PROPERTY(QVariantList vertices READ vertices WRITE setVertices NOTIFY verticesChanged) public: explicit Box2DVerticesShape(QQuickItem *parent = 0) : Box2DFixture(parent) { } QVariantList vertices() const { return mVertices; } void setVertices(const QVariantList &vertices) { if (vertices == mVertices) return; mVertices = vertices; emit verticesChanged(); } signals: void verticesChanged(); protected: QVariantList mVertices; b2Vec2 * scaleVertices(); virtual b2Shape *createShape(){ return NULL; } }; class Box2DPolygon : public Box2DVerticesShape { public: explicit Box2DPolygon(QQuickItem *parent = 0) : Box2DVerticesShape(parent) { } void scale(); protected: b2Shape *createShape(); }; class Box2DChain : public Box2DVerticesShape { Q_OBJECT Q_PROPERTY(bool loop READ loop WRITE setLoop NOTIFY loopChanged) Q_PROPERTY(QPointF prevVertex READ prevVertex WRITE setPrevVertex NOTIFY prevVertexChanged) Q_PROPERTY(QPointF nextVertex READ nextVertex WRITE setNextVertex NOTIFY nextVertexChanged) public: explicit Box2DChain(QQuickItem *parent = 0) : Box2DVerticesShape(parent), mLoop(false) { } void scale(); bool loop() const { return mLoop; } void setLoop(bool loop) { mLoop = loop; emit loopChanged(); } QPointF prevVertex() const { return mPrevVertex; } void setPrevVertex(QPointF &prevVertex) { mPrevVertex = prevVertex; prevVertexFlag = true; } QPointF nextVertex() const { return mNextVertex; } void setNextVertex(QPointF &nextVertex) { mNextVertex = nextVertex; nextVertexFlag = true; } protected: b2Shape *createShape(); bool mLoop; bool prevVertexFlag; bool nextVertexFlag; QPointF mPrevVertex; QPointF mNextVertex; signals: void loopChanged(); void prevVertexChanged(); void nextVertexChanged(); }; class Box2DEdge : public Box2DVerticesShape { Q_OBJECT public: explicit Box2DEdge(QQuickItem *parent = 0) : Box2DVerticesShape(parent) { } void scale(); protected: b2Shape *createShape(); }; /** * Convenience function to get the Box2DFixture wrapping a b2Fixture. */ inline Box2DFixture *toBox2DFixture(b2Fixture *fixture) { return static_cast(fixture->GetUserData()); } #endif // BOX2DFIXTURE_H qml-box2d/COPYING0000644000000000000000000000146412241175670010616 0ustar 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. qml-box2d/box2d-static.pri0000664000000000000000000000274112310072714012573 0ustar # Include this file in your .pro file to statically compile the Box2D QML # bindings into your project. # # Basic usage instructions: # # #include # # int main(int argc, char *argv[]) # { # QApplication app(argc, argv); # # Box2DPlugin plugin; # plugin.registerTypes("Box2D"); # # ... # } INCLUDEPATH += $$PWD include(Box2D/box2d.pri) SOURCES += $$PWD/box2dplugin.cpp \ $$PWD/box2dworld.cpp \ $$PWD/box2dbody.cpp \ $$PWD/box2dfixture.cpp \ $$PWD/box2ddebugdraw.cpp \ $$PWD/box2djoint.cpp \ $$PWD/box2drevolutejoint.cpp \ $$PWD/box2ddistancejoint.cpp \ $$PWD/box2dprismaticjoint.cpp \ $$PWD/box2ddestructionlistener.cpp \ $$PWD/box2dmotorjoint.cpp \ $$PWD/box2dweldjoint.cpp \ $$PWD/box2dpulleyjoint.cpp \ $$PWD/box2dfrictionjoint.cpp \ $$PWD/box2dwheeljoint.cpp \ $$PWD/box2dmousejoint.cpp \ $$PWD/box2dgearjoint.cpp \ $$PWD/box2dropejoint.cpp HEADERS += \ $$PWD/box2dplugin.h \ $$PWD/box2dworld.h \ $$PWD/box2dbody.h \ $$PWD/box2dfixture.h \ $$PWD/box2ddebugdraw.h \ $$PWD/box2djoint.h \ $$PWD/box2drevolutejoint.h \ $$PWD/box2ddistancejoint.h \ $$PWD/box2dprismaticjoint.h \ $$PWD/box2ddestructionlistener.h \ $$PWD/box2dmotorjoint.h \ $$PWD/box2dweldjoint.h \ $$PWD/box2dpulleyjoint.h \ $$PWD/box2dfrictionjoint.h \ $$PWD/box2dwheeljoint.h \ $$PWD/box2dmousejoint.h \ $$PWD/box2dgearjoint.h \ $$PWD/box2dropejoint.h qml-box2d/box2ddebugdraw.cpp0000664000000000000000000001164612310072714013167 0ustar /* * box2ddebugdraw.cpp * Copyright (c) 2010 Thorbjørn Lindeijer * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2ddebugdraw.h" #include "box2dworld.h" #include #include class DebugDraw : public b2Draw { public: DebugDraw(QPainter *painter, Box2DWorld *world); void draw(); void DrawPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color); void DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color); void DrawCircle(const b2Vec2 ¢er, float32 radius, const b2Color &color); void DrawSolidCircle(const b2Vec2 ¢er, float32 radius, const b2Vec2 &axis, const b2Color &color); void DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color); void DrawTransform(const b2Transform &xf); private: QPainter *mP; b2World *mWorld; }; DebugDraw::DebugDraw(QPainter *painter, Box2DWorld *world) : mP(painter) , mWorld(world->world()) { SetFlags(e_shapeBit | e_jointBit | e_aabbBit | e_pairBit | e_centerOfMassBit); } void DebugDraw::draw() { mWorld->SetDebugDraw(this); mWorld->DrawDebugData(); mWorld->SetDebugDraw(0); } static QPointF toQPointF(const b2Vec2 &vec) { return QPointF(vec.x * scaleRatio, -vec.y * scaleRatio); } static QColor toQColor(const b2Color &color) { return QColor(color.r * 255, color.g * 255, color.b * 255); } static QPolygonF toQPolygonF(const b2Vec2 *vertices, int32 vertexCount) { QPolygonF polygon; polygon.reserve(vertexCount); for (int i = 0; i < vertexCount; ++i) polygon.append(toQPointF(vertices[i])); return polygon; } void DebugDraw::DrawPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color) { mP->setPen(toQColor(color)); mP->setBrush(Qt::NoBrush); mP->drawPolygon(toQPolygonF(vertices, vertexCount)); } void DebugDraw::DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color) { mP->setPen(Qt::NoPen); mP->setBrush(toQColor(color)); mP->drawPolygon(toQPolygonF(vertices, vertexCount)); } void DebugDraw::DrawCircle(const b2Vec2 ¢er, float32 radius, const b2Color &color) { mP->setPen(toQColor(color)); mP->setBrush(Qt::NoBrush); mP->drawEllipse(toQPointF(center), radius * scaleRatio, radius * scaleRatio); } void DebugDraw::DrawSolidCircle(const b2Vec2 ¢er, float32 radius, const b2Vec2 &axis, const b2Color &color) { Q_UNUSED(axis) mP->setPen(Qt::NoPen); mP->setBrush(toQColor(color)); mP->drawEllipse(toQPointF(center), radius * scaleRatio, radius * scaleRatio); } void DebugDraw::DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color) { mP->setPen(toQColor(color)); mP->drawLine(toQPointF(p1), toQPointF(p2)); } void DebugDraw::DrawTransform(const b2Transform &xf) { Q_UNUSED(xf) // TODO: Not sure how to draw transforms } Box2DDebugDraw::Box2DDebugDraw(QQuickItem *parent) : QQuickPaintedItem (parent), mWorld(0) { setFlag(QQuickItem::ItemHasContents, true); } void Box2DDebugDraw::setWorld(Box2DWorld *world) { if (mWorld == world) return; if (mWorld) mWorld->disconnect(this); mWorld = world; if (mWorld) connect(mWorld, SIGNAL(stepped()), SLOT(onWorldStepped())); } void Box2DDebugDraw::paint(QPainter *p) { if (!mWorld) return; // Darken the view to make the debug draw stand out more p->fillRect(0, 0, width(), height(), QColor(0, 0, 0, 128)); DebugDraw debugDraw(p, mWorld); debugDraw.draw(); } void Box2DDebugDraw::onWorldStepped() { if (isVisible() && opacity() > 0) { update(); } } qml-box2d/box2dprismaticjoint.cpp0000664000000000000000000001531312310076376014265 0ustar /* * box2dprismaticjoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dprismaticjoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DPrismaticJoint::Box2DPrismaticJoint(QObject *parent) : Box2DJoint(parent), mPrismaticJointDef(), mPrismaticJoint(0), anchorsAuto(true) { } Box2DPrismaticJoint::~Box2DPrismaticJoint() { cleanup(world()); } float Box2DPrismaticJoint::lowerTranslation() const { return mPrismaticJointDef.lowerTranslation * scaleRatio; } void Box2DPrismaticJoint::setLowerTranslation(float lowerTranslation) { if (qFuzzyCompare(mPrismaticJointDef.lowerTranslation,lowerTranslation / scaleRatio)) return; mPrismaticJointDef.lowerTranslation = lowerTranslation / scaleRatio; if (mPrismaticJoint) mPrismaticJoint->SetLimits(mPrismaticJointDef.lowerTranslation, mPrismaticJointDef.upperTranslation); emit lowerTranslationChanged(); } float Box2DPrismaticJoint::upperTranslation() const { return mPrismaticJointDef.upperTranslation * scaleRatio; } void Box2DPrismaticJoint::setUpperTranslation(float upperTranslation) { if (qFuzzyCompare(mPrismaticJointDef.upperTranslation,upperTranslation / scaleRatio)) return; mPrismaticJointDef.upperTranslation = upperTranslation / scaleRatio; if (mPrismaticJoint) mPrismaticJoint->SetLimits(mPrismaticJointDef.lowerTranslation, mPrismaticJointDef.upperTranslation); emit upperTranslationChanged(); } float Box2DPrismaticJoint::maxMotorForce() const { return mPrismaticJointDef.maxMotorForce; } void Box2DPrismaticJoint::setMaxMotorForce(float maxMotorForce) { if (qFuzzyCompare(mPrismaticJointDef.maxMotorForce,maxMotorForce)) return; mPrismaticJointDef.maxMotorForce = maxMotorForce; if (mPrismaticJoint) mPrismaticJoint->SetMaxMotorForce(maxMotorForce); emit maxMotorForceChanged(); } float Box2DPrismaticJoint::motorSpeed() const { return mPrismaticJointDef.motorSpeed * scaleRatio; } void Box2DPrismaticJoint::setMotorSpeed(float motorSpeed) { if (qFuzzyCompare(mPrismaticJointDef.motorSpeed,motorSpeed / scaleRatio)) return; mPrismaticJointDef.motorSpeed = motorSpeed / scaleRatio; if (mPrismaticJoint) mPrismaticJoint->SetMotorSpeed(mPrismaticJointDef.motorSpeed); emit motorSpeedChanged(); } bool Box2DPrismaticJoint::enableLimit() const { return mPrismaticJointDef.enableLimit; } void Box2DPrismaticJoint::setEnableLimit(bool enableLimit) { if (mPrismaticJointDef.enableLimit == enableLimit) return; mPrismaticJointDef.enableLimit = enableLimit; if (mPrismaticJoint) mPrismaticJoint->EnableLimit(enableLimit); emit enableLimitChanged(); } bool Box2DPrismaticJoint::enableMotor() const { return mPrismaticJointDef.enableMotor; } void Box2DPrismaticJoint::setEnableMotor(bool enableMotor) { if (mPrismaticJointDef.enableMotor == enableMotor) return; mPrismaticJointDef.enableMotor = enableMotor; if (mPrismaticJoint) mPrismaticJoint->EnableMotor(enableMotor); emit enableMotorChanged(); } QPointF Box2DPrismaticJoint::axis() const { return QPointF(mPrismaticJointDef.localAxisA.x * scaleRatio, -mPrismaticJointDef.localAxisA.y * scaleRatio); } void Box2DPrismaticJoint::setAxis(const QPointF &axis) { mPrismaticJointDef.localAxisA = b2Vec2(axis.x() / scaleRatio, -axis.y() / scaleRatio); mPrismaticJointDef.localAxisA.Normalize(); emit axisChanged(); } QPointF Box2DPrismaticJoint::localAnchorA() const { return QPointF(mPrismaticJointDef.localAnchorA.x * scaleRatio, mPrismaticJointDef.localAnchorA.y * scaleRatio); } QPointF Box2DPrismaticJoint::localAnchorB() const { return QPointF(mPrismaticJointDef.localAnchorB.x * scaleRatio, mPrismaticJointDef.localAnchorB.y * scaleRatio); } void Box2DPrismaticJoint::setLocalAnchorA(const QPointF &localAnchorA) { mPrismaticJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio,-localAnchorA.y() / scaleRatio); anchorsAuto = false; emit localAnchorAChanged(); } void Box2DPrismaticJoint::setLocalAnchorB(const QPointF &localAnchorB) { mPrismaticJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio,-localAnchorB.y() / scaleRatio); anchorsAuto = false; emit localAnchorBChanged(); } void Box2DPrismaticJoint::nullifyJoint() { mPrismaticJoint = 0; } void Box2DPrismaticJoint::createJoint() { if(anchorsAuto) mPrismaticJointDef.Initialize(bodyA()->body(), bodyB()->body(), bodyA()->body()->GetWorldCenter(), mPrismaticJointDef.localAxisA); else { mPrismaticJointDef.bodyA = bodyA()->body(); mPrismaticJointDef.bodyB = bodyB()->body(); mPrismaticJointDef.referenceAngle = 0.0; } mPrismaticJointDef.collideConnected = collideConnected(); mPrismaticJoint = static_cast (world()->CreateJoint(&mPrismaticJointDef)); mPrismaticJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DPrismaticJoint::cleanup(b2World *world) { if(!world) { qWarning() << "PrismaticJoint: There is no world connected"; return; } if (mPrismaticJoint && bodyA() && bodyB()) { mPrismaticJoint->SetUserData(0); world->DestroyJoint(mPrismaticJoint); mPrismaticJoint = 0; } } b2Joint *Box2DPrismaticJoint::GetJoint() { return mPrismaticJoint; } float Box2DPrismaticJoint::GetJointTranslation() { if(mPrismaticJoint) return mPrismaticJoint->GetJointTranslation() * scaleRatio; return 0.0; } float Box2DPrismaticJoint::GetJointSpeed() { if(mPrismaticJoint) return mPrismaticJoint->GetJointSpeed(); return 0.0; } qml-box2d/box2dworld.cpp0000664000000000000000000001617112310072714012350 0ustar /* * box2dworld.cpp * Copyright (c) 2010-2011 Thorbjørn Lindeijer * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2012 Adriano Rezende * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2dworld.h" #include "box2dbody.h" #include "box2dfixture.h" #include "box2djoint.h" #include "box2ddestructionlistener.h" #include #include class ContactEvent { public: enum Type { BeginContact, EndContact }; Type type; Box2DFixture *fixtureA; Box2DFixture *fixtureB; }; class ContactListener : public b2ContactListener { public: void BeginContact(b2Contact *contact); void EndContact(b2Contact *contact); void removeEvent(int index) { mEvents.removeAt(index); } void clearEvents() { mEvents.clear(); } const QList &events() { return mEvents; } private: QList mEvents; }; void ContactListener::BeginContact(b2Contact *contact) { ContactEvent event; event.type = ContactEvent::BeginContact; event.fixtureA = toBox2DFixture(contact->GetFixtureA()); event.fixtureB = toBox2DFixture(contact->GetFixtureB()); mEvents.append(event); } void ContactListener::EndContact(b2Contact *contact) { ContactEvent event; event.type = ContactEvent::EndContact; event.fixtureA = toBox2DFixture(contact->GetFixtureA()); event.fixtureB = toBox2DFixture(contact->GetFixtureB()); mEvents.append(event); } Box2DWorld::Box2DWorld(QQuickItem *parent) : QQuickItem(parent), mWorld(0), mContactListener(new ContactListener), mDestructionListener(new Box2DDestructionListener), mTimeStep(1.0f / 60.0f), mVelocityIterations(10), mPositionIterations(10), mFrameTime(1000 / 60), mGravity(qreal(0), qreal(10)), mIsRunning(true) { connect(mDestructionListener, SIGNAL(fixtureDestroyed(Box2DFixture*)), this, SLOT(fixtureDestroyed(Box2DFixture*))); } Box2DWorld::~Box2DWorld() { // Bodies must be deleted before the world foreach (Box2DBody *body, mBodies) { if(body->parent() == this) delete body; else body->cleanup(this->world()); } mBodies.clear(); delete mWorld; delete mContactListener; delete mDestructionListener; } void Box2DWorld::setRunning(bool running) { if (mIsRunning == running) return; mIsRunning = running; emit runningChanged(); if (isComponentComplete()) { if (running) mTimer.start(mFrameTime, this); else mTimer.stop(); } } void Box2DWorld::setGravity(const QPointF &gravity) { if (mGravity == gravity) return; mGravity = gravity; if (mWorld) mWorld->SetGravity(b2Vec2(gravity.x(), -gravity.y())); emit gravityChanged(); } void Box2DWorld::componentComplete() { QQuickItem::componentComplete(); const b2Vec2 gravity(mGravity.x(), -mGravity.y()); mWorld = new b2World(gravity); mWorld->SetContactListener(mContactListener); mWorld->SetDestructionListener(mDestructionListener); QList list; GetAllBodies(this,list); foreach(Box2DBody * body,list) { registerBody(body); } emit initialized(); if (mIsRunning) mTimer.start(mFrameTime, this); } /** * Registers a Box2D body with this world. When the world component is * complete, it will initialize the body. */ void Box2DWorld::registerBody(Box2DBody *body) { mBodies.append(body); body->initialize(mWorld); connect(body, SIGNAL(destroyed()), this, SLOT(unregisterBody())); } /** * Unregisters a Box2D body from this world. Called when a dynamically * created Box2D body has been deleted. */ void Box2DWorld::unregisterBody() { Box2DBody *body = static_cast(sender()); mBodies.removeOne(body); } void Box2DWorld::fixtureDestroyed(Box2DFixture *fixture) { QList events = mContactListener->events(); for (int i = events.count() - 1; i >= 0; i--) { if (events.at(i).fixtureA == fixture || events.at(i).fixtureB == fixture) mContactListener->removeEvent(i); } } void Box2DWorld::timerEvent(QTimerEvent *event) { if (event->timerId() == mTimer.timerId()) { mWorld->Step(mTimeStep, mVelocityIterations, mPositionIterations); foreach (Box2DBody *body, mBodies) body->synchronize(); // Emit contact signals foreach (const ContactEvent &event, mContactListener->events()) { switch (event.type) { case ContactEvent::BeginContact: event.fixtureA->emitBeginContact(event.fixtureB); event.fixtureB->emitBeginContact(event.fixtureA); break; case ContactEvent::EndContact: event.fixtureA->emitEndContact(event.fixtureB); event.fixtureB->emitEndContact(event.fixtureA); break; } } mContactListener->clearEvents(); // Emit signals for the current state of the contacts b2Contact *contact = mWorld->GetContactList(); while (contact) { Box2DFixture *fixtureA = toBox2DFixture(contact->GetFixtureA()); Box2DFixture *fixtureB = toBox2DFixture(contact->GetFixtureB()); fixtureA->emitContactChanged(fixtureB); fixtureB->emitContactChanged(fixtureA); contact = contact->GetNext(); } emit stepped(); } QQuickItem::timerEvent(event); } void Box2DWorld::itemChange(ItemChange change, const ItemChangeData &value) { if (isComponentComplete()) { if (change == ItemChildAddedChange) { QObject *child = value.item; if (Box2DBody *body = dynamic_cast(child)) { registerBody(body); } } } QQuickItem::itemChange(change, value); } // Get all Box2DBodies attached to this world void Box2DWorld::GetAllBodies(QQuickItem *parent, QList & list) { QList children = parent->childItems(); foreach(QQuickItem * item,children) { Box2DBody * body = dynamic_cast(item); if(body) list.append(body); GetAllBodies(item,list); } } qml-box2d/box2dgearjoint.h0000664000000000000000000000412212310072714012641 0ustar /* * box2dgearjoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DGEARJOINT_H #define BOX2DGEARJOINT_H #include "box2djoint.h" #include class b2World; class b2GearJoint; class b2GearJointDef; class Box2DGearJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(Box2DJoint * joint1 READ joint1 WRITE setJoint1 NOTIFY joint1Changed) Q_PROPERTY(Box2DJoint * joint2 READ joint2 WRITE setJoint2 NOTIFY joint2Changed) Q_PROPERTY(float ratio READ ratio WRITE setRatio NOTIFY ratioChanged) public: explicit Box2DGearJoint(QObject *parent = 0); ~Box2DGearJoint(); float ratio() const; void setRatio(float _ratio); Box2DJoint *joint1() const; void setJoint1(Box2DJoint *_joint1); Box2DJoint *joint2() const; void setJoint2(Box2DJoint *_joint2); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); signals: void ratioChanged(); void joint1Changed(); void joint2Changed(); private slots: void joint1Created(); void joint2Created(); private: b2GearJointDef mGearJointDef; b2GearJoint *mGearJoint; }; #endif // BOX2DGEARJOINT_H qml-box2d/box2dropejoint.h0000664000000000000000000000447412310072714012702 0ustar /* * box2dropejoint.h * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DROPEJOINT_H #define BOX2DROPEJOINT_H #include "box2djoint.h" #include class b2World; class b2RopeJoint; class b2RopeJointDef; class Box2DRopeJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float maxLength READ maxLength WRITE setMaxLength NOTIFY maxLengthChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DRopeJoint(QObject *parent = 0); ~Box2DRopeJoint(); float maxLength() const; void setMaxLength(float _maxLength); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); Q_INVOKABLE QPointF GetReactionForce(float32 inv_dt) const; Q_INVOKABLE float GetReactionTorque(float32 inv_dt) const; signals: void maxLengthChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2RopeJointDef mRopeJointDef; b2RopeJoint *mRopeJoint; }; #endif // BOX2DROPEJOINT_H qml-box2d/qmldir0000644000000000000000000000003212241176160010757 0ustar module Box2D plugin Box2D qml-box2d/box2dfrictionjoint.h0000664000000000000000000000477412310072714013555 0ustar /* * box2dprismaticjoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2FRICTIONJOINT_H #define BOX2FRICTIONJOINT_H #include "box2djoint.h" #include class b2World; class b2FrictionJoint; class b2FrictionJointDef; class Box2DFrictionJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float maxForce READ maxForce WRITE setMaxForce NOTIFY maxForceChanged) Q_PROPERTY(float maxTorque READ maxTorque WRITE setMaxTorque NOTIFY maxTorqueChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DFrictionJoint(QObject *parent = 0); ~Box2DFrictionJoint(); float maxForce() const; void setMaxForce(float maxForce); float maxTorque() const; void setMaxTorque(float maxTorque); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); Q_INVOKABLE QPointF GetReactionForce(float32 inv_dt) const; Q_INVOKABLE float GetReactionTorque(float32 inv_dt) const; signals: void maxForceChanged(); void maxTorqueChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2FrictionJointDef mFrictionJointDef; b2FrictionJoint * mFrictionJoint; bool anchorsAuto; }; #endif // BOX2FRICTIONJOINT_H qml-box2d/box2dfrictionjoint.cpp0000664000000000000000000001153212310076376014106 0ustar /* * box2dprismaticjoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dfrictionjoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DFrictionJoint::Box2DFrictionJoint(QObject *parent) : Box2DJoint(parent), mFrictionJointDef(), mFrictionJoint(0), anchorsAuto(true) { } Box2DFrictionJoint::~Box2DFrictionJoint() { cleanup(world()); } float Box2DFrictionJoint::maxForce() const { if(mFrictionJoint) return mFrictionJoint->GetMaxForce(); return mFrictionJointDef.maxForce; } void Box2DFrictionJoint::setMaxForce(float maxForce) { if(mFrictionJoint && mFrictionJoint->GetMaxForce() == maxForce) return; if(mFrictionJoint) mFrictionJoint->SetMaxForce(maxForce); else mFrictionJointDef.maxForce = maxForce; emit maxForceChanged(); } float Box2DFrictionJoint::maxTorque() const { if(mFrictionJoint) return mFrictionJoint->GetMaxTorque(); return mFrictionJointDef.maxTorque; } void Box2DFrictionJoint::setMaxTorque(float maxTorque) { if(mFrictionJoint && mFrictionJoint->GetMaxTorque() == maxTorque) return; if(mFrictionJoint) mFrictionJoint->SetMaxForce(maxTorque); else mFrictionJointDef.maxTorque = maxTorque; emit maxTorqueChanged(); } QPointF Box2DFrictionJoint::localAnchorA() const { if(mFrictionJoint) QPointF(mFrictionJoint->GetAnchorA().x * scaleRatio, -mFrictionJoint->GetAnchorA().y * scaleRatio); return QPointF(mFrictionJointDef.localAnchorA.x * scaleRatio, mFrictionJointDef.localAnchorA.y * scaleRatio); } void Box2DFrictionJoint::setLocalAnchorA(const QPointF &localAnchorA) { mFrictionJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio ,-localAnchorA.y() / scaleRatio); anchorsAuto = true; emit localAnchorAChanged(); } QPointF Box2DFrictionJoint::localAnchorB() const { if(mFrictionJoint) QPointF(mFrictionJoint->GetAnchorB().x * scaleRatio, -mFrictionJoint->GetAnchorB().y * scaleRatio); return QPointF(mFrictionJointDef.localAnchorB.x * scaleRatio, mFrictionJointDef.localAnchorB.y * scaleRatio); } void Box2DFrictionJoint::setLocalAnchorB(const QPointF &localAnchorB) { mFrictionJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio, -localAnchorB.y() / scaleRatio); anchorsAuto = true; emit localAnchorBChanged(); } void Box2DFrictionJoint::nullifyJoint() { mFrictionJoint = 0; } void Box2DFrictionJoint::createJoint() { if(anchorsAuto) { mFrictionJointDef.bodyA = bodyA()->body(); mFrictionJointDef.bodyB = bodyB()->body(); } else mFrictionJointDef.Initialize(bodyA()->body(), bodyB()->body(), bodyA()->body()->GetWorldCenter()); mFrictionJointDef.collideConnected = collideConnected(); mFrictionJoint = static_cast(world()->CreateJoint(&mFrictionJointDef)); mFrictionJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DFrictionJoint::cleanup(b2World *world) { if(!world) { qWarning() << "FrictionJoint: There is no world connected"; return; } if (mFrictionJoint && bodyA() && bodyB()) { mFrictionJoint->SetUserData(0); world->DestroyJoint(mFrictionJoint); mFrictionJoint = 0; } } b2Joint *Box2DFrictionJoint::GetJoint() { return mFrictionJoint; } QPointF Box2DFrictionJoint::GetReactionForce(float32 inv_dt) const { if(mFrictionJoint) { b2Vec2 point = mFrictionJoint->GetReactionForce(inv_dt); return QPointF(point.x * scaleRatio,point.y * scaleRatio); } return QPointF(); } float Box2DFrictionJoint::GetReactionTorque(float32 inv_dt) const { if(mFrictionJoint) return mFrictionJoint->GetReactionTorque(inv_dt); return 0.0f; } qml-box2d/box2dmousejoint.h0000664000000000000000000000462512310072714013063 0ustar /* * box2dmousejoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DMOUSEJOINT_H #define BOX2DMOUSEJOINT_H #include "box2djoint.h" #include class b2World; class b2MouseJoint; class b2MouseJointDef; class Box2DMouseJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(QPointF target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(float maxForce READ maxForce WRITE setMaxForce NOTIFY maxForceChanged) Q_PROPERTY(float frequencyHz READ frequencyHz WRITE setFrequencyHz NOTIFY frequencyHzChanged) Q_PROPERTY(float dampingRatio READ dampingRatio WRITE setDampingRatio NOTIFY dampingRatioChanged) public: explicit Box2DMouseJoint(QObject *parent = 0); ~Box2DMouseJoint(); float dampingRatio() const; void setDampingRatio(float dampingRatio); float frequencyHz() const; void setFrequencyHz(float frequencyHz); float maxForce() const; void setMaxForce(float maxForce); QPointF target() const; void setTarget(const QPointF &_target); Q_INVOKABLE QPointF GetReactionForce(float32 inv_dt) const; Q_INVOKABLE float GetReactionTorque(float32 inv_dt) const; void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); signals: void targetChanged(); void maxForceChanged(); void frequencyHzChanged(); void dampingRatioChanged(); private: b2MouseJointDef mMouseJointDef; b2MouseJoint *mMouseJoint; }; #endif // BOX2DMOUSEJOINT_H qml-box2d/box2dmousejoint.cpp0000664000000000000000000000742212310076376013424 0ustar /* * box2dmousejoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dmousejoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DMouseJoint::Box2DMouseJoint(QObject *parent) : Box2DJoint(parent), mMouseJointDef(), mMouseJoint(0) { } Box2DMouseJoint::~Box2DMouseJoint() { cleanup(world()); } float Box2DMouseJoint::dampingRatio() const { if(mMouseJoint) return mMouseJoint->GetDampingRatio(); return mMouseJointDef.dampingRatio; } void Box2DMouseJoint::setDampingRatio(float dampingRatio) { mMouseJointDef.dampingRatio = dampingRatio; if(mMouseJoint) mMouseJoint->SetDampingRatio(dampingRatio); } float Box2DMouseJoint::frequencyHz() const { if(mMouseJoint) return mMouseJoint->GetFrequency(); return mMouseJointDef.frequencyHz; } void Box2DMouseJoint::setFrequencyHz(float frequencyHz) { mMouseJointDef.frequencyHz = frequencyHz; if(mMouseJoint) mMouseJoint->SetFrequency(frequencyHz); } float Box2DMouseJoint::maxForce() const { if(mMouseJoint) return mMouseJoint->GetMaxForce(); return mMouseJointDef.maxForce; } void Box2DMouseJoint::setMaxForce(float maxForce) { mMouseJointDef.maxForce = maxForce; if(mMouseJoint) mMouseJoint->SetMaxForce(maxForce); } QPointF Box2DMouseJoint::target() const { b2Vec2 point; if(mMouseJoint) point = mMouseJoint->GetTarget(); else point = mMouseJointDef.target; return QPointF(point.x * scaleRatio,-point.y * scaleRatio); } void Box2DMouseJoint::setTarget(const QPointF &_target) { if(_target == target()) return; mMouseJointDef.target = b2Vec2(_target.x() / scaleRatio, -_target.y() / scaleRatio); if(mMouseJoint) mMouseJoint->SetTarget(mMouseJointDef.target); } void Box2DMouseJoint::nullifyJoint() { mMouseJoint = 0; } void Box2DMouseJoint::createJoint() { mMouseJointDef.bodyA = bodyA()->body(); mMouseJointDef.bodyB = bodyB()->body(); mMouseJoint = static_cast (world()->CreateJoint(&mMouseJointDef)); mMouseJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DMouseJoint::cleanup(b2World *world) { if(!world) { qWarning() << "MouseJoint: There is no world connected"; return; } if (mMouseJoint && bodyA() && bodyB()) { mMouseJoint->SetUserData(0); world->DestroyJoint(mMouseJoint); mMouseJoint = 0; } } b2Joint *Box2DMouseJoint::GetJoint() { return mMouseJoint; } QPointF Box2DMouseJoint::GetReactionForce(float32 inv_dt) const { if(mMouseJoint) { b2Vec2 point = mMouseJoint->GetReactionForce(inv_dt); return QPointF(point.x * scaleRatio,point.y * scaleRatio); } return QPointF(); } float Box2DMouseJoint::GetReactionTorque(float32 inv_dt) const { if(mMouseJoint) return mMouseJoint->GetReactionTorque(inv_dt); return 0.0f; } qml-box2d/box2dpulleyjoint.h0000664000000000000000000000621012310072714013235 0ustar /* * box2dprismaticjoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2PULLEYJOINT_H #define BOX2PULLEYJOINT_H #include "box2djoint.h" #include class b2World; class b2PulleyJoint; class b2PulleyJointDef; class Box2DPulleyJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float lengthA READ lengthA WRITE setLengthA NOTIFY lengthAChanged) Q_PROPERTY(float lengthB READ lengthB WRITE setLengthB NOTIFY lengthBChanged) Q_PROPERTY(float ratio READ ratio WRITE setRatio NOTIFY ratioChanged) Q_PROPERTY(QPointF groundAnchorA READ groundAnchorA WRITE setGroundAnchorA NOTIFY groundAnchorAChanged) Q_PROPERTY(QPointF groundAnchorB READ groundAnchorB WRITE setGroundAnchorB NOTIFY groundAnchorBChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DPulleyJoint(QObject *parent = 0); ~Box2DPulleyJoint(); float lengthA() const; void setLengthA(float lengthA); float lengthB() const; void setLengthB(float lengthB); float ratio() const; void setRatio(float ratio); QPointF groundAnchorA() const; void setGroundAnchorA(const QPointF &groundAnchorA); QPointF groundAnchorB() const; void setGroundAnchorB(const QPointF &groundAnchorB); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); Q_INVOKABLE float GetCurrentLengthA() const; Q_INVOKABLE float GetCurrentLengthB() const; Q_INVOKABLE QPointF GetReactionForce(float32 inv_dt) const; Q_INVOKABLE float GetReactionTorque(float32 inv_dt) const; signals: void lengthAChanged(); void lengthBChanged(); void ratioChanged(); void groundAnchorAChanged(); void groundAnchorBChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2PulleyJointDef mPulleyJointDef; b2PulleyJoint *mPulleyJoint; }; #endif // BOX2PULLEYJOINT_H qml-box2d/box2dgearjoint.cpp0000664000000000000000000000712412310076376013211 0ustar /* * box2dmousejoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dgearjoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DGearJoint::Box2DGearJoint(QObject *parent) : Box2DJoint(parent), mGearJointDef(), mGearJoint(0) { } Box2DGearJoint::~Box2DGearJoint() { cleanup(world()); } float Box2DGearJoint::ratio() const { if(mGearJoint) mGearJoint->GetRatio(); return mGearJointDef.ratio; } void Box2DGearJoint::setRatio(float _ratio) { if(qFuzzyCompare(_ratio,ratio())) return; mGearJointDef.ratio = _ratio; if(mGearJoint) mGearJoint->SetRatio(_ratio); emit ratioChanged(); } Box2DJoint *Box2DGearJoint::joint1() const { if(mGearJoint) return toBox2DJoint(mGearJoint->GetJoint1()); return toBox2DJoint(mGearJointDef.joint1); } void Box2DGearJoint::setJoint1(Box2DJoint *_joint1) { if(_joint1 == joint1()) return; mGearJointDef.joint1 = _joint1->GetJoint(); if(mGearJointDef.joint1) { initialize(); emit joint1Changed(); } else connect(_joint1,SIGNAL(created()),this,SLOT(joint1Created())); } Box2DJoint *Box2DGearJoint::joint2() const { if(mGearJoint) return toBox2DJoint(mGearJoint->GetJoint2()); return toBox2DJoint(mGearJointDef.joint2); } void Box2DGearJoint::setJoint2(Box2DJoint *_joint2) { if(_joint2 == joint2()) return; mGearJointDef.joint2 = _joint2->GetJoint(); if(mGearJointDef.joint2) { initialize(); emit joint2Changed(); } else connect(_joint2,SIGNAL(created()),this,SLOT(joint2Created())); } void Box2DGearJoint::nullifyJoint() { mGearJoint = 0; } void Box2DGearJoint::createJoint() { if(!mGearJointDef.joint1 || !mGearJointDef.joint2) return; mGearJointDef.bodyA = bodyA()->body(); mGearJointDef.bodyB = bodyB()->body(); mGearJoint = static_cast (world()->CreateJoint(&mGearJointDef)); mGearJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DGearJoint::cleanup(b2World *world) { if(!world) { qWarning() << "GearJoint: There is no world connected"; return; } if (mGearJoint) { mGearJoint->SetUserData(0); world->DestroyJoint(mGearJoint); mGearJoint = 0; } } b2Joint *Box2DGearJoint::GetJoint() { return mGearJoint; } void Box2DGearJoint::joint1Created() { Box2DJoint * joint1 = static_cast(sender()); mGearJointDef.joint1 = joint1->GetJoint(); initialize(); } void Box2DGearJoint::joint2Created() { Box2DJoint * joint2 = static_cast(sender()); mGearJointDef.joint2 = joint2->GetJoint(); initialize(); } qml-box2d/.moc/0000755000000000000000000000000012310101160010366 5ustar qml-box2d/examples/0000755000000000000000000000000012310072714011364 5ustar qml-box2d/examples/accelerometer/0000755000000000000000000000000012310410531014167 5ustar qml-box2d/examples/accelerometer/background.png0000644000000000000000000000070412241175670017034 0ustar PNG  IHDRr5JsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<AIDATx @Eq1J 6H xs|׽6 ?׶>YP8+/ } ˸B2P8+NDpxW(^ qqg/ ˸B2P8+/ ˸BDq 2e\pxW(^ '"8+/ ˸B2Q^P8+NDpxW(^ qe\pxW(^=*˸ '"8+/ ˸BDqe\px/n(^ qe\a t ;9(BѯPU$^$@); A ? "fo~_O??[+/_'Gp]wF/O9:d?A WYd/T&Og~kag{#k  I+Ǝ p<:1IjvMcLeG|}  L/c%Pȟ p 6IU9T%`:W,a`:U)\{n@@=9쟳 *b3yyP:T-9 8V:_ZP ?bَ93/G Kd.] gC/f^\m㨶+ ](`6(!jK@PS Dž 0%1۱ }G50a8l|B LRe_[Zr `؃yIMYNp_1druJ?eURdRdl W=9`P37Ji*sh860_WZV`,.50%Ns\)?dLbZc :ļrV.P{F|6{Pq2Q֫]\\|e(3te- m` /-5m_,X#\p{V<+fmr"W,ap^>h0/Ӝ<DbZ9SkCמlKNMe"C`K}طɉR^RoE[6Kpy?Xt,K+* }fOIIۆ"%-U5vZΓ?tA"&WY$Mȧ@` >lRwn08"QB 0j˦@i-nM ))hKuwcg{"ϗ%tpF/sn P1mm۴D q;K8vqfPjCJʫ2pYrna@{O2yV=I,&@t ycی8X‡D2< ( 4iLQu*PgLlG+}ROmiEem͎zYA S|Lr?*t.]sz_) 9F[JZuY݂DmH*Z_ܽ=5uz]oeY*d!eHXȻ )iu-k;ެb2s{VӡqLhPͧaB\r׌ L,>hh Dі8dg{^zi%b kydm%/eZMteaɴ? %͋HIefTcWf{moo8Ϲ{˻/Efu U3qd$ lvxcMIA#W ȆAR=Slc8Z/.uYJ{O^.Meu;uNɨaEM]R(zJ(3à /[}k"~rc۽Lӂ3qMϑ14R%V3S ]ze t]RCۣWU%Rx*چD79{*^{㨺s5oﺵAVuI\tKKT%ȟ˂M6|xǷ9+N"c;aVmw@Z. cP[ 4P_EvlT28vxa:ZhqMx]7*VVp̳a^XBT˵0-.ɪ+Lt^~8v0xʱ@0 u-7Gg]v$ !Yj{ {>Խw疜gJUSܻlEyޛz޼Hh VW.F"ePp "O9~*{h !܏6j +lwؑ^=I;fJ_"ݙ >b ~OM~jSB;jaP[M9_z>&:&[;zSJ:g5@:|Btvy,7e'+]/rȂ0-D8wTSWP+Q[nI 5Փs]e! VDp8Ƨ1qx [<]lCfGSWUcH_t$a^T[!oS> sS1x.|x]FH_||~` =;.wXtHZ)g_NF}^{#@Dq[t8ep0/m%ywCF)t*69^8BN;Ҫ{>&$1zg,O,e[ D'8 ^AƋ'Ho-]鑅 {Q!|;ۯh$\hU)%/t%*w߆Cm&g"?x쬕O,6o#ҞB6X>z>.\k;EvCK%p^rMۻf6Ievx:-a5;tYDi&v@?p:mtҶkTQ9+b܂e8%%׌yO|sdHҍ:tkxMeD!rY,KZjN 5ri{ S&.v]bEUiȘhkt 5t/:mqzU4)W]ш̓Xf,k e3]3tr(N!;LH9O +%}֚zKuU;ae žbqy8U@܄|Q3R@; 2 a҃v@aԱ)%j .pP6Չk8{/VpɚMj,#޷IF%? 'FHvC=:+\nQU.~(NeAPe6`\SҙR"133{ uB/G< gv)GC'8;~J{7sT$uc(ϊZ'_W3&{2C{I^rO/}͎Ft*GBJ/DPRoiIn>?T^\"ڍ9՞pIgv".lȶ`B& VɁ> 0Asi8P.N} w=QUAe>Ȕ 6d`%eݓzN o*̷v#E63/w=IjS癳1wF9F_˦7 8x\^*`ԍ&r3iw{TVNPH/2x%{9D5(0vz$aE%J Rui nTƀm%i;h/(ԖN'H;9&Ygz.Tp\y|42‰~RZ 탡+%ŭl|~:b]”u'X0TXh@`037N̖Y#eYW-TdHϕ셾r%(*,h0Φ;T ~`YM"d[wD@VJ@h֘ߢްՆ [& fRU$V!8 րmZ^flEvPսʆR:9{CAI}?aI7D%K}(_]$'8=̶6Iޏ GFÀA~ ][#G89w:rd-[7d 5-Ρ-m8%`c 84~`Z39c`hV$VH&HKyWD_R1l_ř3Xo +RO xVSK}@0ݏ\,1OSf'?a=0iALx#啌]]yCkP2$#MVe TKK@ykjL y[$Ř?,R*dO5["iuCjJWh0<&CnmfF `$ dF<}xc_'ch A:}@;W'|+ QRYND ZF]i7$PKEBuURUWEЛ lQ$%܅H5NQ.oꦷx:Súwp~Ro˴fą291: [E& =f}%}S%SWO'}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/fixtures/0000775000000000000000000000000012310410615013233 5ustar qml-box2d/examples/fixtures/main.qml0000664000000000000000000003005012310410471014670 0ustar import QtQuick 2.2 import Box2D 1.1 Rectangle { width: 800 height: 600 Component { id: ballComponent Body { id: box width: 20 height: 20 sleepingAllowed: true bodyType: Body.Dynamic fixtures: Circle { radius: parent.width / 2 anchors.centerIn: parent density: 0.1 friction: 0.3 restitution: 0.5 } Rectangle { radius: parent.width / 2 border.color: "blue" color: "#EFEFEF" width: parent.width height: parent.height } } } Text { width: parent.width y:50 text: "Fixtures tests" height: 30 font.pixelSize: 16 horizontalAlignment: Text.AlignHCenter } World { id: world anchors.fill: parent Body { function getVertices() { var pos = 40; var arr = []; arr.push(Qt.point(0,0)); arr.push(Qt.point(40,0)); while(pos < 700) { var y = Math.round(Math.random() * 30); var x = Math.round(20 + Math.random() * 40); pos += x; arr.push(Qt.point(pos,y)); } arr.push(Qt.point(760,0)); arr.push(Qt.point(800,0)); arr.push(Qt.point(800,40)); arr.push(Qt.point(0,40)); return arr; } height: 40 anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right z: 100 id: ground bodyType: Body.Static fixtures: Chain { id: groundShape vertices: ground.getVertices() anchors.fill: parent loop: true } Canvas { id: groundCanvas anchors.fill: parent onPaint: { var context = groundCanvas.getContext("2d"); context.beginPath(); context.moveTo(0,0); var points = groundShape.vertices; for(var i = 1;i < points.length;i ++) { var point = points[i]; var x = point.x; var y = point.y; context.lineTo(x,y); } context.fillStyle = "#000000"; context.fill(); } } } Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Body { id: dynamicTest bodyType: Body.Static x: 200 y: 150 width: 200 height: 30 fixtures: [ Box { x: 0 y: 0 width: parent.width * 0.45 height: parent.height }, Box { x: parent.width * 0.55 y: 0 width: parent.width * 0.45 height: parent.height } ] Rectangle { anchors.fill: parent color: "blue" } } Body { id: staticTest bodyType: Body.Static x: 350 y: 250 width: 100 height: 25 fixtures: Box { x: 0 y: 0 width: 100 height: 25 } Rectangle { anchors.fill: parent color: "orange" } } Body { id: radiusTest bodyType: Body.Dynamic x: 600 y: 100 width: 100 height: 100 fixtures: Circle { radius: parent.width / 2 anchors.centerIn: parent density: 0.9 friction: 0.3 restitution: 0.8 } Rectangle { anchors.centerIn: parent radius: parent.width / 2 width: parent.width height: parent.height color: "red" } } Body { id: polygonTest bodyType: Body.Dynamic x: 450 y: 50 width: 100 height: 100 fixtures: Polygon { width: parent.width height: parent.height vertices: [ Qt.point(width / 2,0), Qt.point(width,height), Qt.point(0,height) ] density: 0.9 friction: 0.3 restitution: 0.8 } Canvas { id: canvas anchors.fill: parent onPaint: { var context = canvas.getContext("2d"); context.beginPath(); context.moveTo(parent.width / 2,0); context.lineTo(0,parent.height); context.lineTo(parent.width,parent.height); context.lineTo(parent.width / 2,0); context.fillStyle = "green"; context.fill(); } } } Rectangle { id: ballsButton x: 50 y: 100 width: 120 height: 30 Text { text: "Falling balls" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { ballsTimer.running = !ballsTimer.running; } } } Text { id: ballsCounter x: 200 y: 100 height: 30 width: 50 font.pixelSize: 13 horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter property int count: 0 text: count + " balls" } Timer { id: ballsTimer interval: 200 running: false repeat: true onTriggered: { var newBox = ballComponent.createObject(world); newBox.x = 40 + (Math.random() * world.width - 80); newBox.y = 50; ballsCounter.count ++; } } Rectangle { id: dynamicTestButton x: 50 y: 140 width: 120 height: 30 Text { text: "Dynamic fixtures" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { if(dynamicTest.width == 300) { dynamicTest.width = 200 dynamicTest.height = 30 } else { dynamicTest.width = 300 dynamicTest.height = 50 } } } } Rectangle { id: staticTestButton x: 50 y: 180 width: 120 height: 30 Text { text: "Static fixture" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { if(staticTest.width == 200) { staticTest.width = 100 staticTest.height = 25 } else { staticTest.width = 200 staticTest.height = 50 } } } } Rectangle { id: radiusTestButton x: 50 y: 220 width: 120 height: 30 Text { text: "Circle" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { if(radiusTest.width == 150) { radiusTest.width = 100 radiusTest.height = 100 } else { radiusTest.width = 150 radiusTest.height = 150 } } } } Rectangle { id: polygonTestButton x: 50 y: 260 width: 120 height: 30 Text { text: "Polygon" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { if(polygonTest.height == 100 && polygonTest.width == 100) polygonTest.height = 200; else if(polygonTest.height == 200 && polygonTest.width == 100) polygonTest.width = 200; else { polygonTest.height = 100; polygonTest.width = 100; } } } } Rectangle { id: chainTestButton x: 50 y: 300 width: 120 height: 30 Text { text: "Chain" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { if(ground.height == 40) ground.height = 100 else ground.height = 40 } } } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: on" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off" } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: true } } } qml-box2d/examples/fixtures/Wall.qml0000664000000000000000000000042412310410250014640 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/fixtures/images/0000775000000000000000000000000012310072714014504 5ustar qml-box2d/examples/fixtures/images/wall.jpg0000664000000000000000000005271712310072714016161 0ustar JFIFHHExifMM*bj(1r2i ' 'Adobe Photoshop CS2 Windows2013:12:26 19:01:20((&(.pHHJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/impulse/0000755000000000000000000000000012310072714013042 5ustar qml-box2d/examples/impulse/Ball.qml0000664000000000000000000000072612310072714014436 0ustar import QtQuick 2.0 import Box2D 1.1 Body { fixedRotation: false sleepingAllowed: false bodyType: Body.Dynamic fixtures: Circle { id: circleShape radius: parent.width / 2 anchors.fill: parent density: 1; friction: 1; restitution: 0.5; } Rectangle { id: itemShape color: "green" radius: parent.width / 2 width: parent.width height: parent.height } } qml-box2d/examples/impulse/Wall.qml0000664000000000000000000000016312310072714014456 0ustar import QtQuick 2.0 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent } } qml-box2d/examples/impulse/impulse.qml0000664000000000000000000000255112310072714015240 0ustar import QtQuick 2.0 import Box2D 1.1 Item { id: screen width: 800 height: 600 focus: true // BOX2D WORLD World { id: world; anchors.fill: parent Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Wall { id: ceiling height: 20 anchors { left: parent.left; right: parent.right; bottom: parent.top } } Wall { id: leftWall width: 20 anchors { right: parent.left; bottom: ground.top; top: ceiling.bottom } } Wall { id: rightWall width: 20 anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom } } Ball { id: ball x: parent.width /2 y: parent.height /2 rotation: 0 width: 100 height: 100 } // Debug DebugDraw { id: debugDraw world: world anchors.fill: world opacity: 0.75 visible: false } MouseArea { anchors.fill: parent onClicked: { ball.applyLinearImpulse( Qt.point(10 * (mouseX - ball.x), 10 * (mouseY - ball.y)), Qt.point(ball.x, ball.y)) } } } } qml-box2d/examples/movingBox/0000755000000000000000000000000012310072714013334 5ustar qml-box2d/examples/movingBox/movingBox.qml0000664000000000000000000000336712310072714016032 0ustar import QtQuick 2.0 import Box2D 1.1 Item { id: screen width: 800 height: 600 focus: true Keys.onPressed: onKeysPressed(event) Keys.onReleased: onKeysReleased(event) function onKeysPressed(event) { if (event.key == Qt.Key_Left) { movableBox.moveBackward(); } else if (event.key == Qt.Key_Right) { movableBox.moveForward(); } else if (event.key == Qt.Key_Up) { movableBox.jump(); } } function onKeysReleased(event) { if (event.isAutoRepeat) return ; if (event.key == Qt.Key_Left || event.key == Qt.Key_Right) { movableBox.stopMoving(); } } World { id: world; anchors.fill: parent Repeater { model: 4 delegate: WoodenBox { x: Math.random() * (screen.width - 100); y: Math.random() * (screen.height / 3); rotation: Math.random() * 90; } } MovableBox { id: movableBox width: 40 height: width } Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Wall { id: ceiling height: 20 anchors { left: parent.left; right: parent.right; bottom: parent.top } } Wall { id: leftWall width: 20 anchors { right: parent.left; bottom: ground.top; top: ceiling.bottom } } Wall { id: rightWall width: 20 anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom } } } } qml-box2d/examples/movingBox/movingBox.qmlproject0000644000000000000000000000055712241175670017425 0ustar import QmlProject 1.0 Project { /* Include .qml, .js, and image files from current directory and subdirectories */ QmlFiles { directory: "." } JavaScriptFiles { directory: "." } ImageFiles { directory: "." } /* List of plugin directories passed to QML runtime */ // importPaths: [ " ../exampleplugin " ] } qml-box2d/examples/movingBox/WoodenBox.qml0000664000000000000000000000051312310072714015754 0ustar import QtQuick 2.0 import Box2D 1.1 Body { width: 100 height: 100 sleepingAllowed: false bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 1; friction: 0.3; restitution: 0.5; } Rectangle { anchors.fill: parent color: "black" } } qml-box2d/examples/movingBox/Wall.qml0000664000000000000000000000016312310072714014750 0ustar import QtQuick 2.0 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent } } qml-box2d/examples/movingBox/MovableBox.qml0000664000000000000000000000141212310072714016105 0ustar import QtQuick 2.0 import Box2D 1.1 Body { sleepingAllowed: false bullet: true fixedRotation: true bodyType: Body.Dynamic function moveForward() { linearVelocity.x = 300; } function moveBackward() { linearVelocity.x = -300; } function stopMoving() { linearVelocity.x = 0; } function jump() { if (linearVelocity.y <= 0 && linearVelocity.y > -50) { var impulse = Qt.point(0, -600); applyLinearImpulse(impulse, getWorldCenter()); } } fixtures: Box { anchors.fill: parent density: 1; friction: 0.3; restitution: 0.2; groupIndex: 1 } Rectangle { anchors.fill: parent color: "red" } } qml-box2d/examples/polygons/0000755000000000000000000000000012310072714013236 5ustar qml-box2d/examples/polygons/Trapezoid.qml0000664000000000000000000000061312310072714015714 0ustar import QtQuick 2.0 import Box2D 1.1 Body { id: polygon width: 100; height: 100; sleepingAllowed: false bodyType: Body.Dynamic fixtures: Polygon { density: 1 friction: 0.3 restitution: 0.5 vertices: [ Qt.point(-10.5, 0), Qt.point(0, 100), Qt.point(110, 100), Qt.point(100, 0) ] } } qml-box2d/examples/polygons/polygons.qml0000664000000000000000000000215612310072714015631 0ustar import QtQuick 2.0 import Box2D 1.1 Item { id: screen width: 800 height: 600 World { id: world; anchors.fill: parent Repeater { model: 10 delegate: Trapezoid { x: index * 150 + 10; y: Math.random() * (screen.height / 3); rotation: Math.random() * 90; } } Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Wall { id: ceiling height: 20 anchors { left: parent.left; right: parent.right; bottom: parent.top } } Wall { id: leftWall width: 20 anchors { right: parent.left; bottom: ground.top; top: ceiling.bottom } } Wall { id: rightWall width: 20 anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom } } DebugDraw { world: world anchors.fill: world opacity: 0.75 } } } qml-box2d/examples/polygons/Wall.qml0000664000000000000000000000016312310072714014652 0ustar import QtQuick 2.0 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent } } qml-box2d/examples/cannon/0000775000000000000000000000000012310410246012636 5ustar qml-box2d/examples/cannon/main.qml0000664000000000000000000002422512310117170014302 0ustar import QtQuick 2.2 import QtQuick.Controls 1.1 import Box2D 1.1 import QtMultimedia 5.0 Rectangle { width: 800 height: 600 Component { id: link Body { width: 20 height: 20 x: 400 bodyType: Body.Dynamic fixtures: Circle { radius: 10 anchors.centerIn: parent friction: 0.9 density: 0.8 } Rectangle { anchors.fill: parent color: "orange" radius: 10 } } } Component { id: linkJoint RevoluteJoint { world: world localAnchorA: Qt.point(10, 30) localAnchorB: Qt.point(10, 5) collideConnected: true } } Component { id: ball Body { width: 10 height: 10 bullet: true bodyType: Body.Dynamic fixtures: Circle { radius: 5 density: 0.9 friction: 0.9 restitution: 0.2 } Rectangle { anchors.centerIn: parent radius: 5 width: 10 height: 10 color: "black" smooth: true } } } Component { id: dominoComponent Body { width: 10 height:50 x: 0 y: 510 bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 1 friction: 0.3 restitution: 0.5 } Rectangle { anchors.fill: parent color: "black" } } } World { id: world anchors.fill: parent function createDominos() { for(var i = 0;i < 5;i ++) { var newDomino = dominoComponent.createObject(world); newDomino.x = 500 + 50 * i; newDomino.y = 510 } for(i = 0;i < 4;i ++) { newDomino = dominoComponent.createObject(world); newDomino.x = 555 + 50 * i; newDomino.y = 500 newDomino.rotation = 90; } for(var i = 0;i < 4;i ++) { newDomino = dominoComponent.createObject(world); newDomino.x = 525 + 50 * i; newDomino.y = 450 } for(i = 0;i < 3;i ++) { newDomino = dominoComponent.createObject(world); newDomino.x = 580 + 50 * i; newDomino.y = 440 newDomino.rotation = 90; } } function createChain() { var prev = chainAnchor; for(var i = 0;i < 12;i ++) { var y = 300 + i * 20 - 5; var newLink = link.createObject(world); newLink.y = y; var newJoint = linkJoint.createObject(world); newJoint.world = world; newJoint.bodyA = prev; newJoint.bodyB = newLink; prev = newLink; } } onInitialized: { createDominos(); createChain(); } Body { id: ground height: 40 bodyType: Body.Static anchors { left: parent.left right: parent.right bottom: parent.bottom } fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Rectangle { anchors.fill: parent color: "#DEDEDE" } } Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Body { id: canon bodyType: Body.Dynamic width: 98 height: 37 x: 150 y: 443 fixtures: Box { id: canonFixtire anchors.fill: parent density: 0.5 } Image { source: "images/cannon.png" anchors.fill: parent } } Body { id: canonBase bodyType: Body.Static width: 130 height: 67 x: 50 y: 493 fixtures: Box { anchors.fill: parent density: 0.5 } Image { source: "images/cannon_base.png" anchors.fill: parent } } RevoluteJoint { id: joint world: world bodyA: canonBase bodyB: canon localAnchorA: Qt.point(75, 18) localAnchorB: Qt.point(36, 19) collideConnected: false motorSpeed: 0 enableMotor: false maxMotorTorque: 100 enableLimit: true lowerAngle: 0 upperAngle: -60 } Body { id: chainAnchor width: 20 height: 20 x: 400 y: 230 bodyType: Body.Static Rectangle { anchors.fill: parent color: "black" } } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: off" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off"; } } } Rectangle { id: upButton x: 50 y: 90 width: 50 height: 50 Text { id: upButtonText text: "up" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { acceptedButtons: Qt.LeftButton anchors.fill: parent onPressed: { canonFixtire.density = 0.5; joint.motorSpeed = -15; joint.enableMotor = true; upButton.color = "#AAA"; gearSound.play(); } onReleased: { joint.motorSpeed = 0; upButton.color = "#DEDEDE"; gearSound.stop() } } } Rectangle { id: downButton x: 110 y: 90 width: 50 height: 50 Text { id: downButtonText text: "down" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { acceptedButtons: Qt.LeftButton anchors.fill: parent onPressed: { joint.motorSpeed = 15; joint.enableMotor = true; downButton.color = "#AAA"; gearSound.play(); } onReleased: { joint.motorSpeed = 0; downButton.color = "#DEDEDE"; gearSound.stop(); } } } Rectangle { id: shotButton x: 170 y: 90 width: 50 height: 50 Text { id: shotButtonText text: "shot!" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { acceptedButtons: Qt.LeftButton anchors.fill: parent onClicked: { var angle = Math.abs(joint.getJointAngle()); var offsetX = 65 * Math.cos(angle * Math.PI / 180); var offsetY = 65 * Math.sin(angle * Math.PI / 180); var newBall = ball.createObject(world); newBall.x = 125 + offsetX; newBall.y = 505 - offsetY; var impulse = power.value; var impulseX = impulse * Math.cos(angle * Math.PI / 180); var impulseY = impulse * Math.sin(angle * Math.PI / 180); newBall.applyLinearImpulse(Qt.point(impulseX,-impulseY),newBall.getWorldCenter()); shotSound.play(); } } } Slider { id: power minimumValue: 1 maximumValue: 100 value: 50 width: 200 height: 50 x: 230 y: 90 } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false } SoundEffect { id: shotSound source: "sounds/cannon.wav" } SoundEffect { id: gearSound source: "sounds/gear.wav" } } } qml-box2d/examples/cannon/Wall.qml0000664000000000000000000000042412310410246014250 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/cannon/images/0000775000000000000000000000000012310072714014107 5ustar qml-box2d/examples/cannon/images/cannon_base.png0000664000000000000000000002526512310072714017075 0ustar PNG  IHDRCPgAMA7tEXtSoftwareAdobe ImageReadyqe<*GIDATx}nLOqs]i"$lI> amwl"9w&sa0HB WJwywrΩ}mLOOOOW_}UafY3@Yf0af2e3 f , {|s-A,A, +8h&FzWb1hHdr8 D3d J CPZj[d"z~@t&⹋q+eE`u@.rK&ATV  Baf+*./(eF#AdP={FwArCV*9UCF<,LB1d "'A "MfHbxA+B)(~8 EQL$ ڶͪ۴lт%qۧ&4~C,wo`rG)H}b8~#C12bP61{NO"tce#\ѽazd4OZmmR> ځS]ugWϯ0bu: T9avhP J@#0@Y7)$$aw}iP٩γ/8~-(xQU Ϥ/G#(`2t*zG/(P8J#@D@ B"1O **[#{S-Hzk%Ύog$F?JE , Yl G 4OT/I F87+ lThųj Px<$ݐ[/A"UmꚖΐDY2&?N}8W$/K*䗶f2Sh,FX 2Fᘧ؀Djm5~4R&mkĵAդQ˂)LnWԝc/oW{Wݳfʇ.Z`1R9k/Hm8!TC,M |ٲ%Rq61o&b)3AS hLe ftArqSMJDBP*A; 1XDp\Lid5y$١v~;uU(>:3@PA~q-z]{D1=}rƆ/k=qՕW=r/7W.hTKd4$3Aq*= AU5cb2,M!5&HH)=)h" 0d)a_-'|ȺiG #XJh8y+-H^ =L_W1f F.[Db1nosڏ6:m]]g6 hZ!Q[ [aɜ"f|.ijTX#pP`VAY$J܇Ely igs'o_!N8}K"F\zu7 <DcH! +' èSPhhns V"^zơ_Myg)|Er"4,8Ǔ|)F@}֨)o1d*PQZpVW hփY+[͙rҝ>srÊcdo*:r eDx:GDh *3^Νĉ[w}ss+J1:(*J lu`|/ dPY/g=X(Ȅry ~PUf= 119 [&-hba2TNg\hN.U*UPQ^{`xte OYJN.G\ pGASy&L㓓 s}hC0΃251D"N!Х0bh7 ApmgHr@ԙ*Q+ual*erd(z:N#L&J0"Dc)0P}̠Iql6551R?=5(-*<(pB׿4lz#b$$@gX $EZ-YN-)LDJMuBL (鄌CKm4ĪAtd9 V(*K @6@@]gAL2xqP+9]P$v(S=U>rYxvB!Db l̤O̘$ %I@:lvgI(V(Qo_Z(4m 젷q[! aD kQ[]py`s,Z4 (d4fHG̀ M%j("2'(XQFqIddK&cMF:Jx8so@{?#@%#= ƊWY./A(-"':{}<0&eΡb*'ŸL*acHDod\b-7[尢X0,PZ3 :`s@() w=7X+<G EpTRt.7v}G bj.HpWQ͞G"/l2Ҽ$+LOO^Z>I9iD*48F#t$HJwa9(:t>M~Q Ϟ 9@+G0S"Hx& DƧ䈥)Li*Ϟ锪U*?sH^3 Lj)d3L wXA鑆Og! YNȾԜk8'Pb0x#C53 < 0Hk: /-L {Ev_v9je>JMH@,L@2/`Rw0&H&8f443w!}R"MFrH4f_1) UgRܜAqD"Ii RljjήRF8Z it T*C.*.*" "r$~3ECC90IԣeH>vaddP:5ڌj3HDԈJv4PHT糱(J2/5,P HZPDR@.ڕ}| |k+W>.r{ PLqA񄥥U]'; ]jN!k}FD  v<}JςT"A򱉩';X{Z埘QS7ņv z i)(l8Ic5@ BFef頥*5\!.6+}+[W[]6oiUu?+ yۍ/|T*U̦iVƆz8}F34 )F919HǃPݸ㵌A&{\uQNd Łn4fu *$D$h?'́1X@vWG1CY\܍! Ƽ<0f:} iÿ/rg? _`ժyկ8MW_}?^uU/?p:꠭;nafI 1UKzῡ$wt1Tz'0MMeB tv(T_`\CLp$8_ٺn=W5cJ:<]j1{a`& ֭[X?ŋG^x~?̙3W( b4NwDEyZN)GtJU_[??r8w &Gz@o4B۱;V!f7(#sr6NB9JfzP Fp(˗/=8,o _җ~b2Mo-׬voOOOΝ;+zn|+У{hhhX~{Djzz]K5eK7)?4!or6eUtv{-9QJ%W|b3@!lPRCP@oϏHTN'9-8g`lN/Pߩ\CZ ;}˖-k׬YIp﮻{ZZZ_l[ǎ6f&''oqEE =OPVVӉlІ~eQa+_kaAqAپdExݳg}%cM[+JlkRt@t/&$x696= n !vtvώBVfB&i f??ҿP,jTOs5ZQuCwiŸk0+?U(ަ:7n{ŋ[oza>x 3/C "}k_xWs h LxQC<j&xصg c?‚7b-/6ktߡ#݌LzyM=M?o'pnhnluW;o4-Tb4ZREKnk;3/NiG v&H,Lnukx1g+!EE"nsjB08 W0s˺]t զ yQD"huƣ*j\!?MNh p O#)4D%PYU yGP#p]}DZ~T,U+Nww?v{_T5$cAgπ ة)uVc޿{g<B-\*f\ `0dc_H j58mV0YV/_##4݄0ĩ3OYmC/߼yD!G+DVMr!ȍ~i:Sd2ax|/Ȇp|nQA!TڴT&/(:LbX8. |d0$DaR VCy/,zv>4 g5xz=Sæ> [@m_l.̭sYTf&|nHdܫ+F~D4fyIQ( Yŷ;qÆq\*Ap~)-V&e#CM+[lhTMCH}u+/QR$g1I2EPŧX".%Ê\f#6 dgpv.Bu}CrdEc575Hd}eXRáMwDxu5n|vyƒ_A '-M /k[.;Ns3#m?.:WDblSynzA8gBP[qBG}ܟq`Ό@"IxTb2ډ5^"L/-]@X! p_r9 ?(\:wg &J@p =Ud [QZMuoW˳cPHw MMM0;XާKtzpy<}U 하.$bηtmn)e^tZ-2uӖ2ۥ_Ƌcu ~|i荅*Rc x '|$.p4 AbG213g 4\ E3\.Ǽ $Yfj ?'#΅`~s롾CYưD N:zGiQ@ v`mn~2T4>1Qku8O n<+=e( +2Mm] n:jO0υ@l4k#svp|tPp*IC,y4H-$jNjg)NHB[rT'z"ZF2lϛr3vn1A =,2seFmp)P(@Nv c8mBXr5$@3YBUPnkV)N4>YR\* cʞ󌐟gD#@ٿb(y-0 KV#5f.ls??o斜{$/0*nWO k{||5DY-`}GUtlv&ήn8 V;`m PiDqrٶH<!]UQAqa-FCFσf>Zd1[Y̥k^8 sw욣z4 F7?@OF݄]kTf)q@9aý3MC_8o.`xt`|j .=. Oݻv/~Ko699M!jBBIqe& Y/\.??jr^= _B3~t>W:4`4mQD"Q w}^s8QF?DMɑ1TJ%H:-Q$~$!}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/cannon/images/cannon.png0000664000000000000000000001453112310072714016075 0ustar PNG  IHDRb%< pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FtIDATxZ[oGv:==7P eQǂm9Pv X`<%O`OC^$/ ll/0`ZVlQD.M3Ԑ3왞UWU^Xx,1};;N&ioS"N)DS"N8mD4:>R" Clmma8¶m;w:ױ pU躎Ǐcnnkkk, W\A^GEȲ a"MSt]0P*`YZ s DDnݎ$۷w֥_=Mtxv{֭p8lq\t:k^uŋCh4n޼ckkMt/籼n$I92:vww<CE~:Ξ= 8 l64MnAAp]^B͡hncii vZ TiHYjpaBJ ua&F<!Qh4MH)91>DZ=??H)+R%JidF<<:F8!!iZ1. Iܹs,?赯w X`miz3sM4mC4B@(rS=j_[O)=vLX?Ji>[4!Yyh˗ 0 s ÐG^2=e!IF$0 c@1Sv|͏8ljHi*\EpDɓi1V}kiEeιfYt]z1A<.6BOGrΧMw+/<:4M˲Ui6Ft]1dYwvww٥EWMsB98>iYeqO>^WmJFJFBY`(&8F@ǒɹ+(-'jR߆aXSuYQ10,jY-s> &/= xunZ8_q̃99iBᅅ/reB7ؚ|Up+s{쏺8˪Vȓ9 YXLuZJ;v&"aЊ`U=(4qy0Iqkii~4Y=kZ'OZmtm7_> {.pr@ZMEnVeιb x׬Rb4MdY,`&LL8|c,u/..~$ɾa/_6cnnժgvaM(Bل1ƾ=bd8(>RmOFife i(Dd\ '=EɓZרWX,DT*,ʭV+T*ضj^|޳gr9^\\\v]۶+ϟiiP0 !`!IZ-!EJ(zxנY9QZi۶ yCJ;A(^w^k6Hd1c Vl4ZUcT$%IJXǩ{DED ȶ, Z%LӴҦi/(ZR9s~|4ovpe^_YYAT)s]דN ?&m۰, qɏyuJhv`Yg.]w5c Zr8>It: Y55x5}i-Ƙ=MʌիW_J);azel95MΜ92jg/*oơy/VWWyRǼ% CDQ]דpy_xspQ*0l6q}PJ!lۆa8<<*v]x0FLe˲ŋ?F^hdꫯ\rJ̙3zu8.4 [oB_~yjvi:{ xqlv֭[CUT*ܹsis4 u9<c}a0$<84M,P.94E\aA`0i<cOtN8%ⴝqJi;%ⷧ49UyaIENDB`qml-box2d/examples/cannon/sounds/0000775000000000000000000000000012310072714014155 5ustar qml-box2d/examples/cannon/sounds/cannon.wav0000664000000000000000000131764012310072714016164 0ustar RIFFWAVEfmt Ddatat    ""//333311//++&&   ..ZZnn__99 ##<<EE>>.. **NNccUU##vvvvhhPPSSzzee]]ww %%))//SS[[KK99114411""??II??----jjzz$$++..__YY``VV++UUqqyymmPP))JJggddDD<<kkffHH::EEkkooaaCC__44jj}}[[yyttBB[[uuvvTTBB<<66))++ffLLTT66GG__ii  gg55<<&&HHNN77//// $$55@@DDEEEEAA66--<<vv::vvoo1133<< bb  ssVVjj++''ooMM bbggbb55``[[77 ZZ22EEMM __ ookk""99  1144 __gg&&II""GG$$ccPPFFjj**^^%%HHbb88''22  ,,ffmm!!~~}}mm>>pp  eeee,,NN))ppCC!!%%OOjjvv]]pp))''xxss&&ll88xxll{{>>pp[[GGPP""xxEE((  II44yyIIhh!!    II}}  FFiiZZ44OO]]__((__<<}}""~~GG$$  RR44FFkkuurr~~nn~~xxqqQQRR99uukk((jjFFrr<<TT77CCnn_ _ TTZZPPjj$ $ ] ] --RRHH>>kkDD^^..II##''MMll..NN,,BB++xxrrUU   rrqqCCee^^ggZ Z ] ]  OO  ||11IIJJ 3 3 jj ,, u u JJUU   **kkQQLL!!7 7 SSeeFFkk7 7 I I I I 66""eeMMhh!!^^N N \\@@yy]],,ttKKLLooLL  ;;YY% %  GG!!44  zzyy&& 00223366pp x x ==BB UUBB ffEE}}DD* *   bb%%cc~~,,xxbb88j j PPtt((oo0 0 SSW W TTWWmm ` ` k k hhDDee) ) ccccxxJJmmy y  >$>$##  ]]ff))ll''KK((  RR ? ? !!mmEE||!!;;IIC C ;; cc}}h h qqll66AAxx33**++YYhhP P GGIIttDDg g uu&!&!y"y" PP< < mmNN  ddvv $$""!! jj!1!1CJCJH[H[YY>A>A//$$߉  )),,6!6!^ ^ J.J.;;AA@@77%% ccyy;;$ $ ))DDTSTSMM~2~2l l nn,,^^uuff<< d/d/QQeehh]]KK77~"~"bbD;D;\\uuO~O~vvggNYNYZPZPMMMMIRIRZZ``cc]]MMTATA??-K-K^^jj9b9b]A]A ԡ ͔DD::QQ?? ݴ))bb}}uuZhZh]]SSJJHEHEAGAGVQVQ^^1j1jnnll>Z7Z7.-.-+'+'&&&&""**j j !!&&&&''**//F1F1=%=%tt[[UUNNՂՂ!!//YYUUӊӊȊȊъъ]]44ȏȏ<>iimmAAΕΕ""ווOOmmWW((ddHHyynnSSNN..ђђww φφUU bbaaffҹҹ~~uuMM33aa~~PP??__EE–ÈII;;UUMMqqyy^^)) ``^^BBޖR0R0cOcO>??QQ __ 11``""nnEEcc D D :: uuxxSS""**__YYuu׍Ӎ٠ӠӉى$$))@@TTCCYY&&ljΉ^^gg``}}22ݟܟ}}߽gg &&ooDD((ZZiiMMaaUUݨΨzzɠ͠^^֣ޣދ ++nnxx;;||ݣףPP܊00xxyy&&^^::ܬ``ܴش̸ȸ00--tt؊܊ܕYY@@נݠrrhh::&&##UUYYCCگ11շη^^<<ȼҼSS&&SS33<< ѠРUUCC33xxooˋ˧HH%% ݩݩKKƜޜ22aaڦڦڿzzpp@@QQކކժժ棂ӜӜ&&**ייHHPPSS44ˊˊ ee__ؠؠ22TTtt99<<܏܏ZZ66&&zzЃЃ33**ҔҔݞݞ--88ܜܜeeNN̒̒??hh!!ìƬssɳóÿGGZZ W W T T 11ee؃XXII33@@/C/CG@G@<<<>CC22ddbb  ++II22= = %%**44T7T711""''jjX X gg::nn))77<<;;<L>LlOlORRRRLLHDHD>>AAdMdM[[HcHcibib<[<[EUEUVV^^hhzmzmkkdd``bbeeee=]=]MM<<1100o9o9:F:FRRYYO\O\aZaZTTKK*B*B::99==zFzFlNlNQQMMGGCCFFNN6X6X:]:]ZZ)R)RHH'C'CdCdC(G(GIIIIDD.?.?;;;;9999.:.:D;D;(>(>CCmKmK)Q)QQQKKAA'9'95599AA>CCDD@B@B==E:E:77n3n3**}}**LL11zzhhh"h"?"?"  yyBB ^"^"#'#'((W"W"::kk ױױ%%--MM && qq~~&&G!G!"" ++ ffttRR??WW ++k k ccFF  00 uu##..݂55܆ @@ !!cc\\;;SS``FFq q rrff5533CCWW33II22HH~~qq   :://ߞڞچ݆22UU11** OOVV;; &&**BB99ll**ZZJJll  PPyyї[[Цmm $$__NN͊Ŋ77''[[MMРӠXX ll&&//ppLLDD ??  OOxxXXԢE%E%% % ss~~A A &&      mmuuFFaa߇mmL%L%#)#)##__  qqUU 66SS  ..qq f f   ( ( [[Ͼо||Ӳڲ  ''ԅBBҚך٢΢ׁ66\\77vvKKR R b b S S ` ` MM۩۩ ۗۗkk));;==ܸ44yy++AAnnSSrrhhuuـ̀ɿпй޹00nnrr݀€ee66ߣ::~~::,,FF((kk$$ىى@@RRkkQQ -->>##88͡͡RRuu))$$ XXBBEEʳӳӡޡ޵ ##&&H(H(_%_%66UU##22BBMM"T"TTTPPFF::e1e1..44=A=ANNUUUUOOHHmCmC@@????>>\@\@KDKDIINNRRYTYT}T}TzRzRZMZMEE<<6699DD*R*RYYVVGG]5]5((''j/j/<>}:}:a8a8L:L:W@W@GG\L\LJJ@@55--,,22/;/;AABBBBDD&G&GZJZJKKHHpEpECCCCAA-:-:h,h,\\&&55>>::,,OO  ## xx,,//AAMHMH&B&BA5A5((!!!!$$++11s8s8==<<66**XX4!4!##""II PP66jj""ooee""ZZ((**S&S&p p bb""< < (!(!*$*$z+z+ 7 7CCGKGKHH88))==צMM77ݡݡPPۅ  3399a1a1!!DD99 66eennee""u$u$""zzYYB B cc--bbddrr88&&eeRRQQ UUnnJJCCՆFF޶33GGaaաʡʪϪϑ``]] }}]]S S ttBB y y `` bb\\""dd""E E tt::CC !!((**D'D'""^^VV""**//00#*#*zz[[8"8"__ll##  ! ! --00e-e-88V8V8))MM//xxeeQQ2277ʭ𤓠``FFjjņнؽ;;<<88qq..ۢۢۡۡGGNNffTTϐϐѝѝIIݺݺʃʺѺ}}˩BBoossͺbbii& & **DD==ZZ??ee::llHH77ŕŕ``SSiiӢӢ++IIȜȜff00 zz,,>>LLOOFF~3~3c c %%== ::aaC C &&qq **>>LLRRPPJJFFjEjEFFHHHHGGFFcFcF5F5FCC<<{2{2))|'|'..2<2<IIMMyGyG99=*=*!!z"z"n)n);1;1V5V5k4k42020++<)<)))++,,** "" \\DD^^&'&'t/t/l.l.E'E'  ##..w:w:DDEHEHVEVEJ4>FFRKRKJJEE>>66--%%AA  **::eKeK*W*W[[WWZQZQMMNNoSoSXXYYnTnT.K.KoBoB==<<==<<66//`)`) ' 'U)U)..33 6 6.4.4..^'^' ..{{ !!dd33[[  PP99DD ####$$''303099>> = =445*5*"" q#q#.'.')) ) )S%S%66..Y Y ||""9 9 ~~ٚٓœŹSS99>>ʯ˯VVvvccHHڹ33uu hhӶĶuuūū66nnJJݼмСǡ**ąą""pp͂Ղ՜~ ~ 33!!&&,,2288y>CC鲄ʌ``vvwwժΪ%%**bbhhpp''&&00 h h ""C C ii22/$/$&&&&##44||  b!b!$$##G G ggO O ""rr((//ssUU&&77[[  gg&&))##wwccII GGs s |.|.q7q744]$]$ OO~~޳ܳ((UU ''00778822(($$XXLLzz**55ޝ"" O!O!))$*$* >>^^nni i 22;;҃փ֧ڧDDgg}}KKjjFFPPBB.. 33PPLLjjNNߋ66xx9911ȇ‡Ɖʼn,,''XXII33&&%%נߠKKnn**kk5544MM[[hh--$$kkýý.. CCݡڡhhץإ@@דԓzzżż66Ƨffʢ̢yyoo==ҼӼOOۭaa55 **:2:2#;#;88.. gg ll++  &&00==HH9>9~6~688T:T:66++ ii%%b3b3;;==J8J8;0;0R(R(~#~#""$$''))++--1177@<@<>>::^1^1$$  EEll؃Ճկԯ>>}}ҹҹ]]""ɄɴӴHHaaGGddII``y y ttffCC??vv::9 9   !!ooZZ^^""==޻ֻ&&99yyVV į``''oo׷׷22ooggββxx77rrڷڷ88II --ָָAA88WWգ̣PPşğggSSܐ܌ьjjKKٗ__>>ݍ֍֭ڭڊLL11DD(U(Uddqq%z%z}}`{`{ttkkaazVzVMMFF$F$FvKvK_U_U``jjararIwIwzz||}}||wwEpEpffr\r\QQGG==~7~7$6$6$;$;6F6FTT.b.bkkpprrttww{{~~}}}}~~ss{{sskkffdd6d6d b b0]0]WWQQ*K*KDD;;00%%ss SSc c ##*$*$ % %X"X"SSaaWWUU&&ڈ߈vvssƺɺoo\\۟ԟԬ̬\\qqYY֑ӑȗǗ??FF$$ZZ##߉։ۭۭ..//GG¨Ψjjjj99jjccتު''nnbb$$jj//""77++ll ==]]~~ ||V V IImmѳkkffqq&&[[RR׳۳bbZZZZ}} vv//MMDDڕەn n %%  uuooJJss)),,((""KKnn""&&z)z),,....m-m-,,**=(=(##--~~ - -==KK S SUUWW-\-\aalflfffbb\\YYXX[[]]]]ZZ2V2V7P7PIICC%B%BJFJFGOGO-X-XZZWSWSEE9977AAOOYYMYMYPPFF8C8CGGXOXOTT0T0TPPKK#I#IFF C C>>===C=CNN^Z^Z6_6_!Z!ZFNFNBB;;#:#:z8z8-2-2&&GGkkWWLL%%  66##~(~(&(&(= = ||~~XXtt^%^%<0<0v2v2--""YY--33!!¤Ƥƴ̴JJ""zz&&ߨ##[[--jjccqqnnߡ~~@@7722 DZȱ''ʼʼSS""몠%%DDӼټ--ܩܩ܅؅غϺϬOOCC HH{{&&PPII//iiɩϩ//тӂ00TTNN~~!!TT߶ߝڝeeee==}}{{??ݷ00//``QQ^^aa""jj%%EE}}VVAA>> Q Q ss{{OOYYKKJJ((778 8 { { V V ""''h.h.//))ll44--::CCEEEEREREFFIIKKJJEE>>55//^,^,++++D+D+****,,J0J0L3L3r3r300i+i+)),,33C=C=\>88A6A688K>K>>B>B]@]@66&&aa  dd00>>@@D5D5""bb44..AAvKvKHH<8>844)) zz##'/'/T4T4p1p1^(^(1!1!))%-%-''  HHFF##u&u&II&&!!**[[q q xxNN++uullEEUU߇և``77݋FFۈψ{{˱ѱߌiiWW˯WWݿYY55""..çħcc))HH~~}}EEVVɃȃAAաء ӥإ@@hh||cc>>ߟ}}MMVV((ߠѷη66aa֟ӟ00hhޟNNttLLss hh   ddJJ %%)):':' OOSSY!Y!+"+"KK##?2?2::7878++Z!Z!,,446633+,+,##%%..4411M)M)CCZZ++SSq q NN((JJkk99**;;!!<<||pp @@ppCC99ѡ̡VV##33j j FF||VV,,ޅ--((00] ] 99{{   ,,[[XX ((mm^^ oo66 8811Y!Y!""&& NN@@55~ ~ ..ttAA--$$ss <<ee]]UULL99 VV``IIyy__SSggCCݽ޽ޒ   ll+ + rr;;ެ޽ܽmmll~~cc11{{ݮIIaa۹NN DD--]] 66uuzz--33..##HHvv DD ll11||m m zzS S 11@@((ڡxx33&&bbT!T!''%%ZZzz SS܉պѺggIIхօۃ܃[[ٛқxxRRǩǩǃ˃ˏЏԂ؂ LL)) o o qq**ii]]QQrrII--==2 2 ||xx  >>3377''2288<<@@DDSISIJJEEG;G; . .""++ ((115544P.P.|%|%++aaiiJJ$$h,h,#1#1//''''tt ..^^mmmmddTT   NN//AA   __??~~SS3 3 ""{{   ^^55^^΢Ң oo  zzzz  **  % % 9 9 hhAA++aaΧȧ``ȞΞllVV  **ggttޱ ǹÊ66^^$$}}77̄˄LLzz%%jj}}ۚݚ//NNrr$$==qq]]bb@@XXCC iiIIMM;;IIsskkaaUUgg55   %%//77??FFLLLLKGKG<>33++''))//A4A4q5q511((??ffwwqq""&&''"&"&!!aa^#^#$'$'()()******))%%  ccuu[[[[YYxx^$^$F)F)++++((:$:$GGIIKK  ((q/q/00%,%,{#{#ggnnyy""`%`%-&-&##/ / UUqqww: : ww[ [ HH**bb   & & <<uuww>>TT4444KKssee||22VVyy__ֺԺ||SS22ZZ((Ӷֶ֯ӯiiͼȼkkҵӵӒ֒""܁݁ݵ۵((KKԐѐѸиЍэ== ҵεεʵllǰɰɐ̜̐ΜцՆՐڐޯ߯߱۱WWQQaaLLWWޗbbffڱױ9977[[xx,, ˮ̮%%RR@@ ggvvkk((TTaann II mm% %      P P | | , , {{D D   X"X"##D&D&D+D+2299#=#=9900$$11**  $$0&0&""{{##''e(e(A&A&##""."." NN%%>0>0J7J77711''))hhs%s%e,e,//++3#3#66qqJJ && ) )F(F(''))..O4O4`7`755v0v0(("">>vv%% ]]__::ffnnDD ))OO$$,,_2_2T0T0##EEss//<<CCNN  f f u u @@^^VVKK<<  &&XX>>  ;;**ܻһҦЦrrff 11\\``%%wwܳ۳iiޅPP PPۥ٥ڃ݃99ޱݱݛݛݫ߫uu~~ فځ44hh ކ؆ؼӼӆ҆qqeeKK^^ZZ GGnn88 %%yy<>ߪkkAA**!!))XXA A v v n n PP99``iiOO==PP==!!5544oo H H 66VV   ]]xx88''rr||11ss  vv ~~:: K%K%:&:&##cc vv   ss//uuUU G G  hh##KK\\GGWWBB00__00aaٺ٭ԭԗؗ""qq;; ||..==``]]BB--PP||OOjjqq//QQQQ߁ہۤ٤??EEzz//}}99&&11aaSSoo{{<>Ӯʮjj׽ݽߣߣ߬߬RRTTss##pp TTиSS  QQaa''NN //!!  JJCC1%1%//88==(<(<55..,,00S8S8T=T=::00.$.$xx**::GG,L,LEGEG = =330066cCcCZQZQUZUZYYOO&@&@11**3.3.6;6;iMiM__jjmmdd;S;Sc>c>--%%**88{I{ITTUUNNBB66u/u/++)) ) )((Z*Z*..55m>m>]G]GMMNN2H2H;;--{#{#!!P(P(116633B*B*n n 11##Y%Y%kkKK# # k k i!i!  LLbb^ ^   | | NNzz~ ~ (( '') ) {{ݙ̙SSllǞԞ$$QQxxOOBB~~yy!!ۥܥ@@iiLLAArrHH־־kkTT~~֊ҊxxÓккCCǣԀրׯٯٟڟ{{**WW>>οο ,,~~aaxx33xxttPP;;33nnaa<>##;;Ծо@@KK66ff EERRrr``ss/ / mmd d r$r$####ll)) ,,} } !!!!+%+% & &""WW--eeBB?&?&!(!('%'% OO9"9"''',',,,))%%$$%%**0066Q>==88?$?$@&@&q(q(++&/&/{/{/,,O&O&e!e!u!u!%% * *,,,,((2"2"  JJ##((W(W(##eehhBB\\ RR??݇ݯۯuuݏvvTTyyWW[[55%%77AA22!!޹]]GG۞ߞ߸''PPvvҐϐrrhhYYyyQQ ccggڽ߽44KKܠܜ؜22׍؍;;xxjj߿߫ثppВ˒zzہ77mmNN77MM  }}**88eeZZYYOO kk DD0055!!) ) :: DDg g s-s-X2X2--,$,$QQ##**..,,p)p)T&T&##m m    oo v v }}JJ= = ff""PP226633޸ո,,jjvvvv[[Û;;ƫ55ӝН˟ğą,,EEXXOOȨȨآآ⤀yyRRuu~~ֵֵ((ѠӠӯϯϸǸ}}33``~~mmŝ˝((ڄ݄ݓݓݪުxxSSiiuu''NNeeKK v v DDyyR R ))--.,.,='='D!D!&&##--+8+8"?"?@@<<55M0M0----=.=.N,N,''R#R#!!Q$Q$**\1\1554444//n+n+)),,33;;AABBj>j>q5q5**!!$$MM%%=/=/99JDJDcLcL$P$PZNZNmGmGh=h=33**%%$$t$t$&&''(('' $ $  ; ; $$F$F$ %%ZZԣˣԧܧ̮ĮBBbb99OO qqpptt̑ؑ99ݾؾ؍ύǜĜhhž66eeǶٶ88{{--ڳ۳99EEܢע??ӋЋUUڂ ݽٽRRUUqqڢעUU%%١||ppRRIIL L XX99ffZZee__--\\77TT%%RR܍Ս مnnRR ww__VV RR66޼ּ֒ՒII~~iiqqXX**RR--llLLee ??ђ˒˂͂͘Ҙ kk88{{YYͺԺgg((A A QQxxl l 777777QQPP^^KKbb**NNRRxx@@''ll  c c ||iiC$C$))--m0m07171-0-0}-}-))$$ >>y$y$H,H,R3R366J3J3,,e'e'&&1,1,&5&5Q=Q=kAkA4A4A7?7?>>uAuAFF-K-KLLJJ-E-EK?K?7;7;99::p:p:1717//&&) ) ))99KKzVzVWWPPDD::99{B{BRRAcAcppuuWrWrggYYJJ@@9988==ZFZFSSEcEc]p]pvvrreeRR>>//$$   " "K&K&q*q*B,B,U*U*%% &&11L=L=7F7FJJKKRKRKIIEE??7711..00Q3Q311))$$\\VV""((((P#P#ww$$C)C)))$$}}QQ< < ##""dd RR33YYQQ`` a a BB  77 pp77..SS66DDSS00NNKKUUQQ߶׶gg݄NN00DD ܋ڋ``mm tt߂ۂggRRLL,,HH..))GG yyݼhh~~~~FF``OObb [[11kkJJHH" " ddWW))MM XX<<PP22cckk>>JJ||EE((vv((UU^^88bbNNܙޙppXX77 ǬѬ88ttFF  RRGGJJ6633$$KKSS۬ppΗŗooRRgg>>\ \ %% HHJJhh yyJJWWPPGGWW[[00##--   " " ' 'I(I( % %ZZFF  p p  uu##))i,i,--....`-`-))%%6$6$((22Q?Q?HHBIBI>r r rr  LLLL##kkAAssTTHHBBssf f IIAA>>RR ))00ii ccll%%!!qqhh JJژϘAAĸɸCC rrʥҥ KKԜϜgg''݂ׄԄԶնգۣۏww[[SS&&}}<<99&&PPgg]]EErr ==zz((pp//SS77) ) YYuut t xx  ??NNM M yyK K ))pp[[E E __&&]] f f g g   OOHH //rr66))iieemmzzIIxx;;TTRR**ii``zz<<ll.. 77rryyssGG&!&!%%_'_'&&[%[%l$l$######!!d d 5 5 !!<#<###l!l!bbWWttp p $$$$""[[11J J 22EEcc  !!  ((Q Q o o   S S & & GGoo  $$''&&!!ss__..II   ==== ii HHzzݢܢNN--DDDDyyVV^^mmUUll**v v  }}zz!!kk' ' ""  22SSWW((  ' '   AA  CCuu&&bbEEppzzJ J     {{pp@@PP  6 6   HHww ooDDxx55]]<<   ||^^bb  ""))h*h*&&++Y!Y!## KKii&$&$x#x#O O ++II bb44CCSSuuxx22 77GG''% %   WWb b !! RR++!!oozzjjddooHHWWUUTTxxrrVV 33UUdd((00FF2200``ii44RRooDDuull!! ,,ܓٓٮٮoouu**yy77OOSS**** OOvvPP||qqGGyy**aa44   ==nnqqOO r r gg??OO66 mmҷҷұڱ||EE77 bbmmjj ppssޫ BBOO՚ۚ&&~~((!!ѸиRR{{ޓEEccRRxxơš::''**;;bb99؟ԟԊϊrrii''tt׋ .. OO^^ee!! -- ))   $$//s:s:8A8A?B?B=='6'6*/*/++Q-Q-U2U2M8M8<<0=0=9933,,''&&++33==EEHHGGDDCCEEIIMMPP4P4PiPiPRRyWyW\\^^\\UUNNKK%N%NUU^^ f fiijjiiiiPjPjkkememnnoonn#m#mjjFhFh^f^feeYfYfggffEdEdo`o`Q\Q\#Y#Y\W\WVV!V!VUUUUJVJVWWYYYYXXVVTTSSZRZRNNFF::,,z!z!''(($$J J RR<<NNDDۧ$$ʄDŽǛǛ]]##{{gg3377YYIIвӲbbqq>>44>>CC0055//LL QQ11CCϙϙ..66’’ޔޔOOIIKK55;;]]DDbbȿȿ++կկqqpp""WWýýäffXX::""--ii<<Ȏˎ..ĢbbұұMM//ŝ͝ZZ::cc??]]""((s*s*((''++}5}5AAqLqLQQPPLLKIKIGGGGEE??66--((J)J)//m9m9AA"F"FDD>>Q6Q6-- & &` ` YYzz##((--1144'5'5m2m2,,$$--ww  T(T(0202p:p:??AABBzDzDII)P)PVVYYVVNNEE@@AAREREIIJJHH=F=FNFNF[J[JPP U UTTNNEE;;B4B4..))$$CCLL!!z%z%##\\vv^^llP P 33ttyykkYYww  s s F F ::]]hh``  ``44}} wwzz88zz::``MM۹}} {{ooll]]ϊ֊֖ږڂւ&&kk``ssKK))ee}}%%xxLL'' 00NNwwGGll}}oo77;;EEdd~ ~ QQ  cc   sswwm!m!9#9#""  MMssmmhh``HHxx D D ####!! wwxx==YYDD?? ))1188<<;;88665555o6o655331100//////--F-F-..//11:/:/F)F)T T WWM M ffYY((33<>88i2i2{-{-:*:*((((**B.B.X3X399>>DDwJwJPPVVZZ@Y@YFTFTTMTMHHxGxGKKRR(X(XRZRZYY/Y/Y[[__ccdd__VVKKBBw=w=::99b9b9H9H999P;P;s>KK==NN YYee p p Y Y  iimm++ __a a R R !!@@gg\\LLEEBBssgg33FFZZ;;kk..@@DDvv  EE 33~~zz}}oo}}  ``''S S {{ii ( ( **^^ , ,   eeE E   f f k k W W # # k k 4 4 , , 6 6 X X ~~ { { d d ^^__}}||MM ==&&AA''PP~~jj;; gg**66XX^^uu$$<>!!KKHH[[== LLkkxxcc##__oo \\**AA//hhGGooHH%%;;uu@@__&&99~~ MMqqmm cc!!33~~yy|| F F " " 55U U CCyyZZ   + +   \ \ oo66g g nn D D GGMMyyHH55^^OOlljj\\SSvv\\&&xxrr<< ssmmll WW((??00||UU]]VVWW))WWKK**GG~~AABB,,ffssuu__ss@@ZZ22>> ==33rrDDXX>>  .. @ @ G G TT  pp  {{% % + + QQhhAA''qq44ZZyy55HH;;; ; 1 1 PPd!d!##;;NN,,>>AA4$4$%%;";"  RRxxkk!!##< < B B  _ _ L L q q   M M iiZ Z 66f f 6655hhVVc c **;;  GG>>HHttaaNNttKK==DDWW::CC==CCnnWW##66,,KKGG^^AA;;00mm!!ttccaa,,YY cc!!VV##BB((+ + 00  ;;oo# # ^^88nndd  ;;  IItt ==//nnoo99AA ++ffkkvvmm G G yyFF99ss``FFEE44SS 00**ggxxyy""))vvkk00TTHH??\\ssVVLLiikkkkBBoo>>llEEcc BBCC88ddggDDGGFF   vv99,,}}== UUuuLLlleeUU]]rrkkoo22++88ccIIvv!!VVggFFXXEE^^%%bb  '' o o Z"Z"OO**??VGVG<>vv   ''? ? NN uubbiiDD 99~~ll99qq&&AA::ff00{{33||##|| XX;;$$II$$llHHyyGGJJgg44}}!!MM::OO//44__ggOO]]FF%%55%%OO**TTjjGGNNDDuunnSShh!!TT//TT>>]]UUCCyy $$GG11,,EEtt33 [[7744HHjj~~yyoo>>WW  ??OOii++ R R 88XXqq66 8 8 33@@>>vv[[' ' @ @ { { DDIItt  ::%%AA  //--   22 vvOO CCkkww<<bbMMnn$$""$$#%#%""  //  CCB$B$',',//..++$$KK  88OO$$??77  @@\\@@JJ   %%))[)[)&&""TTXX::GGYYEE77qqyyG G J J w w   ZZ<<YYyy((44 HH**''yy HH ppUUJJ99ffeeXX$$EE44hhJJppqqXXccLL11..((ddyyQQ\\ssTTތڽٽ٣ڣ((((ݬݬދ zz++CCggߙ!!ԂԂ RRݪGGNNIICCbb&&$$..&& uuTTHH6699 6 6 bb>>zzEEcc  @ @ gg  < < Y Y ll::    I I > > G G ``<<z z H H LL""{${$%%%%6$6$Z Z   ((^^GGIIEE'#'#$$Q#Q#22NNTT--  # # nnqq##DD   G G M M a a bb7 7 G G hh<<BBjj~~ee%%++ss++\\,,**00wwhh\\YY++hh;;||ߎ~~rr߼ݼFFMM33||## vv333377$$__||--CC TTyy ggoo//**yy66iicc,,vvuu22DD66PPuu==GG==&&ttuu$$< < ssW W ^^++ CC  00\\66dd..77ii % % J J N N zzGG{{/ /   MMYY{{HH OO{{EE0 0 || ,,yy  JJ<<  o!o!| | uuzz H H ''++||>>ZZO O $$&&$$& & VV$$NNZ Z ??22Q Q {{88ww[[7 7    77 55__II <<>>ooWWzz22llPP FF qqvv22 ??--NN??vv++++''-- ''ggNN##DDKK))33{{$$TT  Q Q jj}} | | 3 3 ""aa##BBhh ``## QQr#r#%%##vvkkTTii::QQ..I I   z z JJ(( 77;;>>EEzzgg((  r r ))   ==  //KK::  i i 8 8 iihh""55RRooCC..SSiiMM{{WW\\AAhh yy99?? ;;++dd VV  ::  ::bbggzzgg^^ mm))KK!!EEddpp\\yy}}jjTThhttddKK--##//yySS88%%3344YYWWccYY>>VV@@qqff޲ܲ;;vvKKAAۄ``00&&PPMMhh]]qq))::RRyy@@$$rr!!xx//88~~rr<>--EE{{00FFVVoo33..LL88//II22OO00ssYYKKqq rr00       o o l l ZZMM ..b b r r ` `  bbggOO55 11mmssQQ22IIMM33;;uu"" F F XXBB ) ) 66vv00  ``&&pp33 vvk k z z      ( (   M M ::''ii::GG%%\\ll==SS88DD[[[[FFxxxxxxYYOO;;yyzz--ww&& ^ ^ 77XXBB[[vv<>))SS3388 < <   aa~~Q Q ^^LL{{dd}}yy }}YYkk@@P P RRvvff c c ~~? ? - - KK||~ ~   FFjj  ]] P P X X 6 6 WWOOu u { { - - FFrr''AALL{{hh ;;. . ? ? 44aagg}}hhZZ55==<>< < I I QQ]] g g   &&ooLL[[ W W , , [[ZZHH??''AA--   MMXXYYaaPP??  S S  II{ { 11 CCRR rr99==LLVVx x 2 2   8 8   55UUWW_ _ VV,,II(()) hhBB//22BBee77qq>><<NN((jjDDyyLL11tt[[33mm!!KKDDJJNNXXHH77yyUU 22..PPYY  U U yy NN::~~KKMMCCXX\\]]  TT##llZZ22IIBB}}66MMww((**((CC--33UUNN^^OOkk cc$$UU ~~^^||99>>  ++[[``::  DD**<< %%;; 55= = !!;;661 1 {{pp4422%%!!dd<< ..l l ||P P 7 7   4 4 s s i i g g * * ] ] A A **,,SS : : : : w w } }   qq44TT## > > 4 4 llX X @@A A QQUUEE ^^FFKKRR  ^^aa[[  $$3322[ [ i i  88__gg>>BBssSSWW77 XX PPLLMMGG""kk22__>>xxrrggWWss!!EEPP ::RR22CCCC88AAq q __hhrr((&&% % P P x x //wwcc//   A A qqRR77^^{{PP''''--99  zz ??ccyyWWrr5 5 RR88vv <<ddggDDyyrr((}}5 5 bb\\OO||hhAA[[EE{{__  ee+ + E E &&aaRRL L 99!! `` ,,EE<<gg$$ llYY  A A PP  ccc c  1 1 --ss>>pp4 4 U U ??^^@@KK  iibb::oopp!!iiYY??^^AA>>EE;;UU\\[[,,yyNNrr jjddPP&&OO//ss22$$((%%{{[[]] 44XXJJ\\ gg]]&& ((FF[[11SSxxRRVVuu$$99$$""22~~||+ + 77]]@@b b ! !   >>  % %    n n R R   P P gg88\\ccMMxxEE  ss??VV 44RR  ''uujj((] ] xx{{ WW 1 1 >>wwBBhhppmmss(( ++bbhhvv{{EE##..L L y y &&  NN[[ WWpp@@yy&&WWpp99jjnnJJYY)) R R nnee VVOO99E E   ..EEdd //{{[[II^^JJHH}};;ZZ   D D __44 44 C C VVOOYY cc00HH __@@ ~~00BB^^] ] 88;;    y y zz- -   c c   t t  nnvvccqqOOTT00~~????OO}}!!|| hhBB BBllrr))]]))''ߺܺnnݣߣDDߘ99gg~~ggee>>[[ff-- ==??66ZZoo66rr''HH33KKuu ooll CC$$ > > UUii     %%yy;;55H H P P n n FF  hh''BB<<BBL L II8844tt pp ::11\\nn>>aauunnRR""5 5 u u A A T T SSOOrrqqDDwwee?? LLSS OO##$$""YYyyRR77GGii!!]]HHffiijj>>""..EEdd bb!!QQ++eeUU11``IIDDRR))xx00NN 00IINN;;wwPPcc22==||mmUUI I T T nnMMLLww    C C y y zz   NN++__F F Y Y ;;bbnnu u   __;; ' ' y y 9 9 yyggee QQgg  CC[[``]]KKffQQ!!qquu``{{ZZss&&@@ ;;YY((ggYYBBqq))~~FF##RRUU**--??%%DD((\\$$UUoo::CCUUttSS))uu88pp77BBpp--KKYYRRHHMM h h E E {{nn66dd00AA( (  $$gg||llKKvv ++  ++22HH  MM44}}hh==$$PP99  yy^^nn     ,,``XXFFSS((++((EE S S , , 55tt Q Q     jjttlla a  @ @    ooJJii||??$$11$$ssKKnnEE..==kkmmHHjjtt^^ss]]88yy{{33&&SSDDPPFFNN ߾ݠޠmmvv EE99@@CC^^zz ~~kk RR!!XX[[99uu..{{oobb33\\TTxx55::..88pp77WWww2255!!+ + HH,,NN!!II::EEaa)):: ooQQKK` ` x x JJ  G G 22""nnoo 00VV ? ? GGnn H H NN++ 88  `` &&nnmmSSjj99//@@22ZZVVFF--CCIIjj< >   HHSSee      VV  %%..==55]] qqVVwwVVHH}};;77cc//  e e S S ""bbBBccmmllrr\\77  //&&mmYY~~55qqPP00ssOOzzAA<<~~<>::??@@~~55EEii//gg88}},,uu7 7     q q 11OO..  ttMMNN~~!!ffooff( ( 9 9 t t | | .. u u SS55 <<MM((\\>>GG++FFkkJJ66VV;;MM""GGUUZZ9988 LL**pp99rrYYCC xx 11  rr))ssHH99wwU U JJ WW::--c c EEUU W W XX{{oojj..MM   77** II0 0 ##   ^^dd l l v v    ) ) bbLL99 & & tt // nn..OO  UUYYvv""((  zz88rrJJ{{``e e * * kk''""ll]]  OO[[~~II//tt[[>>44}};;mm::dd++QQ,,ffggee||qq\\RRFFSS::ssaappLL,,aa118899YYYYMMii..ZZJJ**FF,,OO""rr,,xxUUMM{{JJ22@@ddCCmmllqqLL 4 4 ]]}}xxGGVV$$" "  S S LL::11KK''ee>>1199\\ GGaa##ppZZsskkBB @@EEEEmm22oo%%ll DDCC\\YYKKwwBBWWgg00GGrr OOWW**vv==((__xx[[ JJ4455 tt  F F ^ ^ RR~~WWWW  --  77jjH H ""99M M hhMMC C - - + + N N s s     ~ ~ G G 5 5 ss  @@v v VV$$::  77   EEX X rrPP  | | z z k k   OO..""ZZ::[ [ [ [ dd%%ooff 55%%??jj__vvxxqq))~~UURR ]]99  T T ""HHcc kkmm{ { > > 55 II~~iiaa~ ~ rr}} ttttdd  ssee++..BB UU;;   A A GG66YYIIyy 88JJ''UUXXll''ee^^44kk ,,66=={{!!++jj::~~nnCC --bb||ZZ ttTTbbZZaaFFaaVVvvLLUUEEmmjj33%%$$WWttII``GGdd77!!``EE==gg''aa ""##44++yyV V h h UU6 6 ??}}ii,,7733$$@@NN@@oo''wwQQ}}aa  ""%%$$ ooxx99l l v v OOWW, , __^^, ,   HHII\\  qqTT@@))99WWYYnnDD::$$..""99&&@@SS00<>||cc7766ZZqqww>>??RR..**??vvMM^^vvggHHrr##XXZZHHyyqq 88ddYYAA }}33FF ZZ. . kk@@55 ! ! L L pp% % xxqq%%  7 7 H H QQUU ggN N  KKyy##gg99~~mm::''ee   ??<<     __[[>>yy\\0 0   = = qqAAssdd33EESS> >   g g ))qqEE``TTJJQQAA22DDyyuu++dd//iiIIJJ##))  ss@@nnXX\\;;UU: : ( ( ,,# # - -   CCMM ooL L   ]]wwllMMN N  YY    ??XXjjTTYYxxSS   L L uu  a a ttxxFFVVSSaa33vvkkXXoo44@@))ss ##WW||**SS]]  ''ss<<??OO  \\NN88rr~~::]]OOoo??**PP$$GGEEzzEEnnRR((55<>uu44// yyCC``KK44aaPP&&BB//\\--,,11KK++kkcc``oo]]::PPpp,,GGdd55((vv""uu??pp CCNN  ""KKLLCCHHAA^^==AAuu11@@ww??V V 2 2 U U A A Y Y    j j K K ) ) 11``I I j j VVll J J ++==rrvvrrqq ~~99\\77PP  z z nn  22LLMM " " K K d d @@ OOjj%%LLFF ,, GGaakk))ggee::rrrr]] ffii'']]wwhh66RRoo//||WWoo..' ' __jj@@JJAA]]zz  )) [[%%nn<<ee^^aaxx\\  ::22    l l $$aaVV7722gg&&**    & &    ~~OOBBvv}}//ZZ``**HH00''YY llddSS;;>>CCgg66"" yy$$FF11]]&&rrRRhhJJ99VV1188''LL$$@@gg))RRIIff..IIHH 88??YYCCooaa88hh..!!zztt>>oo  FFuuFF}}II``CCOO  j j r r 0 0   JJX X     e e hh  ,,\\qq;; 6 6 ` `   y y gg F F     JJWWll'']]ppBBll 9 9 a a b b K K ..CCxxzzff$$vvppKK00  44WWLLxxFFCCxxOOjjQQ9911uu**==``  77yy99$$44wwJJTTzzbb77VV55 LL88UUmm99@@UU66&&[[yy&&0077rr||ww++::TTkkhhoossMM ))NN77,,ZZ^^yy::66bbbb  ]]KK$$!!88==ddkk  55mmNN}}ttdd[[bb``  bbII WW__##nnccyy3399XXPP!!((JJaauu77MMCCRRIIZZ@@++kk9944GG||!!WWrr^^SSIIWWXXHHjjee22qqee  ~~hhbbIIss==xxbb$$''ZZGG%%ttmm!!VVBB((mmXX##wwqq||OOhhwwMMGGcc"" GGGG11WWvvFFHHii$$eeYY##..66wwHH::  ggnn w w   }}__  55SSeellii;;ppRRZZLLaa7733  ::ssjjee11AA ~~))qqQQr r . . ~~1122!!KK``JJUU  MM     //''}}VVqq@@~~// \\22''aa((MMHH??Q Q @ @ 4 4 OOVV66aaNNCCYY, , SS  !!FF11JJbbTTrr;; >>ee\\ddFFoo22ii~~zzkkXXDD((::$$hh^^PP\\//NNuudd,,**wwll44QQXXWWSSDD<>==eemmLLWW; ; y y e e   hhjjdd  YY  RR99  kkAA  --  77l l y y 66}}hh44  F F //||..NNMMMMhh\\BBddhh 11<<  kkyynnddWWll&&2255WW##cc]]}}ZZPPddppoo]]@@VVWWAAWW66$$iibb88SSyyXXOOccWWyyZZVV^^^^zz ]]IISSkkgg55;;DDooAA77??;;RRrrZZhh  MMKK||@@2266LL88]]jj//ppRR((ccOO88AAooZZ__    %% O O   r r 8 8     M M   % % f f   KK^^ss""    H H //    i i 7 7 : : LLNNFF  = = QQ  z z 4 4 ( (   ## ++AA u u  q q 3 3 * * ;;   k k   Y Y e e + + 44zz66  00__SS[[NNeeiiII,,11uu<< @@jjRR<< EEbbffkkZZ99^^!!NN[[44ccxx==@@@@ii~~!!xx)) QQ00ccYYjjppBBQQ%%??@@ccppCCddssUUkkRRvvxxIIkk,,vv00hh~~ JJuupp//""==''\\//tt""FFoo%%77~~kk``hh==hhHH##((gg??66ii++33WWuurr<>yy  ##ooW W dd- - ]]((EEQQ}}TT}}99? ? . . LLll77 k k hh::55J J , , o o   . . o o [[''99((   00FF  ||kkEEiikkQQ--BBMMoo##&&  99AA  ss$$[[~~\\]]))  BBPP\\!!CC]]""DDVV__oo!!^^..::66RRWW++RR JJJJII00zzllEEgg99BBff77AA55}}##$$WW||||]]--jjvv66MMppccQQ\\uubb##ccII55--00ii33 ((rr>>55xxddFF SSppSS//VVccff''""BBJJ::""aauutt&&GGffddMMzz22!!nnJJaarr??SSPP||}}..ooss==''MM]]ffssqqBBj j 7 7 %%MM  >>22&&UU||44zzLLGG O O 0 0 ##**  3 3 " " c c   7 7 WWpp}}!!SSVV66        ;;BB55{{RR;;BB==tt{{u u " " ""tt009988 ? ? n n   ssttmm%%mmgg  ~~xxffXX**ff22ooTT77``nnpp**^^??||88xx{{33''llwwhh66DD__CCIICCbb\\88]]eeQQ! ! uu``BBSS ((bb??pp==ss66HH""33ooIIbb77;;''??ss**8855LL  )){{ ##WWgg ss::WWBB**@@LL&& BBMMMMbb11__""qq//44}}ppjj66mmKKHH rrXX>>55kkNN11))bbEE%%xxUU--  mmx x   e e   T T --88DDTTTTyyuuwwffxxXXvv llaakk\\!!VVV V q q  | | . . ; ; V V   }}CC!!GG``z z g g ~ ~ N N 3 3     xx``=={{}}WW33??7744??NNggWWQQ}}FFyy22??00jjHH  ggaa!!11  rr33H H * * vvRR33ii''<>11>>uuM M nnCCUU}}55aayyjj UUrrccddggCC }}eef f   -- %%VV::..;;OO**K K $$??  ## S S GGkkCC11ddDDff)){{LL^^||88MMyy@@77eeggYYMMSSttWW;;==ffQQUU))??>>SS$$ 55BB nnUUaazzSS<>{{]]PP!!wwYY%%qq%%uu88YYCC;; --((vvTTKK33__ppyy   b b     ||CCLL@@  ' ' XX  44rr44ZZ vv``zz99EEii uu//   RRQQAA55xxVVOO##;;NNEE44ss~ ~ M M ; ; ~ ~ H H tt((??rr}}::h h ; ; c c OOOONNnn>>99ii > > kkhh  ||   HHvvCCddjjRRTTqqYYVV}}tt ??55 MM$$  KK\\zzyyssooAA ssBBRRrr11NN99EE++__ss* * ZZ]]NN gg44Z Z ;;HH  ;;WWCChh  DDZZ||!!wwppKKffII""00ff<<;;99ZZ77))GGooFF--00 %%hhllGG wwEE??$$((__..rr[[oo\\eeaa  bbCCwwaa qq@@<<[[??~~mm}}rr;;uuJJ..QQOO||  11--^^llNN]] RR//XX((jjbb::..CC^^yy==DD:://@@AA33==[[UUWWFF&&dd//^^QQppnnPP nnLLoo%%..\\TTppjjjj33IIAAww>>MM8866mm[[ttOOPP""))ZZ  ??II66--&&^^::uu88!!NNaaKK::  nn\\}} 77kkddgg..uu??||AAjj11ddMM##^^AA&&JJ**55QQ@@;;cc^^aazz00jj||rrOOV V ) ) ! ! k k ; ;   " " L L m m i i FF77BB<> L L ..__::IIPP@@YY oobbnn##vv]]}}AA  KKnnss h h wwKKR R 4 4   {{ ! ! 0055 VVeerrCC}}EEDDss   5 5 ]]uuCC==;;GGooffzz^^''iizz%%BB++""ee55jjbbaaPP__ ) ) 11;;>>NN++  p p ddKKgg}}qqMMgg''||ppEERR\\22^^tt--((33AA>>  NNII 8 8 kk!!bbBB<<""!!%%GG%%pp55VV MMLL  ,,..}}ggX X ] ] T T Y Y d d ii3333 8 8 & & 4 4 _ _ ;;99YYQQ{{oo&&cc ::ssFFFFUUVVRRpp77KKPP4422KKQQYY//MMSS[[>>rr..:: kkWW;;CCmm""oowwxxRR}}ccXXZZAAAAvvOORRCC<<55<<))TT))VVjjkk OOllCC66rruuHHEEOOgg--KKRR BBII33cc))ttJJ22,,((!!ttVV??dd WWbbEE%%55  ..ii  88% %   11EE>>{{   >>:: o o YY  EEww : : s s 5 5 (({{ ! ! 4 4 W W   p p ] ] n n ||33JJVVQQHH++..99??ee   ^^ HH''22vvSSLLxx==&&((nnww55hhSSXXppeeLLiiZZRR## rr q q i i   4 4 f f " " PPTT> > J J J J o o r r g g   _ _ nn**NNXXhhzz SS||eeDD ]]zz**IIBB 11CCGGVViiff,,``ii||[[ B B B B j j ( ( > >   ( ( ll    0 0 &&11VVAA{{661 1   pp__$$WW%% zzyy44VVdd99OOttffQQ##ccEEssmm00ZZ BBTTmmHH'' 8811**MMggxx(( VVRRvvAA::ZZ__YYrr ll^^gg##YYII AA))hhYYGG<<  ''xxMM44||$$--mm[[aabb[[77ddNN(())""eeFF!!KKss{{^^}}  kk44TT\\==||$$?? HH<<nn&&AA::..[[{{??}}ppKKHH\\;;11IIww   + + ) ) <<  qqP P l l ppI I qqssQQ^^ppGG00==JJjjTT88oossTT55::vvOOMM,,>>XX{{ aaYYii::88SS00qq5 5   . . 11&&==88rrUUPPxxllyy::ffxxLLAA99rrTTLLxx//TTLL xx}}H H   o o n n     ^^ aa..XX--  KK ) )   ^ ^ NNFFAAHHEE]] * * ''--VV//44 ##}}!!""%#%#!!ss $ $ h h **\\W W + + l l e e   DD//tt>>rr!!QQ ((NN kkccYY}}**bb$$ 66UUjjvv[[,,aa~~}}!!77vvIIUUHHLLYYcc~~II44==FFGGOO  wwjj88rrHHMM33{{>>MM33aaNNbbPPNN..||hh]]}}kkDD((ff{{^^,,yyVV>>\\??nnSS88== &&oowwEEJJGG]]--\\""TTCCiizzoossbb@@TT$$$$           jj44II[[!![[AA??JJcc&&kkBB}}ddaa%%UU  w w T T K K     t t   F F k k vvB B   ;;eeDDeeYY_ _ o o S S   9 9 7 7 &&**~~,,ZZ##$$ccnnVVBBTTEErrKKKK ##dd;;--LLkkCC&&HH$$ii11||ss@@66==??{{ aa\\iiuupp!!__##zzYY..JJVVLL:: NNqqwwjjDD7722jjiiQQ558888++tt>>??ddQQ   <<>>WWEE  ^ ^   c c   H H vv&&   H H mm ] ] s s ++ w w   Y Y k k     i i YYMMO O Y Y ZZ__ ;;}}&&""99ff77YY]] c c --bb  33   r r A A   ] ] 7 7   y y uu}}  ] ] JJRR&& b b HH]]VVQQFF**}}ZZ%%((9955~~!!11ZZ~~wwkk:: dd88>>//++>>kk--((ffNN%%x x SSI I : : --@@WWzzhhrruuvvVVJJUUQQ RRwwBB\\ww``ZZTTrr##CCuuhhccYY,,XXEEOOhh88JJww55AA88@@__zz@@__//KKPPii[[YY11''``EEssZZggWWEEZZKKEE==ddtt66 vvFF==  --oo??CC&&XXVV~~__HHGG22GG \\ [[@@mmWW--ssBB++DD~~  WWRRkkEE44$$;;   MM''00**xxWWddYYkk??ppQQ;;<<qqTT-- 0077[[YY CCKKyy]] IItt,,VV@@nnKKrruussCC)) **EE""``SSbb//}} ::mm&&~~$$==55IIgg==mmhhPPmm p p ooii!!ddvvBBJJ44 66uuOO0 0 VV JJ RR11{{((FFooOOZZ>>22ff ( ( R R q q w w hhaaTT{{cc   M M 77oo[[OOvv>>     @ @       II))iibb,,LL11OO\\bbmm~~SSQQ^^  mm..33}}UU ``ZZ\\ooRR@@KKhhYYYYPP77RRIIII {{   ooRROO776 6 99     K K <<ll::cc55[[ K K IIUU: : t t { { D D ggKK & & r r ))IIttqq ccSSrr>>VV&&^^3388MMJJYY( ( KK33p p   DDppNN))nn44((< > GGzz::## ? ? WWDDDD__::CCCCQQWWDD@@xx66NNjj0022EE22UUhhqqii11~~ uuMMQQ88qqgg__((II55ZZ??  ::<< UUiijjAAyyYYffRR YYMM66HHoo  66}}wwaa  IIppNNppKKxx]]||QQ88wwBBKK11""//oo~~cc yy||  66llccFF!!ffcc@@HH\\nnff''!!u u < < P P { { q q ]]33YYXXss''((==hhEE%%vv##LL))UUii++ 22GGXX YYssww>>WWoo((__ ll##{{nnYYkkjj@@ llKKaap p   mm --VVBB--ttgg$$ff  qqll == ==^^!!EE CC||VVG G JJ    u u __  ``77ggDD K K GGuu##WWOO~~00[[O O A A %%MMCC``FF w w YY;;] ]   ++33||??NNII  PPwwvv__LLccvv HH!!j j **NN**``YY((44SS__55@@BB##55ccYY\\   ZZ[[__11UU&&JJ@@hh11ff\\AAjjxxjjQQRR00JJxx 771 1 / / EE q q NN  22CC44cc11==__HH@@BBrr    ''bb11,,wwddttmm33ee  0 0 wwLLxxMMdd JJoo""OO``YYNN22OO ZZggnn))00lltt  W W ))++ ::]]""??SSnn==**$$''RR>>\\!!YY>>//LL**$$LLrr%%^^aa;;@@""  66''  ??]]iizz$$((||XXss,,\\)) ##8 8 ;;__   Y Y   ^^||ffaa--WWKK; ; k k 2 2   jjYYddqq,,33pp{{,,LL88@@99LL||::AA22  DD**77   TT}}7711  ''RR^^jjz z g g kk77 ZZ11U U LL88}}ww%%22ffQQ||%%>>[[MM~~??>>cc**YY66..,,99  __~~jjll!! PP::oo nnrrWW   J J X X qq88gg||cciiOOaaOO{{OO??33OOZZyy77 yy@@##''ooffFFccii XXMMDDCC 88kk   '':: ..11ww22GG))kk@@ 99 TTAA  ll%%" " ee44II**HHpp~~b b K K 0 0 D D   K K pp,,;;66dd  BB||qq$$qq~~PP22}}==!!77KKoo__vv~~99;;SS77uu11==ff%%//PP@@%%22}}>>++llNNWWwwrr&&88``@@1100lloo''++WWxxWWxxVVhhYY""zz,,BBWW}}YYLLBBllTTMM@@)),,((UUjj//bbLL@@nn11OOEE//TT))rr11"">>OO1199  ppllPP&& : : llbb   ##ffHHaaNNAAEE__xxDDeenn' ' x x : :  yy  ##` ` O O    0 0 [ [ \\00  ''++>>\\||yy xxJJ,,33CCLL k k 99;;77 $ $ ccBB k k     * * Q Q  VV..hh C C        V V   _ _ . . ffCC< > mm--AAmmVV^^GGXXww}}((SS44..rr//ccLL&&WWJJHH;; ;;}}++88  R R ||eekkff}}~~~~ooQQ00**$$KKkk nnnnII ``dd&&FF ==LL  wwQQttCC ]]>>yybbNN__XXttII kk--]]1122 2266MM88HHrrnn||UU22BB|| e e   BBHH!!mmoo++SS$$22SS^^  UURRRR))@@  BBww^^TT   U U | | G G ! !   !! ""VVHH;;~~''iieeFFooLL::yygg[[++;;ff@@;;qq) ) C C rrGGxxS S cc}}CC"" ::## ,,MM99ttVVpp;; }}??MM>>99S S ] ] ]]44XXq q ::== DD11WWvv22YY""llqq))ii66TT44DDddFFWWlliiiiii77XX``..<< QQ5522II((ssCC\\   jjPP33DDooAA##ii--&&hh55IITT\\ii]]%%xxcc;;33%%DDAAbb}}UUSS}}GGKKEEWW%%vvTT{{        JJjj^^..99 MM  ll''[[II^ ^   I I K K &&YY z z  ??xx!!ii++OOnn))\\$$}}<<KKGGI I   WW ;;TT;;[[ T T ' '   } } 11xxz z O O Z Z   kk__  TT11yy$$~~xxTT''##CC__>>KK[[GG--  llXX77 c c I I G G T T P P ((bb((FF FFEEKK$$!!DDee66dduu66?? {{00ttmm  ~~kk55qqMM;;NN 77 RRQQ  pp11@@55jjHHrrWW88zzGGKK66cc%%OO~~DD**hh\\  MMyy$$!!--## [[zz..IIOOtt22<<qqssUU;; ))%%vvYY~~>>hh33DD@@ BB8899kkYY66HHJJ{{''^^^^00''ww QQEE;;aaTTSS bbll88oo[[FFXXnn**^^ S S 9 9 j j E E   !!WW44ee^^!!<<\\b b $ $ ~ ~ bbBB))88WW$$((VVnn;;kkffTTBB""jjvv3333ww00 $ $         h h V V   3 3 ) ) nn o o RR [ [ @ @ u u { { \\ 9 9 G G yyBB p p r r 33UUGG##AA{{  AAllVV@@ee{{^^LLWW****vvyyll t t Q Q @ @ 1 1 33}}33DD$$||RR]]ff$$hhnn  N N   DD . . ""zzuu55qq``>>''88``CC<<^^11VVAAeeqq33 00< >   ))JJ z z S S ==rroossff((//||bbuu88  XXS S , , z z l l 4 4 & & R R NNTTOO33cc!!ww--$ $ Y Y AA55``88ss**  ggM M 9 9 aann  n n y y Q Q EE33..''IIPPbb__vv ((UUZZL L | |     66%%@@((''""cc%%II@@gg((aakk:: ..~~[[xx~~HH::||00iiGGNNVV@@iijj''TT&&AA((nnSS}}**GG MM ;; JJFF..1 1 '' qq00wwvv%%GGffttuuKKnniiBBuu==ii::mmLLNN    o o % % %%^^==))66 k k     l l 6 6 ..ss 9 9 L L VVllVV((PPzz__]]~~$$ZZmm44``PPppI I PPBB> > 3 3 3 3 * * t t CCRR""MMXXrrVVqq22zzJJ??]]MM++--kk**>>))..VVffkkBBWWBBuu66ffaayykkxxXX//vvwwHHrrwwHHRRXX;;((DD++wwFF**~~[[ 2 2 < < ssFFbbTT[[==kk??33kk''&&ee<<44sshhHHPPrrmmKKmm00??  8 8 X X %%MMnnWW)) gg))44 x x ''QQ&&\\%% F F H H     6 6 < < yynnwwuukkvvttee66^^GGllMM))ooHH--]]||nnnnGG1122 UUggttMM==GGjj  xx;;IIRR((   y y _ _   a a ' ' = = VV@@ss  nn-- ??W W ; ;  33PPBBQQ}}MM&&mm22[[  rrz z VVuu >>bbVV$$DD``NN##QQHHnnqq# # jjLLYYSS6677zz!!  aaaa[[HHggrraa''qquuSSnnxx  jj22ppQQ5588 KK;;TT&&88ww__  \\  KK }}nnhhJJXX&&==""QQ}}RR11@@66//VVAABBTT""RR--jjYY22{{:: bb__--DD` ` % % KK0 0 \ \ r r   ; ; , , F F   oo33++<>++PP++aa}}fftt++--PPZZ##uuOO++dd99##MMxxDD{{cc]]RR,,[[,,``qqVVVVCCnnmmhh66PP~~DD  66,,//11hhvvrrHHWW//vvaaVV\\++yy~~PP1122``WWCCEELL]]22AA::JJiiaa ]]CCLLFFnn \\,,)) ? ?   ? ? EE MMJJbb..00PPTTCCCC((UUeedd  ^ ^ ] ] ZZcchhssII''II]]``33##BB//nniivvXX__qqss``==JJWWSS\\77 / / v v   \\II::((MM**UU88QQ  bbnn__jjyy@@AA33[[MMZZ((ss ==\\ii $$IIxx;;uu{{ * * }} u u **ss~~ZZ  OO77HH__  ::..,,VVeejj__2244DDo o     LLbb  11EE--ttaakk))55FF||??BB11TT__eeAA__NNBBXX<<'' G G ` ` C C j j : :   T T MM33b b 7 7 GGXXGG{{ M M ((LL c c   / / HHZZ ] ] d d ~~]]@@XX++))jj||llppBBPPQQDD99   ff  } }   ^ ^ c c   >>55  jjYYKKLLRRC C } }   cc\\''  00VV%% qq  DD % % ]]88kk{{44EE    44]]ss//  MM11--zz>>< > ( ( w w   5 5   | | //mmgg   yy88EE<<++uu((MM''++{{  >>JJ>>77DD""zz;;wwAApp  zzGGKKww&&ppQQhhddMMww66^^jjnn{{zz((RR((=={{''ss66YYEEJ J   . . v v   ''nnnn%%uu>>;;mm  >>  ee!!dd9944XXFFNNOO""qqvvee}}||AAjj  f f {{**k k | | k k > >   jj11}} ii--NNLL;;;;[[[[{{ 00NNwwIIDD}}JJFFcczz__``CC!!]]II==bb00  4422]]oobb@@gg//vvCCLLWWoo##))}}11zzppWW&&kkBBii44aaddAAGGNNSSNNxx++""NNK K   C C XX11EE((nn}}>> nn""HHww##__DD..OOXX((GG EE88""vvQQPPNNffttii[[qqII``GG{ {       ||yySSUU\\VVjjQQ88,,uuddVVll7744}}``||  QQaa,,88^^UU**||``RRnn^^bb   9 9   ` ` I I + + hhWW==TT++!!99&&\\wwAA  ssYY!!ww%%##LL$$  99hh      TTd d a a 0 0 B B   >>$$aaVVUU''jj!!llUU,, O O 77``,,tt'' H H EEWW22RRtt33''ttZZ{{??..{{IIaaqq11jjVVwwjj::ccttPPPPnnmmqq66%%EExx11++55ff**CCJJAAHH||ZZaavvJJttUUnnPPXX 88! ! E E   T T t t - - < < uuEEzzMM **ggKK % % TTYY??EEJJtt22))""  m m [[{ { z z   II;;yyXXRRss^^QQ( ( $ $   CCYY   E E   J J W W f f 8 8 ++\\qq[[44hh   Z Z DD  MMCC..II::VVFF$$xxnnVV00..++KKppJJaaeeMM44..]]xxGG&&DDhhqq--zzXX33 VVAAccCC~~aa""BBjj>>II; ; ee33ttYYOORRII^^qqQQ11hhSSppdd__kk$$  MM!!  @@ZZ''88PP--aaYYKKUUPPOOQQ]]ww}}} }  &&__ X X   ,,QQBB@@ KK3333ww ??|| ' ' ` ` CCBB))jjHH99  $$CCQQ<<}}33cctt  ??  HH@@ &&\\__//mm``S S 0 0 T T J J VV))EE$$CCYY ??llDDssBBPP%% GGEErrnn66FFXXjj&&&&jjpp  e e G G z z     ::__44]]  mmddWW22<<WW@@rr y y l l u u   77..KKooyy%%>>##EEyy; ; 3 3 % % ^^77VV77ll33//00RRff ]]ggJJVV^^==""::++KKkk4455<<}}//MM^^DD[[ee}};;<<KKQQyy::::,,11  [ [ l l V V O O  GGmm||[[11)) aa00&&11{{ ZZ~~ttPP``xx;;MMYY ,,OO))WW WWjjMMnn? ?     E E ^ ^ , ,   1 1 B B % %  UUYYll nnOOaa((JJ N N 22""LL  bbEE,,II77]]xx22%% 8 8 ..$$llEE/ / KK..{{,,VV]]vv    W W ;;88gg``QQeell < < M M ``66ZZ>>EE   e e II11IIII22nn>>{{ " " X X H H   ;;(($$ffooff<<eeOOmmLLII..aa%%ZZ ??ppEE!!==rr//TT--}} %%//jj--))RRmm__ 77llzz::ee^^NN--66}}llg g (( k k ::\\&&--TT  ##66##OOwwo o ZZ,,;;!!22!!S S ""~~rr<<u u ; ;   }}oott]]22AA 88FF[[UUWWxx" "   jjwwVV  1 1 R R //UUppee!!WWuu@@ppDD88OO7755 n n & & | | S S HH%%,,QQrr::NNHH pp..??11 ^^??yy[[PP99++HH::``ppQQ11FFWWNNDD J J //OODD 88ii44 ____//??XX''hh""qq TT%%mm--xx[[YYpp##!!YY\\]]4455 dd((``;;]]  .. bbNNllpp33!!ii mmBBssmmPP^^}}\\pp66qq55YYOO~ ~     ^ ^       !!PPVVSS[[ @@44kkiiff$$&&llII44))##rr==``QQ 3 3 55\\ 4 4   TTmmaaffyy00VVZZ''RR`` 5 5 ~~''OOOOEE..LLqqAA))vvyyjjQQee((CC>>&&(($$44 22ZZ66GGcc==>>ff33::HH**((,, ffjjff"";;||VV**++##VVJJ==AAii>>6622++xxoo[[++aa##xxRR44,,CC@@``\\uuVV>>EE""66\\mmgg&&^^44--BBiiWWff..IItt;;%%**SSFFdd[[   t t   ""^^  aa||7 7 CC{{ppXX//eevvooVVllww--((AA&&llGGddRR WW ggooPP;;??MMGG$$}}..@@__++~~??%%ttpp\\ n n G G 77tt5522 R R ' ' m m   C C   QQ~~MMrrL L   E E ]]// 11qqZZAACCaaBBllccHHqq<<^^hh? ? B B H H ' ' L L MMddOO66KKAAvv[[??rr:: i i ^^ { { K K '' dd55ee--)) ((,,ii11aaAAmm__uuSSwwJJGG AAAAyy FF22rr//?? bb TThhFF22  \\..::TT]]JJdd<<||qq44llNNkkBBppvv,, ++aar r g g s s zz::44^^llXX## NN aa~~HH[[==``66SSoo%%JJ<>MM;;MM==ssdd}}EEjj f f f f ; ; X X h h xx''AAkk 11oojj,,SS^^EEMM%%//JJTTEEw w   0 0 T T ( ( & &   c c bbkk[[IIvvff!!22vvWWrr@@(( 11YYLLgg BBNNll;;oo))))DDjj&&ddCC``5577]]88DDkkbb""TT 8800##ggEEssPP3333kkXX//??55EE 55SS\\[[eel l m m iiBB//7766MMFF""aay y O O ) ) c c 55//<<KK ]]hh{{{{\\ss22--##BBHHqqcc::llZZ$$cc%%tt==ZZ{{ggOOUUzz))uuddDDaa aa@@..||!!@@!!PP11NN77==9977((4444LLAAZZcctt GGSSOO00~~xxMMcc""WW77BBXX##  ~~99..ddXX))dd@@GG@@]]33AAHH\\SSjj  t t | | R R V V nnttII// &&vvmmNN dd::||!!$ $   . .   , , [[llFFIINN4 4   pptt,,NN00~~||99kkzz1155''NNjjEE qq88>>ii@@8877bbZZii88OOvv__xxEEpp33//mm~~::hhCCmm}}V V   kk||qqzzxx44FF??uu::\\..##??OO<<SSXX  : : ! ! ) ) M M ; ; \ \ S S ccddggvv??@@::&&44JJbb22PP$$ vv>>__88aaxx..--BBQQyymmUU\\qqRRcc55ggGGYYffZZ>>yyyy}}  ee^^hhgg iiaa 44<<hh==SSvv\\vvIIYYUU<<XXdd==FFLL      ` ` @ @ 77rrNNWWpp66~~^^xxQQ  ""xx22 ee  **%%XXYYLLFFAAPPT T ` `   R R //::bbWW^^^^  88ZZxx""ffAAVV--     CC{{[[}}MM[[HHuuFF..!!hh~~{{88++..DDBB  77FF//88++&&HHzzVV%%bbddbb''ee11RRll00  QQXXffKKttaa!!**EELLAA\\^^    ~~++>>""bbyy__TT==oo33JJSSnn""11;;GG$$==WWZZAAff{{))B B   h h ^^NNffvvPP9988YYBBGGbbCCrr&&((JJ__yy33vv[[ss[[""uuyySSXXGGXXCC__ [ [ OO z z ll||;;""==^^33SSSSnn TTkk8866jjGG 77IIccbbNNnnmmBBNNxx  X X C C " "    8 8 Z Z u u ||qqwwVV}}00rr**9911FFVVUU||QQkktt,,ss44 UU??kk((XXeevvssuucc''PP **EE55||  uuCCvvXXHH((    A A C C   //XXii|| FF VV MM||99  s s q q / / ??rrFFttTT!!__NN~~77vvvv-- **..OOVV22JJvvll]]ttuu00%%ssEEEE{{ qqOOPP==WWssyyoo>>11&&FF==<<ffNN  qq}}  //ggIISS22YYkkCCWW{{``<>kkUU33^^GG__BBFF  --..44@@ssQQ<>qq{{MMPP22``? ? , , 55ss..RR   p p 4 4 6 6 g g KK))00>> BB((   RR__vvvv  FFW W 9 9 ))hhww AA__--  ZZss]]__  55ddtt&&JJ++**ii''!!++eexxJJ   ..&&  bb00[[CCII))11..jj,,uu55jjmmmmpp``hh~~>>ii--DDrr--%%[[ii99{{qq//''YY}}II@@ffuueeff&&PPKK[[8866dd44CCMMZZgg33aa{{y y   \ \   R R DD77kkll&&''||vv""xxffmmmm}}jjFF11tt::||mmbb<<BBLLyyHHmm&&LL[[hhppiioo88tt55""DDwwA A | | @ @ tt@@44m m G G ,,kk\\(( EE}}:: aa::jjFFccggQQ""-- ##!!11??@@MMAAII))UU__55mm\\::PPccbbIIZZDD77yyGGffOO((XXKKnn995533||TTYY??cc]]llOOEEXX00""bbJJ//  AA))% % 7 7 WW??    ..QQ[[66TTLL@@TT]]33DD!!55YY<<**ZZ   # #   o o ccFFYY%%  ((__qq JJWW00aahh!!++rrXXFFbbNNssjj00,,nnRR00))oo hhpp99}}}}yyllll\\w w EEJJ==$$EE ,,RRyyII""WWPP44..ll||mm;;``VVCCqq66((00 $$++11WWQQNN%%ss||ll--99&&VVAAQQ}}  LLWW  KK  MM  gg@@ppbb  cc  II``ssssSSwwXXeeFFaajj[[__WW))mmkkuu^^<>""66ff66<<~~ssFFLL==SSMMRRTT{{II]]55mm  $$\\aa__ttHH++""<<}}rrPP XXBBffDD@@ZZ~~++ii22  eeffcc..hh__6611qqhh aa<<00EEuuHHSSRRmmVV''bb99gg bbMMeeIINN::EEHH{{{{yy__RRii66JJOO }} qq..00MM[[==mm__??hhQQ N N ]]QQY Y . . 11FFYY''@@HH55>>cccc++DD  GGnnFFZZbbAA C C ! ! SS  mmjjXX KKjjtt[[ e e l l : :   2 2 % % T T iixx||nnii**oojj ]]wwPP__RR 88oo}} ((]]bb::CCmmCCiiDDxxooddbb::))66}}DD  XXii%%WWPP]]wwpp..nn::))##<<  kkPPvvPP  yyzzDD dd0099HHVV  d d   O O aa55&&  ZZ??VVuu88hheeyy]]JJ  nneePP$$**~~**%%ffrr==TT**rr^^!!++&&ffIImmVV kkTT  ddffUU77hhPP__{{>>>>``11}}bbGG||<<;;//~~..//llKKxxZZLL__CCHH]]eeMM55..{{44hhcc))xxjjll00}}))kk##  * * G G     e e \ \ WW>>++,,AAYY==nn  ttQQ``>>9 9   O O [ [   & &   66::SS%%!!aaPPWW778 8 [ [ # # ; ;   % % ((ZZmmQQ --VVAA??::vv  o o   m m WWOO``44qqII>> PP @@;;]]44FF==BBaa>>cc66ccGG::lliiEE99ll7766bb++ZZRRnnYYBB WWUUmmNNpptt]]>>yyCC::YYyy66&& II@@88||##YY 55WWvvyyffZZiiMM==ZZYYzzbb@@ee== ||RR%%--yy``OOkkUUuu%%YYDD;;??NN<>}}XXzzPP zzCC;;yyss__{{ttEE33jj44{{DD[[ii99<<)) oorr  - - 88""%%XXaavvYYxxOO))rr00yy!!nnYY44<<ddO O z z !!qq--""KK 11""ooNNOO99  \\yyQQvv""xxQQIIssoo<<::[[GG22ppooss  ZZ``77))44[[uuaakk##ff&&22XX7777hhEE{{kk<<[ [ m m " " ( ( r r O O eett~~**xx%%[[LLddVV>>**88!!ii{{AAYY55vvoo''nn 88GGssMM00XX __llqq::@@,,||rrkkLLFFVVuuBB!!HHuuCC??jjkkRRPPWWyy%%CCQQ  GGvv88yyHHOOmm++ff]]aa$$ $$ddllLL    KK&&0 0 A A   e e   ::''  bb**WW..::jj@@ ::QQ,,00SS__QQ,,vv44::BBSSKKxxWWuuXXhh??11&& 66ffqq88 !!((]]ddGG;;!!77TT||''44eeVVdd]]ppww11{{  99OO77SS??!! ||^^++((||UULL``{{LLRR  z z E E { { y y e e PP==..--RR\\llmmPPNN##[ [ n n 4 4 = = ~~QQ33ss}}ww??XXIIxx==rrHH11||KKccqqyyQQ99WW__~~22ccZZaaffxx@@WWLL: : ` ` g g _ _ D D   ||UUMM9999OOEE''XXJJMM**]]// $$))  IIOO//[[vv;;AAttccUUMMOO##ZZ( ( ^ ^ @ @ 4 4 x x z z   g g V V   Z Z I I MM66aaNN""ff||(( uu))DDHHKKRRDDuu  &&!!>>iiaa117755 LL33oo\\hh449955aaYY,,hhcc== zz55BBdduu\\]]rrgg%%XX,, ..YY==hhXXUU55ooQQTT==OOLLYY0011ee99JJ&&vvOOIIHH33rrXX++CC  //ccZZ{{VVddll##ZZNN;;iiPP??))uu[[--$$..pp  NN [ [ %%   * * BBggaaTT44\\yyXX 6 6 PPKKZZddZZ$$MMUUTT22zz%%ll>>--00OOOOFFRR KK||pp&&llbb44iiHHHH((;;uu--{{mm6622++iiee>>UU22HHuu::33sskkXX%%|| --22iiPPXXttcc<<-- %%77DDIIWWooGG````hhXXxx{{- - u u r r ? ? P P   Q Q : :      ::55ppmmGG88 ;;^^MMLLLLCC22\\UU44> > L L   WWffcc  &&JJ}}OOSSZZ**--``VVHH##00  gg**$$  h h _ _ o o sskk77eeYYmmEEqqee||V V w w 9 9 ??{{``FFuuee88&&**55FFGGrr--wwii  ffQQeeVVEEllEEJJ>>``VV%%PP))__00EErrqqmm;;22XXjjee$$qq  vv""  XXRRZZ^^SSEEUU``88yyJJ ffmmvv[[UUWW??II77vv@@eeff// ppCC88,,~~44  ))jjhhqq??--yy**,,MM??||WW##uu((kkff //==>>||99NNGGTT00rrpp'']][[NN@@gg00 ;;CC^^""wwx x * * C C ) )   4 4 QQXX22ll    zz^^44ii--ooIIEEvvUU;;00(($$~~SS~~H H / / **zz  ` ` o o ++R R e e RROOffHHooAA33RRzzggvv22  LLGGII}}``  ,,6 6 [[!!FF%%  ss11 88 zz 88{{66AAiiFF $$UU55^^ ff]]ffhh__{{ffrrQQ\\SSVVmmiiLLtt__{{[[cc,,jj==XX!!WWmm||xxccxxWWZZzz||lluuMMJJ''$$--UUee<<{{""xx[[DDQQffMM++[[aa33kkVVttppZZ ppZZAA!! ??FF@@ {{wwXX&&{{&&**CC>> ::44ZZ  //22ee55**yy33VVQQ]]qqEE77__mmee^^""JJ--<< CCddFFqqFFEEii::88[[VV//]]!!**))$$00##EEgg    ??``AA88==BB==WWNNeemmGG{{55qqNN ""rrVVUU  SSbb66LL;;!!yyrr44AA}}II||22ss77EE^^ggrr<<55rr__pp<<==5 5 C C r r [ [ - - D D > >   vv %%SS\\44] ] W W ss5588<<__pp''""++UU ""{{[[::tt::%%22[[RR ==55ii==  llEEttddDD?? TTxxxxDD$$ ..%%44TT::::MM22NNTT::??ppZZSSmmzzqq``kkcc>>FF &&==22VVII``BBss//!!::JJ--ll____aavv))''>>  ((MM[[88bbbb22bb]]66IIff77CCzzZ Z ''nnMM { { J J V V v v f f e e Y Y ; ;   " " X X z z   aajjd d   * * 6 6   bbttCC^^yyNNddvv== 4433##yy[[ww JJ hh$$_ _ j j * * ==22**tt]]DD66 CCss uurr 00//]]##00ppww}}nnFFmmTT44VVKKKK--ddwwEEHHgg**LL||[[uuGGPPii zz11iiFF00AA]]MM--ll""00))%%,,""II33{{\\bb22 rr((LL{{bb__& &   wwff  ""44tt==dd__==\\@@!!eeEE&&@@WWssEE!!LL55r r !!""B B & & CCAA;;QQ..qq""llbb99rrMMQQFF 6699 RRllGG..pp--``qq>>\\EE##33**{{==77CCOOZZpphh FF~~EEuuVV55gguuYYxxvvLLRRccYY,,KK||CCNNYYXXhhppLLll__((bb"" 7 7   kk]]ee((;;<<::{{ll77 XXGG$$AA==QQ UUffKKww@@$${{]]YYII''jjzz88==66TTjjSScc  88# # i i KK##22mm,,44AA[[..' ' \ \  $ $   OOUU222211\\22llCCNNPP22MM]]77KK!!ss~~rr((  JJ zz$$'' %%zz4477AAJJZZxxqq//,,^^>>>>)) 99ss[[GGXXRR   E E ""++||JJ@@ ooXXHH  c c 7 7 N N kk@@--xx44::uuvv  44eeKKCC0 0 ' ' ??QQKKrr@@OO))[[``q q Z Z r r h h YY  00RR^^DD;;oohhRR((hhOO uuvv\\  W W Y Y G G c c 11ee~~aacc[[%%TTPPII}} qqwwoo[[CCKKPP8811MM$$BB==22,,//CC~~xxtt11''""&&[[FF bbjj..ddgg//88HH@@==UUyy44FFTTbbccpp``qq''vvnn==''ii//ZZMM''00**>>ddAAKK  k k --YYnnaa))WW||BBuu[[UU ggdd>>[[{{``ii>>^^rrnn<<8811II((IIKKYY$$__cc66llxx##""[[AATT??LLDDttPP11vvss>>eedd ooPP((BB,,&&XX33xx99uukkrrhhcc44NN22//ddOODD  RRqq66ww,,,,0022NNBBcc||11EE\\VV!!""__ JJ,,99 HHggLL((TTbbmm((dd??,,IIAAqq00GGVVww00hhZZBBSSSSssOO||55{{vvGGLL44mmvv88==((ii##KKVVgg<<""^^}}OOYY22XX [[ssllpp**WWAA((xxh h g g ?? - - ||MM77^^88    y y  \ \ <<  88GGUU::xx\\..::ll Z Z ) ) ZZ^^tt<<wwJJ;;[[dd?? ##77XX<<''99%%33%%II11nn  ZZ88yy33MM  BB$$RR" " K K ``##bb::xx[[jj  yyrrEE;;MM66rr((tt--kkwwZZLL[[''AAvv""__NN88==11  %%ee!!##88ww.. ZZ~~KK>>88%%eeNNTTjjq q G G , , Z Z v v q q     ^^??``RR..yyccuu \\rr//88!!]]::"";;88qq\\mmMMvvmm//QQHH{{QQ||nn??SS[[``FF}}CC[[@@JJtt11LLWW ` ` ( ( B B LL }} J J    < < ssCC3344**ii((pp__yytt}}HHGGDD!!uukk``##zztt11eeTT@@  eemm++SSttvvKKzzVV ''CCRR  >>ww@@ LLMMnnaa--]]))YYNN kk PP__QQRRFFuu}}!!////DD''--%%dd..tt--55KKee88oo[[ CCffBBss **@@FF**44==""{{==]]AAAA}}cc77 TTAA__$$}}wwLLjj>>((6666%%XX<<""__qqppllnn~~//yy##KK&&AAZZQQ ^^$$__9944//gg{{;;TT{{IIEE@@ nnjjccXX^^uuvvvv  DDYY&&__WWzz$$kkbb**zzmm((  ll??LLYY$$JJ77tt  yy``33OOiiTTbbJJzztt^^==ttHHqqyy{{xxZZ??##EENN]]JJrrmm88RRbb**llBBRRooee==AA 11  ? ? ) )   FF%%SS77DDjj~~yyZZ99~~__11!!OOtt==((^^RRNN,,??BB00OOpp))aa,,""oouu22RRmmBB RR[[]]__,,nn  QQ{{**{{wwPPHH11((^^kk00))WWPPffGG??UU55RR``SS, , NN{{7711nnww11kk##5588OOggVVUU WWHH}}\\rroo HHGGZZ//DDss  ggHH..==88AA22XX~~rrEE$$ss    ' ' w w 22KK))uu ,,::??>><>iiJJLLbb00__llxx&&FFDDllii,,NNyy99FF>>NNpp  11gg\\++::NNgg@@XXGG //aa~~??^^@@uuqq77ZZrr {{ qq ..kk %%]]??^^== 114477aa]]77  }}''<<''XXrrQQkkyy--@@KKRR,, --LL;;00??**..55AA  22aaPP22JJbb##QQcc**SSllWWRR11  '' uumm!!BB??HH))88$$**II99ppVVLLyy--LLWWNN~~YYTT]]##vv]]WWjj}}~~ll55GG==>>cc \\**qqXX++yyggLL      II]]oo##XX||$$PP// ##``[[;;  - - HHnn||]]NNFF 5588YYllmmEE>>hhvv%%aa__ DDRR%%ttCC//UUFF??RR::JJII$$33##ggssEE%%UUUU>>SSSS LLqq77PP}}aa[[ ''%%GG77//<<==RR\\55RRvvlldd>>;;GG==UUeegg==``ss]]==``''XXLL~~  R R     8 8 ^^##II  YYjjmmhhQQuuuu  AAxx00hh  ..WWdd..UU %%QQ22==AAWW ==^^ FF]]FFOO      ccttff99MMOOAAQQJJvv..aa((ccYYmmSS##ooii}}IISSpp``44aa66 55##oo++yyFFaa||TT%%H H     [ [ O O   }}<<(([[WWBB  ^^XX__ 55MMgg>>    DD //ff))PPKK~~JJ++}}UUqq  ]]EEZZzzHH%%KKkk~~99ll++llSS ??ww>>%%]]hhvvAA ,,..FF''<<__ZZdd::EESS}}66ZZ IIeewwtt||""MM==||uu%%RRppcc ii&&++jjJJ ]]%%((OO ,,qqllss@@~~kkkk$$LLttss>>66((rr==[[  ddTTbb77nn22??22))//88**}}[[FF22HH''  //yy%%ee!!vvKKggFFZZ..VVssIICCjjttSS7755,,KKJJuuRRZZeehhttooOOggGG33..LLWW##]] 99ZZ..nn--??FFBBNN44jj88~~ccYY||,,MMQQSS{{IIii77hh{{nnoo%%"" CC""HHUUaa,,uu22sszzaa??FF##CCcc11""yy!!55NNoo[[~~==GG99rrcc<<88||EE??kkuubbSSNNMMFF44    ssYYVVbbxxRR  ''ii``<<LL!!yyZZKKhhIIaa//ffllQQCCKKoo==vv  **11UU==AARR^^ZZGG  mm@@JJ|| %%[[hhllXXppDD55oo<<iihh@@ddbbyy++QQeeXX(())##44NNzz22^^~~::FF((&&55JJ__oorr__--FF""&&IIxx~~wwAA--ddxxllKK((    iijj  ''22..  mmTT66AAkkuuTT22 --``++55nnPPKKcc))OO>>gg]] ^^??''DD==qqAA iivvvv ddUUmmJJppff11ww--<>22cc++ppppffCCppyy>>qquu--ff{{^^//xxYY''uuggYYEE22++99]]$$KKtt??77~~TT((TT9933AAhh zz//EEJJ66  uukkqqsscc=={{((aammHH!!zzLL88IIvvll(( ::OO]]iitt||yydd77^^~~qqddUUAA((!!JJww""``bbEEHHpp [[UUKK::%%uuJJ>>11IICC99yy++++,,YYTT}}eecc7733DDiiDD\\``JJ{{JJ~~::__bbKKGGXXvv66^^ YY<<4411||ccuuCC||$$1100]]ggvvJJVV``tt99aaddJJ}}SS003399%%OO))kk''::;;++FF  :://llNNsshh((==bb##ddccVV<<||??CCQQ  77YYeeSS!!ss^^''""HHxxKK;;,,\\66PPggxx11MMVVMM88%%,,MMrr{{DDxx JJNN[[ddkkSS**VV66__``SSrr hh33CC88  ]]hhXXZZHHNN++ qq[[^^tt--11uunn>>..>>hhQQ33{{__QQSS^^eeYY//??vv``]]ss@@WW[[UUFF--kkII  iiCCJJBB ??]]RR {{@@..zzGG\\II::tt--YY//UUiillBBffAAMM33cc^^66ppLL''NNkkXXnn^^ NNRR99//^^ggQQ((]]aaNNNNTTLLrrNN..;;rr##WW{{~~^^$$jjrr||aa**ooRR||ffpppp==IIaaAAuu}}iiWWKKMMddQQHHoouu  CCnn  nnWWRR@@xx]]EE##||RR==@@YYuu;;CCII22  BBqqNNxxhhww^^]]==KK""EEGG''JJ IIss--gg..qq''ffrrSS88$$IIff>>wwrr&&UUMM**//YYVVVV  ttss]]llssNNnnkkUU>>$$EEaa..33||ooIInnOOggAA::BBooeeee{{$$FF66//``11ZZSSVV++..NN&&((__vvzz{{mmLLtt^^KK\\--IIee::ll..xxggddGGSSoo}}ff##??gg((AA11jj''VVss yyMM MM//wwrrbbkkDDnnhh;;\\11oozzQQRR{{yy^^GG[[OO**--DD__uuSSJJnndd&&,,ZZ55rr}}XX11  [[ZZuu__ ooGGddzzvv==11}}5577qqDD&&99..uu1144WW[[AA  tt''uueeQQ00SS<< yyddttff33 [[ffKK>>HHzz--rr((YYccbb^^$$cc--ppddggvvttDD22llVVEE99''||vv00 mm YY$$==``tt::!!llxx66((ttwwhhbbEEff  mm''rr%%uuxx==``@@&& ZZppccdd||xxJJ11oo--((RRww~~TT tttt$$<>dd__uuRRHH++aa>>bbwwyycc..jjrrEE//~~vvbbhhuuBB``WWllbb!!NN--''<<ff//..  ??aaGG!!dd22QQ--oo  kkSS55gg4466||NNLLOO))SS7700vvOO++yy22==KKPPhhZZ** }}++\\ttss\\00bb}}NNBB~~))<>aaPP]]jjpp@@ff}}xxNN  ,,**::##BB66OO>>7722  aaYY>>hhllTT++uuOO  bb??aaNN  __  HH  RRMM((kk??UU""**NN##qq ` `   G G C C W W ,,vv88UUEE__>>BB 99cc88**##yyMM##{{##22??uudd]]ZZ{{IIPPddVV88!!%%LL77ttee//UU::4444WW2277oo]]vv77ww IIZZXXUUll&&OO88;;,,ZZNN44uuCC!!QQJJ""vvCC}} ~~ffII##HHuuii++^^jjVVJJLLZZhhhhPPSSRR&& VV77GGxxPP@@II[[aaMM qq;;rr }}11}}^^SS^^&&ZZ77nnmmYYyyQQ;;//%%CCZZFF88oo TTff[[PP}}((ss));;;;77yy== 55UUxxkk11kk ee::zz))QQff^^77mmNNXXii <> }}zzBBeeeeJJ88 VV]]ee{{SSiiWW{{wwffaann||EE yy{{__'' ==NN99xx^^UU AA~~zz88GGiiRRKKaa,,@@33nnXXyyeevvAA{{nn>>$$VV****SS44++AAttMMOOii**llXX''nnYYZZyy;;ssqq##WW;;GGkkggvviinnXX44``uu]]eeJJKKhhPP))0022BBjj ##EEMMMM  ^^..ss  jj{{aa7788xxhh&&&&44..AA 44++;;..hh$$KK77ddQQ^^ii55%%++||eeFF  &&OOeeVV11}}44PPNN))yy>> {{{{xx  ))ffPP:: OOff//qq**EEttbb  &&aamm$$  yygg..TThhdd^^iijjCC//HHDDGGhh::LL**UU''''uuTT88UUAA||__@@vv##BBii''RRSSIIrrdd''##CC^^^^11((II11OOnn""HH ''HH55 ==ssRR WWQQ``QQ9900HHDD11YYRR77""@@BB!!xxGG[[^^JJQQUUttTT pp^^AA^^  ==QQ~~VVpp^^nn22wwJJii~~nn55 ``  JJSSHHOO**44 <<66&&ffYYvvNNoojj{{;;wwyyddZZAAss{{<<rr::uukkww**UUgg}}  CC**GGgg2200!!aa~~SSOOMM??##IIZZUUGGBB__EE&&VVJJ00TTVVrrvvggll eeBBDDss**aaqqpp;;VVjjjjqq00NN}}//ffuupppp ))--88ttLLrr==ggAAww//uuff''MM==  $$QQ..mm''++ddUU""==bb{{ww;;vv99 **JJqqKK//vv66NN&&PPnnvvhhOO;;88GG^^qqssXX11**SSVVcc cc$$$$rr""55--FF55cc++ &&@@XXdd``KK((ooffss&&__nnaa%%{{{{  MMTTNNqqTTqq ^^))UUBBjjttxxtt,,77jjQQ@@==MM!!nncc  HHTTggRR6677uu;;\\vv''KK^^  x x   , , | | ' ' ^^RRddaa~~ff66\\WWaaHH++DD>>qqWWll__$$EE88zznnXX''\\[[zzKK$$HH""    33LLJJDDUUSSAAYYGG99  !!LLDDXX**00ZZzzKK xxDD[[==!!}}qq**kk !!ll11FF^^yyUUffvvPPQQeeCC99gg~~//qq  jjFFIIXX,,@@jj33  PP<<NN11ll__ --SSZZ ""&&77tt77zz))\\1133__ ^^aa''yyllII%%ttWW 22QQ ddDDMM;;rrmmssaa((VV\\NNMMss[[ rrYYyy__%%AAxxKK''<>((____--GG++22KKbbggUU00!!EEUUJJ..))nn]]XXpp''__ $$HHeesspp__GG**TTOOLLgg`` ss(( ++))yyaaRRLLMMVVddrrzz~~77kkbbSS''}} DDll  --99##uuYYll44ww11##II33VV<<^^;;CCss&&iiCCWWXX!!iixx==PP88cc00{{%%xxttjjgghhWWUUdd--hhii--//ssPPNN--GG>>kkPP@@bb \\UUlljjppii((DD@@::GGffZZpp{{ZZuu__--  **::]][[TT""mmCC  TTwwgg""  OO++??GG]]QQFFMMGG 88 >>^^ss~~((gg==::[[hh##``uuRRyy?? ==LL%%>>EE;;cc33xxmm[[..--""$$ooVV))KK}}QQuuHHEE EE++;;##,,##tthhee++TT,,wwCC22KK??HHZZvv,,~~//$$LLyy66||OOZZ((^^::;;rrll--''33\\ qq``[[66__JJ33CCqq##??]]?? uuLLKK\\ttIImmRRYYbbzz``ssVVXX**  pp  ++,,LLFF##00ttxx55{{TTMMRRAAss::bbPP33uu  eemmYYiiYY44%%hhyyOO>>TT33mm}}WWtt%%::44uuWWZZff99++ii ZZII::ZZ!!^^$$;;..wwzz++``((qq55]]nn%%NNNNgg22pppp((~~  hhRRllGGzz**ll))OOhh--PPZZdd22aaee[[ffLLEEAA33&&jj//!!??bb{{vvWW((mmbbmmOOllYY((rr RRll''iiHHOOnn44$$JJSS;;LLqq>>ddZZ00YY// AAttxxcc\\ppeeEE}}tt//yyWWtt99 WWzz{{ppffXX<< eeEE>> XX\\//uubbrr''~~jjNN// ))ii66UU""{{ ((00ZZOO&&ee99ZZkkPP==QQ))SSnn~~''ss{{ --{{nn TTiiVV__mmPP``ee!!--gg  }}GGWW77AA~~~~**vvSS44yyZZ%%((HHaaZZ$$LL__nn QQ44mmPP vv00EE ^^&&QQhhsszz MM::MM{{::eerrV V f f 5 5 MMssUU66mmgg!!kk##ll$$rrTTEEYY{{bbmm..xxjjrrUUFF((22AABB44uunn @@::[[bbFFOO  AAllUU ss))..QQSS55DD  11hh33eennccQQ  ``JJOOaahhPP   ""11==hh&&||CC33rrKK))uuxxYY##BBhhQQllGG\\//kktt::FFLL**sskk??--&&,,SS%%cc//vvrr[[wwrrkkqqDD??EE??;;}}TT@@||&& ((ttbb--  zzJJ!!MMpp  5533--ffRRoo!!mmCCaa77mmrrPPtt  ''nnFFTT44 yyEEJJll;;00PPQQ  44ddeettxxnnbbkkLLXXPPTT$$DDRR nn@@$$ kk00hhllqq~~%%~~ddYYBB..ccmmAA55::??//88  uuAA>>ZZtt44FFkkCC~~II((__!!KKVVGG(( 22ssmmLL""rr00dd;;vv[[aass||hh"",,ttppiiXX00\\;;??WWbb4488zz%%cc  wwVVFF>>GGvv ^^TTii##rrBBooVV''''mm__3311>>ff$$oo''WWTT33~~xx[[[[""CCcc!!MMmm88xx]]dd&&44EEJJRRttccMM~~mmKK&&,,HH**kkvvjjeeqqqqTT==**{{22MMBB112200jjKK##HHccGGqq44aaDDIIWWVVBB++--XXCCEE%%..RR****  $${{\\ll$$88 ZZ NN55ZZYYYY66 22??''MM++hhbbgg  DD //uuNN2211@@UUvvww  ""CCee3399jjMMUU;; ss JJgg88""77776633wweevv%%00 !!kk**!!;;TTHH>>OO ++UU55((uukk%%kk88UUNN||!!VVuuEE  JJVV((77ll22~~  yyUUttgguu##ZZ??MMll[[ssTT}}zzJJDDSS@@ff''II    FFqq>>AA]]WW}}bb  nn//PPDDYYaaww--\\hh  44``((::GG{{II;;KKssRR@@@@II 77{{''ff--&&## **~~''<<,,ff33##MM JJCCjj  ))FFAAVV``]]  PPwwCCuuBB**66ffBB__JJ88jjllff__vv%%}}ggmm88""    rr44||ccjjrr$$  ,,ccYYppDDGGzz ccRRyyooCCnnCCRR33AAww$$rrtt~~QQ kkHHCCZZUU//ttgg##>>11jjDD1177YYWWGG66 aa%%JJUU99rrggnn@@VVZZMM33bb99CC~~HHYY1111zz6600$$aa22aa oo99iivv11UUMMrrWW??((''iiii;;??XX##}}LL$$--__BBgg}}AA}}))ggqqffrr55rr{{BBFFcc\\FFFF\\YY::CCbbxxAAdd44[[TTrrHH""%%hh{{11bbyy==1155%%MM&&88hhFF##99jjff  ==--~~--99uuyySS66MMcczztt??  NN66NNiiUU77kk ;;%%::gg66ff88hh'' 1199OOKK++]][[aakkVVtt}}qq55>>!!SS||CCqq//LLYYVVCC""EE55YYTT~~RR^^77jj}}xxlleeeeccUU00XX2222aarr**}}IIEEuuDD``**OOXXnn""uuffTTIIRRxxssbbTTaa,,  YYmmDDyy rr99;;mmDDTTLL++qqyy77@@77**$$&&&&ss ||AAgg  JJUU1177UUSS%%>>qqRRvv__LLLLPPnnjj]]ZZtt""||YYMMSSffEErr||]]??&&OOff##LLEEzzMM !!jjmm22{{\\uurrrr$$yy[[ppJJ~~..hh33  eeddXX[[ll//##\\11VVQQuukkMMll66uu11wwRR22OOGG((VV((55qqii00?? GGaa~~@@vv55^^ZZ~~WWRRllff''__??<> oo}}aaSSdd..==~~[[NN11ppDD..CC__ff88||EESSddkk]]  ??XX__^^bbssNNxx''ddOO##((RR``++44VVZZ[[dd88eerriiZZ\\rr%%WW99iiLLqq\\33ttkkcc~~++ll!!ff\\  ww;;..eemmGG))^^ RR66NNOOtt##AA44ll;;PPUUNNRRCC%%BBHH''__BBDDSSRR&& pp NNMMtt\\^^ww**hh''NNeeyy55ooGG))VV__ggll==PP~~``22[[||''++hhjjOOee$$QQvvDDIInnaa((kkrrPP//>>@@ZZWWkkHHdd mmDD99CCSS\\]]]]ff~~RRgg..]]FF==hhNNtt>>II**((nn PP%%RRVV..??33ZZ;;PP$$22::QQss&&77[[77%%hhFF88;;EEHH--]]@@qqKKBBVVss~~>>  hh3311rr  MM77==nncc++wwwwxxgg<>PP00YYYY22jj~~jjgg}}++SSTT1144eebbggvvwwOO<<DDZZqqBBggmmDDPP((>>ZZuu&& eeJJ[[&&[[ aaOO]]{{__ccBBYY$$  !!44==55!!iiYY22uu## CCiiee99CC''SS33003333>>ff {{ffLL%%`` ZZ]]TTBBPPxx66vvIIhh~~KK^^77aajjppss55tt>>LL&&nnuu  --AAFF::nn77QQXXBBkkkkoojj@@KKOObb66rr,,..jjAArr@@ll22CC44VV##AA}}MMHH==LLss  mmYY??^^KKwwll--XXjjoo;;ll,,<<''ppDDooTTnn qqII,,XX66PP__hhvv>>TT..ii[[  ,,||  ^^IIllcc<<EE__$$mm//RR?? jj((KK@@JJjjGG%% **TTzzbb@@'' uuSS""rrffeexx11ll//wwBBnnyymm  ppHHPPtt==qq<<99AA````BBnn[[eebb----qq<<YYgghh pp uussZZLLMMYYddccMM$$55TTllII!!AAvvhhddqqjjhh%%..yy}}55TTyyaaxxNN))&&XX==SSDD  &&44;;==??BBHHYY33UU::``NN  $$33..TT__HHffFF));;VVxxiiEE(($$HH@@  eeRR[[  11DD5522ddLLqqffhh77ss>>1133%%ooyykkuuHHzz``""CC@@  99BB!!gg\\AAkkVVjjYYQQ!!  __xxHHzzTT!!yyzz<<33vvllEERRhh>>  77qqjj<>==QQbbIIjjRR88SS,,""++2288BBVVttoo^^bbEE4466{{//BB##55kk44dd33``zzyy::TTDDEE``ii''99!!pp!!xxAAcckk&&%%@@YYwwRR 33DD..\\ssuuiiWWIIBBEERRddww}}ppee[[MM77[[FFUU::>>cc##||DD::44pp>>hhdd!!77^^ii @@;;66::uuKK44;;//kkUUJJ''88 RRGG@@""AAbbvvhh,,00RRpp$$;;  eeEE  dd  bbFFqqKK22nnmm@@##$$CCttZZ**++((DDDD((llcckk``ttjj??}}!!dd<<33eettRR\\ mm}}??UUBBbb**kk''zz66oo33^^%%FFffTTMM``??xxYY xxNN>>RR66BBkkrr9911kkqqMMSS))}}ssggNN cc<<dd**>>OO__ss``  EEkk~~  11NNkkll&&kkCC $$ppYY##zz33ii~~DD^^ hhNNGG((uu11 ~~))FFeeLLddJJmm44UU>>""BB[[33ee__LLUU!!9988kk33WW@@ttIImm**II99UUUU33##))++TT..++ttJJRR;;tt  ``[[HHyyzz22nn--yy))77??ii%%55++vv==RR  $$..iiww))YYTT kk%%ppOOttmmpptt;;mmssIIkkHHll88>>TTWW**FF33ss{{.. xx}}22ss&&33VVqqGGyyff44uu  HH ""PPCC//dd\\55UU GGGGzzdd""YY!!rrBBUUss))SSggssyyqq]]33QQ  RRee>>DD||88yy  >>uu}}))OOXX""<<ss 66ii%%MMNNmmFF\\ttppnn99\\VVqq$$YYkk^^FFnn..  ))XX??]]II""UU66HHKK//KK__;;DD``oonn]]BB((88dd]]>>++kk||RRee33SSjj}}\\((33yy<<^^  22HHLLEE992233::??99\\BBQQ<<aauu ))yy8877''\\IIccjjQQOO[[mm}}xxhhSS55aa__++$$^^@@--**99UUvv||VV&&ZZii//??iihh;; wwaaGG//##--NN!!GG<<hh}}||jjQQ<<2244??MMYY[[OO00~~88ttllvv22@@  qqhhxx77""//KKddjjXX33  99??$$==vv\\9922OO]]]]UURR^^yy88VVppnnLL**HH$$WWccRR00 33TTww  ''""++99<<<<@@RRuu((uuTT~~~~]]%%eellxxJJ==))II##,,YY--88 &&;;kk''%%::88VV??WW __11ss33MMccvv~~}}zzuuoonnyy00SS~~``**xxSS9922==PP[[UU;; 44{{99  YYcc^^yy\\kkVVBB11##{{]]66zz((nn,,yymm~~ggPP<<'' 55kk$$## ""OO77~~PPkkXXkk ||QQBBQQ::ee$$ll  OOggRRLLWWvv%%QQ::66NN  ZZyy llMMFF00]]kkWW''ssXXWWkk$$$$ ##YY ss??NN""ggKKIIcc6677ggVVBBOOkk\\""==..ZZ++--hh??DDoo//WWqq**oo00JJGG--ss@@ ((;;PP``ffYY44MMDDhhssjjnn^^(( gg WW33bbgg77bb22 ,,HH``iiaaTTXXiiss--88qqYYAA%%  FF%%&&,,||LL550088FFYYpp ##++>>NN]]ee``GGffFF**=={{``LLllee||[[qq<<22hhZZ##33pp  IIiixxmmFF    {{bb&&==aacc;;ee&&&&uu((aa66VV QQIIrrKKeeZZjj<<447722<<]]KKqqUUCC88..qq   dd AADD__;;LL66||MM##bb66  XX44GG;;~~QQ##]]``llDDjj;;HHnn@@WWmmTTkk,,%%**UU @@%%((""oo??<<KK  bbcc4499KK99ee88,,GGccNNWWxx~~xxnnccVVCC**[[AA::**jj00ii99ss5566$$  ''22!!ww<<hhzz99%%,, &&hh""zzyy**pp]][[ccnnxx}}yyjjMM((;;>>hhjjNN%%VV==AAbb..RR''!!||((llxx&&))**??kkSSOO__{{,,WW~~zzcc6622ww22@@00&&llGGkkKKLL bb==JJHH--MM''PPggHHkk33<<;;yy__GG))xx  NN22##  ??ttaaLLEEGGDD--00GG@@MMGGEEAAqq55++;;@@33ssGG44FF88 ]]{{__MMGGFF==$$YY11""BBzz55RR[[YYUUWWddwwcc4499 }} 8800 22SS||BB\\ff\\==AA0011DDccddBBFFnn++JJBB~~WW??88::<<22ffXXSS55SS~~mm11SS--VV**  ``%%XX``((NN##88ss55[[oo||00SSxxzz  ""116622----99PPnncc''77  OO~~||bbJJ;;::HHcc||//HHGGjjPP99]]AA[[-->>%%__CC!!..==RR@@<<ppRR{{aaYY\\ffuuyyzz44~~''vv88\\LL++;;55??ee~~44<<  jj||VVrr55ww nnFFJJ&&,,qqVVDD66--++33CCZZpp{{llbbddoozzvvXX99 !![[}}@@ 88hhHH{{rrXXCCkk||uuRRFFhh@@VVddPPmmooYYFF::::CCQQZZVVEE,,77ooQQLL99aaSS ((PPSSEE88OOQQIIFFQQiiee@@uu==//II''..RR""**ddss  55HHKKFFEEOOeeyynnooMM^^iiJJ--99VV__[[SS>>OOEE44((FFHH..99GGqqxxbb``uuhh;;AA22XX66""55ee qqBBYYccmm##oo0044uuii<<33<<bbSSgg //00 rr]] __aaccll::yyRR66::oo44  WW//ZZvv||llNN,,??ss&&pp  33aauunnSS//  {{00KKmm[[]]jj||77kk  bbbb}}DDMMTT55@@uuVVKKVVxx11xxXX--YYii,,ggpp``gg~~ !!FF{{00)) kk66 77tt++QQLLtt>>vv>>""QQ00ooff99++II\\\\GG jj BBss$$^^,,PPHHwwffmmYY{{RR++bb22 ww//BBYY..ee//eeNNGG    mmCCtt RR44ss||//''--||WW==YY--;;JJTTgg  __  **++**22GGee~~ccEErr99WW$$44QQXXXXeexxAATTKK**PP  ))ee  44CC==))}}YY**zzqq||""AAII55HHWWmm VVppUUdd~~ 99VV\\^^kk  dd&&EEkk44;;##||RRCC--xx ;;KK||..::77,,##&&<<``ww??]];;DD  dd<<kkNN  //<<;;33((  ))VVBB{{ggLL%%zz?? NN^^KKcc22ll++PP^^**ZZKKnn~~llPP11    qqeeKK88cchh66}}HHRR  ~~%%;;||GGMM33//``jjLLQQgg,,MMkkXXllQQIIbbKK::DD$$33tt((99wwbb ll44 ((77MMpp//MMhh II((rr~~55 OO ''WWNN&&[[66OOYYCCLLkk@@DD''\\ PPHH  gg{{``KK11JJll iiRRYY77++33NNwwEEhh33WWVV""AALLJJEEEEPPkk""ww''{{88XXgghh__NN99##""QQRRhhKK00pp,, !!66II]]qqjjFFff44MM%%__AAVVttmmuu33LLddzzuu33//NNOOttjjQQ''RRgg``DD??GGVVll88ee((>>BB66tt{{ FF||HH,,cc&&rr  ,,JJhh22..<<AAffRRLLXXuu ..99&&ii$$<<[[qq}}yyffHH'' EEwwXX uu!!KKQQ77xx((\\;;66OO pp##..77<<::**  ]]ooXXYYpp**^^//SS00IIEE&&pp11tt]]II====HH]]rrllBBMMmmYYRRZZqqXX^^ooeeddkkzz44ooZZEEssqqZZMMUUxx  aabb@@ 8866jj  QQttBB%%&&FF//::$$RR9944;;DDHHDD77""VVooLLNNvvii >>''llss__UUTTYYaaiirr  --GGeeJJ~~""CCddtt77ee\\!!||]]VVjj 66HH66KK,,??JJ''"" yyEE??ggDD__yyYYKKMMWWcciigg__VVOOFF77aa!! ""..))==[[eePP-- llJJMMoo##ww>> vvwwllLLRRKKyyKKhhooeeSS<<&&  ##,,..((uu00JJ||TT??7733))ww\\>>## ""@@ooHH;;xxSS00ee  ))MMtt    22QQKKRR ``PP!!""zzxxbbVVLL774488~~IIrrBB!! //** MM ttXXIIFFSSrrKKjjuuttqqvvSS((&&kk##>>..ZZ||  $$00..JJ--IIZZUUEE7777JJrr  !!NNHHMM__CC,,ooVVCC::AA^^66vvHH>>eezzMM  ..??MM^^vvTT||$$AA[[@@ll88ll77 @@ee22vv::tt$$``44__~~}}ZZ))kk..\\++**^^ hhUU[[++::<<""HHiiooRR--~~::AA22PP!!xx22cc$$QQuuss nn))22!!||IIjjKK9900++%%IIaa==44AA\\ZZ ##&&((****))''""""..@@VVmm}}kkYYNNNNVVaaggaaLL-- ))IIbboopphhYYEE11((HHrr88VVvvCCzz00rrWW##nn!!ffooBB**''44NNqqLL{{iiww__11))99yy<< 00]]KKllyyttaaFF)) ..IIqq==55oo((ppHH]]%%55HHPPQQMMCC2277<>6688CCRR``jjmmii``XXWWbbyy55vv,,  ssHHbbmmppss||mmWW@@%%}}^^PPNNRRRRGG,,|| ::99ff //__hhcc__  ]]  22::>>DDNN[[eeeeUU//<<{{88&&MMyy!!&&\\~~YY>>)) 77WWxx$$BB[[tt  wwTT::))!!  ""gg\\[[  55ggyy22yy 77YY00@@DDCCGGVVrrkkXXRR[[ppvv5555ee55-->>SSrr BBttggDD33ccCC  OO))MMkkqqNN$$``CC))rr//UUPP!!aahhCC~~((VVuuzzffMM33  77nnaa,,TT TT&&VV''RR>>~~{{&&JJll..]]{{||aaII44!! 77PPddllggZZLLCCCCLL[[ssXXjj##**//;;NNff{{hhEEbb!!rr%%NNnn{{iiXXOOQQ__ttDDII66))9966$$HHzz RR  SS%%}}ssnnjj__JJ,, ,,``..YY//PP{{ llccss##66QQ||TT^^))  //TToouudd=={{77 BBllaa]]]]ZZOO::44mm==pp <<uu99HHNNPPSSXXaaqqyyddLL--dd((\\// 33\\}}22PPeeppppii\\MM99!!uuKKOO||dd99 sshh``^^bbiiqquusskkddffyy%%ss99eeYY::"" ++lluuVVyyrr|| 00ZZ>>oovvmmjjmmzz&&^^;;[[sszzvvzzCCUUwwEE''IIiimmhhrr22JJ]]ggggYYAA##kkNN77((  66jj==II>>""uuUUIIUUww++rr0022''}}\\CC::FFgg227733**kkgg%%RR||ttOO&&..ww""YY##ee%%__hh//FF~~qqcc__bbkkww 99ee22pp//ccTTXX..>>OO ))JJgg{{ooGG??ii{{yyyyvvookkqq**iimm<< jjII$$11dd!!^^ss''gg]]##//jj ""''kkDD33@@jj==xx{{EEYY==55CC`` ::PPaammuu}}++66CCPPaaww==[[||GG  ssNN,, dd;;KK88IICC((mmOO>>::??MMddddII::==]]ZZ66NNee]]]][[NN11  ff== 22ww//^^    >>||LL wwMM##ssZZFF??EEVVnnrrUUBB7711** 77||FF**UU  jj''uuiiXXrr77llXXGG<<==MMkk    pp33qqhhxxcc&&OOggggLLqqXXOO\\ ==rr""kk QQ{{hhOO33EE||66lldd@@  """"  44jj==\\llooiicccckkzzhh22LLrr== ..ZZJJaaXX''--qq88==00UU??ff  ""3366%%aa(({{iiHHxx}}BB##IIss\\%%XXccPP``XX22VVrr%%----&&__''II^^AA-- &&99VVwwdd33$$@@__zzssXX99aa9988uu __  [[QQnnGGddSS\\}}''ZZuummoo}}  aa@@""'']]  %%##""HHgghh99 ((;;NNYYXXKK33EEyy22QQqqgg00wwCC DDNNxx33]]}}]]!!5599SSeemmmmgg]]SSGG77!!ll44iiSSDD??GG\\zz rrWWUUqqKK 88^^  &&FFttJJll##11;;BBFFFFAA44  OO4455ttiibb``ggyy{{44cc66 $$&& ++QQyy++2255::DDTTii||..jjGGiiCCllLL%%``DD,,bb.. ''DDddEEsswwkk\\MMBB??GG]]DDmm33HHWW``ddccZZHH**hh88 ##66HHaaHH  0077//RR55FFKKAA))II nnII.. ,,@@SSaaee]]LL55hhNN22 ((==OOXXXXRRHH>>55//--11<>!!JJkkss[[??""uuIIuuff[[QQGG==6655@@XX{{cc++vvNN;;@@XX}}&&VV<<bbvv||||ZZ!!99pp..;;==77++zzWW<<--((**22==NNcczzaa$$==  ;;mmiiFF$$;;ii00yy,,EEPP;;  ??""**&&yyTT66&&,,LLVVNNnnbb~~iihhvv**jjEE;;ccww==}}II!!''QQ^^99llvvHHssUUDD;;6600**''-->>YYzz66YYqqzzqqWW11hhBB((""$$**88UUggDDvvnnFF!!aaiiWW$$00nn66  WWrrMM((    rrPP44 \\((SS==WW''ddzzII  ||77  <<oo}}[[&&88__33ssHH&&**,, ;;>>11``~~$$XXvv__@@bb))gg))||]]OOPP^^zz II~~ppoo??]]ff[[AA%% @@ggjj??{{pp``NN??552244;;EERRbbrr 22__##99RRoo99aaXX!!77HHssRR;;,,$$ $$++11<>CCtt}}iiSS;;$$ ''MM!!EE[[aaZZLL::)) !!22PPvvssVV55zzii]]ZZccrryyddJJ11 mmGG99pp::XXggllmmqq{{||eeSSLLSSff??kk''44BBNNTTRRHH88''  ))//111155BBYY{{xxTT55ww TT[[**uuggddpp--ee""HHrrqq@@<>FFIIIIJJJJDD//``22uubbRRLLOOZZiixx))4433''44rr<<ssDD4444>>00  nnBB""    ..9966""\\>>''YY  kkSS@@++kkZZ]]qq ((''rrLL44++//??UUkk||xxqqkkee[[JJ55 ,,99CCMM[[mm--mmFF((BBMMMMIIHHKKOOPPEE,,llFF//&&%%%%^^BB//))//BB__!!**UU<<oo}}hhww((jjnnXXEE33}}uu~~DD[[--ww@@ggwwss__BB!!ooUU;;vvaaPPAA660011<<OOeevvvvbb99[[88$$$$00<>__rr\\NNHHFFEEBB??::7766554466>>NNii##ZZ22\\ii==^^99ttOO,,!!33JJff""KKcchh\\DD(( ``33kkII'' ))``;;KKPPTTccBBXXbbggppssGG  EErr55 >>qq]]66IIHH66 55NNddww**33//UU,,nnLL%%jjAAyyhh``]][[YY]]ooggFFjj ,,II\\eeee__YYXX``pp--ooqq33QQzzUU44{{PP##??SSbboo||ss]]GG33!!jj55ffLL77--//@@]],,ll88SSaaaaRR55ggVVLLMMZZuu!!ss''PPxx__33mmKK!!WW;;--,,1188==<<55** %%((##yyUU)) FF88QQZZQQ88((,,((  xxyy,,DD\\pp]]--TTZZHHggYY__vv,,ZZ99EE??))CC$$nn{{ffDDKK 11\\uuKK!!yyuuww~~vviibbccoo**@@TTgg||mm[[^^zzCCLLbb44xxtt||((XX>>[[rr  BBcc~~ssLLyyKK##ttppuuuuZZ55yymmffeejjww**22-- %%BBffyyhhUUHHEERRoo33EENNNNGG::**vvkk^^OO>>,, }}\\>>&& __>>$$   $$++55@@MMZZjj}}%%**%% $$//55::DDXXxx$$>>OO[[ii++RRkkuuqqbbNN::%%hhFF,,11mm00jj__  WWffBB%% ''--1199GGaa!!77BBEE??33!! rrAAMM''aa&&MMkk~~qq]]DD((  {{ggUUAA))##,,''kkFF''''99CCFFFFGGMM\\rr kkbbffuu..DD\\vvmmEE""vv[[EE;;BB\\ UU  nnaa^^``bb__TT??%% %%>>ZZyy,,BBTT^^__TT==ppSSCC>>@@BB@@66##{{ ""::PP__gghhcc]]ZZ]]ccjjnnjj^^KK11((....--,,..66AANNYY``ccaaZZNN::uuddOO55yyii``]]aall44NN``kkrrww{{wwffWWJJ>>11 zzUU77%% ))AAee //OOoo77WWxxAAggoo;;ee<< GG&&UU((II]]eedd[[OOEEAAII^^GGnnww]]FF8899KKll&&IIaaoottrrmmggaa^^[[XXSSKK??00llSSAA7755;;EESSbbssttbbTTGG88##  ffII--qqOO))zzaaJJ55%%$$44KKff33\\vvccNN::&&33HHYYddiiggaaYYOOFF::++ ""''//==UUqq ##((''**>>KKII77??ii~~OOttccVVOOOOXXjj$$''%% $$22KKppRRff77rrVV??2222==QQjj||eeVVTT^^ss\\ jj``^^aaeeiikkjjff__XXVV\\ii||wwllffcc``__aahhss}}zzvvrrkkaaSSBB..ff;;ww``NN>>22))&&''++33==LL__ww++AATTaallww ..\\ HH}},,TTvv//;;??;;11    qqee````bbccaaXXHH33ee@@yykkYYFF44))''00DD__((PPww00GGee  kk>>tt__TTOOMMKKIIIIOO[[ll~~zzjj\\PPGGAA@@GGSSeeyy++NNttwwEEww[[99pp[[PPMMOOUU]]ggrr}}~~wwffTTBB22$$mmMM9944>>UUww>>xxssOO--22\\$$..66BBSSiirr``PPBB22 ~~ssss FFffzznnee\\SSII<<**ooiiss ##227733**jjII""ppjjqq&&IIff||,,ZZCCccww}}uuaaBB''>>VVmmyyrrmmkklloossvvvvrrkkeeddkkzz||<<99ppkk((^^BB4433::GGWWggxx 00@@RRgg33PPbbkkjjaaSS??&& ((ee..oo;;}}++7755''~~\\==  ttff]]]]ii  llSS;;&&((115533,,""ppYYGG99//%% **KKffzz 77ee  !!!!VV""KKuuMMzz  &&::HHQQUUVVRRII::''bb55}}MMllYYQQRRXXaakktt||iiII##jjJJ770044AAVVrr##ff))__nnVV>>&& llHH**%%--3388??JJWWffss||}}~~==}}**TTuummJJ  ??__??&&~~vvttww||((**''##!!""&&,,2288<<<<9922--//<>HHOORRRRNNHHDDDDIIOOUUVVTTOOJJFFBB??::00!!  ``44WW!!((0077AANN__tt &&==RReeww((88BBGGHHEE@@::33..))""ttRR22<<__{{SS// 33JJ^^kkoommff[[II// }}uuii]]SSMMOOYYnn))HH]]jjqqttvvxx{{ttiibbaaffrrgg>>eeJJ22%%55CCPP__rr##CCccaaCC&& oobb__eeoo||uukkbbZZRRLLFFBB??====??DDNN[[kk}}xxoohhbb]]\\^^cciilllllloouu$$IIllvv``KK88((  ##//==OOddxx}}ssnnnnvvuu__GG00ssllggbb]]YYYY__ffllkkff````hhyy $$>>RRbbqquu``JJ44 qq\\MMCC>>;;8833)) !!<>99::AAOOdd~~||xxuurrmmeeZZMM@@773366>>IIVVbbllqqooggYYII;;4444;;EERR__oottggZZJJ99((""55NNjj22UUvvrrddWWLLCC==::;;??CCGGJJMMOOMMFF99((mmGG!!-->>KKVVaalluu||}}yyvvww||uukkaaXXOOEE::--99ZZ  !!..::CCFFCC;;22,,))**,,,,))##ffMM33((44@@MMZZhhttwwddKK00**BB[[uu ++KKffyytt__DD&&aaEE44//1177<>''uu__LL==00""''??SSbbjjnnooqqttxx{{{{{{yyyywwttnnee\\TTPPNNOORRXXaann{{~~ooaaUULLGGHHRRdd{{ ..AAUUfftt~~~~ssffXXII::++ kkVVEE::66<>22""  nn__SSMMLLQQ\\kk||  mmBB--YY  **33889999;;AAKKZZkk||YYVV22yyccMM66##  !!77TTtt%%44AAMMXXaadd``UUEE44%%vvbbOO;;&& {{VV44''HHii ##++44??NNcc~~{{qqnnrr{{ $$;;NNbbxx))44;;>>==::5500--++++,,++&&NNbb77$$::NN^^kktt||wwrrxxCCvv**88CCNN\\ll  ]]--{{CC $$!!wwXX:: ''@@WWll~~__77 88\\~~ssbbLL,,wwRR33 ..NNrr CCllEEiivvGGddHH// $$1188::55--## --XXppYYDD33&&""((11>>RRii &&DDcchhJJ44%%''66II\\iinnllccXXKK??66223388@@FFKKOOVVaannzzwwjjYYGG55$$ vvff]]^^hh{{33__))SSttzzll``SSCC11**77EESSccuu11BBLLQQRRPPJJAA88..!!  RRuuLL,,iiUUAA,,//AAPPZZ]]YYQQKKJJNNVVaakkuu%%@@XXnn''88HHVV``eeccYYFF++  bbCC**--AAXXmm~~zzjj``XXQQJJFFHHRRaaqq~~YY44((0055887722++""&&99VVzz..@@HHDD::,,!!mm?? --PPssrr^^JJ88((  ))99LLcc{{nnUU==((llWWEE8800,,..44??MM]]kkvv||  wwddRRAA33''##**//2233333344555577??OOgg##..445522--))**//66==@@==66..&& ||eePP==..##  ''//77AAJJRR]]kk}}ssccYYUUUUTTOOEE77++$$''11@@SSii33WW}}""00::??@@<<33&&qqhhggkkqqxxmmPP,,SS&& $$**++))%%##$$++66CCPPZZ^^\\TTHH::,,;;aa@@ee{{bbPPIILLXXgguu~~wwggRR::!! ||yy}}yyooccWWNNJJLLUUaann|| ""ppSS88$$..AAUUggvv ,,CC[[ppvvhhWWDD00zznnggeeeeeeeebb^^ZZUURRNNIIDD??;;;;??GGUUii<<YYrruunnkkhhcc\\PPAA..ooeeaaddiioottxx~~""??[[ss55WWvvccAAiiII//77TTnnxxeeOO66 ,,==MM^^rr!!nnMM))..GG\\nn~~!!++224411''mm<<''66AAJJOOOOHH99&& ))99HHTTZZ^^__aabb__XXOOGGCCDDIIOOXXddwwww\\>> %%DDff||ddPPCC>>==;;44(( uu^^KK@@??HHXXll--==IIRRVVWWSSLLDD>>??II[[rr33BBIIIIBB88**    ppVVAA33++&&%%$$%%%%##ssTT11 DD33NNddww''55<<<<77..##xxkk^^UUPPRRZZggwwnn[[EE// $$<<VVnnuuee^^ddtt}}ZZ55~~[[88""22FF__zznn^^QQGG>>8877@@TTttEEmmkkPP.. uummiiiinnvvggKK33 {{mm^^PPCC99221188IIbb ''CC\\qq66KK[[ffmmookkaaRR??--  wwjj^^VVRRSSYYccqq~~mmNN**zzppff__ZZZZ``kkzz&&//77<<<<88..""   77SSrr$$0055..XX00 ""33<<<<77//''  ..EE__|| !! rrWW<<"" 55KK``uu ((DD^^uu..9977++rr__PPIIIIKKLLHHBB<<7722,,"" ''))## ##33??HHOOXXccmmooeeRR;;((  $$44DDPPXX]]ccmm~~      sseeZZOOCC77++ %%..559966**vvgg__aahhss}}'';;LLYYbbjjss||wwggVVHH>>8833--'' $$44EEVVffvv!!%%((++004488<<CCOOaarr||yyhhLL,,  qq]]SSRRYYffwwuueeTTBB..uuhh\\TTSSZZggww $$88HHTT\\^^XXKK::** ,,VV##>>TTeeqq{{]]88zzppkkhhddZZJJ88%%::RRggww}}yyvvttrrllccWWLLBB66&&ttkkeeaa]]UUMMGGHHQQcczz &&77@@BB@@<<7722++## ++99IIYYiizzww^^GG//yygg[[VVXXaarr ##66CCHHBB55##xxmmdd]]VVOOHHBB==;;>>HHXXll~~wwmmggggnnzzvv^^DD**  ##00AASSeessrr__LL::++!! &&..2222//--0088BBNN[[oo ""--22-- $$&&$$ """"  xxffQQ88 ##**1111**77\\++::LL__rrrr``LL88%%||hhUUFF<<44,,##""..::DDNNYYeeuu 22JJ__qqwwrrqqttxx}}88UUkk{{ss__HH11yykk__VVOOLLPPZZkkmmaa[[\\ddqq    nn^^UUUU__pp  ""33>>CCFFFFDD==00  vvee[[UUTTXXeezz  zzjj\\NN>>,,++==NNZZ``ccffmmuuzz||||}}~~uullffaaZZRRII@@9922,,&&!!!!##%%$$""""$$''((''""%%33AANNXXbbmmxx||nn\\II77%% '',,)) gg::EEnn~~wwuuvvxxzzpp``QQEE;;5500**##!!''++**&&$$''--55998833..++))''$$!!  %%..66==CCHHNNVV__ffiiggdd``^^ZZSSII??::;;BBKKUU^^iixx <<YYrrjjLL&&zzmmiikkuuxxccOO==--""##00BBUUfftt||==bbooZZDD..xxppgg]]PPEE@@CCIIMMJJ@@44**##88QQgg||xxlleeccbbddmm ''%%||||zzoodd[[VVTTYYjj  ++??PP\\bbddbb]]RRDD55))###### ..DD\\oo}}zzvvssmmddWWGG9900))&&%%%%++66EERR]]cchhmmtt{{~~xxmmaaQQ>>((&&--11333311--))$$ 33HH[[llvvvvppddTTFF<<66333355;;EESSccrrxxbbII//55TTuu  &&--33::CCJJQQXX^^eeiiff\\KK66  ttLL)) xxvvzzzz ##))++++(("" ++99HHVVccnnww||xxlldd[[OOEE<<552200004488<<@@??99--  ))//11223388??HHPPWW[[__``^^WWOODD::44//**''##!!$$))--00,,!!!!$$##""!!  ))>>QQhhzzrrkkff``YYRRLLFFBB;;5500**((++..22553322000033222200++''!!    qml-box2d/examples/cannon/sounds/gear.wav0000664000000000000000000305527412310072714015632 0ustar RIFFZ WAVEfmt dataZ                                                            ""$(*$&$&* (& (*&$$    *Z0.R& 88<*B@64040 4jvb`<>,4JFHL*F&P< pB0JLtLt$6JJJb\6@Rl.XZfp^lnfnn^Tf:^"D< 0*J r $(8:,nRtLL>.4NZ*r@JHNT@4>><$LDpXjr`~^~ZJNB:>8Pnx ,^x^6|lZXBDR@L0\8NLJL@>:*4 Xr:t$ 4BFhXpjzp^t^b^`Zfdhrdp\jdft\hJP6JVrl$"*N(d*f"b*h tx0@Xd`v~"*4.zhT4$pz|vttnrppl~|hJxHr<<4  4Vn,8Phx|rv~x xnV >" zfD&|px h^ r*8(4H(L6`HbHdD|rpnf zjX:@>8B*> *$j>:>r4p4r6fBrZpx`tz~ (4n,h:l:n0rBn<bBXXJ@(& vhTZb^XLZppt$$., xnpll  xp|jX\bh\LNPNf|v< \ Z.d.z6FRLNZRPV\j~Vrx~pnjTX|bRLzBlXH:",~fRzVVhn^f^PJ:<2$$lPN." ~p2R~LpLh`^plvvhZB:,"4624>Xdbv &". 6L\p rdx"(28<&".$ | ztl^d`flfjp|~xrPFb\DDj<L*<00 ::*  >NJZr nn&,*866:$2"("4B8@JJdl\RHVtnp~(&.n.~0p*b<d:L,0DVJ"8<:* zxfptdp hljn\ZJNDHJ^DF>*D:BBDDFBN:\:lFdXfPd|x|ztx~rx|xxfnRV>N6T6L:BNNFV0\ `J$>4>0.*<"@*.>@VFJ:@8:H0J86DFB@LFDX`fjdx **28BL`nPHfN:D0&*       2HNfj*n6~&rl" 6|tzj^pVJZR`R0.$"vvtl|n&| v~p~plz|"2&,. 2 86 tpz&< <PZV VVTV^NLtjPljNTZ@8NRNN40@*&BJ.*4 (&~zXxHtlhnxbVp>rHPXnjntvvjnxdxJR<,n,l4*N>D20p$4.| h&P4dhXl"8VD>4z4&"4v ~pf vlvbfn|zz &  NP^zlf^FXfJT\RVd p| $|xbp  4>4& "4 : & $~t|n^hlt|fppV^z $(*,.  $ "0 @J2Pp$\0b@b@T,P4H>F"Hb&^$2::VNfBh\^`rL`88HF@RZ$f$\0F\ j(lnN& $~ DFJrthjXPR f vj\X\@FP0$2H.>^B004@>B0.XP(&~ p,D.8ZF24LN.^xBR@H$ $D6h`2~8Fbflhlzt|n^zhZtZjjxrrzvnbdd<(( &$*  *$2< &"00,**,<&R< 8VH4:L4J:R*ndTJ\NdjV(<(04F@((208>,* $ 8(8  " .@>:*"Z^L`nh|ZHP6:L>@:   02<4&04R\FRPJtpVn||h| n\`$`"h\d~ |rx fN\>&0 ~\Z|($z0tP2F`H`j*b2lz"RD0P\NnTBFJ<jF^<HR@j>tF^fv\nfVpr|rzDf4pR|6~ v8b<Tp^jvltXFTHJF.n*0R\HH:JZ$v2~@4&.&  *(*.4( ( 8<B&0&.bhhr~v0$ ,.&4 2N@$~z$p fD>"xVP6 B@* (" :V"B6(LTN8X"T <$$$"022:6Xd \VN4XTjLt`\@@@84($zvVjxl h^r xblxB2~\NVVNRN^dRhVpTf8N@P^HZHNd^ntP0v*\j~*xFtH$,$($p&,.(,TbZ\PHd@\BNBN^N\bXp^vhpL@bt~|nb<^V26NR:24B<$$.:$L* .     *"*:0&H*.$.VJ40:0 $8  (  8 ">Btf|j~  0, ,(48JhVJ\`nrHjHv~~nt~j^pn`lfdb\fXZ6>,,,&*&B$Z.r\XvP\Xr`pvFjFhVXr||bnbtrt`R (JL p6.,v,f(V LB".>B:0 rtt|r\ntF  ,&4D(>FVbhll^PdL&8pP"BHltZN :>^LVr~~npzTL\Vnz`XX NBV*hT2($* (.4(60 60>2D$.<b6X8LPVD8 <\\XpXTbH62LxbTJPVJ^bb|tr~rrRFpR:6&&\r$nphbdD,z~v|~f~ & 64Flp6bB^8XHlP~Rr@,j,p8l>vVRnL~FFjFn@n~vTp\hxvl~&B6F2$>Pj\Nht~txb`xP|4d`NpXX~ZZZBT`^`^ZnLvFTTr2(TLf46fRdF^V^XBL>`@DHRn F,*$2,pZ^d^VZz<V(P<6"2 R@N(F<.\d40& .(:JNrl`zf|hn0n:f,h*VF$L:bLLB@ JdnpdJz2&b VLb&@vl2nRxXrJ\~z|dzrlVvX`V\|*4*z~ H6~ .nzz"b<F^zbXd^dfjxrZTF$BP\^R4$ ",|*"~>.:d`bL^Rt& jTRFn^2(L4Rhnfvln`prvdf4D:XPvDZx|XF^pxvfvn|bjB^Zntbl|t^tLVD<:^B*6,6>@.""066,$ h\`8*HVP@((>D2~r~xnd|$:\zplJNTtb`H&Dlvz~RZhNr:l>txR"BTPRV4HZDltt2,8448@bl|rb|"JdP:@D\nh|nlzf~pdx|P~`vL> & *<^,V6\hFLp`jRB0B<l\vd~fZxv$b<*:($Jt`r8~4`&B ,*$ (  tr.Pf:fTx 08H. ~ HrtlhF:<< ,JD :jP*Z2B|4z0n:|JD0".@& @J.,*~TVZnTn  T*`hrxvL8z ~^Fb|^x`:h8`RTN^>VT *8><*&@X@68 2(>DP,fr \&",<,&"(Hdbr``bf 6,:Jpn|bn>D@ZxJ*jTNPJNrnL@H&>RdhLX$$(0:J28J Zf^zX@R2l62, 82 \. pDHVLNLDT":r6.*RT6"v@T|DFd@zZ~4frh|vr>F<0FJ4`<`2BFz(xjB <((BL0FpjZj ($&vvD@d^d4@NH62>hR^P6PX(nFHT4>@V R0p0&f^xzvXJXDj,^8$.""x~lhL $0"VtJBDR PjBRfZ><0j n`@fl\H: |lHHvx`~`fr6t2HPndphv*BzLpVvpLXBN >D^N4 djttPfD02PzJ:^fp^zz~,0>("2 "J>Px ..H(.PN8fLp$00N8&Xxl B&"`@d&  ( $ 0,2f.\>\hTDDjx^"vF jHX`Zr2>:|<B`H:fLr(::.vtxjJ~FvdB(P@"@6jz*LJLN@RXXXRL p( NV$fVp&2Z\Xt8.>Vp^4B>,0\p*" nF$t*@ZL2> lZ\& x:<J\~`d@NT N$h,X8 @ DFh 6  8 "8P0 d RZR& &r 8 z2@jB~R>dB0P|:NV@j^&V&v0fh pJ4,>n6$ 2^ > BP`tf.X."TxZR@" T 4*H2R8B ^r"6&| td BNTb*P4@z &fLFD r >h  r T,^NT$24    Zx@&T d jVrz(P"jTDfZRFhbRdn P\:2Jjn~` pfrJ*(2R8VNV20T@XdT.>.h>N8.r>zVRBt.8XHtnx2|JJ*J&>4tDr`Z$j * L*vpNH@~f~0T6< 0   N  n " T 8 J * 8 , L b  t 2jf 8VXRRdv6  *d<PhH\D*d~N4*p >""&n xZR|*&Z`B0f*z@b8N2rp(Djb0V jP~NFXH<ZBNfFpF2@>jzxb46V0@RTb:6JfpX`8h(0jVj 8L&p$v<Rv(\r^ $  r h   X B  X N4 P x 2~vd: B . T*:Rx*j@\n$b^nN^V`P l NR0@*N~Z4X.f,@2fjv\"xlJ*,.Lf2N^Nj\FN4> nJ.Vrt8fjJTB2N*tnnn| B6lTf4 R>xJ|P:4(dX`*x4DDD |*zv0v82$z4z :Hf*^v4NL~ $fX:~h@ NpbvH22BT:dlvp&0* Bxh|&l`D(:,b@ZZ|b6<<X:2xb,~ BblV r( F zH4Hn&6 n$@H*FLF\>.x&ZzX.><2tRpd^.DrLhXHHPd@ vN> (f *ddlNv&Jlx:t,t`lnFTtTTffd "|z"h <(0nT:`r `nDjzvXv$@.Z|JBV<`"B<PbX2&D dD|\tDPjZ.BztFFJ$T<TxlH$8 6B0z.$zJv2^"6H  H4P*(0H6pH4Xvdf*:>&`T.."`TT :X>tfTv~,r\.2$dxF$&~flxLX`hF^l4<$@*l"B~T:x&v\.&6V@8"T*nZP$* LRBRv bX 62Z0RZH,J`FZ~8T:PPZXlH\<R<F6J^lbPxjl6pFB6&n tLJ T4 B.6RP|vnH@^  (4p<"L*r <&D`dv `Vt^dLzTn:&fP JhZHX~2PHXvjf~,x*~Zv $tL0V ^t*f6l*RN2TZh<T4fhLj4ft@rHl 8 8`h r"Rt&JT~J6 pR8ZNV2j$ 2JDbTv`p$4LndB2D6` &6*:T^l,*^b|Z(fD r8z LB DVZDbDf ~\NJ2*"Nj.VPr^p|JNBtR6Z d.x4<FNZ ~DB6P&"VdFP*< t$bHt 42 b:f <rL\~~&hf^T:"T\B>ptr0btP$ZT>\4T8P@r:xlZ82`8 &  r Xbz6n z . \L pT^l^XbBPh  0 R  l`R L.B.. ::~4 8 ^VF & * ^F z  & n2d""bb`v" $(*(p(LV\*0 BhƼޤĚrp`$͔`͖עp <v * vt"!t T VNT F&d<V@2tP@Vט>F:(@n~\ <~#$@ bRF>*j1-:6' r  hZ  v  b 4$@4l`NDŦJBֵ:&Хfbtt& PϠ4lX&  #N%L#^)6(*,l.+L2*81)/6(1T%T3(#64r$44&5%4#.l#Jr   8 4XVn@l:^h4,Xn$  rvb \~X@* Dh$J b& &%h/*60`;06<9 ;<7;"346,/$.+B R(fb%.!^ 2,.J&:Ft"B l>ܤbZ8vDh f *, " D  x rd" l@pFL*8~H(zF > <z&" 4" F2 , D lp4&vl h LH,xJ0> B|:v\֪<n npBB6j*8 r "~x 6 2 :.t.Dl`Jb 8(DZ\V Br*,H j~J j zB:D||~>4L8$0J\d~R4FT,j2D pF24*` b ."h |""0:" B hZ  H  D ` P` p  D R tt`pTl F F8@n8N|88݂ݰ~@$ ؀V"JL0 t.jRH@j0B2v|r  h P.  Z , |  :~  68T0 z ` ~Tz< L|X& 4B< | >Pb:T f `PXfV \~Hrd,fl v . (   f `  < 0 pb ` b Fv<z(f ,:Fl,*lv.pR<(h4HTn~f6xF @<j ,v H  Z"<(  dH*Z  r VR 4. | v & t d lXplV:~bx"RN`.$0pR\hNPzhTHdJ>: JjD^zN$"$XBV2TRF:,|l\8&f*<h(dTtT*bnFd X  zz  T l  * z p ( v 4  @ t8`.jBl$: lR~Xp(t\  X hh@ &:t@  z t  X&<,f *bN$vdtl\B.HN8TDhjx$ZZ.N@r4v.>lBd2Z,(pVLD.^d:l( 0xTH22zZX$BT`|xRbdL0~dPhl>"d L ^ DD J 0x4XNZrF| BF&:$^Nd0zrNhp~x@N$  .r,P0(DhT~RDJn.^NdfzB&: `:.|~bdHjBh(&L<H nX |0BXb pJJRZ(.XHvB8ffT FT V lLr$JFdD8J8 0  j :FHjRn4^rnftJ\Hpbv|>XRT8 0zxz^\r&n2$\X""X~BXN6|vP"Bx,zJR|@bldhrpzTRj&\h$8f|zz:t H8lD<|>pj @2.8L"p >~6nBt2f`086\<0tp6~ *nL\<0jN":^,Pt:B2(> @ V"nl~:.~JRpvDXd  NLj0nJd4T\rHz~T* P<00vb.j\D dFDhTt@THl^v| 4jt(ZL|:BN PbNjjzP4&j:z(4,Php,htZD FzT4n^bVT.:@LF,*Plxhx:n(n~v(~ppJ Vj ,D.|p F0P`PhFrZ<^fLH2NzjhXZJd\\"J>ZR\&x(nJ80XJ$X~ x VFj ,4 xbLPB,D46btL 6@\f.:l2>Jnx42 Tnnf^l8@PvFn.t<>lHj"|0f`RDBD|x|"\,>0.,pFlF VFvB,J`ZD0D^XFD6JnpnZDh tNT`"nN.Jp:H0r:D:8\J:Lpf, nT\0h.~X\`rPJ8t d. `* D^0J@Jln"p86pL`^&dFzR<<$lH*r |d8J\Vv4Z& B"F2<<, b&2 >(FP:8 &Rd h@t@f<.|<.h*Vd X,, B"(8X:x8$H*f24V:|68^^*PV^V\p $`LL d"2.|Jf ^ x4Zhp&X "4d P6j4rDFh0jz(nPLd& 6^~@0|D\XB4d8FZjD BJFhp >H^t \$vN>*60`ld\@n@ @v|>`~lN2LF|fj@4`Rl^ @ Dlxfv|\JVd2F(<Xx,z:T(8r^6>2dHxVXVT^dZV~^frnl$8F@( |hB tP>r4|Zl@Z:lH*j&.@LZr f.x,, ":z.* v@ F0T0vvlv`@p6f<82R<@T"nH2dprvXT40t<jF(Zb\dl|t<x:dVFl|v|~rRp24f$|hh\: P  dLhD^jR^l"" XN2bb0<D&>*D"F&XXn`<`fnVVzf &nv`xNrR4@:,"2B2V H`:ThV (Nf@xB<N>(~\FH`xvz6DNJxl|^Jbj@ Z**hXJvTJ>BTdRBF:B n.,&&6Tpzf\ptLV,B<,4r2.8^ |"Bbx BNdv*bZ`,nffjBL(.Vvtz4V\zH H,R&<. ~vH4VjhNDVRjrVTHT`fH\h$<d V4jBp,LDF^$6~z^Z&Dj,^>&.4080BP$d0V884(lTF6$|dxxLt|0 b ^BJdz,j*4D,rZB(vdldvXFpd|>ltt(Fb"zLVjvlh^$zzJ~J|F68XlVB&lF\PPZ.d( @D dB 8 |p|^2 f".tnhL.*0~bV*$Trv`PT&"xP @4Xnt|b`VXfNlHhFd"J .<>NJ,$RL:B:>^^Vrzdfhl8&0( > B fJ8 tfFtr$. dV\fTHt8l.jNVf4dZ"<"0"F<26 86xzr~dF40.:"Z&`<^xrFXX,@20.D24,(*2.8.8.*:HL8" &0@>,:ZP&* *06* PbP^@d&dTD82~2>&$.6" :. H,&zl .F|PfD^6`*\Zr*~,^$VzxfVlVxrl\@Lvxj D \z .4 | dbf^f0L"Fb|& t^4"$n JDbptt*T00&&"* *4"T2Tdn~4 ztXND$ . x8fZL^H *&  &&^:r^Vn4x.z@h0bl^@6:B<4.J&J0*@DVBtBz*jj&Vxpnx^t,j"j8rB^>@6T&^DHVBFVpbFHpFV$BRP6:RRF0lXpvrxhThn< ,@8~fbxv|~Z|z~:xHX8:04LH\FLJXJ:DTftr r Nhl 2F.,FdD0Pd|6&  jnj\dpb^VfX4Rzt`,p^B., ":22Ph~jprjptvzf~LTfp|xjdft &,$*@T| ,.0Ntz84 zpdH.B0L:N0PJT\F*("<J8&&2D<PR>rZ$ $ *6 B">HZR.XBLbv"<zd^:L\jnRz,>r b zXHD>J>`PV`6\&P0\:xJbbPPHf F.b T <H4L`B((p"Z2plpljxl b rpRLXTTh"z*4v,jt,x8f t0`^~>@RVb~ ~r6j~pjrN$|~~l^ZNLfpX@@N\4x820.0.H:@v2x0JN>HR@t<dN\ln\d~nV^XB>2\PL* $D*T&0.&( HHN~~bVjz(<<8006$4&2$.( $:0  ,$( $D**RN*&$J  ,0*lrp0B<NRnHT8$$ & ": NPTd&Zd~VzXfxtX>..86.0462&8XJ8Z,(<ZPZtx`f>T:F:^:x<d4\4`F<@&0DTTv@j,h&6>4<JFR$f N$86L>N$4||~h\PFRljjR\J`HX40&"(@" v XtBvXpDtDjJZ0R"L&<&&62 (.&"*6@R fd Xn ,| @06.>^P znNHj:x:T"8H(X2H2:"<,*"* <\lR8::.$ z\(R T $ (BTVRPLFTdX RXF2:2,H,>T>\VPXFFL:h2x8fFf::f~*BD@Vp &H"xr(<(~N~blv||``|pnVP.8*0H&r*:8h2d>v,^  &nJd@rfxBBHHb^lhrrXTf TNd~ntLj*V$N.B$:>">"6 ,$P:zH~$b\rxf,^6jPz~  `J \Nr.  :^h$d~jfRv|pjvzL<8 B6rff L lx, R  ~   N J6(,Ld`. ZV@v | < @@x^   nR XjR V@!V"L fx*( V Zb ^ Tr& r *r $ v   X h F  Jl(n f 4>*LjJBBR<,\ ~..nJBT>"b nF <  xr#&n'','p.& -b#>*&!h," X#~p"z&V6:0r6>PVpJԞ|<bp,Hr8JhF$ b *v Ld "P%f" z<<vX0vhÞ6(j*VȻT|Ѡ@P,<ͼׂp(2r~|Xt 8 6 &%\+./4Z1V4&8 ";"F<<"<;F6.(V%#V | &Xjt@Hz8z2J`hfjJx"@ݬ4 :( RZ BN|."">2Rz  |8( ^ 0  h j 2 BZ* ',,4$'$f B"  :l!B H" 4X@j  Z : vn,>. R xVdX,\*b,@ l~ fv &T @hZHp"(,  D  X x0 @ 4XP``R^\\T     (DRV" d ^nfT ڬ݊"Fv|LRrHp xL   \zRRFz^""&@Tnb:)='l:4$7<4F/fx*% bF \.L|jX@ZվӶѤܞX~.4F$  x \\  L &"%"\',&^L$8!dT* P D6l~^:xNRhZfBP<0(nnfr`p.>fRB Z zX~ h!$n!(',..4<-6) 4#t-n|%Ln" D |\db$(^|ld $>\@N  P  Z~@(z:JHdNb"$&ZB>BLZv v hTV2D,R^^x޴b(*Fb4nd4,<<t:> @f *  ^ f J v h 2 P*v> D`vv6׀b (Ӷ>hdH~lR vh:lh|*68 *`D|  NhrBjpRXN :FLP &Vjt J^.2x $|f\(|v 0 LRX" v  . H  ^ 6V4zn0| , b&~2f\Rܮ6B \(pdt . & 2lZv6^: f(!$,8 lb"Pf&@4n "z f  N r ~>  P> <x n<t"RX.`XTP,"Z`:(J .j\\ `(>~pf!D#`%!$&") *`($#"^(vl!l,X@b @^P"BDXnڒh. TbVrfd^Jl J Xl Z 0n6V"!brz6xDNʄ04nƿӾ^d|Xx՚fbPZPLB| > B&*.X11F0t/:12L/,l($ Z!   N rJh~F:`"H`x|v^ lbX2 J \V t4hZvBV `Z "  t t .&jN$ p2Tz VJ B!J# (zX:d \b"6B P   Dv @ J~2*(f42h jx ,h0d d  2*j` ~B X> $j $"(dXT  t~FhPt Z^  8pH(l6(:*(z\hRd((v0T  4 rLb^VRzܾ߶؜x |֐͐Ԙ*vצˌT8ݨєb|۸fTz$``< v0%j\*^-0V 4 6p!7T"7`"5 2-`'T8# xV.<\N~ R*dNۊtd\ ""p,Tϐ(>D2߀\@&z~6 h v X v#L'd)0N'x^#~ Z X(hDx"XV߬ݪ>n*pߚ%& '&',(0F)\2*t2$+2,3/|6/9.<,@=':"<3*r*x$! V prp( *Z:J`NFFr T 2 ! ~Br` >v*JX"DV* B  JPBZ42nRlFL|lp݀J޴@bd~ p<6B  8,.Bp dX (  8L X `b T *4R.Dhz Td.`>TT ZJ 2  R 8 |D8Bvb 4|t vھݒz>F.^ 2d f :"  r, V *V | %V% !v2@ txl p  TN ~B  pF  ^x Jdp& b\FxJ $Bδ,dȺp8fҢBبޤV6zNnZ  B, "4 '< +,+,*(.@/4/0.+(~&z%r%%^" Vb " dfBFL^۪F`^:߄ߔ@ߦ2*Rh <x d B: 2,2V FL0jL||R x 8v8p &VfJbD RL&l2nB|Nn V^ ("#%v(X+2/100V,&&d~!8~  d^~L`0֔vնFӀ~˘>bvא(fզbێ vߌFtZ jr>P6jH" #$!R#$"8&B %4# LR rh`؀؄BغԠҾіժjvT`""^t>ft.L &F   P , v J<Z Vv f> bX 4r(ٺrf4 2Hpr " "  !&X'$$P  $ pD#"" X. " l@>r H   X Hf<L p h4 2 > . DR~xt2HX0zr"2B4TtHTH`2N! &$)+).4&:-&t@,B& $$&4@XjdT4&vn|Ѭ,xJ0VX*|$jVlh$pR: 0~":` .j ^\.nj.ll8ɲӒbX r `b0آ*\vtH`t:F &X |#b >** - -B,L-pr.</ 0J20.+R'%x.%$"j @ \lt zp*$BR$zfTN ` 2 H  TJtN!V  < R nT p "j`.h (xBZ$   BL *&4~- 0x/d+d(,& 'j + "h1#5J" 51^*$ Nf>p ^L n~f*,vZt22lhX0jި.b  $DL:v h  " L  Zj  J6v>r&t b J "" |  d b $^n$ \(|42 8 "t|tHX  LT$ Z6> F  @Dl..n^0ޚL>Вfɴڌ`l8ޔ `dNh L ,6 ^!*#|%.~*1"n78#8v!5/(N#:TR Z2R 6 ߄ݎBFx*0ۚb0B^> `>x R ^@!(>&d)z *j$l*&'"'f#r%b #&###F   b*Btܒfޤh^ސBѪ ΪTնހΨ$V~4Jr(h$'@)>!\*%+)-+N0z/3"45\7H57"25-R1&f** &"jv<" $dR (ݾh(֌քמBz>Dj,~ ( 4 rb V6F%0)4N)&#`!!8!$#Z%$"$V# 6bLP & z(@ Zd.0nRt*\(R<>6^Pt!r Z:Nj 2:TFP n dJ& b "TX( *: dd J Nl& .X P `^  @""(%($,!- (!Bnh ,$" ND(<^llRުH<`zRhPD $ "4tN D f 8 (fDLdd^<6Z\&lծJJ8FRޘ6f Ʈr&lǐ`8rfHX>" b "# :,<#Rb(n,.-`)|f$z"p#~&'$Rz xb   ,<"lNv20>4$"(ZV^p$v8x\ TnRnHpJ FDv.,`0zN t | d    X .8V` T r ,\(6`@xZ|~lNv$0V n < b jVz^ ~0~ nݼڌ: Ԣ6 $z~ՠzրBz0>:J4VdN *t4vD 0 | 2N4!d(j"-,x(n8#PfJ 0~bl0HܶԴh*&ʔΎ^`*݊pV&۶ؚl">r`t^ZbD  h:X"#%($* .)L%  Zj T T PF܄f,ۘLb `N׶ҬhL6ɾl٪h&^bNp F ` !$2'r!*&-,+..01.447v8z:<:?b68>~.7^%R.$2H Z xj(d8h6BN @8h ^T 8 (Thd#'<)"* *T* )$'$&$$Rt#d!. >v(  >fp2HhB`2 x\V:tBbV<tf,>Ll"~  >&(.xP&RPf||ffL"TtvLDF^T $l(^t :f. :4| P`r v"zP^^z"JTL6b*d@NfD&@*tx$l46lX Z 2`^ 4 XxHb "|:4V^<  <D 2 X\NP  dv   ^ p<dFZ  p0H":" !F" lLVRj6 hf J h,  j xV* \ x4np*D6(B,Jx.8`p x HBl  (!r8#B$4"`' 'L$8V!z0Lj0z Rvf .b4r06  4*h|pv~z $   0  V$D,d|znTVlj|X fZ<^"0,r^x 4d X20 2 Z 6z 4(  H L BHd" . ۞@&"D@|N rD^t`2Fl x#8&$#!P "L'-d10+H%T  n  2` &~VJP,׆nnF̐jhfr`40@D H $6&"V&t\^BzLJT(v2~6`ߤ2|.ހ߲hPd 4n(*>pB0<0p`~$"nz<4b6(8ff&jbT8~ND L` V`p 2prfx>B`8~Z|<(: B6V@$|(D84BDf \jXHdn bL,6llz||ڜ d|h`,,08~z "pZ , z T \ TDV, * !6$p&'n'&F&,$F!~~ <: `,vvLx\(RB,&,lp^h("R4 ^ * 64J|,X$|zTD6 d  DzJ^T>#'8(&X#\r$  ^ ,|Z\ db؀BJ<պ׊F, pR Z D t"H$ v &v N  ^0  b R t < |D8 n04 T` 4fr$^ T,~V06TxhNJ F "  J&xF &F 64 j   ,(*Zb\ d NBT42 ~n&B dztB2llh  T6V(0d(טdӐ& dR~^Ft8V2JL& ` |"hBz \tb  T *~ۨt T֢֖,٨lN߂`B:NxZr|d  #&>X)P+!,%*t&'"$|~L J 4"*8R* NۂF<p (N"V^t !$($++-V1~-(4+4Z)3v'2<'2*(3H(2V&/#-$)X$l"DZR`JD z( dz*d(Lbb d,2 | x 4ZnR\(lp PT z v| b\Xt~:B`P6( f|TH0PLL|j~JF"fxt|:P6j$*l$X84d:Z0,L npzX|`VFn  J.xfLRF68Lv$$4VJ6d:tppbb  @ ^< Hd|ۮז׈lހB@p:((,$6x d"(@TNt pb "zlP$  bRND| @ vnr T0(Z v8 t :"N!Fp.^b&: N6 n|(  PXf < \Pz\T^VrPv(.>Z.^ DF 6.B>^ db,F"B& 4J x 4 b H D TrDX*2R*Bzr>nnH2*p(lD:xLFt$&(>,b$v`>ל.Z|`Z|>zf . Hjl vLHrt XP ` ND n 0. NP  ZR  0B@ @B*l::N,>܈ &v 0h, r!:0l($Z ^z:XR  n &j$Z LX l*p &T. Jh*L4   FJ P & (bl<~ZR(ݮB02 8 *  Nh: nt  \48  n h  P:d   ` J~f~HV6|tjZ   Nv<TJ| b t , b `&f0T F88 tp :`0n2pN.&TVRT X^"6^ vJX :z!%&$8T!V " V~h V FfLl`$d&P"jf4Lpjn`**~&v&0d 2 *  Tp*Z*|dR t2P *:݊j`2(~~B4 8 0HLx  \R $t(*|*")'&#F 4hTJ  v4pDtd@F`06  xV h|Br,|^Xvpnjt FJ D ( vfb(Lt"fd"0JFBr:"x `XJL Zr0 "&dNBB  &t x ` `^  F|j \ Z8lRF $ ""6rvJfL6$>P: ^" fd  D tF0<2.D ތR.l*`p2lpnxpBF"B^jj |fx: ,pN<~ ( F4 vp 0 6 N Vt`8 R 6d|hxh&".:DbX\\j  *Jvr\ JJT"!0 p(:8H*4@:, R>  T Z v t |TZ0p $.x$P LZ&J    X r @| :rTF\v: X b2 0l|&8drVF&4z0~4B^zn |\(zTJNr&P."XLvp.<0  22 n <"< t>t.*x D,!R'Bn)~(4>%l ! T<66:j< <:F:tV^t <&dh6dd4V 22۶p$H . DlXf  . rd t  $h\ D, T  ,r ^z:^r$XxJDlB<X  XNT&dPv:d~ j  `0jNXZnv>Z r l~$bNrl xT N Z` vTX4t Lb  * H6 *`, Z "j & 4 b&8xrjB4*F:&Rr B "F"ln h d  pn F@p~JxV. 2n  .VttJN`XJxT"&6jRVnj N&2<Zh d  `L` dR X(jZ& P`4@ 6$:V"2Rn֘ߞ"@ ߸X>HDT,r,Fd r f v"0z<~n@|ߖٔn֚.zݾ݀n*6$RpvN"  f 4 &$X)"-%/,(b0(.4'+&#)~'T#xBLL<( ^ H,b.rZ8 n`J, v*p& D H@(BT0(5 36h9b3:-,7)@2Z)B/,,`/h/1.3\)3!.'(b D^j$l dZ8X&(L < n 8v~Z^6  f >`FrV4v@Jh`(nP0&:6> L` fx&~JLlv8"P >.*HVl>*|\6Dp & p*8P`R.0L2R`p<>| D 6 x&tHHr*ZL,Df8|~ R    2  : B! : 0"`\ T  brH0 LJ~V0 TH" >&2Z 6 v ~J!"^ T p6zPzThb&J B>h ` l.t& \ j 84R <T  f4bp0. b.Zz(`Dlt*0X N&P`\Ptd 8D`pl*.RvdH2R^f:>v:ZJNz"DlHDh  . zb  X ZxJ8 " @:4FLLJ\`Rv~(X@V|n8  & . T x \&Z  r p`D~Db n L : b  > t FNR\2rl|hZ,fl:f0 ,N(hp V d , .8~ `Xb4DlTtHxP\|jT$<   (hb*Dd..n2  d`:(,64>N8ծ"Ҙ ڞ XL|$nB8fFH  &0v,d:Tv(@P܎8޾$8@ٔ:nZD;H>tB:;D8hA6=6;796292\8-5)1x%>-!'!Z V@ ~Z8X JX4(  0\@ ^x4(j۬لNܾNFߪފD~b0ܰ(.J(Tۜܖ"*4\< Ltv JR @n*&^82t*D>`lZxv.4 ::$ >2dTHTrB>XlPf<nf.ۆ`ߐ2.H 6X~:4.DpHX \f j 0NfB` p 8   d @x 8\B>H<hZ N~T XB ( ( f Xj8" . J<d 0fZHtllv &:2 j  d   $`L, | Z J  T dpvfv|LLt v@ Pl$8 b   V b $ v  P  LXh rL   b6  8` ` X f~v^T@llDl8( BPN8nߘt߸v`Nzt^4 . z@r $ p0"p"P2 R"L.> D j B\ |^tJ ` xf4&  "P:hHp>.|(*|f\"x~\&Xߌrnެ|zXPp <^l  >: <t` X,`$ " \   8 ~ zj~VdJRXZzv   6|N|.bH4D & bN .  8@DPh\~ 2Zf&@l$0rZ~ X n   <z.nJ "lN.ڶ޼v`pن:RVf L:*@bf2PfJp~ *8 vHlhTTrFHِvlנTz 2~T" 44t|L\:  .lp"%46&H% # N"""!4   82` (* * pX~*t^HJ<6~Nt ^ "  | t&h. d2V+12|.4*2(.)+(+f*r*)'r)$`(j ,& "6|x(B& .j|drdD <z4 DX< t   6 . V NDJ Z zX@zf2X.60|~("2b nB4|rj 6n>| n z B r 0NzFj,Lx|BL &4nh<TX z0b"xpPrj@$462 Fv:^ ~F :ffB<$ ۢ<2vPr~N$Zt&((  P\8P(8x" 6   ^ t|r Hp&Hx (   H * F ~  dxN> b `<v `R $|PH2j.L&xn8 thp48RRVpx $0~\Pt <,LZ(,Vb jbT$z v fL\j8  L l.:$"@H\Ftf*8V r>ߔ.n`",N*2d6&@ 8 $ <h( 8 t X" d 88vttT f   \hJ`vLd"vv,F,j6 :lxr  fX\*h 8j lB . \$V *vߚ<" bl Xh tF , $*x)(.h#-f(bH"H2 ""'!`+j*Z&b 2h~b 24 NlP (< \     T  <l.:nB@2   nV,\Dx2`4Lt*:zJ&,. 2,  @ l JLHZbpx R L&zt H nFLj6 t  jP *  t : v ~ `hfrd@v$F$v&$8x0܎X$&ގ `lt.HXhz jl$nlh^B "FJLDP<*T* NBH: <4Z!!^"!! f!4! "d %N!2&"N%$"N%0$ !4,BDF " ^, ^VTp<>LL,< 6 h @  @< ^r@0 R  T&pJp  V:H8. ( PtBf"8n*rh v:v>p^8PPR:2\N vVX> H0Z*X ~" # !\j>d ^$ ߂ߐd@ >:<&,Hhd,< j  >t(z\*+6+( L".Bz L^2\BH\\llr H ,ZB X288 !"b \ > 6 $F.V>~n$N$~,Z8,rDR 0 :n~\0 (#<&#^ \ V6  @Vv "B ("DL& z R^ 8HnL8 ~@ BrB۔fDhҬF~:ݾϢDn, ނ߲-&&p"H  NP!R!! x! * f x  h r d v  ( tXz~fdzXJ b$  dH  "^ @ pD L  n  < ,\ &h D,&:zT"XNr@Nt݌Lݤt0>T^4p t V~j&tn < xfRV^\xPzf *&8&`*8 4&>.xzLljL^:zXFBTpHFv2<*|nD&Frp vVR.,6 ,B Zl8 vRx\ @ : BV,, * >Xj x  \V""LH dT\d J   t ~p >j fz.(dDxP f~ ~ % J*"L,T#.+"' ! rVP6BJj~ ,~R|j^r8z&, h2hp( dF  fjX!F"%$x'6#$V*HDf,!x!b ^  Hv J 64   6(4L>&$~ ۬tlb ج^:ޠ>t6^v>^Hd4Nd>& 2>^f XX  j4n 2  d *X<pV\* $ d " Tj v8   J"^x*2BD4@&b06\@zFtZ&6 ~`  h  J 8(   D |`  *XjDxz\ $  r P x@T(^bT  >< b\: P6.t  nT nTb" $ ^ | <.F fjNJ*2V |D4FP8"$ZJ N&" lh #&(+#,**-%N/ /...0*1>.d( Xz ~JRN<0ZzXnZ(4\ LP J4X&>~:$z'&4# hBD& $r$,B dFbn r*`zT>jr&nld:z4HzXv`ߢvj:݊ߞF&6^JZ t R ^,    \F6V: , PN 4N :4Hf"| BT0ֆ^x|$R 0rX2b!).$D0"*-)L*z$&((+b/#0j)-+<'(h "0p<nflB Fnd lvT l` n      p @L &v > 6 jH @L" 8Nf$ B *lL(p$6`$>2z<``0p4DPPܾPvlߘ,(n4Fnh0fX Z fxtx62 XJZ*|TPNX fph"Th(lx0J:@ZFNH&,dJ2:fb:r"xLpptf`Z*DxR:P"fDTl` 2 H,NHf:8Tۼ@V܈H,&6"&n|b&D|f:  F   8"R`  r *H 0f Z4$ HnT@~@" Tbx Td^t !Dd!f lZDBv,>  N r  N L  |Dr8 , dB `PL!# F4|8: "d vn L^Lf  6 R>@ LTH>ZBzr`6FZppJR$"R DF>xhxnzr,\|vz&X*F^, h @&jxv` Z | Xr "pbXBJ n~j^jf!"v" fzpFHv"z*2fތp0dDضb,N.P >V˲h܎BH0PDFr " @bHjB\f:(:6N `(Dvz FB 0~,f|DN4Z  hVB,|B l!F~#<$# X $~ > "vB2tNߪ`~ۀ4լ"V"H<~& . D j $rT  p!>&)*)t("F'~b& T%J#X#2&T ( (( 'F# @, H>&>&Nn`~^  @F$dz 2 b `r 8 D pd\JF^NF8R " * #%H&`%Tr%*%v$|#4H" 0 <R2( 8N @ ,.Z8$ 0 ,J ,Txpp N(tl&z "0zZJ@`$pzD\X|h b~ߺBl:Tn@XzJ4r fx,zJ  t$%*$ d@^LL D~N88j8P: 0DPZ*&pT~@^pN` >dj> lD R#`%4& (")$)(%( $p%d!",&^&(^(  ~  *  &x~`  88b 0 x* R ^ \@^ Zb | t* v @~ r26lRZD\ (bb 0TR|PT"tDh&ܒFdܢێߨ8.ZFP<0 .N "F6r  " j% %V$" ."h"$$%%b<#tl`.\*^`Pd""l>Tf^TZP8xr:2  B:fLR"`N0 Z Ztx`zN hH>Bz.2|> L >JP4H|BnxD 8 V d. bb dZ$ N&n b h 82  *0ZTB|"n%*!p%|#4%%B'(+x*0f+\4+6*6&T1 ' #&b&!l RP  6v rZ d  Z6>,N66 n4 R4VF\PXv.`JJ`zjR&t\T<ۼP"NZ lR %)-F / 2 4 7v":9^ *6~,/d:%rjF6v N|nՌ Zxp :fʖ rȲ^Ъ"*tdLՆˆ*0ؐ>^\0 &"'$V*pB+*)F('!&$$$ P" B0 VL V2LfN&(LV>*R >bDzJD t l& H").&<-((+z'|'$*#! Z.!#t!<'"f)"(# b:^\v` htVܚ>8PDьf8J|b\"BB>":tlx^B( HV&*+"*n&# !$#J&Vv'V$%zR~   b,zf: *.6:^(X 4 t :>  dXh2N $0 6v 0.t&dtzܚ LV >jR#&Z4(v*L-/|^0/,.*,h% R .T Vd"~"XBnf@,0X(: Z  N d:0*FplL@@$.2JT<\$2"d\L޴H ~^>:l޸4BBP 4p"& LD|@Z#h`( *2*jR*0+b,-f"->l)r (# J *l|F^b8.njƬƺǎȬb΂ݖ &jd 6  !$)P .(J2-311h1X/:/.,.<).&*-V$*!$'#zDL  V t* ,XNV4T < & bJ Z0 . h Z  ,6LbP6L JRv  B " R P  X60N8z> Dbb>l.\nۀ<׸~ڐZ٨<׼Ԯj*Դ V' ' '$" ff Xl< H 24@.h~ 0TjV0N ZR2`^,p`x:  hJfNDnr PDvlvH&. |H&^>fH60h@բۮ Nh| z V#z!(!'^ P#!6!N&(,:32=6EP6H1LDV+R:%0$b,$*.&Z2T&6$9V8x/ !@| l \ZX RHlLTL`X$6 V*n  "X (j~LZJ x|\djvDz$ ,Rj$<4PPT:z> ~tRnN &~,,|1<579;=.@A"AP >=<6T@/h' LL< ,Hd*4. 4<:r̺XBz~"R4N֌T.Ft rl| 8d N l$F+,/!L0 $x.#|+"x(!& !*% "XJ~H$ VNX4802<\^LZpPH@<6 h V *f~!!6%&&(N&&%!#h (N~bN 8$ 0x >t.نZԾb,*DȎĮPh&*VՖd$`H "@<h * p"2$n$$8&F,*&.120.<*b&@"L` T&bZ F0h ~r:tJDP2RT.*>`n >  "0!@T d Z ( 6   vX6,pH>߬0ߐd8rHt6&Z b  "*1n5P.64"12."* ' (& $ !&0 *RV2*tx6T* r~ r>N~ "*zh 2>Vrf4|zV&tjH8 p@FHT@pN6Xfd0x82h@ *2Zh z'2.3 42V/ ,hJ*).z*n*( NVjLX8ަ & xĸ°2l( D, #(,!X.&/Z*L/H,/8-L1.3.264/$7.D6,~3>*,/&*"&@$"N$! BH N BTPVfV8J l~ j> t  .  Z *ZP t 2V^ RZ  B^  lbxt:r(bxf<|F&ntH&ِزBzdڞ>њۊnۮ(lj>(N" Tpd`8NTj $*.hP/|F- )# DNhX :V"v*6.zXz0t6j: $ Pb|@FN>|r@ \ H&~L)&L#$b!)$1")8:X-@L/C-V@(7#.|!*!D+ L.t 1r20)pzt FD Z^RRv@@fF*p"" h@D,JFj lRX 4 BPzVFv~0JjVb>p&rr`(Vn4!v '( /D6<@PBBBD^FHL<|f ',- 6+n'$"vP!j rv2T vNz`pf2v0z\lݞ4p|:t8`  ` v"$\"<B >,t!R\l  zp6.@" Hrb @NҀl\|F4"n F&Tnx l D,&fL*++*PZ*+ /"4%`7'T5( /%l'H!T!N!$!4%$X X%x"H l|TZ.pDp\ <4$<(Bx v N < ~\6xRr @t(@l8z0b@ܾxD60t8@: 8  ( '.d5< 87 $3-j ($V tf dB n:* Ppn*Jڰ>0n66<X" T |Pj$V0:<0  Z0N6LfPx*;#;Hz3\) <"""j'>,6.-X( xD<4*xthRd2 TȂ2ƠϠtDN"Z`R<@"` *0!2X'0',$D*!(+P"/&t4-B6@231B-+%\"h F P0htL<2"D NbZPr~4(v~zLV6&`P:<D nd >N*>tlh b  . |f JBFF8h:N&@@Dn :&.zNN BN Pb > " vT0TDz  t @h>* 2p8Xp"f`B"rt@nNV|~8^ \ 86T 0R02 !0(\+N.250T:Z09-Z54*./&(d#!z#< :%#(%h(V!(^#&Xp bH(X>zt8@Vf$l@~& DR Dhr2\B4z& xt (bF <. D zTF x4^r nrފLNPb ~ &V ,B13xr5B7H<$CJP fONGb< /& ($dFL 2րϖހxtjΨ@Į6@Ƚlʼ:4bhӄƲNώԤr8,n r8 !L '*>,-.:!0%03)3H+0b+)F'\N   , \<~߼ Z޸ݾ6ߢJT~*<:d tF T xHN  X #.F Rj^D.$6Df Z 2$˦ ~8Іp^,Ζ@djvV~ j:  N2(D xD vJR0\!&4,/Rf-R%x  T.H$l` :$ >.r Nb n jlJ` 4x   h.HP"n nJ D<VJ VNTDl\pںdXP.|$" ~$` l$+"R3(;, F :  tF!"@"t''f$t  2B!&v&.!6~PR\nD<߂D4ݞ؈ќXJ.lbZZ~* >X R(-`2"N5J&6&80(:4,<"2<79 83V4P.,*|$(r&#":pn b ~, H@6`F| $ ^ Lj  *ff.,f   & j \   8BzRl@xn`0V0tb V P  T > 2Z LLH4^Z(Z&`   n$ rlX   @RF$jn j&X lb l  f *XBL4 ~L8H J FD|ڐx LR P*" Hh6V6tj>>l*!#*X*"6|.*>r.p?+;(R6%n0#*#(%*6&^0z#30(fZ  2fB^btJ"lRj @,@>  ,  : TZnT j*4R^6rrd4b(RfTR,>2bڪxvܺp.^lZ> ` . 2'<,J.^/ 27@2!KL#Q &QI0? f4t-)'d%@!x NH: pprH̨PNN˞ZZĒfB*ոȖ4`. VۊxV l`d \^$((+ -/d$|1*3d/3z1..%~'BT88 J Z2 ^ VDlx*r\d(BD&\r~4r Xzf "XXfdr & $  T  |FX tܴDІ jlrFTnF׀ (Rb^fDX@X~ H>rNH\ r .R"&PB(:&Hz!.v !! BN (  h zp` JTj.tHhz 2| x  H  Zhtp$FTVZ>\ h DH*0.ݸRbR&"6v,b *& |b'f$/'7~'<$R>X p<85>.4J3x32-B %t620Hxx82܈t84>dht *p "(8|`P4"V (\zT<< ߠtLܶڨ4 ۴ӮڐԮڸJ݂ۤb*j 6.x2R ( D,\#Bp&%L"$n$!p+#F0!/) Bn6|~d6:߸dݾ؆ ,T|î$j Jb.nJ 4$P<)p/ 5& 9-D;`4:86\926F/x2-.,Z*+&^(P##xR8Z: j hTp04 Z`4tJ" |  n.xb  R&L&  6 d:&>*~ 8 j  (LFvN&x,l@6J p . V z 6| &F > >   T \ H ^jPj4&Fߔ lxN$lD *H l "4 ^4 64nJ ||~"<  6Dr\P B f p . ,ZL:& +,)0 $Z#&h"|('b(D+$+$, @ * *$ vBJ&v"`$XPt| TnZ 4D $ v xV , 0 x H^^n\xf Ht$Z*V >ܐٖx<d8' -r162J33 6f2= F Md O"KbzC :\2 z-$)6<& P \44͂nTZښƜĢȾ4`JJ֜˰x\DJD&HdP !b(.R3j 5%26*6.>6(151L3 0.+&%f !Np BR.\:RVjd~`޸@0dHl P XT0(. \@lpZ ~Z tJ 64 bp4˦Hjrǜb LӲڪ 0Nj@ vN zzbr! r" d bb `nDl ^26 .f  (N@ &B F D * >b,""^%V!%F!L 0bVFz ".*~zF4:RP jZ6btR* J  z J~&h!P":*(2~*:)A&D#EF!vB?v=4;96:2 *N!H 0"n dL (ټL׊ \Zt H |vNJ *L0@r 0*8DzZbNV.Jd 4FXZ"8Rpޤ^V"~2:Z,8(0(nL޼Xz ($$L"%0%.!2&0JF*#   |J% +f 14F|/\$T>> T@"xِߐZlZx4`lhxnZ!~'N ,.... /$!0#T0x%,%'x!j"FRhV r  x~ tJt0FX~F0b2,V ^.,"<^<^^x x \~lB 2pZvXdt^Dx,($ V|J2ZpRF "H &( f+ \/ h2T5:@*=: 4j+N"n\Ph4bb |NnzBd6`Xhh*d0n$hx ("HxJ`^D<0P84>`ڠޤ&׼.0b\b.  F2l(H f.DLRP22xd \h N4\  R( r : Xf fpHx 4,T^ " 4XߔPt,X& <&0pѮԼ X jdnVVJXtҊn2 z. $^P8B pv@T%!0$5$3@#-$!J(P#!P "&#((#, h, &` X^ @ ~\`b"@ xLDXT4jzXVN8J b & l,x P0L,& XVB.( jN l\p`6Zܮ,>ݴ~ln%( L* F,d b.Hn2:N:D6"zM6!P>KA@ d7J/t,p,0,$B)d J 48L,ðH|˶΄8.آ.Hܨʂzd޴t@V v \" f$x'$+:$/()t26+1f),##N   0 L pNTBD>6bt\8nVL jf  L~p 0` 2b:F N  R   x<NԀnΨX r 2Bބ ,HRb. Rph,  `@ <6( `n $.0$ zT : n Pp x `l  ,$L |z 0l"0#$%!$  LR  >6*zxVް^ۈjLprlX:|  tv :%!r,%84);)&@&FA#@ <T83.16r0.~ )> 2* xNߚܖ0ڞFPԚlՐ.l8tH \:N 6$4Lz~zXVj  $4 (xR,n<&v`B ,Vעnӎr66>֤ՊHנؤ$h߂ي@* Rf@l: n0F '`"-,0f/v|-0+H+x+->.0d1Lv/)t |.X:lL8$Z~8DͶ"ʨ^ |82&t, @n&# &J)*+r,R/$(3+52466/Z3D(X+n#!.!p  \N | \pz"bjH"(phr*fvp8bV >"VN^   Z v 0f,XNL>,.^"nRb"p4j t~<6tx<$ ph"@HFZ*| $ >+ 1 J2.Z(0l @z^r 4t2&ZR Bz, ,&^j:04D^R p2H8@L bPT( , .^^ 2r * J$\2Zt\& 8 X X N  jJT > N ^l  ,X(` ( $|Pܾ ZZ 2~J lИ"X N(F*44 Pnb 6 8 > (\|z.$+p,\'&fh FVff^F::."dB:.2.ZN @J\l6,0V2|4(fZdz  XFzld8zT  NTvLdP4Lz,Nddb>`BvD !F + b1, L2v /,T, 1~<8FKIB8x/T*(z&Z#^P l&@v h>NVdzzDf.Ȳθ>͘PξϬІ ւNr  `T "B!6n  # $):-1|56x9T67/1,%(,r, <L~b&*X< zB.d*J@r Dx<~`l` (x x^, 4 ɤFb`nԪ߄pbdj,@Tr `f^\^n  >  @  dJZ#!8 88 l 4Nh8 2 fxZ4 T  rL X\ DHb"~ $ "d :Z\ <  d<"t .HFJV&^6vB<67 .`#VZ ~ ߴrFdآh`8 &(PJf rl r>F VXvLv"hnl\RXn"h վ4BB8ԀRԴf.bǴnɾH6ՂגH2j4,2X $ ~  z$r 8@>0X\v#&b). * \+!j+,#,8#-v &-*j2%r Pj`FB(܊6VN&̎.&0zɐ2(jZ~fn4%*@@.T/bL.!,R'-D+.`.000Z//++%',#&T  B>r2Fj~VLlfJ:D& *,  X H zj!` V < b j2DX d*\ 0( <" %.Z'x(PT+,0$7B:$9 4\ ,#Rb`B TP4nf@Vvpvr`,*F*f$6 `z "0pll"XDn`>@n < |$ R0Z0|^D  ^6   2 P DN:&   "4(bTNބ>(Hn R jԲ"r>*Xڐؾ܈ nVF ljH . t : z $t(L&f P<&#z$, 0 & Tn p D  H~2 *DFJ@$.x* | L h pH d X6*@h  <2~|F j,8NNX|bxٔB<߬nj:| bz\ "r #! !z*D&6!:B&'HJ*'zKH!:F6=65XZ0*.J. `.|+#~Zz Lpr֒hjVV26ٔL ˺vԘ8א\\N.fz^ؘ0X6 $ Z B NL " !v'X!.-V374;06h(,- f|J6 tlFb<h4f "&jx>  Zz 8PpR"x  & .8"Z<ּӄ^0Ժ: :*>"F:pX>(h ~2  H p  2\$ $ z Vb 2T`~J8 Bvp*212<62/T4p(,f!^#X0 xnh: l<dh@DbXn6B0>^X x **LLVR F F   h jR2j\Ptbn2|Z>߄06ڶHF`"H,&* rX2Hlp! f&v*n ,j* %`.N ,F>|dpn..2,x &$V| dJ& l trbX\zTX bF6fZpz\Zj0 .BHn|fF\ >84.&D8\D*vP(l  * B8J" ~ 4HLd rt6Ԋ 6J"z؀v 2H:ɼ(t&tݠJz.L v $*tx |2. 048" "f|j$L.*->,L%:z~z|vDj, l|X0VnD,2Fj6~rxN2j*$0t 8j|  Zh^.  < ZvJb  vh<@n<22ڼR(|ߞt(86j8&BB >%: ) * <(>(>.8!Bx#VHl GAZ8. )d(*j*f(p|!D6 L8`DdV*Z Β<Ζlٺ&J&&6n :FTݐ f   ,2 F2  ~#j*+04d3b8085(d," p&Lb.pf! L"^>Bx^\4RL|  *z@T 6z8` ^ p Z 8 Z6l ш.ֶZ8B@٢ Z$n8|r hRR  R < B 0^d  r^x f(X b@x,D pD&VV*"Tr(, tH8\62" `#Z"" : xR DfrZHjF"*ܞؐ* "~Z88X.DX V$"-F)26,<,@l*A(A' C2(El)F*H0+I'LHvAL6 <+J"T.^  ^TH$bbNP64 :F:(^<vBV :\  J RX 0<:bZdvܸֈԒvd&l ^v@ffrޚ޺xNhުD 6 4t 0H!''0p*6*8).7r)4)2l)T2Z(3%42 +< bLR42LDݠV$ӤBtpb*VԈ@40( ht& &)n(,&T$X$Z&B(^)~!(@"X'!r$ Bxl B2t@~|Ntbdh,z0tl6 X| Z Z6tl@: l \^: $R< j:\d(4*F*PXfxFv&HL$*4 BF ` < " X"( " 6$x(t07F: B6-#F\Lp jl<D0BRVVJ4t0F@zBv6"T|FpLTnLHVZ*x(۾v~F`bzp40 V 8v Z  ""~j*~R2 *  $b8* P ( vpzD  4 J T0b rP>b R< .RNݞ ,2 ~>vLV~z0&܌ ~ xXޮݐN  h j4&02< H .F nl $)p)&!^  xh z$ ^x8N"v.h 8Z2l.4< \*`*2vh " v f> x *F p4 d x \ 0Xv tJ b NR6^Hzr$x<|"D * X`  ~>(|07;;83 .*((($8  \6vPD&&~zЮ$Ҥ(Ը|dۆRB| 4Z^Hj68b2F  "!z*H!j2+7`4h7714 (*r>! ^ #"P :z zXlBfb($z "b  VZVjH 8" j T TRr. N d4 ,h TZ:L0PP؀Vx8|2L :N^jR:h > 4D N`<p VRd ldbX&8 &DVBt 4*h0 ( `T"\   R B. * R0z V,,RBv t~j*X8p8L޾ :~nPPtHj4 T:r^%Z'.,^6,":8(V:"98"F:.(~=.B:3Gj2I*+E(<1'F $J ,rHׄ0ִ<hrDְ@BL|ה2D 6"|&~z( x& ^<\ ,P $2 &tv Hnt^rl028͔Ȯ2jӚj΂P2<4ZT! F.`TH$, 2,!R4&!>2b!.d!*!d("&)#j,#/8"0N.&$ f&pJx`|JzpX|Ύ˖f<Ўب &|#8& '&($)$P+r-L1j"4'4*2 ).#( d#p"(`T ":$> pn<8,P"& VB,l\x $z 4 `TR tlJdnDJذT^ ׂ6(Nf&ڂ2۔.NBFt B$ "<  B b$hd-$4H3f,H#.&D$2 B^jr 0>BdD jp^&BRDv2 xlP^fV^4Ppv<ܶZ tPJ\zl0    T V j| D BTHj\6T>,L  d:  f`|t x R   @x XT dLV|F  ^ `\L * XR|l>tTZPXZݼޠ(f l b&hXH R  $  )*&L"> F$T*<.B.F% . T&\j( ^ v D ||\\$$lj ,zHzd@ z t&jD ~ R  TN ^h  Ppx46 X(HT>٬dߞ&dPf*P N@!,&H +034n^3^0 P- 0*'&&$F!hp"JFjz(`ǚǒ*\ т۾ӄrڂ2HJJ~> <T$L(:!+n'D)j(#(#rj~|!"Bp"  ( "t( R">z (8 H >T Xr2T 0 X:V^r 00 0RD4B2Z( x6. 4 ~ RD.z  B0~Lf()" l"  R` ~ vHP8^*`  n6d6> H r ,"0~|J r F\b(B Z2^n݊Bz^&hrBT0Ljbr^t:l t`""*4%0#1B/6.-Z.| 1h%7'=$%=F6+ tF| Z &vJޢڪt2r\DH߰B24|FTz( | v N n v6XNb ,:t (ZhDPfF߬ސD̤RʈLŰt\.T4$8H:B.& v" %' '&z#"$N)x40&7+>,-Ah.D. Dx.A,>n&:(|4-D&z JvLR( l8lnXpЎ ,P2& T ~!tH%f(P (f" %#h"@!!" "6#\#P"T~F. FP 8 db20Nzb`H2 VV \d dx 2N t  VX 0 L.D8NFD."@&p"HjhHTh&Ԝ`֤Fd00H:XT.L  b  v" &,D/ -)&#~z `~4 2^nLR4"b~0(,x\vJ2H:zvp^2FFJf܊4.tXVhr~^  4 B:B8dJz^ئ~fV> zɞ˜Ӱnx,bfBѨB|>* J rzJ8 ,! n(R +*% X6"hr*@:06/'\:B JB . > ( 86`nX`B.\P pRڪ z^zv `^fZXx"bB  `N & ft L | Px XL N042 r &j0ߢfؠێr<ߚjX f PFv" )l/&21 -8($zJ#n%(h*f'!H" Jd2N bJ̘d\PςRV(ۮXL~,p`04 Rh Br \!&"Z*p&*&'%.#VN!Dr"b4 d  2\^P6 ^ P@Vf PJP ,&|> t$r r~~:X xDL f F P  ۀ|٤B8LhXd|^jpRnHD>tFP h `h jBzJf  D^xZ Z(v\B6>H (|,r~ &  F  ` h" f dv#:'r)'"h ` 4 d  z N d4Pp,@8X\BVdZ"2 >H p 8$$0x+9+*=';!8423&*9-BA/E+A!7) :0z <V&ll\(DX4X2 ی&hrjX$.(>d-:*05%/(*X&<T! 0$L J0 TLn֜ժ,x( 6 j >" v& `* Jz 0 d :RJ.TndlՀ *\pNLtX.vL&2hd bd ZXT H `X % (6%z" N h^h ^ >FtZ2Ld`|Z2^8p`Dd 88@*,vJvHVnB  b^P*  8<px b  * T    jHjH6  ޺njN d&Hfpzx@\BBd:NՀ $ pXp.X LT %L *v*& | 4`#^,/b*x! |n PL0   flzRnZP^B~ll@&z0p"V^8V^ *2 | >T Tr |: z  >h\D B(  R ` r P0 (0 dP\~L `<dV L N$,12&0LP- D)t$&f$r4$d"%l*&V\%! 2B2f4>vԄ̼ ̆ێfxݴj. , (f0. ~ Z t.B P  vhHf VT~< vV"<p  @   8 L2z0$ H b,p tj*^ݬ>fj6jb߲,.HNJ Z^ D&F/#6&%;&";8,4.1bN4D$F9(=v'=!^:@2 (bN |XT d2, ԀӢ:Ԭ׈P,Lٰjޖ^`j& R jv>Zl  " l   z *t0vB&(>ڶ*T<XŞƠPи^ߺ$@D:tۊrN:b!6'n+Rt--,Nl*,'0&N(.4&F6*<@lT*JXP$> V >  xtl  D<( 8v  46R*| .J24D .|8*&6.4/.X2-J * '#!8$T | 4 D :ߨp6tߐ`^ޠvҰDT$xR.BRVv v" !Xf#P!2 F b :"$$p$R!zh J\     .$j4>B z4Ht|V\l$ *^2 $   8 LzD:b  & tlBp D v~>l8d D D`nZ < x 0t 4 r> `"4L( fH 4Rp$Rzr^. j6tFz \ z '6"J)6%l$`b^ TVۺPf"XHߞ ^FN`Rn&6 hV<~>d "*z3 ;$B$D "CN z@ `>#j?r%B&CN&LC#? 90 &l :tBNr vߦ<6J^߈`T|. v" | 2.< d T X~ "$ .r.V\`ٖѬL*@Ě.8&`ܒւ6\јj"لVlJnt dB Rd l "$, 4+#2&78'8X(J72)3l(.d%x*!(~(h&~.  Bzx @\ݔh^^*z    B b* *b  vtl|dJdP^ j^`B*ݒ&BnJ(@6J. 66(z`znZ @ nB (  X^F H#4%$z rf pL  l 0*Db^*dB2&L`zH(|0,$\>vT>D8َ2P*$ .<xB T D.$\&(h& ZHhXh 4<pvt6r@~H@^~F"& 8 ^P&J~v  vVdHt@  V :H xJR>ZJ.0dް:60x02pJ fؚ P"2ZV"v %&B('*1)L6'5%B0")#!d%P- 2p0.) < j$ xz4 Xh.zl2lf^j0HL& z tbf <24vN   td"d&bl~JH D 2bzZl"0pP  T(2  `*T&" d$< >$ p# (#h" bbTJNp4\0<\ZpVzJr(ݎ$j`jfJTzp(V^~ t l! pzRz P\!4"n" P^<    8  n&".(`6  Vf2 Z zxt$B ~ 28BJ R ( " lx4`Pp D $r>tr@ J NX H"Bp(t"ndj jbPBZt r~4hh\V0b8 D <`t@6  :*(h8 p$ (Z j2ntؔ܀ؠTRtNF.>Xd\< $  8@ 0#j*4B#:!=rp=T:6v46"X<$@"?8/ %,8Vz ,`d&L4vbjvp f.ނjL*  2 >pd\4z*zv \ ld F B4F `B r 0rߊL׌Ԇ͈^ЀɾnT 8fzh >xj " llv%.83^"4$h3&/'b,Z' +r%~,"..f*! r: TvTt"ZBdTJ4H϶^lJ $ۺ,8:Db`(B&Pdl>& N\ &R 0$<bb$,HN0.L&XZ^ f (`lxF z ,dt0t | nv@$  T  Rlz,bRHJPr~ $4Tp`@:0^Z(D|8v b pV~.|Pz,&( P&6 . /p*,\%6l d hblx"~Z|@>:Bddzb4 6 L6$:~pPRrX  v @>z<r f! \j~ ,&vX ><(z,$J*B n( ln(  8 Pl . ~ Fr ..|\@l llb4`|Pd$$j6Z\~2>$VX͎,ڒ~ ҶИլތ 6^,0@\!R$'&/%2 -!  TR !* /Pb*  LPPt  * ~XJrN((6f drr2x^ |v  8 Fz X4l4bX ~ D \TB>Zh J zH  B. :  |*z8,: f LRVJFVz!n Z r$|((^$,dvD"XZd F ~< H(*N^80߄nלF:P~ߌRN"8TTBFXl b: `z jbt#'$'`(n!%t &p  $ Zvl@$R2Jdd|,dPDp: $ xX@ l20|j,N@@ nfl", 2 , Zh^hfF @xVvP!p 2@ pp$ 0x8 @*:fZ N Rrt& 4 T8Z\0>` . ^  z|  d b~:نdDTJB<((>JXdrdL&Z"2$.!7:#=f> d;`6NN282Vb6#l;$$=9 36*V 6!$t | ߔ>Rߌ ~ :R: ߨ^.(:.zT>r6lb~j x R,P"pj tۆڈ8؆dbؔ<(n2 & 0L  " N.j \$+ 0R"3!54!6#d7)9/;1; 0^9)5^0L(T @ (P$2,zِԆ8FՔ.p    , \ |!8$V&N#@\<TJ h* 0\"" f N :ܦ٦ :8 ݪh,`FPLf ^  dZP<F"&l$pF  0\%d(>%z zx6>L2Z$ r & >06b.n~6>z~*&r2~&$R\8 tt*bh r X@<(8 n R zHj  ~   Z H VD rFB`v:tbZvJ( z|"L!xf>"X !.!.n , pD 0D t0ppfFܠ"bb܂8`0P"80bHl>^ bb2%4"+'+')$&2!#Ld! Z!:#.~$%L(+",*(&#%6 "rxt  ^  Jth 6ntR6Z4z ~@: H `bn @ z &8 (@*X lt p(vdbj 2P R4v ZX ,  l(: (  H !`\t \\xnP$>:tn0  " l$&0tJ @ T h 8 @n^~2ӊ̼:6j@8F4H`,TX@:V #V+2@8:T:.7,4P"4<47T$;&=#;l3)d 8 $ 4.~&D x X fFp~$ Zl*VX :l  > 6HhVbv d4hVflݶPHL88ֈ̪2zf<֬xFLt&ӎx:|06@l  < (& -#H3$P8%:&`:L)8n**6(2%*.!+)&:!* @n`h~<"pDDnX82pҮ4v܎bp& B. | x 8!!@p|8v<8 b 0h2thF,fL \ &v  *` l*^ Tl0*,r &,p  r` D,.8, j>rh(b:Vl*bbpf&XFr\|\$|Tfp@V :xt*|Z6 R(|,x*,d V$2n<,(r~H d"jd(L`b$hBn,.B,<h$ڔ^( , J nRfJ. $PFX$n~Rz F $ L0 , 4>Vx~Z |& 8NXLb&>P*PDT >Jb Hِ: >l rxv.jX^vӢئ۠N6̠|^f L 8j0B 8!.&%(z(T&R$ $p&'*'*$!L ` V v ~l2@*Z> Ll <&,P ^ f  >> (jL,2  >* dj,8 ftF4 l6rv\f R zHL@bx zr"&&6#!H^# F&T)X+R*'d#\ ,Fv ~0 ~ P@~H^Z2*fb((~dJ4,r8 TD XTJ@ `:8,.F <|#&,j$z 2 >8 ~^42 d*$F& t n:~F<:2fj\xX\ܨ&b֨עp6و6V, 4 Lݼ r> |قR*D.H(: n2f j (<  ^FN. `zj"( ::LZ $ ~r0 ( xDNZ *rZbRft .  R$ z 2r!&%+"<-)n"rLB`  H46t l|ݾ߀Lڂ،"* Ֆ~ں6VjvbpXBb .">V \#J-7 =@? P/,#24#3#/#*F#&#x%$2(:%Z,"-*#Z *z\ vRL<<ϸ:(\f D$D6  6   xJZ$8XHj X (R.HX0tP | BJ $ D.X. PL   T $ LP< .|2" NPNZ0n| L|^r$:Z.P ,&fF >^<"dbZf"b"tfH\P"< 2 HnۜRHDN<^F` 8r^04\ߖ>ߊ   J NDb8Nzt( \8F, h^  J , 6 ,p #&".b&xZ$ *$$&.#& NZ0 J~ zz؄$ (jB `,ӆBҰ$ FV~0֬բښ nPVnV& B6  #Tb%$ #N&$> z6&0|: .f&fnH**D6N>B,L VNV

P(j8N\6h~z8 J^ J8 !L!p < 6^HHt FB B   !~$ $N XX> ,F ~P:BB H4r^X.<\~ v0*v <|6֘ &~:\ dT z$LbtP 4v< X  bL: X Z,dd Z&nD@",T x6R>|JnX Fnd`~<P FPJ::ZR8T6۾DpZ<߰Nz\ x@ lbL$*V,,/h25&>-H-N'8OK`DE@~P?R@~!A V@ |:t"1d &bd< JxNf~.bBZ, Ťɲʲ6d 8~8Z.l ^r>~&\: `|P.( d&60TfNٸȂ|ݮ22ԆѨ<|f F Z  #P$l-^(z3|+64- 8, 6$)0&+$F)!.(Z'&4"DpF .<``4ߔ ޖvלЮŘǴ4ׂ8dL ZRJ0p p:Fb \x *   r2F~TvtxfNdV t,>@ "  rn $Vd V h dzX.rNb&& L:Z | jd T.bj(8 tBxD> . <*,&&B* RdH L^:^Db^|6|&Vjn,xN~ $ >@j~R4hnx08ݔxϠ HZLޒ2j  X  Rl ( B dt V T b6^Nf8Tz&"l"NTz@ fFF.<p~ ".JF Btn"v, " $,  @<  6&n4"6 <^(8tVR  6 , z66~d ~$ " Pd b (B(P  P,8* J N p&NxBTTFJh  .~dZh R4t6f"dz*v` h   b.` P @"* (J@ N0T` vx>,*Pd< x*: 08 V`h*" @JL 6 H DT\|~ 2J V6VHT$PDp PP$l, &HFHr%,*#"XB4 >f (N "(6$) #Jt.0"  PRt vF f .p PD 4 *<  $ "~\*>PbvXPr\ 0&# p)$&069Z9 b6X20 146T51xJ(,. LtX4߰:zf0( z j0H`"њ>4LN\v6 vFR.D, R:("Hn8h4^jH DX`<>Dxܒ`ުLFJH t(Rd z: H p N.\ x@ P2 μh Fr\nFǬ:vZ,lbn6մT ݢ`THP f֘4 d^%*)l,N4)j7X"18(j8"#8-<4P4",     Tp |j4tX2@T|ZnfDL. b"8DJ2n.&%* <nTD` &  $ " dVbn&> < X @ ( f L b.$ ~  ߰HnDLPPV6 #f&^'`#z*6^rx`V 0ln|J*4thzzٴp 2VnL>$L&j|X&zPpnX 6r!D"TZ . bx ">%D~% `  > &d6V&Nt2TR,ZRVd~v2ٚ bݒH" &PtNn46zLBJ~FrT ` B  $ 0n 4J#& `!& $J("6 &B$Lb* `4  >08 $8$, V t   $: @ <LB2l"۠ΐ6$’Ͱf<тٔߐZ`ݪDx LpX:!D(+7%C%IZ H@E@=H=6@T#>C!jA09b. X#VzD >&ހ6,:~Zl24ܒ22ϖ(ъ82 .x<6B 6.v& ,<b*2jxzPf6d߼ֆ܄ٞݜ:HXBפz2FxZ@6H " ( rlL!'*h*(%L#:&z$v+(0D)2|% 1,&6 06Z `Rt.<`,ղ>ט2" |2 * T` ^ fB$\r B.n^ ,@TL8">Zx* n    6 z6 XB <V|N* <~p,Z0jn:jR2P`n`b0RFLlj<6@(XTltfd: ^ Zx \z6 0^. FFdnxp\` TZZ\L2jH N8hb F HT^hTިnߦ @$ЮϠt^ PT0xRV:  L$8 z J0^Z <>Z TL^     tX V$ #\"hpr !:\| R `4  ؖѢV( ۂ ߘ zT~ިxVԆ b @tZ hF`H2@ #Tr(N&"+X1t*$6%2$*"(#+8>/0z+( $ "X :Z:P82N(vR4z^F@"4l F(l2~ P~x& LDN (  &x4xv*lTp >vl $ 0Z2J\" \ > Vh pF N" ()b%dJ"*-l+R"%&  0 JJZ F&>^2jtPZ<jhbZzz"T 4z$ j  X |  xt( $0xR z#$f#6T @v t V48 f<$nb*2lB ^ lV , 6 Rx. $b D~> 4 t4t&."'&!l Z" T%d #n*z jJՆ: 6ؼ  ߖfڒ"" *l \j0\ tF r L  &"T$($R,$0/@7-6.)f1"+d&%Z*`1x3.N*#vD\b *Xj0lݼ@n^Z"դZn$"26tL F $."t ^ t $ ZRNZ"<.n`P"zbbx:dv$ Td  H . J  |"jB% $ D<r h@(jj,\n.>*x4vpD>& 6l h&r :TLH T8<pt ( DD0  H "8 $b dx Jv@"B` (jlT,ݤ޾ڐҜ~. 4 j  ` r *,0@ 4$ @ $ X  @:<> D 4 f~bLx 4p  4 , r v#$ jlFZ 0R  f0 > v  h jJ >\djDH6d 4 f   & . @lrzbTrT~վظL߄JBZ2Dh. 4|d$N (^ , 2R9A"*F6 ^G,`FvD"Ax:? ??̰ߎ\vth׶4Ť8ո:"l T|f~ 8X|.v"n@t dbx\<@ pt&BDV@,nf ~xl  P$ BF.pt $ dH.  b\ j2r&p~:48.8"(jRXDB` .&,( D>  $ +(pZ6 Jt F<>*v` BzPv*P,f  fޘP$>XXH  Tp  F F <X *$ j NR   .H*TP4 &R>R 8TDP L,v Z ^x$ | v $,P&@ 2 d FZ :lb "F ~ F.: (PBV6PzR &8lHh4\d,l*|$.@f  pFl"XP&J d4^>$v|t.D4Tj ' G%IDFFAn@=F<j>BL FCb<|1( V&& &dBZn.T XҒض ~ ^h&JTFr J @H>Npr^< Vz:ߌRڮؔb2z^HNBު܆D"rZXLbX\*D@` | t  H# 0!   H "x&vl((x($FD,VF p<ZxjVX~ vxvpV\:ےפhب8`PX > FD 40fZz J4 . 8@R\ `XT6@ r@.``@ R   JHz\v  `N|* b*V B"> R^:l8XXpN Z6:d"^L$.<**@\@ h |4 R(Tl6 6JX2,Rp( F  V4&.lJh`h$^,:b@j 4 `(>hT8t&b\^DԤ"(|۰z&ߌ:zN&\.. tZpDNPX hV" J <" zP L~F$%"D4 R j  zt J`XvN@|BL&$Ԋ6֪؆ ܖZ2 bltbF RPt@(bx N"*!%'%'6# vH  ((*& 6 ,$x< d 6v$vdh|`|<t>r$Lnj< .VB@l ^*$ H4v"p @%d'>'$H!>x<xHjp "  & 02 v dۄ4l*L|0bf4ֈӰ^ְ ~2,4f0@np@fl(8j" :Dt TbPT*r 0v~v~ ZV t Zj $8&"bt2 2   ( `R`F| 4^xTXx<  B   tN 8&\,jդ:ӀΪTҒZ"^2 `H >  L$V R-H>7,A$H!JHEnDE~LHJDK KFprHn@.$TDbP DvRHJ|vBrZ> Dbv:Z\ݶVjVp :  r6Jp" t~r"#t"F!!#&8* -00j,8$R, (n |$ T|6,zt&nR"ٞ ۲D(~* B Nl 4 pJb"d>Tl$ 8>h 6*zd ".:jBp> b6 `   | z|lD L v J*2dpbBnNVZ0l4FvRVF\ݰR~LT nr .j$nfTr(HXh~L&  J ,n"Df>  %P "TLDP :rZt^ND|J>\~DrJ`tn r2T\(  R.Hlr@Dpےф^>@TbNtH4zb, V ^&JZH nhLN@ f&|fH 0P   jt 8B!z!>B @N. ^Bp| jbB"jFԮr . . @"PJݢ߄ ~D 8$ \~Tނ 4l<& B# '%*,*-t#'xj%*&,^v&v  v nt |vl,<xn&Dv"Rb.fx4@|v: ` pz` p6r` .P  JvN $`6:* NzBXp @:T8z^d>f8& " >VP<,^DxjzvV @b&hxD @T lpN 48 X"h~ `b"$"tx Z2!#b$L$#VT "Xv * hl~ n\lbߐH"v΀fz~ު ^xdp NDbp>T&NH@( @ Z! n2^jn T ,  Z^4F  R L&\' & t ^  &-JR.f )Z"r2l p V 0N > Bb  l JN4 2p P6D|x 8v z^lTF٢ ш(40:(|$0 r (:p4`!?:$G J\HC@v4APEXI4 PJE0< /#jR *ߘݸrڰ^׶՞"zn޶FhՀR\ж$p2 4 ` v\tT XH\B`,TLV~vx:ޔ4R&*Vv"BF܀߀ dl"6>RDXVV 2ZR&,x. ,~&8!jF z#b%)'0 (Z5'7%B5!^- !Td *btt0"P4Z*Zt b FV 6 . 48tXN x V8ZP:8\h< L   *H \  l  z 0trb>J rFtN ۔׀bPܸ:߬,`J0JF,8  :n"j tR HxNN lRlNv `^ | B *LVL0L xZ"> vph*bl  4Lv\(`b dz |\ V N|8Xp : RZJ6j*6`DxԀnF pP@b@ , nNzx>n$ 0 R * pTZdl " z:4 F j^( , N f ZN @  *( h 4݈$jl0ՎH:*٠|zل 4 F 0f z߼ ~ ZjJ,F^ 0 "P #XdB"l&J%L BN , T*"hf6TP2^b|2rp""n x2 R$B8p j >Hb$"j ~* pp . l2 \,|"68^ > l\`$0*lj$8T6 8^Lx6bPV x hn:|P.6ݴp:Vلfxd vh(  4JLl@R $  hH0 >#$!jF& n80DF\ T j~ z* r8^V\f4H" TֈdR\Nr|VNL(͈tbVp  : v h 0 v.h "$ L@ $  ,8j < V:>j $ $!DF$86. ,x R,L" %l"X`F r T |4  z  pv J P^   *  @0< fp`\R޾؄ӌ"(j<Ͼ"R,یTr޼$ޘں:TV VR *`6b A#jG HFDlBCG!HJ"HBZ29j,ZvVJ |dR|TrjZJ^|zڞ tHϼ>Τܺh2ׂJ ^r426P^f | p & NH :hj$4jbJDnPb&|$ DJ V.&NzXtvPVt"D(0d\R@`V<zL ~  'V-|D/+,'$$&*B-".z-p(vb 6  $~ݶ֤>Д0(DThzj6 ~x"n  \v(  h &4ZJvD$VDdP p$n8 rR ( <$ ^  8f ``$"P~n , T܊|ژp8܄b0.x00~ZB* *LJH( j`J. tpF82 J0@ *V f : ^^ J~`l p( Z2 |v^T@r8X*~lV&vFҜ:Ξ^\"F~\ pא`ѠHݶx0Xf, t^@`Z.hh  Z &rv$jJb * nB  f$0( rN,  T @ P ` 8  d~jZ    NB l"6 2Tb&<vjv*t$< ":n" x "*!v<` J D (j,2Rlp^DV~z 08NZn  b$nt vxZdVF&0bt<tJ\LzD(|RT rp" h (<  :f j@l^~^&bfϘV͢RҘXۦ0HV2`~ZJ\Jr|  ",Z8!\B GnG*xCX><P?EtRKnKD9*..H#0. :jZJTv ٶ fZB@@Xdh ( &`~vH &j,rh 8$"@jrhbZ4DdT2@ݺ&b>  T4 H^j #0"'&x&\"~PV> 4 !` j"N! x x*"2& &82BH.8bB ^J68rt"D\@j.f < zR J  b B BLd | Fp<B,j.bTD2b  p > l n " ^ZVh0  \L~H@@TBJ`j\V\6DzpJ08bHZ rj.P J$:j&^( ^<0(p *0,2BTVxp2ڴ,ږ*|HH:F& p  z68"p*T2xf.rݜ$X^V:T8.*BRJ" .ZR  4 !n0(>Z)$ >xD\ $t*,6)f `vN ,ZT"Z J` F4ڼ@ڴ٬B$BVѢ ~ TN z۾ z Nh$l&"~b 'l)'"$LDNB~H4>*ZH0 "^ *Vp ~J B^ 8*T " "@tJNX xt2:`RLF0Z t<dx 2 T *r F vh h  :"\ p 4fx&f&2 4! % %x ~hV 2ffl zB @  " &>V$hF. F*zN&"6<2X0D>r^ B \R LVJ.,$ hb >R   tf v "@$Z"l,8l:pnJ~*$dfxTL$j 8Dv &llH\>x& NT!rV*  . 6H "^RdL fJj '0 $x .  >N#!~6F "2 t  .jf  "  NH^$ lJ `BT*Tvھׄ.ٶhZ׶۾B4*X<(~^VzfFjL# * 4=VBBH@ V= ;Z>$DZI8JEv< 0%>.RBb^V*|6F*ݜ Ӫ.%jH,.,\)T&%h.%&()~(#Tb lH.P J|"tfHt@L|6J`T0z H2 b ."D 6|T: xb^ X2dzݒ||*xnfvL*$RdHB`46ZLn*^ ̖rԸ8޲2::^zxNp6v.D :8 : Ln 0j:n.@ L .^ "Vd` (%@%Nb jP ~nR4 jݺ>nB :Zv$ | ~\l hܪ  jr@rRfN0n*!#,$!FRr 0"!6~4N&"'!(j04 (FTX "hPhxfJj* | ZRn\lDT4.2  rdF< l Z!RBjvdB*@0 j>J6x"N6":XV<| FRz\x@rD^hT 6  L>`##f l4 .Nv0t 4$ !T$%"r "Xxz2p0<*Nr*@z X" .  Z  . " hj  zd: f.  X Xr^2v4:&,>DbN8!$2b@|D @ $ '#r4F t^ z <:| V x :dtRR 62 2 h^~z \Hp( J\v8jTj׺lbπӸlhX N r2$H  !,)fT3,vHvPd&>zb|Ft6L(jD>`xܪ$"r~H4P  22&$8,f-h+6(:'z(.)D)b* ,T*f$~LPr>:d \zLr@ښJ^|nߺ Z~F (&4> L `V z `d$v  .v    f 0vDX D @V  xP  * 0 4 H  P0D0\|z,4\NR@F4n6d2,Nh:(@TpnFR" 6 @ |t^F F n bT <\ x<L,H, <V0 B |&LP:dܒr~@ \ > N<ۼL$H՜6DF*D( V۪ 4:2&8j(l !b ^#n !`X&bf xZ$8P  |T v|J^F vbb( V8`x$^B6 `|z6 rZDnL:\ThPph,rt  z   J ,  L`d!"&D>h F 'z)%  8J"V\.2^ڐֆ؊\`jٮdH24~d*\,ۂbߜ>F V0Dz | &vJ6!V#j~ ln V2r F~$R > 8z b >n\D $v#)N*Z&6  R F6,n$ T  R "`H~" *ܔNZ^D:(p$4pd n8T *  b 2X$Rh.8~# B$I4!B6.lh)($%. JJH: |ܪܦ`r  `d:@`F tPFh~&nzNhLl ,^8,J*& jrjnPjZVVN<* F H  (  V *" $ #  <  "\p%"$::< jFZR D4D(٦^֠.4dHN Z`b 0`$P|4n x F8<pJ z &\~J ZpXL>06 (P>8 *d <  bzb 4 f Z~(2:<(  ^ * x6 ,DN v|JRjN>X. zZ`8  HB "> Rj (* )h"FTD ^^ r N N ` 6 XL rH <"Dn J0߸j26p߄<@ޜ|t6^~|p,PFD|`BF&,ڄZb|ߌXBްRޚzf@fLtB^H2~8 "4>&(V('"Z\$:&,@$/&t- z%D  h Xp X8,P& lܜ׺jn\jؒ H`X  Zx < ^ d`vR xh0(zL*" N0:tF~ fB!H"f|p< ')$ vH~l h> \ xp`6T@8Xh(H j< ^.2xxкX 0 v jV v ,~2< F H 0 N N b DD`* PT.`V &:v` 4vd0Rv*jZ"L\rF(:<h2VXnT6 Z, 2dvP<0H4:8|T:JݠhݢXx:JX d^LJ* $b  P 0zb2f!6"!  @"R#!2JJrB f Xj<bj `68tP0Z\2ؤz>PJ68 0.<b8 0>d&D,6<r p* x.B)   F8fB bvnf %hN 4R( z#- 2Nh/0^(~ $LD(bR"| | 2 Z^ P L0R6l|  &*x   2( f@. ^Rېv,vv\`fFJ>6 , *%|\.v6<&?&> ; p;0 v=p@CD"DV? 07+pH!^ Hr:4"גt"ΆH|:8"Dfxގnj(˂Z|ވ6:&0P*<tV *Bb`nbV  < &^ z\8 < DN~(8TD|hRN*`rHpt( " * $>dTf ~<D ~FzNPrNB6Dߘr~\&6|"v6p\^rTD"R TnF&z6JHNhRtR\N" 84f~V@H> 6*~bf4:@ . (Dp NjvX| Nn`D N<^d2J6lJ~tzߖVv~zr*^< |\> tzz  ~FtD N vzn"r"&< x ^ L\: dѠT4H$DҢ Ԣ|z2Rղ x z޺H6FVD~Fvb*Vh0nH 4  6V J *z LXP x~2t F ~,@Xrzz, " T 48XXNpJ,\@jx n @*Rd~X~FL8 H6< f   pt$X `,: xxb:Td p2N`"(` >T~ bJ,v~H@8V&J^PHrVfV4p"HHn6@j| D f^*l>` ~\ t V . 4x ` f*   >D< Vj \" :\ tRx26LD\jvN6DLf*.X.TH8.d*ݢ H R l r z .N 4^D!$!Tl \~"J!BF T )N>). @PP PT ~$-(0 t+8#|p   2* z \ *Fb  R Pd~j pl 4.n r&~tp\2vtF(DXtDFV"b"P2% ,t3`;CdGZH^HHJ LBdNXNLE ;1d(RZ"h4Nz:0ҌΠ~̈́~.̸JʒͰdܜzT(zl2$ft2 hܮnp\XZXNbh"ݢ ^D6 p`RzR J8 hT^t(NvJ.*& > < r0p"djj^hr nLT   NN t& fzp\l, > D &&2JR.ږf~H:&:r؎44nz~V, J vh p`b `,0 t |\:&+! .v#+!%Zj l @| P F.:^ n$٘$Әf֘bRBbDhP ~X *2 |٢t N>2Fj .4zz^`l lb  v  $^l6~ F, J  4XX  $R `FX@jT (:r R Bx d&  |  z4t`0 T:l VZ&th   fb<*dNhhl Fl~TD J " XR | dD L6H 2 *nb4&62~F642n@N&tRՠ܆L2d(JԆ"ָP J b ,R6 B ,0 (x :ZB v hr n xv !RB$Z:v \P p6 v"P8T * +4~<5 0.#Xr4(l`#((Xd*'!t |  x \l" %&#` ~Zp $ (: HnvzފbؒۊL`.@ހr\FFd8>N Df, V"$,x4l!,;X ?Ah@>?EFFL!OMFd;&.`$$<*d HNTՔ:͠8 4|hפXR`8̄Bф:VPD Z 0:&:N\d$:$FBZrHT $T  Z*2n6 ,84R br F",1t1L, &V p#),*$Dbf` R xR: R`FDVBr|@ ؞ NjXFh4HJ\^Vl ~`8!(!0F*(4-1**"! tv  VvD,ּ,ZzZtȞT:ˆn̨dLPP "L&!z"r8!JTlNbHr4" . TZ F j vn < 4<Nv bd xr.(z`  @\ 0fh>^n 6t &0 b0 dfLz` z (p. 8vr>ft|zt Xf6N~Jl8tF\jZ<2<^D0n: Ll6Dl J6h!(!xX t X < b$J!$"n+n,%8nZ>&nrتذ^P|Zh:,  ܶ:T j 0p4F&NDJ$0&,!`v(n n@8fv6F(v0 Xx  D  ` jjD  *P D $@ R" z  | *.:  &>43*r%^"f >B 2& &ӌBpبbB\<`J԰ 4՞ b *p0" *(~J^~J4<`<^xxTXNjBJ~j0n J  ^b  f^ %4&\%h"F Vrh!&^* +2)D$,^.v LX`<$:XH4p:\` v . b P@ntJz z$Ll< R  t |`jtB(N|<hl^6^p6J&~Z4J"(r"RHnT*V ^jXRn&vdR8 x 4j>`P vRft:V*&܂, FZLd628LR<$r %JB*#R,%<* $%tf L DtX "bL&j, r"`0(â0ĚlfN&bL" fzڔ(ܮX\#"t("`(@$XpD^ @ >&T ,82V 6 \j , $ 06tv(X:b0v @ J   hx2p  dzhDD*v , nd.X6``:xp F F  8: `N"2@2 v H N0Fvb` BH"`@ l z 6  < V`z>f<  P`d0@2 0zp"H$&&NR\&L.vdf 8 4f|^d~ n <6 fHHVH. fl^  X Vnb&\<<lfjBb2Ӷ4z|dR(0 6R<p,Z  @x *r^"h'p&P> : l$R%(# (<>b$ b4VF \$28ZN $.0 , $8,(Vb$* - V)B  $B28 jl| 4tbr>(htn*߆dxݰT0zҺԞlpXb^&2|$n^H Z)h34:*=n=*V;Lf9 ;@VFBJnIzE8>3F*@#VV^$ p0>ҎR4ڰڊ~Ә֞Vܔ V*J BBRRzTp&88$ T*$bnP$HB|Rp^~Zn0.6\h h4 2<< Rv~V H. &%&:#* Hz BD!N$n&>%^"dh":fT 8 0LN|vb|ߌfj\&2X* t $ H 6( 4 8 t<VPZ|8 |d" 0 *Z  :  .0f v  8r^ N*@|x$dzHl4z:" >,~x("L<6"(|||Llz|j!%>& r#NpH"4& :T  Fj .D&B` `~*>DR  d>l,$"n^nr  .,  b  L:D^\ t\zbrv,jd j 2 jH    \X2*8   @~L2 P8> <rr f H h>JD<RH b&prPtN.xP NDvR2^ :.B~~pT   tZ*4*|F!|!dXd zB H "B"($d"$)'L t BJ@pFb&Bֲ6V\Brۦ^>TԄԲz pp H D j  BX 6$!~$ X n !2 80 tPVhJz  l&(R $  !BV\ l $ T<NZ 8`Bx60^Lvl h.P$hd8hv^^l " T\* 0*3 <$pD"G@F6DdCPCEJ IVLTMzHP >>H2 8'4 8ք"h 8ؘPτ lpJ*V v&NfRHHjDrXF ^46T>Bjn Z>*N <8<fR>t@ xxFB J*1^1,V&Z0 TRx$",'~3*6F+*5|)z/<&%!dr >p &:n|>L D0h:*ޜ20" hJZ"p t : $ l*jb@ n P J 6 "`ZjV*   f| bl&pF@Lh6hTj|v@J$Pv TFxNTPth ^tz*8PbNFBp`<,b<  2J, X@N N`jLX p \@ 6dB4.T x * p@dj Zxߘz>(TR 6JBf r`2 N$|.*".|&l/'-`&'"0#N!R#%&x$8 xH,^n8jv^״(:jHrF,jӂXb B R߼fLH!@(* n(,#"z8fj<(H& |<Hr,4<&vNN` B H j 6 \ P *2 .b`NLzvLdB zbLb6~< (v4R~, Jf  `"()@,L0-(* % ""^%x &( 'h&% N f RZjD: N d* 8<D6 <$X0| p" Vz0j 8P>L6vn$߾ 6vFNbd<rN&,f &0 $ ~ |.p \6 f~"P%%,!f$@"h T0&VVJ LdNԄL>Ԣ@H|px8߀t.܎؜ v$ ljPDb0 z$> nV%^L(j"p| l Tn %:0#l  0"l6 b &6$t 2P2R!V:&.$0^l|T %%\, l:* X < r` 4 ^ l&|:6rD.nBܜV Xfܨvۖ:޶r(,H^ZT\n B , 6#\+ 5,V>"E#K(!fNdN|LjLvPTU nWVQI=>2B)Nx#2Z ~b>X~תbtҖfӖڜp\֌\@JXR>RzTRvFzF`J ` ^ lވz8Z"(r߂8XB Z$ ,t>x@dxJ d>\ X`RR@< r$"\ $6"fL&*l!D#`!2pPVd4 < V 0~ , X  &zh$ <<020 z  .^ $  <2 | "    v : 4 B ,\J t     vFr "f(6\zZpVhLx^DtpdBbBxvfhP:(, "xh& lDp V $ >,F" "rf`v 8d|Pp>b:*^$"R|4L2\6DDj~Hr\4`&(n :    L\ ,Z <(B\  4ZT $@d4~TrztrT 4p<n hxrv: !'J-.1T!t3b$2#*/6 ()# F  T.,J~ RJ j@xHv6"f<2@2 Zݘ H*z6|!0&fL(T ( 8% X> X"F<6 bx ` zB l Xn|lL~V0nfvZd\R Nx p`t<~4X XjHLpBL:vxpzp~rN4N^*\ H l B2$  f%\ &X$ ..&, zpR,@"* "*  ^`@d@8 L@l@@.0 l0p2zN..pl,\\vz.@V:tv(h :  D n f R 0, 4:"`n!8* << t |#$$+r>*, :60\P,T\PDPP"hx(Ѿ$RH͘L8J.   l ~ F :^"(<(j!< 2 |!0`H`B4 h^ ^l Rxn~"$Fl#>4,f L!%J&# ^bx .bJr& vvND 0\ lJ H*$N **0 2v  #$" z  2nz ($-0(>.(`)$`F f nTB(hp6ZX |JT׾zFX<Z`*V0TJ, d   hlj*<h.@Z(F:HZH"V8j0VF P0rR.v02NR xhhhL,  ` 0 8Xn   8J\ h| d<Vn F^Xf($ 2<F  @ :~ ,"4hZ\>~6` 8n H(BVT rpB < *0HFFrRN@ZhLۘ$JR`02p$T>vJ BtP,$R+>B0< z0f!,b'd~$~6#N$*&4'VD"HJ`tTv$\nr`"BNĺF>ɔɎd@H р`(0N ")b.V0 / +'f^$br" lf^PHZTv| >h N b<P8,&R^VJnBjL.  H&  :F 8>  "(V vp`v8 H^x  T0N D: : z0r R<nP0&Z"#  $  LTJ""h04 N0Hf 6 ~  .X2JN $  TZ< |HB2FX J@*|,h(nh T 4^z <~rT20dF~l,x @ > VH.  f (TNl: 2 D8\(H vxL,Nr,|,Z.ǮbĘȪ2μFVҦdҎ F0ʘxpj8 J H,Nx@2 > `!)\*Z%.Z &r)d%R,lh0,L rD>f"!z!Nf F<*rbtt!T4(*':!XD(\!"4"B!jLHpjhP fT0Jfzr P`ZVNt8J~& L0,bNT  %,,\5>L EHDJH`HGHpK LLzhG|?5J, h&B# ~2 T8Һ2Z2:l<Z,^LPHh\x\&Rp*^*<>&HfB D8hVbx$ftjld62h r,d Zv  & hj@x PZpvx0T&n N #h*nl+' ! B J(`&4 P'+^"0,#(t""Z:l " h bbp\t(Xz lPr $> Nt,LP 8 . x\2" fX*8dhnrP Z.RZ`j Tt < n  vP Ph^ڄl(JTjlh^d b|`NL0 4 `'v/ 2<%1$,T '#~D"#4%T|$: n|T8z,n֚xʒ"Ȑ&|`̂@ Φf^Ն ۾\rhjRjp&0B%+..,|(lH#l\\zl(N|HRBx ,v \ ~(Vt"@Pxh0p >T x`z~Pj``  R :Nx~XlRz0L t,@hl  \L:F |6: H^&!&&l!jLx|~8D `BP@4^BJzhd< l< HZX .<`JlFJfhh88R XRTrlvx\Zrb:J $$L4<H" t |<2Z@,H٪Jf"p Ҝrx ـF6`XJ^`~02f | L b d\&d.4!7$?#Dz"F`ElE:FfF.H.I|I(EZ=5Dt.($B>H (:զ,2rb2 xpbV<ڬB N  .F< 0 d Z .V*\ JdP@0`B|(NZ&b 0 6 H B` $x(\H,d2@*vn@D^ D d* F vRhbBH*,.2&pr tXJ@ $hD ,\P(D(H8>( P 2   X X. :  p `82$ B Z \  T ^  D n 2 :Zd dr  VxJN~lrzfr&~4p4ltJ\D D|B vf bnJ$& r &|<4">j@& Bn(^fٰ jJԊBݶLP8Vh~&^.Tl Xb t RTD >l f B d t b <  P |TL020 - (r b$ j"B   \~ b(< z :@ N:DbF((4 X4tXP8H n8 L H &|.Vp.@ 4. ~Zv(J.\J"d\(:@ h z^ tJ84r|p x` !% %> >r.x < "X|""n2l*j ((.8b N Z 0. ,n<fH@b \ d $ v X |.  @"|zx @N<.,zvr`88 x6 2`   F 8r>LH"R "`  j6 F,Pp%&#+l'B |. V^JZrl8bѮ0ԬԠլ$(Rpո:R:f" t Rz  X *%"< |J z @` l# J!lb hn(t&  p4vh:rf J  & p#'Z&!`rL | \4#!"$! xfNH\|fެ$XDV0rzFɖ F~>Jb(H@" $ \ 2%D>+F ~3$0=&D$#IJKFKhKKpKFXJv\Fv ?F6f.r)*&b>$8~ H:Tв~b|.ڂ X*RrӺjfn |B zlx@pf JDL4prF(hPJrbr 4r @Z>prl&R~B R>D>͜ ϒ@њn ۠h r\Bn"(>.j 1 1p/ l+ '$  B  d hLJ <  ^4  hbvZ.l PR< v\* D  8< ( tH <8>& jp$6 H`~ ( l4\flf\: l  (8&z~ v pD n\B0  f" '&nL!D62!$xB$<,Rl>. Z >PrZ.: Bn  N\4LX^z(`|T^lxr XNrzr ::X2:|z(&8Ff:8  4bh &H ~N h42VR r(|4hR2Жbӆ6\j^޲~ݚ :~\0 \:6<.|D$x n+-*X h!LT &)&`|8" t H 4 N H2*x NHV`TL62 Tn#R%Z$2 <T  pB4 NB b**&00`Fx֜(f,پ ^:*nZ  h v rJtt#0+!5$>D$2EJ!IJPdIt\GxFF\FxETAL.:1*R&\"HT :RٜNv֘"ܰlHJp@,. .x`6&. @Z Z P P j`:^<2v~Nږڸ & ZVL xvfDj`ptH ! z0p2 @&&)x *+z ) `"Pn$r B r 0 Jh> zz Z Tx J@^|2rdX Fn8ntl0">*lV  N 6  p  ~ Z p d ^     vr 62dDLvb` :<~28vrH6j46\l(T@>HH"Lz Hx\\^R0^LL&z&J^Bt nF L < b$B Nh~B.~ vNf8pFBf4܎.rLx:4FHj  H*xB2zvnH j rZ h@vhP(ftL.>~vdV6p8j| ,$*-,p($! !0"v6 FX N `*:JrXhܬ؈T"jŤ ªV$>zZ*@ Ԏ  46  Zh"$H$X#"!4\ zJ X "\ j p@2 :^V(6PTX th n "x| T V  v  dH hL,fT^J6B>X * P <   $> < H  *" ^ pF&-Z0( 0.' \B !h F ` TXH<@6|^  "l p^VFfF^\bn "4z xV bd: & rVP jXfZXި>VRB4 d& , n@T,LJ N |0XFz*66*&hdzٞ$0XdPX:|pؠVռtծrz hVj ^T|  2$ N'()#l(r" (B)r2#  j\T\ f XZZ*N FpZ#B%p!*4 B:&\,P ,'D2  zv$>"(^"r(%( > 8Z 8 2 2d:6Ҳϐjζ 8J~Ė.V:tR * TZb0'DX.j4$<)zC*bIn(N#8Qv2RdQ OzN NZLMxI&A5* #0Drܖ ~rrb ά`n\Xݤ.r׼><.j R t $x ,&$nV~ "$BHhtXRt`ߢ02@jX 0 ,~p~Lrjf"b#~%'2 $' " b2&jxTn @d 8,J:6 X  f 0T r 2  8 t H"*X6^p.BXRN& j L"  Lv|`  d   . ~  8>n0 2"  THppB(<&zjB,BDJz^$&N b4z^4 "Jpf&\VJ  'L.'B 8\BLdl. pPZpD l.8@(*X:^2`XHBL&bv݄4 2BNv 8  L  p \>F"~$&0r ,0v~~ 2& ^Fn:NV"J 0&,1"3d$3#|1L". ,- D/N d/z,(`&N"  Zl**,VhT>>jb̈́2&h"Dl 80Jxp(6">H'&,021^.|6*.%8 l!n   J\ >J$<^ެ٤<(.LJJ F(ZN  lPfx  &l* :lt r ( f(:6 D~d>bx H H t.$ \ p. 6 2 n+1"1, %z   "~$"V0>  X`J&pn  v <\ >vT,Jp h`| & >>jpp@BV^rZ6~~6dJHn<D z0 hX2h vp*6@v t4zJJ*hxDPHRxhX֢r׎J4nzP Hn",&#j+| @0 /R x+r% "F"L$ &@%\! N 6 x   "  b r< NF|Df2v,$ $'&d"Z@4dv &#*!*&&H :< tR \jTB.ߊ xՀܴdւМ\\jf˰ÐB,$0ߞ:hӼZB.fV~~n6 $ JX\ && .#6 '8?'G(%M"RZ!BVR!dW!V!URfNbIB91+'j"$,p. Vx.Ϭϲ 8XtאFbRV ܔR^X hV Jrbh2trP6PzZL0H4hxX*b$p(bDl x @b\ N  | b .T T@ ~`bR!` ! >jXldh  l zH6J>8Nۊ@h ׆R|Pt"nݞߞF"BR$$ 0d $p~  V$FnX^|jR"~,L( F  D  F  ~ R B  (@x  . 2 0`2NzB:NVD>8lTZH268r.V<@J*@  "& *LfjN 2pjfRr <&^ pj< d B h"rX&|BX486 rp, Nf`$Rx <0`26TV ~4.   j xx *PB&x*x( !P$*~  .!l> bVrzp4 2 vX("$ \`p ^@0F@LX >f62BF\:0\jzfnT VZ$rhbp JHV$>,  ,.T &6l:Xp\ rH" x( DpLB@pנJ մTz lH: @`6n R,D%6 ,.v)fN6 #JH X L|P Jd& H zn JPdh\&~^nLV!X')&d!`\L  J* ("$#H8 h | J<,>0V&ܮٰ(bF͘Fɲ4( ,btH"|2 | l f< > 4t"2b)^2#=$Ej!KNvO\OHMVMNX0NJ|nTV p8(J>n n0 Tr v  j &b&  P\ P߮@ZڠX@݆JTpXl4$ lb     :   2 2~  dL B  .  N(xx 6  " (  ff DT^  ~,4 "pzPX\&"vHB*f(@z~D, |hh *>VHtz Z Jd  8dj6p   h6\xf&<r޲d@H8:8nr4  ,Nx$  4 .rZ<bFZ J f p tNx`x.xx~V<$ LHZ ~ F 0"'@) '*#<. TTjt NJ &X&.xߊpvՈ8^$,Ƞf\Ǎ"ö^6ʲ8Ϝ dߤ~,ll"x'b&, ./ 0 |. &+ & !   r*$ rDzDlr *\4P$ .N  Rl^J2 ` p < ( d  6N:nxZV . F` &>ZBJ$  H Dn  F 0@.>H!Zz& "&V > (,*V&z2^:p  NRT x 2H"x` r ,8.NdP Z6 `*nL(d p<vL 4HRHP$  l N D b r:b ~ H  F(N n: "H0(Pvl2L$߬FҒ:&NHє$x׊@\Tj Jdrblj&( z ^ !H* Lfnht4lr>z@ Z `r\" Lp~(>XjBf  4N     VLP@!#j"  < H8P @8͢φbh(ˬrfհ̈nܮJ:ئN:LZ`D z4#zH*"X3P)=z,&G"-O,hVR*Z(\'\([8'0Y$V 6S(N@G?8N2r*!.^ .А$HtBӺ0׬LFڬ@܀PThD\|fB\rD pv zX~$\&T "^.0l*xN@228N>@nPR vRDrp(f ! !(dhn4T.x > j6 4 &   < V X ,N>8Pߌzܤ4ېڢrn~H^<.Jh 2 <  j Rx~J^R*R\  "   R BX h 6 J v ",B~  2Ph" n4t< "FT46,>N:l66D`4 0*l4>(`t 8XBX dn &\ *Pl hf$.:Xޤ^*N*zvL߶b^tR&<4h d "h:n^v@pJ^ dv\   ~vV N .rZd,<  B "$"~tt  &~d&xPvvZ< R H8 v* N*!%(( &#z  $ z $fBzhl4vRd"p^ɔ>tdhLj 0  PtD""&0)&)R ( '%$.0#H &   0 d  >0X:\l ,N*"".Vhd`D N ,2^F @` N < X nn.ft^d  Vv. Djh&jv.\DL: Z.bv f|r! hd>4~ *:LFv*d Z\j R 2 DJZ,L@\$`H `\hf4\0 *xNf f (("3t(,?+8JP,R)V &V"R8 |NL0dKL6K4 H>B4:.r#<4zNج *XP>pflL׶Jhrldnv PR~njB\:Lx\,*j|F|` lXV>l2xx ܦL>J,0 " d &RPDB "V|j8:2~ ! J&b ) @)F#|F  R*T $\ r$n$Rp.2BBLN$ 6 ~  " 0 d n &* Fh t f $ Z< xt T p H ^  T hF & ~N~X.Ddz*B\fv@b:FFdxJNrT~ p:2pRp" b D TN 6h TfTX  F F L$ 8|^nD&\Rz (`.dNDzxFP  rlB f4  `:n  \4F":Zr\ \rH8(NjfHF~ ,Dv :&8pRR &%)\L*$'!N |lFN p 6(j:ˤ~ǀN\dX nr >T֊ < h*th zXR&*,,*Bx' # Xhl  X R&vzr&8D0Dn6.2"Znhd ,4.F| fz( & x   n ,r  h^ ` $ h@DHF `T`2Fn  \ b `  ). X-*%RL2RLfF| b \ , JZ "dr t <` @6XDfP4*$&4RBx"~r(@j:nTFR8 x\ d  * fdXTtH rB Z h D2|r R X>z~,b۠nϔ͒V* $4ҢмDl:zPFt`xT :vR$&xD$ J d. rFh H$>``  dL 2.4V6"hdP.pl dx  *f VhpvH, *"X !Pt,   <  d$ll٨Lܶ6(Tը*բ؂`fxJަb4$ hz. > \$V+ 4&Z>*~Gr-$Q.Y-._,a* `j(\%X"DUlQ,BMHC= 5z* & `p((J\B~jzx ,&&*tV0 L~lF* @  $RJhD:n6l tv .^b< 4 Fj t v fj"h% %"@\< V B($NT l "fF$.6ft8t*j&6r*8z z R6  ZHdp< F28 z F~Bn.H@nz28ߒLHHBP0pڤHvjp:r pvp * $D6 N Bp &h 6 0~Zx$Hd@2 ~ ,8p".*|p``P:\$  &H$TT8$jb <`!&"v"D 2|  n < R  N*.:֜xȈ$NLrbzrߪ V<'h/4n H7F$74 0N2- *0'H:#Z  T @  l.4>X<l06~X B ^T0* xff@ L6 LXlNb dH`* nDz"h>"NlR ~$ Z j N l ^ L!T$ !,^,  ^06pZ*8~j6 <H0*dvPzHDz^2"R 42  ^> Lb4F* NtPb06,\B   J p& $8<hb#$ %#"j# D ~ B .|$'#P*:&0 b PT"^:f$6` J p^Fbn&&`ܬBf@ t( Tp|tB p x4&4l.vLpbhV.t0dMJ F>4~*" b r6ˬȄ̪8l0,L2 &f 6 R@jX.`| VFr.bJD8*DfB$6>r,f:hlf@ $ ' h(8%N@nDV\!!hVrJ b|^  dd( Z r(Dvvߊ``b޶>ܞ>BF, d66&<8N ,bT0Jp: Z&,tt:N4~ l\J Fd L n .j " `h0zrV:PnDr$,8x 2|&^p8*NvL8XJb VHz v.>0x &|L<"pr8HrpFF$0L>B: &`jD 4  ""DN ,8bzL 4r rr: <0Z^   N F`N6\RdZ|ܪ@2t,t d 24 8L& Dd xJ$> ,  4 F t :l  ,˨\ǰØPP޷ XRvFѶ .B <@Jn r&  dX^&" r p 6 @x f64\<lb . t   f^!&T& &R"^dN~  p^ 6jjZXb6*V f D   0 HhjZb zRvz Ppfv6rp (zx*:v|XT6d( h|R4"Z"z|LN,H*  , N Td~ ZRfD4^rN B <   ~@`"bbn&^$n$8DDDrP(לԌ8ӼӶ2ֈݺ(ނݼ" b"td8642L!*"$ 4t .8 V".|^N 4  dn|$0~> vvHVdf<L""bv, N|Z0>~(FhN @!! xtd 8( >> jX\nlNNZ˘Ȧ`ϮƊԸȘRLFt TԌRj~ 4| #j +`%H5(>+HP.S$/>[N/ `/a@0`.J^+Z&8W!"T",PnJ D>=H3L(@ltT ,,fˠDFоz"N@n׾tږN@(T:N^@0t2 < d$N$J`JFz"8`vnT\p6n64D V`&>* 2, @@ #$ #d"x$ v." v$ n%$l" r` >.>Zzh2 n"Rr"|(^FHf*& h F T 8^ r 0Hp6zT8 ^f B  @FJ 2     *l<6B  ~n8,n`X   pb ^H<P z `r> ((Nl@hr*lLf:xH$|hXj@\nx<X %' !l\888Bn& H p(<<ߖܰh @4p|r6brN|HLdxth<l pP< RvN* d 4zFV(4h>B\d"R*dlZ~>n * D~f !d&V)*BB*)T'%#&> r  `j6<ݐ҆j̿LZ¤n68DzH ڮ Vt8."X2$*x02F 31&/ B+ .'N `#z~V\p l JxlTHP@B@Bֈ>TnJTXH>T 6 ~( t zBPT~v  H 6 bZT~.4&2 2f.Jj0f^B@n  l4P h v>L ,$ p8d< bpvjXN: x@@dd . ZJr`p d4,,8D.   2"2pdb$~dhldrt2@""0N0\D vFv8zzl P~:|*t  d  :f4, @T z~j(߄D\d4˨l,ʆbF̈́Ӕ` X Dlp0"|"' (z%f V"LRTJ & P N:@~^2 tDNP` X b X~ blFTXr4&(J>4 B Htl00PߐRlj4dv\ ( FtHN* Z d B f  Rbl:|d (P   j.0VN , j  &T` 4 Zv<*H>`nbdr6^ޒlj<,Bn,*\\xX | JR LRV *D*| " >H <4.z<ܸL,Rޖ6:4(L8&02$$&z ,Zb0d\ ^L 80 p(28j h" B<"&L@|*B*nB$`r ( D h& d>X#$,$X"!^!!8 j2 P bv|v",R~4RJ8ĸR זܔ\<%,X01JH20V.*'(#,d2Xl 0RP|2|x~@@<nL 2$V0( 2 NR !$z "h\  zBn4 RJ: ,P^Xl.JhJhzF~P(X~>< bfnXrHZ$ 4 \60jJ.F2Bf&r. ~ * &P R X"6 # jV\ ,f hr6\ v$#jBF^ Bx܎0L&~ƀƞ>zdҬΆN˚Dz Z H@ ^ z ,>#&LP"hpX^6jBZ~ |$&hV " p:zbvJ|t  6 ~ &\ j^"L^#,!|fd~^nF d&&,*04+1'/,!*N%D J.( d(LR t`$~θ^l8̸ͦ(`fTPׂh۪6Rn, p ^2 $"+3%V;v)D +4M>+`U4+RZD*Z'4W^%S#QOXpKG D@X9X0Z'v0 r<̞LJ`8ļH\DˠlΒ6>lBݘn\|8` bL|TtFZ pf. "h ^&j4\tnܤL$*F`~LFXnj >4!:$%>#6h@pX "2$:r"::f\6 fz h  $^dz  hFTf޼ :H` VB0 p0\(DFp8 D L V 8 f < B .< N|V 6 b&Z &&R|l|4|`rV Xn6j~$`T lt,.F$tjt  t  | ~D\ r& f(NxPR| &Jv>2f"P@^h>pFl n$Pd *DFL `^F X ` Vvt>&|Jx~6dj4 v@"z2d T&zXn8T R ^  $4 0j~RTFTԦRBvR,<tth l^󄾐^6@L "*t).Zb1h ^3X 64 D3 1` /L->\(4# z ". fNh ,@<$f"8.nxr 0d$^ v pn \^f\dvxttf<4TX zN&JLl\2    & d  :B~ $n(N.( #Jn,b`Pd "p<np L6L ZBzRZ ^hPt,D V|8|rzrH6lB*l:, :~Vf0:2V. fn   0f   d !h!~ v B jX"@ HTz >6,<ۂprɸdz^֘2\ؐ" *lXb <&2lpxlh'B..(-^(6! &j~ !~ !  tn ( p  BLT, l|tX^lXL(^D b l lT^(JJ2p n% :),#|*")b%`j hB jD, f&n.F f̐>Ft$ɚ~ȒJDŽ8ʨ<~؆6pTj 6 T0xf(!D2(<.^G1rQ1rYd0^.*a,_*\(ZZ&X>"ULRZN &IZA27-%xn Ftȴʨ,Ҩ@ـڶ^Rrz b x 2  R X H 6t,d^ b<.dlbhj Jnz,NߤܘNܾH,:XVL\$ .bb V T P4$b HD!!r\rLX| 2 f |  6 ">^zXhj ZbHP $ JN  l J   T rPv lx|RR2T2t$8:^P, L tjN x `4 z pRPb> L2R<@J"Tx:Dr88.BF2@ 0&(#    86|z Brt BPzx&Vtں <~>n(d" V6VZ 0 Z"V (8jtB B&tlbbX > <>VLXh  xz4 b& vPX .l$R&N%!n < |>X JRbL־ lpPĂZֿdXtjh FB ݺFb$\(D**(%^#  JrXlp j  "nf\Dfޔ,F|`\JlpL ~LbFL x , 0l $>  \tf0\ .B> r&hdH 4.6  p 4d&  !2 % $@v,pb   ` ,fvPV T0Nt2` *Lx 446*H:`Z6pf2tpNd ^D^N`>n R6$8 zX2  d \@ 6  >0 xXnJj Xl x L.H r2l2:.<ߞ$LٔBj&ȦŔ8Zʞ6X jhD ڴ ~ $fFhx V$< $$#"z>\Xd  v"R"~.N@F*r j$<BNx  N f tBZ,frd Z@ `8Ll *׼fJJΰH:2D^ۤ@v؊V٪LVt:d~ , !v^(2|/"7)A00M24&Z25c4h2i.(gD+b(^H&Bܘnf $6 >^4~ z ( n.R.x4ZJ~>L,0,~xv|vݚߞ8l~tf* >lV V2XTbhXZ V ! dLf JJ6l Zx j^ j& D \ 28B^h\<\מ~܀ܢ*ݦF6 R 8 6 6$ B68V BT 0j&j@@  . nT|>H (v  V n  j   N   X . t d p  Zt>(z.z@f":..hz"ZHf6vffF V   TDp 2zPZ tpR@ Jxڼ.lbTzvz&݊*&`rNtJFd`t  h jnHfN T# x\ X4F 02Bbz Nh * 0 Lprz0(d*d` 4F $ `>|68 l!! r6*&Hz* ZNT,٠&źn檽rRbllhԽpBƖ Dު.Jd"h)0b45D(642/,,LT(v"< J""2 l BF0@ V`V$8"bh.|~x l  n$@Z  "T@hP rJ j*(.|D h&.L B` ^ ` B> `    | V0l .B * 6L" jb dF *h4hl`^ *! ~ @V^ 2v xTdBtn,DR,8N".fZ hpN    hX r< "#"$ ".!t$0dz 8 ,4PrjX.tلBєѸ$ل0ۄrݬ R" J8D h !h'-"87d*hC~/O0Y/8`-b)Va&>^$Zz#WF U2SQ:O^ J*XB<84/J@%< 0 ,шʖǞ:DFDVҀptԪ׾@ل j0H D<~d0 0B4~R.d v$HTZ"VlڲRۢF dV@L~p*<: `> pZF&btJ*DzzZ 6:$> 8~ 2HZ`n<,H*  z <l4.xL pLZ,vLz d.&nfx z H V r T  TZ x ("F ~ >~  R 6  Vp  .8 F  ~ J f~&$NZzzZd z PRH~r"  `` z :4~ F x8 F(4J<&h6ܜ~ܮ"Z\ٶT.&B|d .",0TN^$>V ~H.`@rFx0 4VfnF`z* ~ 8 @H,T,hbb (4j 2 &DT\&Jh@ʰ<NJDpĤXʞ `lڀH>bR#b+:2B6&R8<8b64l2B0,'T """( &L  @lٺ0RzJ0zdbXnZ $Zl82<   $\$Bz  j r F z <!T \X  "*\@@:. .fڒ|@X\>Lռۄپ ٪޺ N.zX><Xnj $h ) R(b \$ hJpDZ!DX"r r~*hF , JN L@0,X8J \ D 4 L HJD( j T@">tLF(z!b!>$"&!%$F#8t PJf 8  @8NLFPXj4: FjP"@HF8  .   !: >(Hv R0pJ4@($ ڎ("ڪ݈n(tV.n<`Xz tXhn 2&v <l Fjަ8޶*t n*, nt&p Jp t "jH$6h>,2LJV z :<86^pR &  t 2<H P0""&b%V| p  R| *ߴ<(8ʜT2`ĸR  lD 6P% +.N 0 0 >/ .-L +B((#60 zB,Hd4HnP~(:V\nttb$ft4^ Np x8tN<v tTxB$ F\ \F ,6Nz>, ~b j8fHtPVnl0v &P tT (HR^%v8+B~* x$jL@p`~RF( *2r4Hfj"@ x *r  &\ Fjj^PxfRrX r&N>n6<$~2"4R*bpjbtZZ6NXLv zTx$ > 4*|&@z | D z  0  \ ^,&pDn&"~:.NLֲ802^fRhɌΎvӊ`X .\*RT PjL$:+ v+d $d< H #d"BVhHZl 2 8| ~~f4 l j , H,0bT"2#P( &\^,bp"x $#%P#F% r#< VTF* j B: TD>Jhb &dhX׈:ژ D4ZF\r 8  V~Z'(/#j7(@*I)BR*Z$-`/~e0f/Pe,ja&\B\VbZQ .M&dHA49T/(Z$"\ڊ $ Ȱ0fDP0z͌.>x,zp"jnN 2lH,d:*vxhސ@b0,>Dޚ P\jX l"z & :)** n) &(8 '< 'p'& x%"p< 0 @ Rh   4 dt~b8zX>&~ f & f,p"VR  N .2 02  F| RZ Nv Bh46B4H0 LN@ F4 D n| $ $ Z JX@^^hvl ޲d0ߤzְLRߘ:DLH&n<2 v(r "$ FTRr>: d2\.NrRՒ՞Rnjlۂ`<8>f\0~~fj|j0 0 x68"t z &  (  h0ZZP Jh(8 T R   n<T @,! @dD n!2*J(ZlD  ,tJpl2 ~~ rr  |* & P6p^ (@  (r& ~. . P  F,  p 0 f4dR`    & L8 N^ 06ht|| $ ":  r"T$|rp8&HlR> VpTzRN<|PF"*x,`2ތݨ~0 4@htB r~ ,d \!jfP*8jb Z RN : 6h ,rjnRlJ t>H6>R.b "X6< H tz!'!)!'l$l 6R&Z^x, ZT><>>P:lN`N&l@ֆFlִTݬ^RچftB z Z r DV&\L2"T2zt\d  0r 8@ h R L*>>&4 V . ZfJP L @ ." 8 & h~n4 ߚtݬ$x.ZXh,l  vB D D  p H VFVD@jzJ zDH:H | ~ X  N>L v DX  > V x "H Z6t>pF:4^ Jn(P`XPXF~:d> V@X > z 6! D!DN:Xr \8l". 0 | DTPNtݠh~nאr2(`4JD$8<P ^bn r^ np4ߚb0Lnl*H6&pL4b&*8R6j$,nZ^^~D: 8$!\"<"b~"L"\#%(|R& P*4 v~|t6 p̪ȄƂ0B2ºʶF~\¾d:\$0Ѷ `ؚb(228H:L:^: (;D n<  :@xv8 6^  @ p2"J0$D4D<xNr zn r  x' >*8'D n\^*~v`Zn``$$ r" TX J"` 2" f xZb(("*>\ bNJhN:RT6,6**P6"t(d~ FLt  P  |.#x"\D&F  " ""#$!x| p F : ZF6$>ۦt& ˴ xLHxXj՚pմ :^*vXN`&F NBx # ! @ 8>N:(`6 $ 8 R  n*P2" PN  vH( d 0 x:6J :TN,* "bD:8D6 ˸` \Pʰ^NբԌՈԈ֤>ٖx6Bb*": B< !*!*5)B -zM,U+[+2_)^_\(<]~("[f(Y%XP!VWjU2QKfvCP:$|0f*&X< ~N@~ʄf(l^L۸Zߎ| DZ@"0 p\ N f  \(D  r V l@*2>$:4޼\N < " " \8~"N J!& x$ % $.#""#^#Vp#v!(v b ^$t|b  l4 X"d\J|tZ ݴX܊p j>xN Jb6RN jx dBbT~|v J*JV"Z<td"\l 8J" ")X'`b:$x ^&D!P v2Vp&@ߐ$D6nF6TBNHH&<hRF! D!JXj "f p tfl \$D. l lvPNXdV TP`r^ 6 VT  zT&zH,F > ~ !| z tdrZ PLh(6޼,~ΒZDZn~8Ҹ ҹFl&FX ZӀ J !V)1j6$ 7P6\ H4 t2 J0 -+(4$ |hj Xxp`XB  Lr4 rb4"b68 h <| H jX( Rf0 >z F z(:^rB    *R b  2tl<V > @z!2%d L'.$jXp jl&N4<n .zpr t("$\!0r(tLfN~rpx~$Ll.,2(dvl 2rH6HDRr*|>:^b:J d *V 8"*@ @r d T$P  l ^  fb X,`d<BHվz \rB*0l$lRBpvlN N"l#!@  $  Z 0x,X^|^v҄ĺ` DH<:$(ƽzF$̪ Ӷz,$-F5;<h=$L<z:*86x3jb0P-!<)%n$$Z (@Pzp r ,pln2X6RTRlP |<Z <8<4 $VZr  VB~,: b R>xv. .v ~zRBXH   F  z  ^4P\~~ Z T @ Bt@J&PDt~2<l JRX6 h0@rNHz\|R@ ||&zx8߶b2v,HPR\Xd( V:! f  h <4~ >Z rz(f"N 0Ҹ$&®t(LT\D٘\ޔ.N *ߠ&V d |ZZ#"(h* )^$ ,,|^$",L  ".,4Vdd \ d. ^ . ~ 2",!>^^hX`%lL) *V"*L"") N&"d H D vP "rnbH۔8Ζʼ>t6 T֔Tՠބhf٠ZVjB   X`!J!,':*F+0P2*\Vb'@Y$YJ$X$W"0WWbNVSjN HTA8d.P#`^d*VH&R|FhbT԰׸hjP624j T nRxJ@L&(P n(*V|Bh, ZD V*^ (#v%ZV'z'N'&(8&%$ #X!V< V 4,@> @0xdnX`>Rx " T :j: b"LVP\ \NH,V8xڪ4֘<8hފ06XnbPh^ lL>"2"t! b!."X*jz`PNz| 4zJHjR> :&~nB(jhZ0@4HL x2*P>2"fP ",%%n!,  f2 \DbDH * J8`\PT4b$~јN|6:pnʻ됸j钶ƺXr `f <  Pvn0jZn|: D 6~v$@nVpR$0 D"P!|| * @N$`tT  T \ b d * DH&Hn4&6.&xN(ԂZۘި޸^  ~`4 86X$6(.>(^ % " $ ~dLZR\P02tt""rLϜZ>d  P`L`( 2p$P 2چTDN6Jj N. |  z b& dhJZt 8* D>T n Rn "rT  >   V^  *L "d4`dVfvVx6 &xHj.Xl,6\zvdNht J+2*f #FFx'+P(8 $ D:8D>ߎdV6ܼR@ڼD߀.B0J&Fb0$ .>nH t"!j r N,^ x &~dPB6jF0| D <x 8r4"x20,6j&  Zf"\!. ~,` j"8&'%&D". h4&.< BB4l~hל*F¼$Rz40J*མΖ J,xh>DH&0-t2.4@3Z2nv0- +:6)> h&`"Prh ZhdJBZdn86ێ`ݎR|D*,0ޢ   N ~ ^  0TP:| * p>68D* H  hp V .@T6h4@ l"Hht& r$ * 6. n.p)N#h^rZT(tt&4F:B0hth@ ތZߜ&j2h*". NxT">"DV  d l4 p ,V D Zt B 0rf^݆n"FnFۖߘlbX:Z߼@ߪ޲ \ f~D 6 "#x@#\Z". 4" ""<" H  D2 :|"bh .Z *PnLP\l44l l(Jd0 0 D: P Z66j0R@ L |4j N߲FdFbr~Ҳf՞خ:rߌ$:R L( >"\'-r"6)B\-M^.W._V.Jd,ve^+nd+b)`%] ZW|S`NHAR8`,-2!6($>@>2JlL(ЌhDؒ* J@4nHVX N(t2vX @pfL^J"r6f4:b<>*","LlT 8 F R  dV0 hP ( : | *   DN"z^P(@pfӠҢN|6ۢfߴ <v>FR . | @ xbTD ^x8BF6Fl h v , 0 z > :n|~  * L P \ R. n8Zll N|8HJjB4>>6 $b*# z ( @ V$T"b@  nV*6b՜8NZ:8؊\ݶRz tn|f(xLH |`Ljz@zF!##JX ( :8|PR\ ` :hJV޸F߾H  8 bx.$  NTTf P*z`$#" ` *(P| 6$$ (l'l#J v`\   <fv> J0\ `>&.x~vĨ,ʮv Tfאdhh '0/3^ 4P :4 v2/-*& (.z$4R> BF:<$:Dbv\ؘx*fx\H8|ۮpN0t nT  J H x`L  <@D *&`6tp  *@  Z 6 P t *D N d  & D ,j\2\ .D\:\ d<tR #~ '&t"pH "x0n4dbz,R 6@\(RFvzxV4Z (,&x R hf: | n `.   T>B\P0 n  0pHJ ^ 8tnj(RZ@!\&(0&Vj!:JHtdDD :hj4 $ v` $HV L ^ * $&,)'"Zd.Fj H$&8'.$ TPFH ZJ p 6.N,$hH*n~߰fjNpͪJӬzݰ^&݊0ތrn^ x > N' "0|'9+LC)FK'tQ%U#W$ ZP%\&b^($v]tYjT|N\ GA<>6->""XD6`"^6XPҰfP`Z8<tr*(TrbH.* > 2 ~$2,HxR|0 $ۄLܨnXdR 8 \ `b 0 h!"'(*V)` ' $"!bX!N! z>~V P R  P <  202\ j d6^  "R  (.V^l`fd@ \nt Brhz:6FzPdj"d n 6h * 0"$^ vt n|FV :^h|`p 2$lvd*  z nDP XN Hp~2 V"" ~*nhX*f <> ۰h`z"TB2*: Lܘ,ݰt2 PB ~\#V#z$' *H4,fTl8z* BDB : tpv (@6J  #'z%r!h 0h!\% >((*t*b' # !!l *H rt $n r:Rn۲Ϯ̬`jN̸*̼>DJzDή.h$ hԼl6#+@j/"0/"//X-fJ+)d :'"L^ dVtzP|:"2ٶn,ߢ n( P LVn  ^:6 T .`x,fZ:l"v: ^ 6 ^vF\ ( L 6 $ N@: L` nt2  B(^ , ~" pXߎߴN:<>~  X$L> x !NN(& n)<P$Lpj*TrN~v^<4`fV2zFfh~N&BzvB, jl ~|"#~ t h p\$  BrhHL ">\^ `N(TB@$FH.X^̆h`0 "6f d!t$d0( * ( ~$* @ 0 <*  D `l\r @(R" bLBjHH|r\>D<r B> 40%$>\ &~|bzhrPf4:ZjRl @`dB`*ո2h<2>nNΐB҄פ٢ڜעذߘߠ"`|d* 4^X#N)X:0"82&6A&`JX&Q&.X'@]P(_(_&]#.ZZrUQ>M dI EP?6h+ݤ:8 Z B> 6`Ê׶Z4XdNx\( @: z^jL$6l|Z8r2lXގBrHVhb~bN .F"'*,+(% .$x#P$j$ z$ ># FvH  H`  lH>:(DV& 0 f J| f ^BPt"~Nf x$NH2<@@D>h@rL bF \ ZVxt>0Xl\ xvԔܴt6ܾh4hԒTٲHxf28ZRtL r z pp `T r" 0b L ޞp֠FT4b 4jbf N ( *RFlHL ^ ."~'>'".>d ("$>#p"B!< J @@"V ~>`ڮ$>j,`|t’2꒴F8Ϣ \ ۠ ݆4ݔ! )(D/2J2D,2 0 . -,,+ P(~!,v  v^Jv,BLB\rF*^Z 6 rL. HzFx8X 8B 4r`:0(,b j" *H  xDJDJ0 X`z*   @ J,hh,LPjBp@6 ^LB`l"z&L($ 2,H..(,t ) '$ $ #L "F L f N& (*>R0*@P$z@|&Z$ fR\ D!B'.(l$" . $|L:!8 . 0 :,"r*jj&ӈ>~͞ǘv24\&t^T !" $"%&H &:':d&&#hF2.". B v dD:h(@NN(0 ^ %HV'T&."&(F 'j%-Z&/$8-V &\N8  @ hv n 2.N`00 ܘ֠ϾtѴҘԲ۶xRD8z@dtl<zd\ J "z*3#4=`&pE&Kt$O`!QQxQlRbRfPMxNH" xA4:8>3,*&> J^.vL˺Ȯ,pɢfrڨ,ݤDJl  |$xvhDb jh (   (vtfT$40\@0 ^R  ` d~ nv  F" b#* d 6P   j Z(rn&  jH ~B8@p nBHrn4t"|Lv4`BTvx x Tt J l$ \$J$&FBZNTbHJ,>2NfD~2R0\TzV<8H,z , l~n | &p,`dz t R D8|X &|t (4TTd0(,V>P>4j 08 X F r D XT  @ J f& hlRZNj<޼٢֌,D؂ۖDz2\l&.(th20^bH$:8"+,+)t+. 0 $@hz ^Tv LR b$(.t *"P6 n\(.0 2B@xX Z&$H'h'>%8" ! #X ')*+ +(>& f% h$ !R  h T"vNb*\Z".P H^B0ގᜧЬ\,""Ą$zDz`˲ $6,.1161"1H0/.h .VF-@!H)%$#. bHX  x r>6P$ ^N4f\B@^Dj D: RN,.z \f L*r&* xRf(z6dj~8z& *" \ R  &$T8!f D#VZ!(| N`p~0 N0H: \b8| x@ % *v |+ (l#x  Jh 6 Xllr p r.x"JD@nbtL BNl: l $(R.2@$@ @ B> r . : 0ޢd2߲V^^@|vd⿼(4b@Zl H,Vpl dP6t"' +r,(L# z~.`(0P8 * lhV h,tzjN<F N2 L@|F`dD<:Hr J 6( lP,vv|dnd>֤lZʒB6tƌ xvV$Tވڞj&ft*4R"r N->'h8*>B+fJ*P\(T&~U%:Vb&V"%.V"6TnRN  J DD|= 5f,t#P*LȲ"P6*$>۬XlNJ b>x2 z  * VR$HT$4^0*  H\ `JL>xb~zZv".@j D `*  @#@< R| DRpf|,` H N0hٸڌnݮ ,^fF<.&F:Nj zF,*2B``th&xn$ n#0|'% *  @ Dn 8\4h.vF z  0j( $$ R& %* $"\r\lP PL@J2*H^frD>̈ɰ\Bֽ<&䯤嶭 ꞯzZZĄD\ ӲXn!(*`1r4*6 66 5D 3F 3@ 342",0$+#$P  :, `   Z  ^r40nT&PtjP 0 <LxD4$ ND XX\X26 l dd& N $ Z TNR$`.j8  X^.f    "%%>#&&|B HXR$4Fdl  l 8hb>#%~#RF2hD.>^tpLp .p0 VzR2RB\6> r0v""$X r d&T+ ' X  `dR JHzߢ8\j ׂlj@ʺߎb>fȾ@ VH@^X n6 l J::8 !6 )<+&HrZ@& d &n ,H XߐRT0**p|`,JV ~$$ l :Tz@r<\ $l  NP,P2LB0&߆JZjbվd pBj$&"Tx0 tL\<!)( v2%<&D$JZ#PF$T&Z4*n`d,d+f'dt ^LW .R MJ8E?Z(4'tdpd`r\lr~Ş ۔@ 4j tv ^>Nd ~"H6V4N2H<*ޜnt޾،x"^zj $T)*T '6 " ! !f L# L% ' j'X%N h&   @ x<  D lD :pxLl* T B>80ln$TBLjv .J.xf&b$VTz(P< 2  H db.  lp x " *  2Pn>x>:r<(^J׆jݴۄR:Nrv<\ t8 4 Pr#%n0x ,.D"Hٺ(t2H`V|BTb~T.p|^j~$nTV !#(`H R fj҄B֎hF:FJ v( J *.>Xbd rp .v!)",*&( >#""j$< '(,h...+&!Z>0(f .NdjJ<ۚԄP̈(f’b6Z`4` 6 TۂDݰhZ#Z*V./8 / J., +**<b(("6\ z,ZNH8,"P|T t .2`J&tbl\^$0TzZ&`zjZ  6 p~D ~d@ 8 p0b0h  4X p6X H X("R~L:x N*X^^ l"L&& |*R.P.F*d & "V(r 6 >zvRf Tp(l((*L|tZT>(~fRV'/"2&h/Z#) $j  !:'6,"*#$P  H  > Tt8۬ֆ~$":zj 4,ɶz0 T R(J *H p#8'B(^%J 2" 0F\  p "n (FpZt`82p@L~2JtT0(8`L  B& fZHlH  ~`8l(Z^  Z$DN`$LҲقD|x٬bnB0&|Zh" v  'L0z8l#x@r&G'rNd'S8&V%Y%0Zt"YW\TnQLj :G&AJ;d5B-F&j јh\\j`ξ:Ӟ|֠נD8ކ*xR`x&l8bv\^0 h \>t: *@^ lbnr 8 l$h N&PX Nxd6~&:HX~` h( Vt&:z&ll<h~T(r\  ^L >L H@ @x8t`NzH*~J,R@hdvX P4 x  & 8 < ,& vH fHF,0 `z lznܬ|~F j@ZVP\fh>X|R@ v$^6l: R 2 8$P$6 b@"F d t |H::^` 8 :j& HH Lh<~D@X b8v٠.(D֐ܪ0FL0, :0TJ t Rh( 4 \HBv4 &L&jn* ,."@dR"\ Hx 2$v'&0!N  "**-"(! zJ. PX'%v'x* $2N2\Rrޮ$J.4 pz8$F,@3F7t43&) 88~( ,R( h($"#X, < \ې Xx@ ^x"J>(N*'.+#rTP`PX"R% `%"R > V \@h  (PhxB*@Zͼ$ʼҾ&|4$vܠ޶fhl~:X$ \ZZn$+"2"t8T f;\=@"F&N)U)LY%WvQ:IfA^ <n9h614)~pt4ndǀ.J6|D&è~R, ` BD .N .:z @| *| 4H 4~NBݬ42۠.z(.Xf ND l 6 ^ nBv&+.dZ-n)8&hJ$B#! N!p!>!&F~r f:  t| `   FV4Nl4NbH:| & h R.plJ\4\L 8v Fl|2Dvp>2X blh @j Nh&V,"~<LF8Pft r p4 |>TBv,8 Jބ٨Rx 8 "*n*p D| 4f >   *NRv>F\&PݺZֲh|hXڀhJ*0J(Dd  Z \0( 8~D.<JP V|2>.xHh~֪Ӥ>֖p4Br0|  rfp`nnf | 24 p 0 t&*|)%$ :b" %j'8J&l" >DBfj\ JrD<"$F R ӎ8@\ D|@2İɸЦ |,^ێ($,+^/82~0>+"(`()lf'H"  0Hl4ZR(nv2@Jf&n0:*& .nT @( |  , @N&"BtFJD$ ^p|<ntD*jT *vH^ "Jv'z(L & ! z 6 fTrRl0|d ~$(%" \ N n<%:(T%!X2<P  0 \ fN>Xϼxɰլ.Җ߸FhĈv4 J.t <~ ,F6`#R7"$.dJ"z XT  `"TF r ~ h`HZl~& Rh"hJ,Hf   #!$#N##~! ~ t!T"b"&%&T'."'&d%j!^ff& .V6Rxՠږ2 $4ߚrڸڒޚz:.Jx(J"X2J~bp$|-6<>?lA:ZE#K&FQ(V&X LVQK E?81~)z ظ Ѹ̠2TTȪ@vdx^ӂڜ"dD4V<Xzpzx*2P<xvN>2TbxBZ*Nl lRTH6* v" < X \ '+r*p %F @|dR2RRR4t,   tp  r~H"N2XPrZ6X(p4z P X|HfDn|dFFXl(HN F X6 ` N ~tT^<  4  p D ` @ p v @JND(f2ޮݲxDL`*ܼTPd FFD&`x$pz( B ,^ \@ T v", *& lt>@ L ڶ^:(JR@ڶ@HJ"ܘ&t|j6rF&,^ p> ^ B  f &l%D'%0nz ^df` .(6~ߺv$؂V,bD2vJ. PR 6 :!$   꾰>˨D v Ϩ&l-^0:21..^/TV. ( !N& Dj f<:p8|h>|h 6,>v| 4Z VH   jztj T J , t<" l  H   V  b   X ftb^f(D"x:F,2ߴ$pjn` . J Nt!|&+ - 6,X )8 '#!> b XlJ@\H6`zX v|4^T0r2*(N \lHd(&)&(Z$& &,R 6#(F)h%&6\THT *Db t *^՘v՜t߼2(` Ĵhp: `L@~<Ft")\0:3(P0j|+, L'#v"| $ @''JB$ f4|.\  |* $DvB&H\j|b $ ,"6z#b x.pP,@N" $'$6* ")F%<RnJP  nfxD6FLtP>ϴ̜֒ӢNL~ݾ۲bBlh~L0HHx0, t($b06<CI bO#S&W,'Z$[LNZ6zVfP RIr,BJh\nԄZԒn"(@l(@\ \|TB J d v4.n(2vn\(vL r,|T TXz N,\n (R8V 2 b RfJ" L"L 8!f$<&"D P<Nt   J ,JZ>N6ZBt ( L n P6 Z(RR`fzX v" > HT :DP( | ,* 2  : F"2L  TX0 J 8 ~rN<4  ` L & ` pv\\H*p@"TvThpN`JR:F|N  $ . Xf^* Z  h2&8 bTPPNx0׬*4 &>V8\ \޶`BzZJl6. $N D $ ~xR&|d.f dJ~ߠ$ B b|HjVp  V\ 06N j 6fvn6  % (^*D*>($#D#%.<$:L Z D ppp>^dX:ɂ$Vf뮺䴱Rf"*^VjTŎ06'j-\13T3,1 f0P/n$.@+)Ld)T%2..N Hxx x4pxB"װ0٨rZ$@B *B |62 d|>p6R8\P(L<  0 |t <^J @pB `*jd vR t Fr`!""2 !"$2%$F xJ z|p4:@ܠBD @z,T4X Z " 0R %(j(^&T\%JJ%v%8%#hXbZ^*~H 6|ZL \zPZZJ.H"h6rN ` < NxV * T #Z! F B* Z`jVz Zx>v4@nN:LZǨ&p|  'Z.. *'dz~@( *N "TB B,F"B& < (J>xBvt6zfN` rd p8x l ~>*J5"7@1:(: &Z$,#0$1".j(!nD  R (@ 4pZnLj $tzֶَ@H"8|4nj,x6RP^L@2P#0"*"/3L69d?G$~P&'&WN&@YX!rV:P IRHC?d;R7D2x|*j!@thβzʚ~T446Ƃ(6"L"ZJX  |~p xz b&fF6j\D@lZJئ՞ؖ:D$` H`&(Hx :%<(`'.&V~$">\!(!#6%b$d 6 X Rj 0VT  z |<$*P vF, L X |   xTH\vX pB @jtBb8zLHfh DJ\*J, *t|R  r$  *~ R~ N hJ >$  v  L :Bv ,hr 0>۾D`߈ BH$&TXX<Vے*@  6 :Zf~~@ `6$x<T HFJ8f"x!#!tD|4H . : $<<fl2 NΠ$D:Ϟ͘b(ĺ~慨P8іBՄ 2 ֦ |: %~,^t2Tf6f874  2V21.-| '$|!n^j&p Jl$ 2 v,L&t,8P" >LBd :||J* x jJjNt 00b  H06  \p ("zh BpX (    RrLBJ  pR2r& V"J:(V<"Hz. ~!TL'$ (f ~&# l@&B.$>"R0nr,LfZxxZ4ظ,P:ݬ\N"X20l hT!"BV: ( `X.r#x(($v (N:. p <lX v0`Zb>NJhZ4">@ͮDݘ R^^8\~"R\)*6*?1v@/8$-#*  #8))#RH :V DX ,h&8  >t xfR~P $V nr x p",xj0~.d:)". Vz!*%d', l(&!BX4r . zT$6(PBbf>͌ҪVՊԀ(d0( H &|+.V1*5\=E L vO>MxHrB< =Tx9v5Z0L*f"N@d  P˂|ɬL$RˆʰbBl&RnrVzn   d n> ,   b rz""Nj`n6 0.^l^P hHh >N @ Z4 $&*`+)j%( !D  * L  "\ " *  >>T( 8l    jnFJPV R*  ~H * pt >fV<HZZl>.Rz6p|hz~NB`(h2tt \|( B\^&X  zjn  | l D th:4 .@~NH߮& vڜ~nݼdp ddf 4x.`DnXh$+V>+ ^#j<zh pZL<ND&\L*~BBR۪l2*B> h > N"6 X86VpѨ΄6҄P$R~lHHNT\`ZfT pDfL   l,D!h $|'$) 'x# T8j.   <~fh.">FŐJ딸x"fȵ.:X( R ,ۦ",4n:V< |; 09n 7D 52 -,HB+!v(n!"xT4: RVH$ (zpV\TlL20bvD(x (B  j ` hj, <T4|\^d*Vn&H&PJ Pp$f b4XT bH@ j$XB<F XX |HJX^">'$ (-b 0 1\ 0z.+~b)'%#v.FJ `x4 6Z8f*Rn|.nD|l<߀ ݪlr8jB|Z.20tL2rT ZT>` V0 6 r!l4< \:"F v< ^ DFr.L,B8Rz6R6L`n* RR4zpvB 4"+~3 5|\2h-X b( % &J)|Z,T+,$ 2xZ F h&Ht4d>PJVtRf J#X(2'p"ZH*` #&'**b-',"(!rrt8 !j Jd00 xhnLަв>(τҒz~ٖNPb\2\8D XP  B'.d4f:@F Lf$LR'V )zY'~Y"W>TdOzJ$ @Ev?x8z1*#zڎ0&X>Ȁ6˚<v,f߀\ p.\>.(| FPH|L><^ 6R8T~x(hF^D@pX޸|6"\D @2 L ^:  #f $!(6r>:& .bvxfZ&b& X4XXfXd 0~ J(vVd fj6Hv"^0R 46.X ,    (| Dz*l4<hpx*f  > RX@` nd|hvFX&H B6$ht~ \fZZ<6D`r bR4:     x 26 \^>N <htDRٚ "8hrN""ZPشZ"JD~*LD. @ ^jH\,Nnt :(2v^,tXTR ~dN \f,|fT$ 6 # 0#rp.|t#X* /01: -.(#"""!2 Jtr: \L6^֜vԨp\HϦF$224t4 "&۶ J(0V7 9 7 54 Z3t/L+)$)r#&#v!>"  |N> r ~z P z84B`:jn^.nd l 6 *fbD*< "vZ.hbF6NRr|b(jV4Z*H  J"* ( v tt  | BV \ 4 nv d b, 0VVߐPPz"< NB,b FF(&\ D  r!"<#x LD@H&"r $\Z (xlr|ߐLǚŲD* "hDB.$ 6 v+1 /:&f  Lh# @)t6'Rv d nZt*N: lR $~NTN4h6@P XP%R(%t^ ^R $$('L(x'.""\t"xn t$Jx8ܒFJ(fhhrR B4.T j Zn"v)T.:0r12&5 ;J D#Mp$ZS!SPJD ?:(6 l2.~,%<D VrʺnBʼʲd̐V jVt2 > rFJ ~ \~.8zrXD`*THbD@h~|4, f ^ H  J#H),v,*h& ! r ":hFlj  0 ^4$BT: `Jx: x&l4l.v t:R\42  `n"|Rr"xZndl`>..J&R 8   p b|zhj  x >n f 6.V|xXPbD(Zr$<dVdh0`^t (tl`6*&FdV&% 42| X ppt:d2 ~ܘT&$f\~۠t,B4,* >4 Hn $fR^"׌dJr:p`ݠ*f @vl>~ b0p^ F|@(l<* D `< ,h&X$$!% `' #PVR   ~:d\ n((`زdd "`* >fʐH n0V0ڬ@|#*h1786V5&5,3 . T)&z$2""tf & ~Jh l | ZBF:  &NJ\ l pdfh 8 l .X  L  r>"$J6v>4 J^F(Z6 ~  L  z."$ h6r `RR߂|htJv~L6 8r,\4!F'z ,(./:0&/F, Z( %@ #~ Zj(hLz" L|JDx"6&:\ j`br,R N !&6$<!:f d| L$~$(:!$ "  ~&N <   xV.$~պNrߠ٦ߐێƒ&v¼"Ɋ `8 Z^ f Nf 8 :|J .9";X$J3'24zv"6J*+#Z  D p f Ztx$@ >^ .R~ZBT$!l0'5~'p4 $.(># !"(,%^ '%))+L(^+2"'!&~F ld  &|@^0ۂX$DT(۴N݂hzP "||"x).":1z2j3 8pf?! H$N#P6JMJG"Br ?f<823D+"&H,4z ZҤzЬ4|\d(ώ$ r*r4\\"h b~hF"@H ,b2Jv0R*  L n  02"l & :) (b 2& "vnLX| 22.   <,v>ftt|$0l Zp<lX(d\XL <Z^h^P \F~` Zf T 8N  z 6 : z, d 2 B@z&H`X|"4~,@FrvߒdD*"dZD`d.d.>pv  $n& @J " rx"Dnx,hn,``ZTPD@\ 4: f j B p `"~ B 0&( bTV`XϸvBNv2HXfdBzlb4:( $ *  rLrFv:JH! $ & P%z !f8XJ | \`l4` ,ϒdˆtʪ2z2H4tLª**| H F BrՈZ"4v*D&16 B9R 8 z7` 7l r6x1+tx(nT'F!&##h, 2H nT NRn*N\H\":N"2 l6 >&, B8^&  , 6XF6"$VDX8V` B L. hhTR Z F4FP ,  8 J|0bbXf` lb T $nT '2.&33Bp2.6 * "( &$ % ($&n l4:.v\F ^6tj~0nxjzn DZV< 0$&N\#\ndZ* $n)%4p $L^ *Zx6Jzݬh$D`*04߲<8T.t H:$,5X$x6"0'x< J v"D*4b, '2.B p xNZBN8 .^v"z*j:4L<4 NP f  N pd v ,2J!.2r,#P f8 t~&|#-X(3'4"/'p NZ  f*$2Pr(X$4Jr@2 pl&p r 2$8(:+&-F/L3:DpC#2J"LxJRE R> 7t3D0,8'!(`n^̒bά* *.,&z<60n~zF(|6,L~Tx0z8Nr2.@Bp,N .V&(B6d`Pl N! & ( $B2 *N>&n.:  " FD X  h ~x b>LRF~P~~.D t vlt8,|@, b` &&|nP$VPPbp P2vJ B ` H ~*  XB`$Df<Td  ^N6j jl^l~:*݌*~(<^0@Zv LdZd tjn V  T `h* b  , Nd ""nzZ DL2 J$J "*zVjHrt    bb  |T*n np6טnj\$`hBzjHvJH>rjT`>6Z(:06*"t(+<V*$ DHt4LX| n > h* j..tج׶ؚ\bNHŎX¦JҾ D X JPZܔ!)n05r 54 4 (5 x40+)d'%"!njL DvD>@b `&26JZ.N^V .PBT$  V% (Z *d + (d$TX<N<" x,DrJ\(.42"jlZz (" n "HBD~0L8> L#\&r$X N` N!p(2P,(!*)!BF ~Pl J  BXf`F8&l*n̔Th:@~RLZ> LJ P *0!*/'hzdB\dphl! : $ 8 v` 2R>v0  ~dnX"|T <$)N)*%h d$"'^")&%f*  ^ ^ l Pzl*l:Hݜ@ېݶ|ۤ*ܠ(Tl$LD|D2b'6/45z56.6B9?rHr!P.!HS>8RNtI. C>lr8 3-($܄ض $R$pӘӮԌz 44^ F "L8L" P\@@"",>>4$.vN2Vf8  > *j 0vB f$ )**b( $"*l p>FXPz RRVLB\fDN664:h>:tn< J Zf,r| & Xb r*,@p8^80PB`$.d V $HD  L ` Rptn*@Jf  P h 6 BB n><0dlNݶ|&DntzLn&jXB" h4  r^ ,  $p> fp *X 6݄x&b2^tj$&Hx8h  ,r z \|"x H H* |P( bv&pܶrӼnXL$\Z x.< L Z Jd( h!Z ' @(Rl% !4b!*%j &6&Z $ d Bv"F jVJtJ0:@rlƞr2ˢ*BĀ8:^B*HŶϞ > 8֨bHN&-408//p.|,J)%  z 2j 0&0ltxNZvL&N X0TvV 6 B \ ~6PhV0txX64DDZ"NN &vLT   &  "" < t $&(: JhXtܖn&6>DZjBv.~h8# *$D0z3:1\+ $ , ,tT| jHRD.T~ڀ\\&FHNT4(^P l r"&vdZ"8&'P&R~"\0dB  *F 4 $ :lp,:ތ$D&n&r lߔnڔ4بتvF<JVl4 >*D:4T8,!v4 0,# >! $" $  x 4 n(xz@fT*8b bXfb NH DtzF,(!"6$$vt$8p#"<!b h V  8 \4fR\^ t޶\ӖZXtT~ؐؒZ:ߺ ,0Rn"fZ x $.,NN2rP6P8:n`>BCnJ#P#FR\P LVGBL ?:5x-%8"6n H0j~՘ ҺаLtN@xh n^ >rXbB~ RBFX.Bl.:f(^dP:F"hz`p40hf ZBv"&~$(D'#~ x 2* ^$l<T> 0  lh B   t P^2 nx*"@  t JZ|LH08N, \ phb >pNXN2Br> x @hL ,~ t  r  ltvd,0x~l*ؐf`FJ$X 24 p ^tf j 0|  \6bfv z !P62 xv p  FLZ@XV*@غ^V(,4zN~:0xZ   r ,\.:  *j&R b 28H6Vhx>>0ުH:$lZZ6.Bf\2~" $ h P RjT ## J#z&|) ^)& j#!4` *fX j0~ 6 ^0Nɐ*̌"d>F<d (شٜv׺"+h1Z42|2405F685& 1$b.f *.%!D  Zz(X` d vZTB@DD tH <P\bxlrJb|8Hr82r::$$f @ "V d  <  Vpx Z<@8"n|0t޾.lVޮ``dl^@X  #:>,rN0$/'*$&*%B&+.13#2$+ v# p * : 0f^@pF2""TDD Ph"&$x:$ #d"##T#6!tjB. @  Z<$ג\FBZ>@B4Dnjp|.Dr  b^z &,1j347;>lB*nI"!NBNJ@FA =L:t6X/'V(( 8: ~ڴ: ւٔt& 6> 20|Lr 08 2 0*t|* t~P&`4vL\R~2DV* rb#%TV&X$ Pv \$2Lx ~DR (. bD n<@Br&<$0HR:~n>. ZxߔbbNZ*D~x 4 t 6 \ T  t8\|.< | . f ZX lh |vT\NR8r>v8Nt& `T" ,h x. D4 lZ|p!b$d %%# : PLd <L^b0`t|>.Dz¶VpZTZr暶PⰮvf2XlÆ, `8X JNdb%+/00v2F4 1D,j ,((<%"( Hx xvt,  6  l,<N$PHnLt"jl& " xbDzV0& zB~2 |2|\R\~.08&B nZ$ d R l&0FP !N! Jl .P8vdBTz z tt & 2 \:x!&*(-//, (h $ ^" t*ddH R2dx^fvdzv,B"ێx`Rhr2jr "P$b $n hB 'N-!N,$"d x^Z8,ZL F v*vќ.ڴv"0߸ŨT͈f BR`B `nR ,d7\!8(2 ( d*" J$j b  0P&lf4bD.: x<86P 6 8 t(X#\"*H&+$)<2%fl2L V"@%F'&)"l(X#p6 X  L |\b Dj&BPۦڴܔ܎p>ݾx:ۤ܄n\Zn.<8^41..J+)~^#(ڌ *DԺՆB ׬tךpl8<*`v. t2 vvb "t FR>L.<tnZP*,6|2 X0N 2 r>2 P T  < h j t nHNt   & 4 $4T<J>::b$R( H0  T j &| X"N|>BNz@$.z2v  dD\ r &(8(bx @ F Z Pr Rp PT6~P,h*"n6F $  X v$ . >  hf| d "D2bvF6|&Pݖ6:$, (b8|4:Rb*H*vT<*Bt"6! 4  ~t>Lvh~8>zP:RfvbB::Z rbr r\<#%`z$  HnXd*.nvLz` r dl(l^Ɋ@,xʊZ ĪH툵옲pP4d:J Xnތb'n.F124j52->* 'L&&%"*~ ( R  Z 6d ` vP B^Jz ~BV xBT T  B\( dVjX6b@$D  ( JP \  | D$^&$L \ <^88.\$"v :t&bNNrLxD*nBl$H )\ - -)#vN rz4"$b6> |6~bNB<<` ^""48 ` 6Z!6  $<+,b"( ( r < ^ "b v D L< b|b*:PB& \>&2B6#1& &F ! "8 h Bn04 ,&  (,BRBZ .\X'^*)&~#R!!"#~$t"& %X<$ DP( * ^:&l&"\0bz6߮܈8TD t݂xZT>\2 & 6  &z0*7;:X829X=CI.L\JrF@A =R:r5/'z4 BPHT  $ۼ ْ H(bZhтжT tްf p4^ V & 0 &((.\vx8f$:@l*\|::zt^ ~* DJD"~% ( v) 'H% #B "T,,vnJ ( pd0Jb RDHZ626.&6: DRDzH>` jDD0."|$$Z :f"^VD P R&t! VdF 4 |, p`  h $LB.nBݬۺH$ϴܦ֨pHx8jJ\Jx,t|ZZl" P 6x>, *   r H`T ,h<, pB2HDhz4ޠ 6&.&V8~ :\  :   d  L \." L 0N` T :4R`2f@.0*0 0`z^6rTޜFx8Hx\^,bD 6n""!j#$%v,'(rf**  )4'#'|"'b',&H$t!HR^R j *8&Lj:" ,$| r&Fh$0Nh 6\: F8b$ X"*145,56Z8;:RAFBI4HE\B? L<882 *x"^rJVܢ N : dztԘH&xV@^r * ":&  @ 8D r*hvJB* `` fX  @2 TLLD$ 8N vLfL H < d | > NB~, \fjh^(( \pd2^LfD4$ "> "Rn2,< X`HvVhFPNfjV0L> @ nP \ 2  X@ H vn!%%F"`^PjvJJ, PTrhHLxB6, bj b6 F j "RJܢP 82D`N@fZ6   fJ ."L 4Fd! (V, .(-^$* L& $ #>8!`n"0 b l@d r x4~ٔZr^ɠD8*HBhü  f\8#(*P/d1<1V2h\6N8Zn5 / *&d#  6J nP^ LR>r<~(Fp`R  6h8l@,$~\BJXfp2tpZHtBx ` (ftB  X. L 2 ,J n4t\PzpF(2*( Bz.Zhrx(z! z'*/Z6:H:V71n+.(L&r $2x&P rplDF*hR&2rt&6PN,(Vr8% +#+'(0&# t %|+H!"/)|/-j*r* !: H n bv  ^\J b܀ݜںb&,Tǘ@Ŏj݂n:X:rbnxZ  ,-P n&D 8(>D. DxDv|  bt߾ـ\׈8 "Jp"T4R " LhxZz@ !> J !f *prh 8 r|@| Ԭ L*݈60߈&,0t6(H*4PzzdhjV^lx2t 4  Z` ,< |(T lr>n*  F LlvV8~2 . JbXBzBL  &t6 ,rf~L 8bTVRL$ @r22> 8r zxH*:l^V,fv\ z ,r H X 0 6 " FR\ P628|,Z~ >bX֒*hٴ68f Db  H ^2 6r:ZתրZڎx&R4zj$(~XXfRj.z` 8(D"! P lp P'8 .f3664"..@ '$$d%>%."pR@ \ 8d Xܴ֪l6f~4\<B@пR€b \ю~D"x',$1&3b4:$7|J85./ *)D(6&# V @R n 2 d D R @hX* tpp &X d8~V B tޤߔX~  H"D~> %DT(L(&!rNF  , * R!!Nl 0PBfrPBf B`Bf\"R ~f| >(4f1 7(5)-`!%<h P x%-~0 +j!#"  z hL6D2 Jv.,V`F`$\)Zx*T('.&%&Bh(('h%@! Bx    D"rr26`2pԞD(4rpBfBלn..>D DR   %b ( +@.2j7<@? < R:v 828~7Tx3-F%b, ۞J8b: T׈Ӡ&`fj>$ Z66 v " ,|px, @ &F(:VJB( l:DB 2 @ 2 &l"% & $(*~*)H(r% h  b~f&~   2 <vxf^ B &0 4PJ>j <|$T2 f  j Fxx`pD8,r2(" ,J^LPLv   $ @p b ~x PR 0 t * .N | F p|  xPRt6@߄VߠޚxӨߐߞNڎj"x4|Jތܬ.vVDvF$dTxlV  8& p dTj   r  ~Pf b>۾B݌*@T"(B8@4F\h" ZVr~ (~ Z0 R x h R J24L`TlZLnVV` 0| >RVbft4,      ">~" ( "hP 2x nJ" XVj6Jd zlNP 2 ,4z J"H  4 V b RHb| TFvxhD~(\f@ V z v |NH`FF"R `v . Tr  P r ^|b8Z8V> D|% \,3,:?!@h= L7B0ZH,j (. Z% ! .~~jnD6&Lbr X: *\ DfL`vP(f` b pjB44L < $Vn  ~F v&Z^j,Jۤ4ʤ:X>\$ت NٲZ00z 6"8&,004X1>1!0%-r%B*"!f& !v ,zZNHt0ܖZ2n vNxx ,:  |$ t D6#%#`X<|rbHjr v jFj4``p*J"׾6&^؜(ކ~BFZ8l"T"ZB02\ 6 Hv $!H<)0Z1<8l=,@BtCvDHFjIIId*ILG jDz>*7T/l(d"hHpZB~ZN4z, ݜ DߘD\ 2 l^D ln> Rx ( P \R,8H>6rb`~T&d"ll<|d>,(h0fL> L  @ $2N"|h \D`. r @f zNnPjh<0x`2xJxj(l(FJ84 ` 4&<d. BJ 0V24|*\lX 8   `b     ~r h4z t H  6H 8Vt8 h@$0@XNT.j t~Z r R 6B@   N \#L@ h*H4\\ pf2 ~j $Lr@f>xd|2<p4&<Hr 0  L h6 R^HzFf Vl l|'+&+,/F324V1\ &.+(%!\ 0:f 6`"6 J b0@F*"r|2Jn   4R> |0 v^Z4\ Z  d:DBj l @2*  ^ p v >R v^ ,x* L:JP"<,ZD @(b&2!$>( t- .-@ )$" 4.\h(6F$tTtH xrN h<ߠz Dtf P 0nR!#h f@ t 8 $%X %H"z!4 D :&( @ >Z.<2&^`"زڞ6P< LP\zLP,"Z0\ J ,24#3D$,$ Z'L./*TH Dx,8j  &zRZߎZ^ ,B2d f~fp|>:j> `j$| l~@ !6 "!"8"$ .;`5.d&@ h޸dݼ lޢ r, ݄V nhV FP\ <R: ~. zR L@xLN RhDJT2 . rf|!%R%" X zfL  n:2   Z B 8 0*2^l`d4& ^6 T:&jfvj Lj FX f ,~^تH4zNP  ^   rd @~l>|   T^ f Jzp&Td^ n$ l8 r P` V, D 8 (  ^ < J  NZ`Z`4`$" Hhnxp .fZb"<  bH0r   v R% &T "2^ X&@D6>h v,ܦtھDپJX>݂P00Zx l,\,. h (*/ 4Ht3.j( " ,^PJ 6lHD !z (*%n t  DHB RHf N`"|~vR$ XX .@$2!J\$^N&v'T&"DB P` v 0 V ,|Vft4 |RbfXxX4Nx"$2h J  @ & r*x,^ . 27<@"CB@v > =;H8R2jH+$B8F`V|FhL Bޮ8 "|n PH d t8R^v8 FRL PPJ:>rtVf:Rln dRp" X*N#& ( &) ) ( % @!nD4l< v &d,@Z^HHbxT,. N~ L`hd r,0,8V d J`x H0& DTHlF(@    ^  ^B!t  d @ JB("~p pn $N^npZn .@:  zp2LѪ >V\t΢ɖ.Læ|êdτИ PT>j ?;5/H, ) j'#\,(tz~:\H&~VVV(2ljh6PTb|0t *Dt b V%xP%"P !%JP)+*' #2hZ b   LBd"V0  Vܠ ܠ zL$.@$۔V r ^j:*1v"1$-!%T8JJ *!l*!f  X P 6 `phۮٜۂ\$,v &zr~D 8&^ :X"v# >%\'*-:. ,'H #,r|p~, |Xz$(֤֮ZώҊ V*TB@Nۘۈpڨ`Trh"6,v , x6&v, f1` 458B<vAzEDB@= ;n9"5"/N'n p@tH4 ^&*  ~8pPN: p`4 bLZhzr(xfJ~~~XDf8 dzH bD \dZ(j^!J ZD(>~ LldR.l d0P8~4:44  rX JtNbt " j 4 R n 4.(:XB2Z T.@pXbrB$nf pX4Btv F|   6b* ~ &p@ B*  F^VnfpvJZ (H:v:<\ D(|R 8th DP Hl   p f4#> $Zd 2 . l8ݖ&jlvrlD~@޲B~$R &L.B Z< B 4H>x\^ B"&&P&6 "Pxp~LT0n :>PDx R BVV|ђ& lǀRɨ2b*l󀹾ය$b v H˔͂ز '+f,P,N&/T3z66^4z v00,d(J8&<$ < (vT   ,\L  v  0LT& @ h pL&$8R~jrhL4< v<(  : P^ V " B,Z"Z #hjJ L"&L0xܲ ڠ(x2d 2~6z<" h+3,750 )8 "JtD@R0xJfߐߪnXB@:F<݆zܦT6(zd,"@bZ0f  tJ"T %$&8'h'%#$(,b,>,'n4  Pn PH 8rRL`8|><4j Xl6׮4fH" <d$^\)0*f'h*#6  rt# r&@& FN Z$2PP*(<6"*\z$Z :  "%h,3L"6"v7V4-D%L `vH! ` >&6@@.D&`2نܦzلHF܂`@>.ڬFݬ6.V0hxR 84j! %'*/H5:X>?>z: l7 6< 5 05 $2.,*#n> (tHl j ߴX |vؾ ׊XX: *( n8( 2H $nL06r2(Zl`d$FN0p>n J  4 tPZ6  J!,"& "p V B x 0f @ L*  < h & @ <j$ b|.~d.j$ ^b x  bfN 8djxV `H &pr84x"jHNp`\D`hN` `>vt v fZb,X & ` * " j 0  x z @rPhdHpR߰hDXdޞ& ܜv&b6 x6LhXL bb rV Db HjB 4$vJ0\hF R$jj.0x">v4|l  h t@ NT X!%v"l0FV N >>nVv4TژN>V<tVvb  r<0 " ~v$62F*$`) l+ ( f#FR|(djpT V0,- )&"`8 PD8">ZJx(jvv$<D 6D>6F`. xv LDd8^2&^>h$pX88.P X$   xXj#j.)* &0 ("  @R  b  !X2!zRnv.R""hp .J@v%.,2(53/ * R&d # !<P r FV:bVr2F2TܐܪfژJpD4v:X28Z h\"$B0$>  v J ^ J z n Rbj.bh0RHz"ό.|VZJ:nH&27P"2 d)n 6$ *Z)J#zj|z"&j*@DZ:Fd|ZH$@` x > ~$nV()R*Zl+Rp-Z02JT2/NL,8)&B# 0  N  TB4b4P88ߔRפжRDlTj08rJ>DNp| r 8H #4%b& )/`7D?xB~AD=h9, 4h1 /+H&z@4$BjVv"%'P$&^#T "NTl(  &fH26@0pJB~< :z \b$ X" j6 XdhL8h~ tn^tl$B݊ N28:8 Jf 2  Bl  LbB( j H   B 6 & ">ff(Fږ FHr(.^@2J,((~6\J p Tx> * " V <.j @^h X&:>:v@d^ zxnz:F <fBnN h8 P$l`d @H^*P>b: ԤJ~rftRhHlX"p" L n4^~*D  $H n\NZ8#' && "4rj$D p| L|D$2>rDp(FvlĆrP@ôFP:Ҫ \ J> ՄRL$&&b'|()z*)(%B "J.tl 0@8THd R ~v  h D~ Nb&\4Fj  t f t"*p>RN:0|0^ 8ZPrRn`&f . v D &!8(.)J%R ^ ^ v T  T 0z  Jb<~Bf (B8.8"d"n,h6N<X>L<5.B) &$," &\`nd@l:n"RZ$"XR޸hpdf\ (݂ي4ۼZ"**: 2 ^ ~~0"zr%#H  lZr0: d b <~lܜ\ݶrݾrppܮض(>.,0<z$f n^ #(0)(& &d' )(*b(z!8  P\ tNrp,t<޾066 ^2|rfNn\dN" )$0)6+9h)6 %0&(v!RL~" !#"6 hN02r :t6l0nݦߨ:th6f$t^0X0 vLl : ! $'d*L /V5\8 Z; <<9T 8 7 873-X&z.F .  0ތ X 6vT\&V bfT< & . n l4Z NpTJF\|l`DH6jHp*X4LDT"8 z@R N ~ hjL<Hn.jb4 TlpbBr&TDHNFF$l^Jt0Fn d  | j ` Lb(.B>0R0^P<Lv >r~4zl(l6Tt & t p (   <. J !!| .(zd d^ ~x , T0XlRz6|*nvvݬ.ݎl~dN(p  bL 0 p^ X n H x2 ,V4B>0۾<>d><߀X"" :(0F(:6bR8~ ^" TL0 h r|>xdۤ~ Hf ,0:z|Z    $  ~RD#L# B8 t&X+ ^.f&-( $n|~2 Hl , * |L 2t<~ަ٦غ@ذ`δTrl(̈́j F v֪0ߺn <%'F''()(J'b$j f   d\D X68 <@x40(*Zhn d b $"j(ht&ZB>vhr&vZp\X8*F6 , b  : v f j hv 6$@$ .j bJJ nLLX2ڐTݴڄtl6b hF~R @@TFR`$(.5$"9z!9 5\x0,b+'Zj%x# !jb~ <Z"62l2$>*4$TdD2|P4xfP4 6&Dph4>(*B#Tt&>'' h%\ TP  !#!v|F Fhx* \ $,$ jpHٜ.ނDP6ڶD٦ت\8@Lz08\f !|" hH.bFB! t rzb J݌*FB"xHNzV,6L.F%Z, 2"H4^ n2>,%\$F,&.bn|z :jJ:&t4 ת>bP,d:X*zT2X &`j| Z$ \"~&B)8 p+ . 28L<@x@B>JB\?JL n\>6&F  N4 8PP r 2n @ l ~T 2p n p  D`pN*@B6؊*NJzՎt2l>nh\ 4z.&T 4   l> T ~v FN T^hd$ , X>6V dV 2*@ &N  XH R 82  <FX.D.4Ԛ٤,|> ^4"frXz".4T`*f & f~ X |lR:%+- )R"rb:zF V 2 . 6Nмь6J&^zx$\>dь  f`؂`t#V' ("*+,\*'0%# #$#`,`0l> " H JP` >jfFXDb   ^ ^," <62V~">vV$LZfT$ z4b.Dh XB~<\"BD@C?&=, .< r;d894.&j&:Jx*߈zߞ ޾߂p^ r`T~T4 .(b:   V |8$4|4|^8x.nR,znPzxVpZt2B~ `n f p"">  4 (! 6$ L ,B N(<nH`(*>~0f&60j,Px<> :  x ~d : & l.B.\> 2ۀp"8$FpDvRn8ZzB8j6 r $ l##."8~ P  h"~ NL4p6dtݬ"j&nx*P$<N 4jf .  v ~\>#f!$ V 6jt $j|Hh2T&z@>^z~(xF2 ZH:. .b &0r&0 $.F(f.BZ^~ldФ (rXTv 6 ll@4R@ ,,  <N ,B"2$! 6$>v 00~t߲`$ xȢ\v(RN".*j0n: $@n~نL$2'()j, /P0Fj/.,'f 0$"\!| , `l T~ X6  V R4tx t  lfX4>r j( rJ PJ @r8rtlxH&b@z4T"6\ Lh   0 &dl"#rx!b 8z D@Px \ ^ >,* ߪx<H$08Jd\T2#J +44<? >8z1*V %r#(#N!Z d:b$8R:>Z~@t:,Hrݠި"Rjz`..VfrH N:f  z"" ",j> P ~"04`\ 0J8xTtv< z!t 2,"#X!@B:n"$ RN BfPTv(ۺ`P xN"jL&l,LN" *&*2D*:7)"8%"4 t,4#$jX~T!Hx:D@|j&vn $@FrDR$nhlFvr`$4 `*"h ~ #'~+ @@? j<:b9h8;4 < FPL4*4!4$$<~&z F( ( &v |" \H 4X\6 Z   ~V2jTT `JV44("8 8 ( >FT*zv&`<f ZV&"$R(v&n\>  HT j4  HLLvXZ"   . v v r  J8 z@."rR\Rnޖ8XLސnpj Jh*FPZ d BL |pl>80Jft D . 6 NXb,Xlr|8R.l|zѶpՀ4z^2\LZ46lV`* 6X b, <  Z6#"Fr$F~)B* ' "V`, @ ~ l2 \NJЌVό(pήtɞܾ즼6> l . b  `ϰXB׸:!N:#~$*%H%$#:x!"`2Nh&  x:$nDxV@tZXH`@ xp ,  X^6z2dBvh^X~$< lF24zV ZXp   RVr~B"'6(~$ zL^  XDd BtLH܊$>V^nz..T^LV j2v0"r0f#2*$2r7~!:: l8`3&\,6&# t! "! 4 BD$FB6*4FxxnFF<*h04t(b"h@$XPB  @t RX"\#" T r :NPV  $x Z>:T$V`TԀZbتd^n4N(x$^jjb*Jl#X &j&B$$:D$v%Vn'' 0Vp j 04,hF.f~l ~px$fr"` J~d2$+!0 0,p&XTH(r~L >80"\TPrxp.D(&BZd0jbN 8J* ` n&^+N/2 6:>VxA0D8hFCbx? "< :V9^61+v#|b ` L ް Z`H *RZ b|JXh n| d" T.nh TphDxhjHTH߸N,P< ~pV. ~Brt"<&v'x'z$hd>r B f,$DVlLr`6v,J64 BX2j  @ b `vJHp*B( z$l| *   zn0\ Z 0vxRxn@ H N2  p P ~XRBNbl.dޤ\<~TLppLj (,NZ 6 l Tx ~ 0 n2  *b0b XR @26x&.$V6`|*HlTj @L^VLH B  .$fr v < \^|H"jx"@t66ޔ2bP>$V.\d4t L ` tP d  $ " P"PBV"j'($t.p(. H 0pf@ 6ۮ6Zh|NBd^.nX|NætL ~< զ n&(^ڊR\$ &"& &Lx)h,-, B(8r$!X$ <`4F >p: x . $v  ^BL|p8P ~pvvh  trfr|8rZr8jdlpxL4 .6&f 8 p ` v #*#H   L 4 t x  Tߞ&Hpڶݨn.*rB$:< hH<fzZ.'Z0n55^2+$X $.VN0 B(8@ 866\(fF@jV ((D>t4& lnB 8"f',"@/"..d)r$!0 6$ (,,(<`` DRnlL^ fP|T"B&߀$V\| z 2 %&`,#l:#$^'t' pZ Nlr2 vb$8^&,b06T8~l J&$ -"2"3!v0)"$H\!X#b tNRFV6`t~hݞ߲2݈p|&>tf>\p l(&! %*F045@ ^9 ;0 ;" 8:5j4x>55t3.'NX*t v F > z 4d< R @HN |D&F (0 f   6*BjrhX^,\p>$4r jh<p ! &v+ ^- - ,x (* |& "J " N( (.j & j V"<Zd>j6t@~& L R F ($ R4 Z J < : 2 $tx~~x D:V&߰(Z8.Z`JPx*N@, ~  j ~jDn*x<p.ۄxݮ(xdBj(մzRݔ*.b  * "*b2+ .%*.Xrn djN~"B8X $d4V \l Nt>$ r"!!' %BZ  v`VHݔֆ>ծP`*dNL26Zf"t  f  ,86 6 .(f H hLb#~'Z'`L"xzDdx 6dpr^(HڐPjАЬzNpL^*TN섽Z(<|>̠z` x $"&#"%'p)\J(~%4"! !B! z PL6 T  j  lR.JT  Np68~x F 8 86DL$Vtn@Bj BL   (X 0  j HPFj .') J&N!N4V&@V b4$ &~bx :PF >.:!>"D" #(0N9?A>9F40z^- +(>#~ vd"@~^T:H$@Hr8^L@6B04fD( D*"  x hZ!l!H! !b"%N'>'# JF0&T & f &t&^( &^H (* Hh:"!B% $!zB h B (D0 ^F , ,n|! D 4 D< t F Vz$zR`&.0 |nL:ٸ،2,>2>rXnX \ 4lt "jB(-14.7<0AxE Ir,J84HE@DCJ |B ?"9N1d(L!  ~~((VRJD z*P .&4BX L r P br&" L ^0j4$ f.fXPBTz.|j.TrVv,h!|%Z'(( 4' *%f "D 4<H\>z * N    ^ `P$($V<*Tp8N&` 0 ,PbLb Z :2 B H zx4LPܜ$^jRjV8<^x4 ( B V |j  l X H@Xz"Z^b   *R<^ bpF|zVFh:`XLD<.׾ڠDH~p~FXnB\F |  dl t4 DF t :x"D b 6j׆HpX>:ކFr&$x N(FT|\RD f.&fT  ~4 pF0 J (d " JhTd(8^#t&l&B$"t"4"x! : Rpv 8|6p>\VT*|n~~ ^nlL<f#,B4 :r;@8f3 ,&#`~!!" " BJtbNڂDۮr^\2HPl<,xZ P0 B% %!DfX:8% r'$4 2 * & >6l .ݒl6x\p n޶068j0~<,NT<~ HX ^ B8L:TB$H^(6\J6 . bP@Tf|P26|*<: d D@  <  " `0v6 *  T 0>@NDr,^j8X$ܚNۮ.۞>X RX`vF0(ݚފ~:hf4F   >bf b,Xd vVXP0HvbJnhB܆^6ݴNbhبr   *2$f|޸2&\:F4,FޖJXt.d.4P  L t ^ z    &|#N"J2 rX nbDx 6d,>߶Fܚ\&"Pxn*>B 4 J *%, 30885P1f, |(% #^ ~"  `n N^hB |n@|l~tLpd8.dTPLj@@@bpZ N,, 4 v" Ht T"t # %%Z0&$D"\l < ~ f H dxVzhآtfd8<~۬6zHBr h P b##.t.vD . Fv.4 *Z4t 0Pߖl҆DӼx8H:LT r:&$`BHzfn TB&)F($d^ NtD t z| p ^ " d  N :*tb0 ~J,~ ( .>P T 8 |> ,2 < H xr,ܪzH٬x\04tBh8  X |V   npjN x  Vl X~F>PX>NPh~p^&8pdTp. z 8J  :2  6BP8X `!p DP p P ~ 0L.NެޘJV(ߤbRB`:nXxv\p r.HjH4J zN|X @>L|x|xTFZ2\ޖ d ɜxP6(L~V\ 6 x,F ^ j VFr$zZ!$(*R(""0 0.lJ * <$X 4, zl@ ߐN@ Ϊ24,F@ BԨ  ޖn#"'(*|^-/bX0.bL+ &#X^""" V0  P * 4& l4&b*. P  x ^N "D "J24Vp hXBL|xtHB v4R B~   D d(\*~R**Z 8Lj*~xpHVPvҬ>ь.ԚNjRT z N n x$.5P5/%rh@RT Np<8.Xr&0( &Rbnf >:!2'**'   llN^"  ,~l 0r\~Dی@"hߜBd H,H #D&%|"v ( . tz `z b2(hL@@bB0<  LftL>D$$**#00.#h30 b2,l#V < n   ~(\flTN PD:ܘ04v(6NJHDd nr x80@4|! (@ .V V1j0NP-xd*X(Hd(+ N1443-r%. f d X ,|| $2|%:"d`&,jjx"lx^2@z0 l^hj`f6@p "n,z.F  , T!B$t&L '^ @( ',V$`^: vRznj4:"l0bfd@X0ZVL6PF<D: x6 b L xlhv0j R 8z^"P`~ސBV Bt2Xx xpRT$ " bJ ^ R8N  @  ,@2 LzBPbӊѪ@\8j FVH`x&p.:R ZB  dfr 6  6R  (D >n >2p0~:d4ߨ^R6 t .LP&RD&b    d"TVJ<f|R: 6V ޮ6H  :~Db^Ѿ6` ֔6xǜ*N@˜6 Ҙ  4 hz(2tDܖ $B % #Z!&#2%H&&.%#B$!ZdLv8 ,r 2  : X  v|j*  |  rB0 j  l t ^28xz tfR:8:>:B " > Jrj h  vL"H  (   <(  LdH ($.,86ӆ&t\>h<>bLDvrN>,! (01:L?j>*903h.* ( (v v(p %@N <>Xf8tVjJphrH48Pn~ H:0 $z, "r(#!l hd2X"2%p#f  @j B B t^ 6~D(pV2\tj|r^.~ߔBt f\ *:ZL4 *!D!6 Lr& :p" F6T& pzp,r^DD$,2v@NT *,n24  :(!-!.t ,'4b!f6 J^8 *:ZPj Z(xؠ<F >z`H^l  F !p$Nl&(>,Z0F5& |9l |;^ t:v 8 6 j7,&8 "6^0(d LF\ < Z$ b|| 2<Bvl2* v  : b $ ~ T F`r ^(Zjf~ D(dx8 (| 2^fz"2%'x'&$!fVn h"P2d|tr,p"zZJrNVh4HjH(, > f8j"Ljd B8&x PNBN T4pXH4@Ft|V6D    v  J<> JNn\  nlHn ,2b,>z.ڮ(~$ݰ*܌r,T.n"$" Jtb:.04x j d( vT>\&2ߦdߦxJ4J0fX6(hVfz" ! xzx\&TT2F,Dh^88l4R4nt*   tBd  Z :28!^d ,$"* +r(V #4X4NLX.Z B &V@^~NԶϠ\8V込t:$ʼ4 J̌̈́db6"#$f%6&2''rF%2": z&2XBPn D2~T8r(fxjx`DrTv ZjjZ 0 R*R hx46Df.P< h>:8 Z2     V R\`v  4 p\ Rz ( |  ^ |Zp .lxd4(R# +bL5>"(D@#$DH!l@:40-*h, D+H :)B#| ^vZ"2blH Z6 ݾ.ތD>B\"*JH~0<rjz  TB:  R|vDrb"J"LBV@BtdvLlTt߼HF T <jB  p#" < #6#x H n pLL R jpTb2r^p6(hn2 J <d Jj#8"*:$ .<#@- :)"0rdV,|p0X> &fp (>xPLBrhFD,B8@:H>FZ  \2J *p  z 0 0 pP8P(H:  L0 jhhXF(Dj&ע 0ۤN8p$F &b 0 l:f V V | 8lh Pl Bn@ 4   r ,^xb`ZlR\frD"Fx8(d N"LD 8Z   |  h njPf.\ ` l f $h(t޴8ިP܆۲0BPD0rdNPlH x0Bh FhFvn vB"v.jD( HZ~vZZt4"ffR|b *V > d : B0Bjz  v fnt%~( & F"8b:v >HH~2.Ptt$tL|Z4Hr֢FҦĐ\nf,:,,. :8v t#l:%r' *,./8-~(F#@ :f T L ~ z  x >X  :z2p.^ 2> ,B  N&HpZLT.0 ܦJLH( l V rJ & N 0  & , Z h t> v P  8 x, 6 j P.h::ߖ۸#^>X!: l5\/|*f(6( ).(b%^ V>H,4L.dLNb< ..:6b@v$6(>Z*:X N!$>!\`^Vn! &$ d  x@2BpLZlfڒfP:D^bxtPf: \hJ P'* '8 $8 D"j 8x$F" D:F>2r.n XXb&~<&%.X)4^)j6%H4(.>%DJb. ^ *NN,6.0tHJv0.\>@|@4Xp,8VbzZ<0 ~~lRP^ $ )H ." 33@B1D-*V((f**Nn,h-)f`#j ی* <h ߶d dXjj2j Lf" h 8 (0 "<`"J \|Zz4f\^dH(X`TR&j J.Z$$!X."@"#X$& ^' &$n zFljnR|VvvTx*$J*>X n"4R$v\   @r F vZ6h $ *"Z8ZBH޴B|dJ.nlL :x V  L & : & DxX > |"N B~|*لzB(fV&"^ڀؖܶ8*\ LJ . t  dDt &Zt f>V:^( (ptL>tf*vDvRF bp b^d*Tt "L2TRP|DRrT4DT$V 0 b 6xZ^N ,nh Hl 2~v6D, *LLb rZ F.F&D<'+4,(8$R ^  >(VH, Xpn>Nz^.f6>ޜ< ڬڬ"~@dzz!0Z,<585/N) X$` x! N B N :f $jB *RD$ JhJے 8Ljފ`N|86d *f  B H D \<d  %4(2%: h :jlFL^^xN@Z$6@DH dxj~ 8^x T&@~  < |L HP4 Tdbڂ8X HR`fh2xPRd>F 2F T T $P()<+,n/3t*6P7*6(42\3Z33H0N*D! p d@t|db BVlvJ ,xbX: F $ dB ~DVh*" (LPPX&R>f8|BP@ ,Z 0LV`ff2"!h %&(**)( &T # tdz b vvt`BT H("L~rbpJd|f,@<X `R:~ T J fh,"HtXTl\ \tLtz.2R&x $zFl.f6,  J>  \xj$2 *D &P p( R*Jl4JXH~Nn(X"֮rӮӞ  l @ L @j4*zx^PVhNl V* ^~"F8\n2Xb\V \X(L (@ v (t٢...Ҷ .bz`@ÌbB ВкVvh $!H"r$'('">  nN VNh`X`&B4nj>lv * j b 8(>x,nv*bJFRLzr$z:, j zH   " %,j.,8\)&%D%$D" "T*jغfFP2ܺ&j*Vjڞpr" (H:j*j5~!=$@!:=5,d & ! " $ 4!| T\jH6$ 662|ݲj߰ުަZ f*z. %"(%f8 Xb" '<*(( ~& @0 0JDz ^ ,.x 2 ^ R,X&:$RR00*6v8RP""`*nFpxz8jFd$rJTb NXZ40"L&D(~'"&r#< rb p,n&D<6FJP6z4X:lj`@46n\ B&px<:&*TnFlN NXFZߴ^DTd:*^LF8nj" v ppPL : . 6  T(<P t PP>|VjTT J^6Xx:R T B>BJR  8 ^h^L0 , 4r,pdT&88@:xH4V"ff|bL<  L2v 0F >@",X#4zL: !&^'\%!$z&2D6 D l l D"L*r` rF"ʮ(Đ8Th.ζ \& l ѐ Rφ F:ӀF!&%r%f#L#*r$&`l) *t'$. !T ~ \, Z h X X P~hh(N&. h6RR  p  | ^:<FNht.rhfvr$zv|$ P"j`^h>  ` p, h &Z T,~jR&&d h8 ߌ־8&ݠ@8ܜxd^vBr( <Pb(!z*Xd2p6N6j3-( $ L" " f"x \d2XrL`"$2fF H߸<$$nR,XXxP V<8@|"&T(l'4#x* !& ,D-*#x V x0Zr60P~VJhj<D > F  b V  d2"&%&n" P&\ 86 h XBrTjHdܮNNvp `>8||p>:DX$)` :--(+F'!b26xld H  LZ8B|>~$߄vܨdFnL(0.  V V h" &)6 -@ b1 h4p6$828*5v38D3441 ,H&Np L pjN 2 r > &f*6 lZ2N~ V L :h 4(  ZN(V,r Dnr z@~0dH>lb.:V0ZBl~`B\ n  l F "2 x . 6 ndX..ߪxjh l2 0| b@h  >L   T^xh Xb ( v b $ H * 6 XPpZLb6~F BfF&>bTr,P p 2 ( N `|`& T 0 6. . " N |\d~J,xJ~:2x`r|<b< 4>:6hF T|JN V4H4(8~2zbЀΪZ҆68HjvdJ 6T4:\@ 0 d X R P"p | d!  @H:#d(*,'&&"VX <VvF x :bl,(xVPҾ2"Vx̊^b2> j& ҀՂ֌ `#&((z(jV)r*+~),%* < \RN$:  pDH(Pjjz <  j6 :L x  j"XTZH:|6Vx:" ~H^L ( 4fr l fT6  #f  h4 h hB $d\ HJZ<"jڜ~8"xޜjD. ~<xN&& */X6f:X;83B, &,#!^""^" hr:N~"nۜڔl(VH>*܆N zz X "!\*XRD~#$&|&t$,N h R 6`hrRJ8rۈPDj4xHb޼*bP Db2lX8  &4(8&bh,N. <@:: \."dD$z`F2 .P>^z &|!. $85T$48"6^2+%0x, \ D4tLr,.DVf(|<8T \h "rr\bV6 pD'( ,p0"1/,-b+T+F"-/f1/*$H n( JT J L$xx *߈P& |lln~ |$  @(R<\z:t $`8xf: &Fn P| nn4z lPd!Nt$ ' R) N* (z$ *<B6n V,bP4F*|B6~z8,Z6X(8dVn ~@f|f:~<DD  j4XZD" (HL"j\Z`8&D: V  L TT d~& $H`*nR z  "R Dl6F"(ߊHZXFH4@4D\H tzB 2n 2z4 , &t 20n tRXZdJ2xZߌ4pN^Nbp J  |<^@, "z $pV fv~V`Ӏ>L2H6L@(|8  x Z> L |6 LB@^ LnnT!@V"8".L ZX:@DBpL.&ژ@dzr dj6lD fԆTb!Zl#F#"6R""T4#!> hPjXp f PF  hP  6 & j J 4 ~ N  r z 2 ~ t~ J`zTD(V.TNr|p `(ڊF>Ԧوj>ר*$ (0 )1<7961*~`% !x  & d ^ &64$\hrr.P^.ndl߈>frPR&z*4T f&V!.&j'l$bX" p# <(z)b'"Z vp L"v 2 8P>^(XtR4".zB Nt2d:6 T "Z#X 2R B , bj n:&:<< Bb|6\\": 2Ft& RfJ4 "|""8l!>"#D%)t,.-)F" "  l V dt LD@d  ^LfDh ~d v t n  XT   2 HjLzd*~Bb *TӶ~ҰҤBFpՆ|Լ|$֖b<," :F V @< DF t , &HL 64(pJF ߪ<&@ ݖLfr.hjrf,0P $J 4 VT\> Th0\460p0 . p8` b`ٞPx:&pXZd|NHj2 tvzx R , `p:# $ ,* Bd" ! "~ Vp ~ޤ:&06>.Ӡ tTϒ>Vtϲ"0r bVϾ@z (2&t4jDzBj<2zB t404 ~ L$ PPfFbL:P2 p x  ." $DX`R>8,0jjp>Vd> ,`:~Rxx&r,|-z)2%" v 0 x22V 6B܂۰PfBv4: 2P"f!$' -h5<6@? :zJ4*- r(^$##n!*Z|D:BXPhf~ނbB4ҪжӼNט ֔߄Fאb@ߺLrf zZ\. 8 ~ <f 6#"x B8>XLz ܾ٢`~.HߔV< < \> ",\ "b*%$J"r!#N&X*!,!r+h#~T f n 6(&v>jղע(TfdN(f fj(R,`||!N$l&:+ )/ )1(n/h$t+l%|!B.$@!V  jJpHn|T.߾dN6PV0l~(HTztX XH J tn " t&l)F,bj/2"58:,9v63 3R442-%jL d  r^\( xP N  ^$Lh> L&Z< X ~ 0$"`&x|L` ,P*hp>*nJXtZ8p>,lt6  6$8 &$h!X B6|. v,\D j ,z.Vd>BT>F n v\2>r  Rv z@0THXF& N p D P l . X240Z@2^*ݲ^", ތvb@ʸH"dD͘"n4> |zJ$''%%'h*,+F(j%j (# ! d6  x  lN`p DX$"xL@h Vl  lR> *DxhT@jh> :`j& p ^   >tV. @ 4 R   ^  , .hnPz\ ؐ4ۘ܀trBvtBft2" v.\, %N t-@4b&8885r/vr) `%Z:#" l#& " <V d>pN4XV,2`&<݊ZJD(^R@8$F J*L$(&p%!N 2$>". %H&.#> & 0  4" B\`rF<2H8(LT fpDxbf NvVB H  : @^h!%0^'$h08(r XjZdZ tL Xpzp V<8@,d  @L~|Bp#)!-".! +%FP &  p(Nx 4 HBfd"ߠR`zxL"fvf2tz zLTvxT$p(x,(/V22p0-P+4-~/@21V,H>%P`T>2\ nN :H.(b R Bh&. 6@ R^4N : pPBvLZ("&b~"JVR<nzF`vxfH6#V& %8#.Z8V `v tp|Dn4R&f>224R|`@:V( R  Hl* p vr.0|"0  * Bp $8 ,l|.fZݶlf0pjb&@hL>.$2jx< ^ ,N  ^  : LR `dX`x`Nb(vzfJj6ݖ\4(|  F jP"hlJ \ H@ h>|XDN&߄(HbjhrN6  z6@&j$f* JvBFhp*ی ԴӀhP>pZ$VrdN `f"r frv!$p R80^.$&* +d '`"R.d:b>t  < *| p04r~F`n P2֘".>x*\zjj@ B|rh #"#h"D"#,%&"%^# N  V ^p z | ~ Rz VnhLl"@fr@TD | x $ |VvtPj ^(h+)F%h! t `  |R^:4R h2$tF:ZV6F\0@FPx &0:?>r:3~-,4( <%@h$X`$0!JpB<,,.p \V^ xN HZ"8RB0h~\L z (LV,\d~HR 6$F)F"h.#B1t!J0+D%z"  0,4Pz@ vJ4BFdz^ *2\8> ztFxhPPn| n$ND2P >" (/8 84& 5j40Z+(R)-1f2/8x(pNT P Hn04z F* H\""BB xp h8llPl` $PH>P<:Lt"NpN6xT\ZXZ 6 |&Z"h%%$#8"l$|n N&N0fVL ^\rX2jB4,<n J`^\HJvRHTvJ l 0vJ r>DXjV.$$@X FH f  V.4D@H JrxzL R d  Z <,nT2b Vܴ"ڄא" ڐv08R٨D0܂L6J^pp j" (h, v ZZ\& bx |P. ^"p4T P 4 p\HlJp\Xv@ݎP"*>Zjf L|Z&H2.@"vn~plrT"ܖЎݨ˒n~6$:tH"ZR>"z Z n@ r* ^ F$#v2 LTr "b&t &* P"rZ dd RPF6> l 4ݎ"@ڌ `ܒ @|6(~ʀ: H ֬>V2<J<"Z&p'dP%"L"#%%r$D!@bz|$dp  B F  , B  T  < ` "T(V t`  \dx"2$x x *ln X: P   n `>P !l" \ pffP`* B~׈x(V&zd|ٖLn~* l>J".d%.RX8Z?"Bv#B!l=680l+((.'$8 Rb .Fn܀$`4\$P.z~NF $$ <#%4# jd0 >L x^"^dޔ6n&z&ݘ~2hl<  V  LHB ."^&4%L \pR ^\& 2 0H ,:r ݪpb0tXJHL*<.X<p!!&r&b,* 2D,5|*f5&d2!-'"*tbR> ,lP*H bD`dZ NF"Phn Pbh!6&R,/ x0\/^,('~)H,B.j,z'B f~v h n Hp\rrdbvv@r,   ln ~ fhR>@*`R*tVxd*XR" @l|h.z4 6D.  >"R#&%F &| 'N :&x#hd >< *2RvPXDF<(j,     X j.Bt8LV0.j6f & $~( ސ۠,ڰ>(ۦrddhhPH~PPp << D:x&F4J2,V6 h z * `` VB< >.x~b6z*RP ndF ߰0 j~T(8x.r D@ Dx&(lzN @n>b .d&t,,߬b~־ؾ".2lNL~l `h Dnp  d!PTxhZ,bތրTLݢ4hB^PfL`$^   ` " n t|BF xH,# %H""Ptp >% )L+*\( f&:X$xf &&p |n62 Lh0n0(l^~d P NfL.>~*2t`\v ʜҴ݂"N%v~#j",#`%J'v&6$|Z"!L !F b\^dJf4Z < t jTDn h & ,  |r^Fp6@~.`r"DhV. n   L b dn fht4Pl $ |^<&۬FR^٤.ݰ X  $ HBX " xj*1\4F2D.)%<#j #D!8  < \ Rddp"*nN6@h@8lH>626Hv& f <0P| *">Z` $@\6߮ޔ6ZHNd z:BR2|!H.!4 4"  $d 0j| D @bBj<6n(,vxvr~xdN8L 2~V"0B&!T&4+$0> 1F.J*&h$.fn"DlNvH@d>8ZpZ8Z*@&J\B\0  ` & n#$&'B(+\1 Z6 75,*31(22B1v@.Z'JlZJ >84 BRrt(HdvZ V@(V j R$f! ) .$|/R,.)pr%p!Rr"HL<z ^ b j,D^`pvlZ 4 Fn0FVNn "  .d  X $\  LH Zh P|n@݆pphn&r"z\Rd6 0  ^@   v.N vh tF. J r ,~ph`&2@Lzרd6Rh"tdv.r&"`rJ6p2r .,@!rl  4Bh*"n&&* * %<6~ HZ`D r &(<.f$,ҌTȢ鞼6@d̀ʌJȰz xDF؜^ & 0"%b&%#! , >.x@    T DFj:6Pz>Vj r@2VJ4 4$ T&4rPbZrdz6P"V|& $"  pL^|6&T%(/`l4.\4"16~-*dr)8N)2$*n*~ 2)|$J.P(dތjH <bBV*F" h .d! +4d;(<92+ j%@!Zxx> * `X<Jl"\n< 0N`ֺT׼ـ٤ؾ8מF8Tp"^$0   T86:z ^zBvF!~$$#j~0   X `p  6P2bZ864jl "(٤>t'++J B)*$b\*\n *X<:h ސ4j~`\T P D"8 %")0&-)1H,5-8+,8H'~4 .)$t "8 0 6Z(80xxPv0V$<4 "8!` "b' .- \2r 5>h4"2n/f,8+|,:/^10,0&6h> VZ  dHz^D L D : nztH0tf > . Th Rd (&DFPbbh6\Nj$ n!#n% P(*6+p l+ ) &z!R\  8@:|VL~|J n$ttj`<llD ( xh xx`D.|vlD:, RRd8T^ݒ Vv,  p B ^d6: Lv!ZN <P xB   BB2Ph 4v܄>Tܴ~jZlhJ~Rܲ&0h Zf f & 6`Lz0z( B & L | F 0 v D:v"dp2& ݲNp 2z J lt  F <D~""V"rdL:~ bl D0V|,ذڦR|<B`pF $JT<J  X .B#V f ^hX~jf |d^F@N2 VTZ8~x  ߈DDbҒPԲ 8خ.LJĊp zԂ Ԟ p ʼ Ɇ8 "^"2 @> T"#4"ThjPt|pl t l |`44 (D ~ ~ 2 @  |$ bf,4&>$Nn >4`z4F<<x  B*@\ #"(ZF r !!" J2*\@p: DݢۺV<^XBF6(V߼ܘ *d  ^ &  &X $'`"'!n2 h @` :H0("|Vjv $rF"~V@ <6dvN P!&&$,'1'~3#1-0(< "H P Htn4 < (D4Htfhv2H@td::ljhx*$ ^LVrL $&@P+./.R+(&' *&+) &F `~"& & 8Rl|z f! :zP2, l XZdz,fB Dr` #:% ' P*x P, f, * 'n#F`b Fh6$nB*(4l8L<06T$ t p j Xz *V r J 8HpvlњTDҴ*Xzߊ|XN$<X , f & X TP T Z4z p  6b.~.V"zRؾ,ۦxH`(PvL|DP |j brZ *    6N@LD Z:":JBNpߐ|d^^:Zfh xh~Jb2Xd""""  .$"LJ$f<|֐@2"@x\v~tL . \ fl XRrR , t6 (hDp6!Jf$ #&!&`t\\T 6 : V66܄ ftv ޒ Hߒ ѐTvrTHtb8͢:H BBF"ߎ"V#!*  f 6n"j.$ $& #T ,.|  pdH DN, ^ ` (| VRT lhpR 2 ~6D8t BZ>lP: ZL@D@ r.Nn  4 V v R \ ,F 8  @`@bv 0dڎ\۸"@"0 .F"< X$:0:=;P6/)2,&n<&d' & " V6:h V^dl2^T (h D #%D')>. 3 8 N97568 :<":5L.&xx@\t<``2bv| P^T6"""^T 2Z  ^|N `4 " v x z`r|4D.&`Bx6,XvDr  ,:\ @ $p$!fBjb  $n&zH^P bD ,z*P22 r h @zBr:Rv >@ZX :vJnD0*JJ&v JH2XJ *x߂ J8d `"~@* t `Z znF `N \@Tp| V Hz&.ߤBv`2XܪZؐ\0Hޘ޲lDj6hT|Z@N | <.4\ R bZ |P ZJnz8l 2t x%2+h*8 t<|H4|RbߜL(ZP"&Tv&&zp4DhP` zjr 84 f2 t`!'D*> |'2! z8L> ^ D r:,0"ܾ"< .J4˄vjx@~: @׬ d d܈ &)*+*zV+`"-.,D) `% #"$! RJx P0 h8Jf, dr v T| d @bn :" r ~\(>^,<.L ,PFbzr  "<.* h  6|& *^(&" $H#"J ! L$T Pvp8$`rh4<ӘJpϜpb`TH z#-h5 9P 7x2:*H$  @  !r Z  l&t  D`Rx(&Td:0.Bޮ6NjvD "v!T>R 4 $ b<Pnj4v >4(26(Zt >&p8: \r #N%Xd%l%&Z(!* -t0>0v<-'  ` > n >4B"vB،.Vpp6d|2 @Hzb04~  6Lz"2" n.!j '^B-V1TB2v/@+H'X%>%'fB)D) &(N$FBb . DB>$"v, `""84"!2 p\,*L.  d "Hl H<$40LR Nll&0&T<@N T$R!h&d))F`( V( P*VZ- <010 ,&DH0(> X$p@.D\Z@|2@VP F&<P"BL^,~  | ZX@Z08,*" ` hf &P$\,8 l@R:> l Dn 4b t:4|L  z06  @VZ$&8hnJ`N(vdnjF PZXT   ( <j 8 V hv.Vf(l&"hRr.:^Z26  B|b  jB<.j J|rl l4$(h՞^вӂ"vv@ T~ZF6j$ D*<  !!px 4!` Ll(( Bb`j$ ::t(B܀ۆ  |(X<ؒ P:($ގ،ےL$##x j~rxHDrn  ,0F0@d X n:~ \ L  B  *  ~.r:>:Xn2 VFTnJl F 6: JL@ :V'.1J/+~)(~':%" X: &6ݠZj0D,*"ܺlfj vR@&R -4|:h= ;d6r/,)%f $v&( &TV X@RVd:"R܊ކJ8z j$64r  xN>6N#R%Bn#VP "X &X(% R 2 J `4 0@ V@N0bD<"T LF @D|@6Bp <&'  Bn H l &nBD݀n 0jnTx"d d& F ^F   4TNZ4HjrP.@zT`$pN p B z &0nr2ft@ּξ>ͼ*2"p|z ZX2f Z  ^b h"$R  z"h!P |"nJ$t'.'$~ "<@42TR* | <r X& "݌T. 0 NxF@ H ޾ D  tBӶT!R#&#""t"x##z!X0Ht6>h( F  N  ,zF~\~r  R | N  ^ dF (d n B 8>6v`l,:b ~.xR$lp| 4X0lTL  p >t~#&P$z"d6!j &* < 8LR>: $4\۔۸|4ڴxێ2drt hRxV( '01l<8;R:48-t'> $ $p ')'(! *`FX,Z >VFlVlv`Bf<^2" 6x ! !n< 4 $ $"F J : R V|f\x6\n~.j46z^j"zj f Z*, F`@|\H"&<%& %h  DD88Txl8"v" &Pl<߰ x@pF4"T6LDjJP$h"*""-V-*%V8|   v .B  V( *@Xh@*>RX"06vrnd*> ~n!^". " "$T(F - 2542.P+)2&+p6.00-)T#(<,( F pP>4h$nvJP X hB~NV fTvjTLfF8r2vbNb0JP BPz"F"0~ *4"$ |'r))n *' <#~\ @ljlJ`^4bR"`&TBr@v " 0 (d` $X  Tx FB`b@LژJٸn^||J :,*B" *T . p JF| $ B * .v j  <L6,P>*jzڤ.0֠\.Z^2PڞxlXh   ~v x* $ $8l L <vN&B 6h.Xh$`hlxvv @Bv v  bxR B"F tNNBҴΘՂdjd df"\8P8Tp H  vl!8 ptXP0d*" " v fd|8 t:p 0(vܸ : <d6j<в6d  D@؀4j"T$ $2#P!L ( x :6d  ,r h" z^F  8 tR*2jP\xrT | ~dFd6p,$BzvX>۲RHH J4 L d0 | &|N V |V 2 !d!F \ D^ D` DnzNT@ @  !!R f$ @$((#Tl@ F * & :ZTP(D@h<"hx rd @  t  0  RL\Pd"*". %H,@"&"& B\*DJ|jVxpzp$rbHX8L 8Pf`dp&pv ) 0"4$4 %\2 -&|pn$! | b^``0b:~|2;63fL23 J5h252,%(VJ$zd * :LLTv4BZ!x&D %`@ ( ptf|8lpRjf|zLjL0X(XjPj40* v & X HTlt `n#!T48 ^b^T0pj(X.j| *6Zx, xB B Tj>rbN0  ~ N> :r~خ::dbjFnRp" P F p 2L ~ L(N d v  n HLL nD<$^Bz > N ^x(8.  h8~fN PX 2 z  2|^@.Dޮ^ݒ ި8Dvœx &f@.| ZVԈ @% 'L'H(j)+\,-`,|x)f&R& ( "+ x+f &$jxV<   $D 6<@L> V(r vr ," & $ (f L 6("bV j"t(@H`~hz``F$~ ^H Z D|8!T'(& l%"n%.&D0&p ,% "n |" ݸϚѨ ո`֖PӨp b4   , <\ 'D28j7(1D"( RR r f6 V |: VB@"(FD*F@(Dn dvRf T |"D& f'!b$  `" '))H&"  LD (XT,H B,:Pp4\ (L"bh Df"#^""6xdr > p n F"^NT pjVNR^N<2* B$$##F$)J#- |.d* " fdt  fxBl xF8>XRT("FPb@ &b^dLf$ Hb@2$H&+R.v,Bb't! @$*)~)$%(@ݸ62LT XD|fN 2 , V~4^L^`  X~ V \ ,H(dF`B\hf x&V~>*D4  N^"J&B('h&|' * $-/1P z14 .L)^",^ \lb ~8<V0N>Hp<4* jL  V 0Dz*RT&":(  :8|4ަ"܆B"(jx> ^x>BrbT n "#!@z0  l x L& 8T4&~$$T P>p$n`BH8nzxz l  &> ~N V hP* $z"0 n rH 0 bPb(|6J Vf.4. $ L|*t6,F R j 8 " $b  h!%`$2z2 l zd tH&*R * (P.&#Z 0" t ^Rd dzZjF&F xlj4x x &݄B ے" `v#!(zzlbFz  ^ vx \B0L n"V|^:~.0, < j4P!<> 9h3`\-)0(),Z,&DH(T~J: <*0n~ߘܤV"|2 v4&8\v߼6@r8J* :t *^ .F,j Rp:V" %|t% L n  ` N z `XBd ` Zp^xd0n60>f@0,  4h `  b2!%)"$,"*| #f|>  P tB Z6 6d6ftp$: FBJ T0x  ^f B~F6P$!%#,'3)6v'z6!h1@)L! pZ2z|Njzh4Z(jn,r`X~nnz\X:pp2@`ZF6 $ @ `P .R$',) *'TV$N*"R".%.(v) ' F HB LNT.<4&"b  ( z"^HRn ^* 0B ^$l0ZT,x`r8|x(D,x^& hj* \! .$ "( !P"&4),,*X'H#` &N: 8 X $ 6 , flT8h0fF   , @  R &~  , (   Zf 6 n *Fxzp*J0 4$B"Bݶ0P"<pB>f ( H X4lt ,  b @X.Pbt  F TrLF xPjV&|X@P,88&PL\pz\$tnzxvzt 4v > :dlDb(Tp4v$fxN4NX**,v. ,>08:Rp8T(.: : 2 pZlxB(P@ 88 04:`\x|d4fbx` TH  T n$  j4*!|lrB P^b* $*LT2  &vv D Z0 0b جϮ*˪jɆr r۬ڊD!%rl''&0$<%&N&|$(!lj H   ^DD VFLH    L|Z& 2 >  :b$ hn8\~TLxhb>d0 l l  j\,Jn J"#&"Z"  r < nnv2 PN@p< jXZ"XԨՀ*@8 n \4B )17f9&882* $Z l"" $ % !Z X|"Z$\6B`\(VިJ^ވ&b ܼzXߤ$> d8 l4DR 0p6~  V J#4$% $@0 nLF`FzxJ<&L@*v@*"`<Z 0   8 H.   #`b&t'"$ ^  .:~pjdRF@ڎ&:JLn46DLB&` |Tt PP !p# "t$'#V+"|- b,($v HD$nP  J6@phJB. Xl*Xjp"t4$$r@` 6@ L$B(( '%#F~"$#$v%~D$8"2TxN0 nB xV 6r,@8j .@ | | " F8 L*6.x| ~:r2"Rn@L" db vn !8!^!&f"%x* &/23r 0b*^">Dx$ |8X<n@,zfj XTZrjr 8 zp FT<8Xx` f<`Dh >z H < f$nh~X6"d٬یV^4<D"4TrP @8  ^  <R  Bl F~< , V(~٪| \6P~*^4\~`x6n *z  . F~z J|P (br48 h6btZ BL^r:d@<~ " vb (.  N $V)Z'$D<t28ԼzNװ"\:2D4lvtn 6X"$۬:ޚB0T $0v6Լ2ƺ ŸPpdDd؈Ң,̢ Ϛ4!8 RFfnxt t^rR "2 `0` J v T 6 \( b htVJt 8*tRnr b(@jf(Rl0!d)|/p0.d+~z*)Fr)(j& #XV D@DrtRFd^ڎݺf:JH6h\(N ,tۂr(V|Dbz.lژ(ܲ< ښ޴P܀$݈2*r .4.`dXf!f$$!,d 0D2BPN ^f0ߘPJTH ` Hj B  J!$T&X$(B(l$px6|  F h v,F`f"~H&` X\Tbpt!'-L 2P2p&/)!B 08 T0 T, \| 6tx0|d:ߨ$ަ B$>2 HRP@>* ^$ FZ `$`) j- 01-8*)>+D.^h0/*R" *> x`" P 4R!` @Z F ` . xN"J  8vvDZ4VvxL$8 (pZFj  lXXTLd|lF" ') |(br% "Xd BT$,n |dp&F2VP" 0$8z H V ( < Bv tpN&Fܬ^^ٔ^ 4Fjrr2 4* * Z $ x\(`ZN$ * dv  *~ d`LNdb$4VZ\x*^X>@*6NHl d  jJ B " B    X<  NRVbn"bDt$D 'p & " f,,z>F B N .Nfl: Z^\2N  \. ɞ 62RҐh JD&NZ#L#B#P"L""##8" v .$ zD Lt  F,| . 8 jvrj4t BJ z x   N`dpR zxHh@,پX$*L8TX (t"d 6 &d V $$2(*)V('j'%#J L,v@^p l޼*` ~$و@v@j>6 8VBf@@d$.^8f>&AV><7./B( b% 2% d'^( $ pjFR2~r&rJ6(ztVp^HVlZ,ZJ"bb\n4@!~ (& p B%h'J&Hz#h ~:@V ` & xf6ll &|x*vlתTn|ޮ>. >p<0"&'% x 4Jb"~ 4"4>x>fJBHj XjHd R( >R$!*#Z/"(2n 2/**$8Zptr H pJL0~D d Fnf@|&t< @4Hpf$+".,2^)H$& $#H%r)-8-*$8 pnx:,Z\V,JD: NT 6 ZN``p<^rj j>$TnPvV&vlHn|~f ~6B!"d"#v% 6(.+0, B+ '"` f`~f0"z2`z~$v bp v@   < X \ B p  v,   f ^ \4$~>  j~.,X8dܒ>@":4|VDp`t  t\z L6 d"Xj\R  nD840 N~F$ X|xtH4``V",tr^Z d  $&F 2: X\XHjjڨ^&NTrd l<`D "b fF64J8z6~rZN&hL vntP&~zn|l |.4l>lЖXfh.>~bv"N` Nd(\  >j&t$(b.& PH\dTx#& 8' $!,V*Zpz  D~f J.t hz>״j ެd (ݶr.̎J h:F Ҳ  F^l$j%#(rjhF nN!@ & |0>b&D$jZ \ .$ d2B6V.~ N  ~   V 4^ ,fR 4 ~4tL,"^0 T|P6Pdx p>B| "V |ll$ *p0*B' $*$$#Lb" ^ z h4.ٮj2,bT^>Hڐܖ> D.\ | @*(x'0584 @7>2,`'<#"r$H%\"fx rz` l^(`dnr۔"bJ$ߘ߲ޘݞFVZ^\" |r !  Nx^#l$N8 ` f r J *x V JnLt&$"\^@Nh( H P 0$"" 6Z,!F($-v&,N%#\: <vT* ,<:j`XݘJxL^R@b8Xf: 8Lpd\f  :T$4! ,r#1n#2h"X0>+$2 $$NjFX4lVdh4xRZ"bn@dRB0LVxplnTB"B h^XH!2&~*.H/-Z<) &H')~f,6.,'bh r lD8ZbH F :h&*n$0))&#D8 n  6j DDV^H^bx,,,jTrFH6L$&Bf"p \0:#%#Pp$`!& &p n+8 -:*T$T>. 6l 0 0Bh0fh :x, f  r *  D$   Z <N>NZ684@hx>Bb6 8|:r2V  N"(dp B R J ,  l ^Vt ^ (0 jb\X h0&^f080d۴4D VRLz  JL:vHdv\ h N$ $H. h4x"RTpZF B~ D>Z vTp ( @P|~4*#v&.D0j:'f@x * ZlJfLܮr|hZ"r 4FH 6R86&f FTJ X N ^\R` . n!rlZ6h,@ *0, <:N*thזxv .ۆ:xJ:4&6Ġ\ŶˮR\8\Æ^4$&%PV#"0$l&<&*&D& 'H(f(4& #fhHr B6 0.  `BzV 8  X\pDPB ~d d b R\4vr6:J n*@^Xj|4 T &^ fz ,"~~!Tt'V)B~)D:(|&j$&" Z 2 T|"*d܎&ݲT8ܞ"גئx: vZ. df*Xp@:hzJXnRb \"J@djp8Vh h&)f")"$ xpn BZ^2rzp0ߒ@`:R n b fB&f%n!+!/j0tl-' (( `4 T.`JD.`Jh(jJ*fD$ f\>bLz")<-N-TZ*,&$x#<%l)+6+~(HZ#FXH  d0 b 4 ll\Rz`.R48hvl| B\"v T>X`(XJ&ZJx| jL !b@!!n #H%(,| -` - z+. (|%n!X 8^\  LZ " zR(4, ^\ n8  nx b   v R2@j(`, T >8*6`|&׊NՐ,LT ^^ N0xl\(  D  h L  RD`L"H D ,tD4&h^F8Fߒ۲"*V.6(ېH۲ޞ`rTH 4^NV .v Dt0 rX  t&HPR: t Jhj \|f^N@ZV~&> :&H P  6j`f ~P Z)-R)( N *  Ft(LX">0~N$(٠ RNJL(<6FX\|X<d D J0^ ^ nJ2N.. "* Z"n \zl@ ljl,\B2 V"ܼhۘN 6b .fˠ~X F ,ٌJ> x#R"PbR@ @T~^  L vx J nfR .   VF (t2* f>\6. vR ^bx0Pp>hj^Zb b x fZf#+B*/~8.N*&Vz$""z! " ~^R :|.Tv $b$X܂pnLz>^z >$p)t4<r@B6?P0;d516/p-VH,n*%  : p rB0V 8$NܒLr޼܀BX߈tZ8 \v bF6v@ |f"4%T*#L .Hz  h.Jt>D$48.$(LNdhl8 > ^JP$P|dlh"F^'fp,F14|x53.+,h0X45H3|8,#B\rz Lrl`Xd>xT &V %~))X%F6DRTrn:" V\ X0~R Nd@F(NJ 2X,":n\r \,,~(h 6#%$J"&<hR, p<@JFH2|fD^ 0  p B R ^,p2 B P,(&L "ܠ^٘ ٠rܦrZ 8HDjZ < *t L  LF  `r,| 6V^bhN4v <f܀nVݸ8F. R@^ݞhdjFZ*"bd JJ~ D b ,L\ n "<F h  L`d.v.P2L`(fbz2XDF66,j R `<(|Hl  .FpޒH4~ pNՎPVN^`DHbHH,L B * F n~" N6 "^%@ %r#jX~V|RN "Nz4~H 8 :Xzݸ.fp*(8DĀ6H ӆ.Ԥd`R *4ڄ#@>%%d$$\% &>&#& `6xr@ p `:  ~z@PH  4 RR zn~v  jZV| "\*$pPVX`Bh0$, P| `fB j *   &"!Rp"&X# #Xr#" z$ fX nvp,l߶d2xdT8^t LF2~B'/47N<Z=9>3Z&- *)X' ' ) '|!`D> Hz:jpfP@pp rF ߒ~>ې8<@*tP zr `jlBJ (#n$"$ D.@* h RL|\:R0tXpnl<`f0߮ |8lt*N$  \L2 %'%l B Rr (tR~~h>&lۂpVjhnT v 0F^ "&*%,^%0#.3 2|/N* % 2,Z d B:*JNb0&TvZVxJ@ZZ N0j\ "NVh|0%\ b+\--D+8(j%BH$.%D&'(%#P,XJZ 40Lf8j\(fxpJ\ , p  2@ &6|j.H`^pxpb$drfN@DJ|(b j BV<^2r( l^.rhb D zd &F^4xBRRٖ4frn..ۂ^2p6&p zj F2 Xr:, B| ftP ::XzfPfvz.F,\ 0",T \ l : z@8n8#D`% n: ">>^p"D`rD"ۚXtdp*: vB4J,: R 2\ RTnD0\T,ZV"!Z *L0!4 d# .# B! fF>fX$ dvN. d .Bܘ P ޸J`~&4t b ن`dԖ цTբ&#$6&`$!BV8(x&    0zbRf H xTbDlJ JJ8 \L ,j4J<:``vHRVlpJDHP^ j^V >    R!""":" $ 4 V^ ^>, hݤPNhޔ4|f`Z6 br %H(/F 688v751r/$/P/d.$+X,$` >^D2>n b|<^B68\l06|V߈b,2B2N.l`r ^n%Pr%H ~j$`4&r)j't"V>j X> :0H ވ2jrLlR6Tv.  ^   X$B* "(( ^ ~ rpBJf$v>B$d X &T< \>$.*>*l3+8.)8J$"36*pP & "H F$x8LxTD|T^lD66*\Bjr8N: VNnx:r`Jv"P%&<%"B.fLZ.  &^ b T *.X 0 vd0j N  : @  8  6  \6 $p\N Ff Bb,,&x8*|0ZDxpF8h V  , 6Tft,rhX*v|N H  <&P@$B Nx2؀8ߪJh6H~Rfdz ^ @ Z<@z f |r<\<8N$ptnZb >b8 l *pR&PxH, 0  Hxd ^~Xl> t p T`:,t0V$~(\6)T%^ɤ˰DZӀ D &LR Դ bDV!&N(:'%$$`&J% !\DZ NBD^ ^ Pn&B8x p N  0 4  d pZ |8Hbzf<4048ڜ Vdvf&^b^f 4 z  f$  >  8X.`n0 lp Z \pb2,ѪTBbb(ӰT0\ڒVpd` x ,N" )b0^4\4*06+x&N $ $X %pV'd& z!> r|\hXz <V R4NPxx^@ r4&zT"v H|&#&'2X& $,%&'8*, 6-*x#d dNv rx dn  T,*|0V Z$*HPd6Jt&. ^ ^vF" * d& .p lLbv^$ۦD"HB^ @>\(0LlR6h\V!<"" b x .Jtd>6ߐX۴L>>|HN~0h`fJ@"v(V6 .J   Z x$v'((H&4$ `D>~*P` l R"4 *j>.H0XX"$n$D!FRfPfV~> DVNltztRH&pZJ `> vt$D'$)R+~. 0n 23~3 1 , (#zl& D:Lx,2$d$2Bh0fD, L^DxN pVLp2(>  X f~ٔj,Ә ڦzLJT rB J R\X* *   $d  | <\|Vb6 RކTl|HF(VXH j .  t V R   ~*d |" T j p *$>h$Vrܨج6z۪^, l0^0" T4LXhJZ^NjJV^0$l>RF^,j> V  rn!L#!JzR4F\H6 & B.<$Hh@f JFrD `V`#NP,(5B;J?> :@x >(z;6@2H/F..V.H)T"!8xHt \bN^,H6zlV$8B||TR߬2bjbrj4P*n!v\ R ^ |HX X$%d DJ4f v  T|8:Z:6L"jB2tp&~>F< p>n8 xrt $+,#v . vZ Z  ~^Tzzz`:>D "\xfbjh%$.*6- j) b.V1"2X0,tf)(<*--&+hF'l vDX t h. *n:8hn $%#tb:&8\vP&^D r"b&vRDH>hh:6$2 Hf,0 h&R\^PZvNPb*FnrX | NBN>P^6*Fz . vj0^,`b|b ` * b^~x.z BB T " n 8RVFH"Dx&XR\ &" ~&@< "n$0  V`Z$N#~ * 0.XLJzZנ8l &JFX6`$\ * ^|dfvJ&rh p ,l " D 0^rFnTF`~ \\.zfL~\2<8X :v  4l(z0VF|!|p"!T"$#!hB pj$\  :ۘnޢ*Jߦ>*6HP  |2pHV#Z.f7j;;7T/"( # 4"\ #p % # xFBZH~p20~HT>Vd|N\LTr$V |d^v:,> ` z 4!~ $8 'b'$2T ^ P T 4XB" Z(z\.T \v2rRJ^> Pd \  P 4 d&F8Z Z :dd >$"pFT *^Z"'XT)(p'n%hb$:##Lj%z'T( ((z'p$Jz: h d.LffhjVBZjvr PJftRLp<:^l|&F d B  TT*Lpd HR ..dJ$\ < <d$D>V|b>LlR lh,d `b z  N 6V2 "#R ^ &DBVD20J6>F*Jڤނ0>DTZHJ 4 Rn  . J r6<rjr.vZ ZܰPڴ~z\@LҊ: ۚ ޢTpцjD`  H0* 4 dJj@"<)+*Rn&`#h""2 "L,V8`0HHP^,~,z l n, "r 0|L bL 6 . z:^8dfD`J\:.B&f> 4  > $  L  tb` h!2 VDV"#t,#vB : L Nv(2xZ.lhvhb~ D 4$@+2.0(x1V/@+v' % $ ~&(T,&\8 " V ^J.d"l(t8H ^ v z 2H P@ !hd)D-"*" 6  X V <d jb" HnP*Z@@ @: L <^"!#" nF T$L%+8&1#>2l. &6 l6D8@. R<  N b4f $*$*T\|@.P<xF.@Z6, "bp&~P8Nh B Nr60`6j0T~6B&zF,..,(#h zr"%''$% &X tdpzn4*"*4v "%2*,,b,B*\&d!h$|j ~~L6vH|x$V2VFHZ  t$fnb t dj j< X  .6 4 b ,D,&$@ذVو2PL>dD Rx 6 B:   2 >&zb> x b `d>>$ւH ے@ J~*ߐv:TnlP6 * `0jb tlZ@@6&,VJB.pr.  . | $ &*B%l x,$JH:x\֌4ޔdX^Bh.j>lxt l hBTl " 0rhh&RTR .p|,Pںph dpBDv"ժ. hd |ۦPZ.* d`b Bʘ|T 6*ֺ#L#j!dV!H"|#j*#V! hz!# B$ 4$"!zB>r0 *  < PT^Pd0 h F ^ ~" j~TN`v  zrZNP<4Pv H:@8b <t~ f t r  Zr$  X< BX ft^  Nvj0D.v0NJZ4HzdFv  | 2 X&.63z:3/( #2v \, jf F"fpDZ8d&"@`bxN$0R"bnNߪ&P8 x&R TL*F`hF% ))$". V^@  J @< 2<Pz$0  6,Z b #$Z 6<d H2.<t @h@\v*F  0| 8#l*.0.&-t( x!6(L ^2B" Z`(>806 rfD,6rj@:VxZddV2@bB .h B!t)t0 3 2xj/,b * *- 1(4"r41+$z*Zhzv4v~ $ :*txXDbHx : z(dRzn|Vxlt~^FBf.( f `vDjvD>b Rd"2##X>!2T4Vt .,hbt:r.d$&p` f8:,H:*"n" f ^B|, $ rX l^~d.bHrL:t6Ph ft ff J> 6 *|^J,l . T hX4d`V2> 8phL z . pxF tJJ *:lvhbHրΆZ(&0XZl|`^rHH "jP d P| J `f H  <zP:"%$8V lhP2 >L< P @:d.`0Tf " 6p8ԦӤ6  Z4 > NּFb"l%$!xR^ T@Z"D.L8: v@ "n , Vn Pt d r`L@.\   2. |rr6:nf8 v~$`ٞDݤ`& Pt*fdFLf  " Xb #l'(N(r()+f,6+' x2 4d.Vdjl|>^؎b*ր׺tڤސ>8"jh .v$* 6-4l;x >P!=f8 f1r+$ .( ( 2,T/-$,0nvdF6`fjޮ&:ۊ(^VZ6ޮނ`bXNXR H&LT$ &#\Tn|" $`n%t$t Dd  >2L fbP&B8lnrdbF8r>R t z V:! |$ $"!"|% 6+ 0 3t461 ,'%8&(*)'#rZ2X $ 0hT &xdJVzZ !t h2xt*l D l xP`thr4$:.>|b.Tpd~ZT 8   dP RpHB "  " z@>\bzV@>ղ FHNp $Z<N  >N PxbF|   n`n  X.b<>v*X,ܘٰ$ٞٺbxPx܌tܠfXF,$l|  <  d $ 0* 6.L tP&|<zX*P n*f^>D*6r~    R rL*"t("* &#& N XT^4|JD>DB(l8ҮPڀN4rHn$>0  n D 2&&$2JNh" "( hx R 6X2"nz| x&,ݒ&$ :  ΨjHJ.6rbڸ Vd6Ӕݾ!t >,>TTfN J  D0t^~tH b  ` ( D tX ^N|bz n \`h P >6B\T8PBx>^NT"<Ppn*  lz  p  Z~p  4N T F B |J6|.X|L.8:܄:ݜD|^dFv88:z 68 h$",0X20,t'p:#f!,!N"!  <^~v"44VlT"BdXX@`R(  ( 4"B$N%B!n :$z: n(H4,v*&pnz6 DnT,.2X 6``B^: L>|$ L& Px !%z <  >tP"@ T^8&d::.Vz6p,pdD~L0n$0&,)3)V6D&T6!38-rX& 4p^Xh| @N^D(.h tb~vZx hlB rF Ft$d(+T 14T3$/>* &J^%^'*R,(,`@(B!,> xp߄JN nj<$d::Dj 0l r^"J@4 ^^lN& 8D $| d .DDn*X4@ (p^ t.*@L h#&2'%#!&vb  <    .8$&D,*dl20| " |  ` ~ X  :  22 N0:^ 0 ` T D~.X>v"FL(pL6N^^^(df@R^t : d   PJ "v"  H   jP NbDj`zD*FFZfDL82,,VR XP tV*2`LvD dp.L"  x<8vTn\zhPT "2$$ZxFDH\`tTJ(ZnLZ4bhTdpTD* 0  L ~N*Z  n b0B4^!\&Z :)H ) V'x#.v VL R ^b"BB j: & hxFhj8@͘ԔbPٸ4.HVHbN V8FvJ >>>H dX<|Pf@  ` @>j,,> X~ Df">6^&XJ:N,^xX44JX4b X Zj  b ^^TZ&F"Z#" "H ""#Z$$~#P l!$:> 0Dڶ:fז<0ۮjՔT,$& $ 8 \ d0 D~ , +2\5 ;$ :b4r,( %  V "h! j82tZl(zRLH*t Rv R@dNVvh <\t N "!.0b D6b$!""n , z| , P bLpxXX4lhn<:j ~ bN F n4 $D\ b 8 ( x 0p~b`VVFNLB$\ @ 4|<8tJ^!*&+>-.,p&~ L rT R vb.PphLHdV .&*)&F":2xR"Z&>))V%<| t ~f2pVj~$F"j#B"J:B(tDRzJb \^r|hZ lHv`D* *:h p6 `V8#(&(2N((,)+> 4,D ,V--P~+'"B@6@"^\Z.2tJn":b(NDf`vrr~H lN v|2"P(P*"t 0  Jd.^޼82zbڈv*Hz,Ft 6 F|L  vT  |.JB"T d 8*4rN^`چՎ 6tzDrJVp|֪:RBn^(j F r 8 d |4vf Vj|\:R. 4h`hd$JhنؒHݒx4<jf Z,<  t~"0(.+4r'&xb Z jV@B*v\dx^z*&|8dzNF (|n D2J r .H($$(0"&"!,Z  F"%h& f$ : lDl&X@: nZXZj^ pܨצלr܂ &F@:Ȓ2̂ (x8Ͳd ѐ!j6!p6 @^~rDT6 | $2 B4x &N  p Z6d  b z FJNކ:0d>,@"*۰Bj>0X^8d >&$\  x :  j">"!z#4%8%($%d"&J` vR , 6D p @( !,6b"=$4?%,>"0:4.<,J,.1.2'R((T&>`D@tnz0l*`$` RvlJBzV`DFP #Z! v&|$: !#d" P zB 8X.,vZHHxj0R>ZBXT V^ jj  $0f"D(' t~> "0F$ۀ 8,8h.2\t^X R 4.HRx2r*|#|"*'1)6(9%H8>2*J":(@ ~ &V.B6\>.,jH&:xj*0f: h^ !(#`T#:$&V+p0b589622.\-.<0F10H,H$&|:`  d(zpNN"<v D >fvH4x, t`&JdBl`V2LJx~bF p&RvZb.6b ",("v"j n $ @H^&>,Zf @  p > p p  bN   F B  Z 8608$ ~ 6 $ Bhj*J.t܂ X&Bf@jb8>8 B&"<  :|VXvL|f ld  :2~l6pN & NrpT02D`j@(ߚ`4 vZV@804 ,,vJ~:xTzD4  6H|. ZBF Rh"fB"d!n z $X~z,dLP 6F<Ր4v@p: &J hdFbF `H( 8 .ْشZR :P4LpÐ ΤV$n|ϒ>| ʞRL\ܴ#$'<&$L#X#bP% %$" 2V |!2j fJ$ B** d.V  r,l 0 , N *bL.2pz߄J*$R. "t   | |T z :Vbt L2 20R2z݈&XTBd2 ~@P|xX :Tv$ -4f7J8681p,( &^ & %H$x8 @ Pv(8"v^6n@:".td*0rpX^߂*:\ `j"T fbF&.^ X V! d6 : Z"b&>nn@JV>^Tf~zB 8 J  6   *"|%JX# d,^ 2 L& p|xrp! tf, jh|4. Z`z~86zBjn( Z *    > LxV N&vLP.|"!h(n ^VVz0  \PߢpҾN0 "(| *rΔ(\$ӞLھ 6 ZN<'F+,+b )&&l'.'%"( D  b"& "$$ T~<,  :64 bX , f   F & TJ 8:r| 6f 82l(jDRbxTFBD6fJ>f B  8  \ ~ " ~!Z !#z$Jf" jj vt~\LBD<>ْٚfڔHddJ  d`N!F*015b:63,-'J " ^! "xf%$ DVjx~\ 6\Vߦ@݈\ ݤیٶ"00D$ ^XN$L !`2 X~z %P D(n(6J'r$2LJb B~8DztN& pDv j < 6   X<LzX"#J xv t "2:>j88`ZDDN z>b# )#X.V"1< 2P1,\0% Fv   hD  xH v(4p<2FBh4tZ^ZV*>R $0H8 r zV2 'r 8-61~1V*.DL)b$"X"f~$&.'$ X,P*LjR 6 @"4~J^ $>>&>>P4XP8 4  zXtVL&>F8,\6P"0nr,<H >~Fz^""$P&z'~( ) X* <+4 H+ x)b&<#8 >$h4ZHJ\ DHn"02nFl@>&~&  $ b  >\  PR, v^ N ,<`*vr*L P xtnߖf ۠*zXX(`pR|8~ f 2 ~: z   Z Pjn < ( p~N8ݺۂڂۢ&Xt^2TX`0@N|  ^ H8& & j J T~z`F d Vn@&$PxH2P\ >p 6p (, (|>t:8V^ FZ^lJ> `"~ 0@   r P H :  < Pb  d @ Xh NZ.(jFR^VڨV߬J.^^:. R@  j  vH ( ! %*''Z>& !v (j^fNl.z$>^RҢ z~, r LX&b-1t4~4,0)$8 "X #tn&J(&p 0  f>Nj*zn.J`Jb l `p:`(`VPv@*D Z*Nlb!0!~  (  !2# $&2)x(nd#*<N`8 dfXvdDL vL htzD"  R<VT  nH \ d .f 6Xf <vf b*!r"""$!&Z(Ll'fd#$ f  Z $jz BH\f*8X&Bn|dpLD`^\Nf  0 &(R J 6V,R"V'*,| -D4,Z)'&$'z'%#!P4ht$z  r j x!!hX!0 | Z"$$PL"p4B d X z : R||<4 xHvX~n ldbJX 6 4:$ Z$N':0(pP'l&&.( * -> -D+T'  &\::`^06N>0p`*dRp > B"^Z4 Bnj `\N<Pj6d>,$4ܖ ֢&X\0r X>z > ".VN J   XRt.d ~D PDjN6:&HlFXJ (2V\xx B <  vj   >44X: T0@.(tLp@6 hT b r .xfz#4)(n Vj\tHR 0ۀl4&&Hnv*p04:D޾n n:~<Tl@ V  Z >" Dn N\rb4F8bf6(R Nn: 8ӂ ؠ 2\ xz v Ҹ*֤0Z#&)F+.*T'<%L$#"8F""^"P!F>@j,J@,PB>N&>r p f  0 &  Vz j$ x d6F(n 2pްpݺZB<3T7h63R^1n. +^ ), h(| 6(8%p\rb Dx6xftb8t&^d(N4H"H~ b~|Br&4Z0R#'$|<~F8&,*.*t$H 0JLv" PRp 6F<|b~V2~b Hd$dRJ,F v$XT,%,$6$  0* B @&R8L"zjRrBH l2f%\&0*D9(*bޖ ^ F .L:~$ < |bh 6~ , t`~^HBD df~&HF8 dhth0,Vt&#%#0lL`0lf"V pX<*$6J  $ HNP$fr|N PX,  Lz B $  z L ` |r  d ZN>&|| \ V F.2 `HD~f $  `z h , H6 tpb"2&>t@,ٶDݶR>Rj(z@ބf4 8vxPB:J ~   n,ZN " 8$6" ^ nb#B( *r)x $N6>(H DTbBZ L DVZ(պ~Ӫ̎ 8ްv~!r6"!V d:l:\4N< 4F*2":,D\jZV* h0   (HX t (  HNp bF,4z4xfNx.6&-,& R# x#L %\('J!^:t>*>rZHn>\4ތހFXnbrN ݠJxR|p>v  2& @v!* T 0b$ *'T'#  n 6|L6djb:< <$ "px.N RL8B,*`>,h bx vtXTfDRBn.jFF܂dB8ߐ|v thhXNh~ <@$@%&l&~''P((0(& 0"  n,rhzrzV.^0  <$0B2b6*&`rP6 n  LD|"%N&D%d#h!(~ j:@\ rJ|T 8pZn :\"v#&l%j (6  ~hf V H$V&xtDlF:H.t| 40F" B%)b-n/0/ N/ ." X-xX+4*)n(4% Z .6>j&x:"2(\l  :  P B  ^  |b, ~( |d8^ݔHFxhd݂bR~drx4n ` z j> 2 n L,*<  Z~NLj V`j6hPz .T~pXF x~   T"   |VHp4 Bd ^ ~~ߌ*6*lT@2F P  > B"#,$`20!L0zh$8( .L>vl ؊n@XFp\(j>6R\ ,x\ @X!  ~ H0jj!% >'>%2T!J 8 0:~&ޢ@۴P*`X8ܜrĈP 8 FTzn |bˠBXل!r&6'd$ F!4  p@ZThnDl<x  j 6 2Xpd$f8l FV@ VL h 8*Thr6R|Vr <Z@n&Jd: h   V" H j" Z *>: 2:zf*!v:"\!f J *^X>z\2*(BH@@ 2 $^ x'/ 68j8852P. + ) J)(vH$ nx dbn|\nbL|B.؜ے8`:B|8*8HX4 x\ $( *  jfj 2$. 8xL LRbr۠^lb@`$ZX. @   n :&:H %4!(*!@*#Zj" `6,H6dN.h`\z*t\F*ZD#&'V-( 0$.dv)! | D :x0j\v\hHF&p&v:>d|1/,r@)()f+,**^#48f 48 z,$vJ\x xd r4 j TL@&v @nV4 N\ ,$:jRhr"& ,TZ@ rXN8!\"!6$l2|# (`+N8+'$ H8.n P8:"r z@h\JzxTFV   ^ d X T   "D4~ d$ \ b l $ 2&<lj:ӴRV`  rnT& . @|d  zVpD R  b0h T *Z ~^0V ,D nL\Jzx.~PNjB~B0PPr  N` . j "p^z@  z  62V*:X: 2 Fv"L|`@b\:>JT\,R~ |vR( :Z vl,*BrPLb:"T$h. ~,p4P,ThH&T\* , ^6jL6XbhT|LTnl2NT ZN< 8Ht  H"< ~r ^x thH!^" xL $|P&rߢ n" P6$0ԔՆ:hH64`|`RԞJ,T 2<@L%& f%>#" %('\v)D),&T v# xFX>&<`$( ,^ ~\6 4$h 4 T66x jND .Z^"|8@j.z:*rx8R|:8 bd0 fN  P P <>NV&,0)t(, L' $j"L:!x @~ `@݄hD8 dbݴ^f֞ضݢJ2 $Nn8<zR" N+24J6b5$0)% !z 6 B 6  * p|&vph|r^rZrT.ގH xlvf۾H.@"Zj Vt L"   # j(*4`*&0: Zt &<\&ݮܒ\ߐ4 bnHR :(p|\Z@x0Z%)&  LX* Fp 6z`8"X&0n :VRZ!>$') , 8/N 0t^1B/*,L' "h Xr6 2 N:B**2 R>(:$VfD$Lb*  * r"\xh6#r'(:>($ NX ! 8 bX B@ hD (>ZjV< bR8XlT`br  ZD4pZ,Ph.vzPZ,>t@: P  & T  : l 4 \Fp,`DZV z>0nx6VX><.>ބz6J`6&6Z dL0D "X    2 6  : 48X 0^ @ ~(JXpD44^\zNܐޖT48D 8  z N r vx f2D B `, <"l 0`2pb*rx|hx,\Pz 8Nzb X JB : x~`|^`̶ߞȮɂ,@v ZF8dj,,"R vjN< r (V~dj"j%>%"b0ZD>T dZf ~@"$8&j*N8N:j2L~ B0B (-.+"'V $pP##>#`! xp4  .HT   | Df T b  (h6. D t. ` 2``p @r,JJz@b0L ` ~l >  r   .XX  TN  0D| T>F׶(n:^0ڦېLfT, X,>0&07"<&?^!b?P;>621//\00-& *f0tR$ >\0L:nTVl \N<^b   < Fz * t\bL 0 |  P\nP*2ߨ~2Vfڈ\߀~2Z$j|rLznvrlF !*~&ZJ(~ *$&\BBb0 P4  hn<:J"& ܂r$ Z.XnTD"")&/%2x#3t/T*h$<r 2 6Dl0 @rXfhH|(NfXR t < L ,&  j !l%*x / 2b3<v20^-,l.d00"20-)$ZH6X 06"Bv "%J'T)~(% ( fhLNX~dZ6$"T(8X0Zrf| Nj @L^.z rp N L r DTzrڐ<؊l *.$rpX z v2hPpXP.tNL@   (~H"TpF*DRVz~ \Jnz  v.F P hFXZtf ~ RdNBHv^lr:D `r*Vp !#8x :0hr d Jz,Th*d~ Vz>hLh$PJLx4L F(  Z,^ rdlx!|6"l26, >&V xHj@ڌzt rߴ ( BH`lXӼ0ج ݶX` "˂>*Z 2HX~ Z D Z~Ѧ"@8),,+pT( <&~&''d&Zb#   tn0z@,`~t :B `( Hj, T tZbT z T f v~&| 4 V$4LTZ6&N t(^D l D:Tv $2 0<` x f j  T (p l <6Br d nPt"LڲپL.ۆdݒl~NVb* h \`:bH( 0j56^r77J`4||0-&--LH-) 0$ & vT6zX `nې ܎V޲F J.x, .>\^~^@d 6F8n  % :'B%! XB & r6TvHPXۨtZ jr2DڲXPJ T$j,TdB%*|)^"~^" B tB z >4NRV" (4Zx@b6>  nD2 ^(%$ -&2H&5\#5<1* 0#~ rDL<P\ D(VZ $ V<.td"Vj:l>t> LJ\ V.LB!(,.J-+(% %8'l*,.+n'6"<VP N R H "L J2V"$2#nH!(lH~F > N@j82~D>D 2nZ&2XZ.$Jp6V$  V h"x n`R, 8 bvBPr 6j"V\66DXR D& JB| :r t`:  ,  ^ ` F( rR xbT @0$݊Jfd\>B^n>*r *@ 8 8 |l : ^  H, z @h|Lfx68*B FdhLv"4>fD>X.V F  nFTR N lVt^L n~B2L\R ߌ&ߨf`rH|ߐ >ژlV:ΰ .|؂&̎0jp.",%j$2" |t!nL"2!l >Jz6Tvn \ HZ*| ZF 2&TD6T~"d~ l R  th\88BDTb^V"^~*&vZT*4fB0 4j 2  .<6"()x2&| $|$&6%&'z & `! . HBnں یpڜ: JP~zv 8 'z(0869R9x25/* \'j% % &F$jH&^V8Z݄b8܌D:LZdی>ڸܬl`X :j^Ln P ,d: t Pz ! # #R!*0j n ~X` ** B,x,r4Nt>8B>*nN`:NDz ND "&  < R NfZ6R  n nlL$v&.(xhfXH<^ p$ nH 66ZF>|:|#< 6(*t*0' : T D $ n"ptb.(FrX\`::`z6*    NL >&T ,l n008-($X"($\H&x(($(%H!`0v  ^r^D`RLfp\p 2:@  ^( `8 Bf^8\x^bzXlTTtPBXr,$L ( 8x"V'R*,,-t- - ,B +)J&H#:( T  T8nv8 r2v|B~R$.h`.. >N $p  rNbbt0lz@ltڒ> ~"P H>J pz  "z(x Nv|24pZLpDpx\|$f ܦ܎::&RL8  Zz~" r v HTZ|.J  bb$l&T4RPB߀,Vj\ b$|VL0z"\ BL  .j $*\,|&ldZL|` <6\Jٌx֜|x>DV|T $z*62 ^FX ,Fr x (  P  D8Vb `r^">`tDԦټ(* fю8<ʼv v 2تTͪȎ > R"Z%$z*"`z6Rt2  NF    2~ nJ4tr  d B h R H J & 2r\~\ $ n2d<0.VBjr8xD&.dJ2#"(X(p''"(2) h*)&!V <:DvBܠې(d\jfBx@H8 j nV"h$ -d`3>>6L75 b1,)h(|@)N*)#N jrR.~^02LZ2 RٔxܠdDXb֠>xܮB(6Rx'%(F)%*' 2Z D T^N:HXvV x >H v 4 $"j\"!(P%H.$D1"1/n*"   b n   BH4.`rbHVFx4tT&x*Ll^JBn .  $\~*FJ^ 6% (8(:&#!`,| "X4x\h ` <Ldv` F XT" h*FLV\ ~H |RLzltntH6pV2nXtPXD.^ V" <" l$J(** +< ,/13<2 \.l (F":n, h&BV.2j T.(rZ>:,X ~ vf HT T  P8^@   d Xl b vN~: PXܖ8^$ٸx|.znZ~j  FLb, `X N 4vp 8  VpP@8pHbوJذ:؎R2D "v`\۴ؒLߞ>v 8j*(b2(:@\ \&N:*< ~0JD~@:xrV4PZ8Pf R| JF z$   H^#) z-P*. dp R v^F"nP4NڔptdV  D  R F4! "b 26\<!vr# L"  @V4: LLݞTלHPZܔ ߆ jݔΆnHÆ^, R( ,lV~  <ڰ<$2$>!X@6ld&:226r0DJj >^z(bd>8ZhdT:4. 2,.zF 8 .@~H:^Fb>"t *<^n6Vn VXV D"`2Z  ~D!% #v j Z"%.(z2)' #0t~ n(&N8݀N(|zݲ@ bv&N .R3F54r2-(* #!!< :" !R  jHr>4*bTL^ߨ,x>t޸lN0  8 d $"%%8#882B Dhn *x<,FTfX$H2V&`*4 L  $ htb %)'Lp < ,   8r\f"(\tv4Fv fl|p"\ z!NL &X <%(':/%10 /v) !hn 4 l>4f6pL`^L:~`H$Lj|Fn, P HJ n 48 j%l)x(%,!*H $F'"\'%jZ X \&x޸ RBJ8L4<<@ ^pZ>~F$2 H< J  ~ vn:X&VF0p.V.$(:BX ZrLn@ L,$&& x(d***+ L- . .B ,(v%!hL ~* d  BV6N<x  ^x   . v   2 , j |l L 4 LF<rz,.PR`bZ|Zz xXf 8( jRZ|R :n XF d| Dr ~|T2.|b~>X@,2:NbJ. N 0L0zx"B.H DJZz%v/7 N H$&l JN~jLz!!&$ *`R>@Z2N zX*.>:DJ!&*6,t>,V'^ *<J \rlV,NF:lDzBjD"8Rz28  6,bpr$N*H,+>'#^ fj%+/0X,H%z8  n lr2<NR^(nB\Hr$b0\d&*$d r4~6`N4px,z\"lNd$ @ xPf""!6L#ff$,$t%B(h)*j+r*t)@(P,&! (|X hBz|pV pf,,&v"l`\ v  |>&4,jz & 4 >"xVڌ6؜ؔ$:J`jvz 6 <   &N 6 8 :TF  r6zzl$z"P:0tކDV`R0f^zܦj@( *0Z nzD< lfZ |8Zh .j`2ۮjTJ4|4v|D60j   N|~&Vx>r" VR nZ 8 8`hRޖ$ז ߠFB`h*h0p l   D r f$^'6r$ L< (% ~' & $` pz" ZfX:^  VT,TؘռNJ8 ,br $0vzԮ 0< 6 \҆D N| #l%".rbt6lprTjnB \zfJ hz J  < T   6P h$ D  : 6RR8Z: X.*: t`H>:>z 8< ~r Rpv!@j% t$ " 2$T')*<)T.% &,`RF6P4؜ Ԧ,Ԍ"Ӿt`\&z@~h0@fV .> ~%+40.3b3^/2* %#b $L'>)' *2NHj(F <&<@2ڜB݂F>H2Z:&`6rPr(TLv$*Z ` \  h\r #Z(@L)~$8 P F|H(pݤJx:<j ~ "F bZ  d#" @$ "& )*(0+*5)T7$62,$D'jZ"8vvb 0nZR& .pj.nb4l6(h*f4*^^ RZ0`bz4 z B" z ":~.rlRt*&$x~dh6FhbRRl j `$^'pf('& & )-|1*20 T, |&R H<L 2jj0Zj6rp (.jxJzv F  Xz V$ , $", 0l,^  &nJV"vL۠PҎxԨ`ٲ,ZjR8j,h`(^ x Jh V H. t 8DDX dB>Hh|zN&*~tr*4dZ0d|\|N.H2zrVjt~Jv &h($8.,T8n>^dٶrZ*t& `p*vH 0"r-2@-B . x\,v B dJfRjZЊ jlN &V@ Z|BX:PV z4f!dR N! 'Zn)"( $ !( J|Vj LZfv :hdެ .N8J6>Ԗ D~ p:Ԝ0Ф Zװ n","f!^ :"V02htdn $x T8H. PVT H\p |n8dvF dFrdnrbpt Jt &>~hf2Lt &0'p&%0%&z,(v~)h)'>"FHڂd(lt@܊fvpl p Z~88xz2>&X/434P2/b*z V&##z" p! (   ^Bv"*|:nFp , `<tx@( z$$`T((&"$!$*!z%*,(*~d%"d:X d  pxdxn> 4*Xjv &@$fX ~ Rb :p,v\x0^ZB "f"p|& ` dFJFJ N!4"0!!b#T0%:& &%# !PX, <RL"\ 6 rvH>Tv@ h>|$tf  b H    &&D* Zߪ6~~֎Հ8֌ێz2":h:\p V R LL    NP > ^ >&TRv^4RJ.8 ~lHh@|x`tz~|~Nr <  V\@  T0 X&^~ $  ,$,8jx0Ph.J< ,\ tX ~4n!&( % X<`FVht4| 6n4" 0L$J^H,PT h \ RfT N :h ,j ,nv\,(#*# "x88dv ^.*nJ p ,0NيDX " lĀx ׸ 6v b&@4J0XZ$#zT#h2dnL$2XN^ 2 ~:  d bhJP  B bhR6(|v  Jj NLt"P.4D* 86Hf6X 6f :Px (` 2ND&! /1.$+*Vj,.0/n+0 #8XR f n@*F֠:l,(8J ~&6$ ,4T:$==70D :*n&%n ''$Z T v~2Z@n",@& 2ߨ:F߲.JP jl$JJb@> dH HV2x !x 4b& &:NZ6ZZ. :(Z*d4X.( PZ2\$F8|\,f*ܲ:n$N\xh>p>f,~,Dn!>!>!v%T'B("%H l ZX  np&V,Hߦ`R$&bdZ@x,JVhTd, H   tN2>Jb N$H(0j)R'$Lz V\ D*N`d8\2 & P dv%>('|&B%$"*#T4%v''4% Z B f H 0\~*6Pv6TVpj@(D6(`8TjBB Xp"(&>*`-6".v-,4*, , v- Z-8 +& ,!Z0 b(08 jxPn:xbHF@Hn  \ F@ F h & :\  $ L0 Ph$Z Jx d@ؔb.b<ܖll h` ^ tf"B 2  4PtlT 4hN ."߆p4:`P~Hb." j.6(V,  LX  v(b~ v2 $b 8.|٬`r6:0p^x~LDV$%f2 `j@ 8 *Bւ6 b*v$b(~ \ F& l ::""* \p" &P'$ j!Xln*@ B^ B@ HRN\<d48 hRF:j ܂ 6 djlTn!'H2*0)&,b#~"LL" 6 Hh*:(~bTn22 L8Z`V( \ h  Rz6Fn ,T TJ j^tnLNfx~^:ܶPӎH.4N:6~lll4Z 4\@`  6J L. N0 T BfFڐbB۞4p<ٲڬ48X 2# */@z2T4@,4^1-(+ *&*+B(*% Rf "& d*dlVV.vfߊ $zt"~8P t"&0$8L  p\\! |'d)&'#*|RR6 v8L0VhL8v0Ht`ltB<Xj vNX  : > J hH%N$p$":2XRhP`FBnv~PTz݂>ߘ*Zpp* n0 ~ DtNT"&n%-$0*!.() r 2vHBb j:RpR:::,H`N<@n fNL.r *Ljh4L""~0&0''J%p! !$.'v'F&!6@< Vn^L߄ VrdTF:V^Tzl:"06Z LTt~ Bf TDj6RN\R*\4hh:4 f^~xn"H!#$&V r(R ) l) ' $!xZhn "66R:jJx<:rxf\ JpLp`l p .,hh(Hl :~  N F B߀ڔ2,Hٴz|.Ld:l  j  t , & x 4&  J 8Dxr8J0(^ِ jddX2 D<04V  : XZj4 . B2(Lr:jpXTvvbr*T"< DR$:Zhv$hXt 4h |J>v#*Pr+j6# .d| L6h VHfpTVx8p 2 &jF(b!% 2&. $b^"!T dp tlN T4" ~PHޒ: jTb\ ݈Ӭ"μHЎjp >^ :ւ$8ި#D):*'$T#H%V&$"!~tdf(zN" :> ZZ  6 tlV4h&|$  H $ &x  jp T X XZzB20@jXޮB:&>\6F,. |ߢ 0|:\l T ,,BFf r  ~ X 6xjn B ~R:H :|ߖNLݢۮF,N\8Zl0lPXJ Pl $Zp>#!H) .J12.- &  $  > h t Jxf4b4:bp(4NxB@`,:HtFj P` N<F(H,t%,1p1.) %f""<%p&x&`*&H$n"p*v߶ \ \: "NT#\"!z! ^ !B#F$$*# h0TH^ pLd(Rnn^J^bXD^dBh">^`~2NFhD& z  d"4L(+@x,r*X'>&'*6 -.-0T(|!N x& ^f>:N f^*Z2 jj. V8$(  0 ,,P V V^\@T : .&*|:R fvdՄJ*BP,<,> zh V(&l    .2J4L&L $n v2NT 0R@* lrz|x| (P. Nt`4jjv6<  J   ` p "F0 |X\bL#Z #d "LLrP4$ t0 $8h^|d\ 6 zZٶѮɰ(D \ bb6ϼ\˦ vN !" B$ެfTj0Xhx . r<v . *V  >8R Xvb  T 4 F b ,HXX~f&vP@*hn6Lb 6h l &$:v ,,$6'&$$`&f'n'$ $lr0 Ftt~V\4T(* tچL6ܸ$2. 8 rl) \1B7;>l=8.3 /pn- -.r-R(  n Jh0`$$JٮDb,H|2ք݄"ܘjبޖlZJ VV@ v"R xh"4$ j$:R$#H  Jx ~ , FhHz,*|BFPfBpxz@&L \<.Dpj8P(p  :!bj   H .6$lPrf2 4B6phfT0Z \ 2 :""<(!@-,:/L,d& 2` F  LD 4 \v&"fHh`L^6$\``2/bB-,|-L0~1H0z-h)$.dX$fXdh2   &"R#"4Zr0T6X Zz vv 60XPbbR6<006X  p`X $DN` f! ~!l r :2!0D#j% j&p$f @rBPp ^rj`j@x@"`J|L0(TNDL P l ^ , t LP z8Nd Z t `|h~Dxv>, L~רB2^ 0x( l@4\ 4 v j  ZN6Vh lX2\Bnj>^ަrrZb`&TD|P 0tDz:v&2  ,ZP$ 0 "  d @ l ݞ *hn8t"~FFPT ( "~|BpbJnpLr 8Hn.:^ NtPڜ& Tnb <X N z ,   rR $6%^#t2 t`P \&X*B*L(B % R (2\b`pF *n<8ٚ nJ zd$4Ȯ^ČƘX˨$ xl f:rf RˮFH"$X# (DXx~x^^X j>t . F <,hZPr2X ^ , &  z, hZ` 0thbh>$||@2(BhDLRp^z~ @&f@L 4`n"%l%&n%8'.*+@,B*$ ,TN R*`n"2ZV:٪*ھ4"$`2 "^v'd/529;83J.*):+Z-,2(N2~*^nV"*ފ6*B^ڬڲj4~f.Tx $|<ljh `n.blj!#| " * 8 d P h Pd VݶRX8j B4JJZrdFh | L0 > T  l B!f"|#0D#Z!*.DF` tVVR~B$bV^"<, V P4*jH( @#>"N(!,    6 v0TTz,( Zd~N>@ LV   jxBVz*R(lf!d$f%%v#!fLl` >2 ܊ @ Zx~x!" !pLV \2LVx:|fxBTV4N"f~4 (Njd $\(6,,T@, , ,-r/L/-b l)0$f$ :\J<XLr4`LjPF@8 ^ b . D  2 6 p v @$8rhxB >>nzZRbؒd>0Lؤ|2@F.TN>| p J P.6N z J `FP < TFlBp8t" 4p`8>lr,ސ\tBh$D\ F B j FZ,20 BF<@ .B:h& H.BNx\ݴڴ& jݒd Hn^L j~v@(   @"(^@' DF^ b &N8.fH޲PԢ֒ܚLDX |~T$2 \>$R&NL 0 8 ,b"bh .*H!h#j!2TXN~h:nP4ۨ V .nJV `T Dښtdў T, jp',-x*dX'&<,()'$t ~ "  8^Hn2~XN   XN Tv:Zd   ~ f  r> v26 j" |:\6*XF b~ x  |h.  r ~jv"h  ^@  v dHېJ"Vڠn"@BBڤްx&ljj jd (L $-J T.8/./H2-* >(d L&$"86x JJrvLDpߞݔߺ@,8^ߖ$߼X.>X|pNB tB ~n N%*nB,f)$PRj 0x jp2vT28& >rbvxRrT&d"\!4` 28"B(%&,X(*4&P" *`z8 @.F |J08* Rb Jf p jb& ,!.-( !X b j \&R@R8rX>lDF*Z62rZPJ`NX ~T^BP.4 x&`+8-6-)8%z"@$&Z)>)x'j"   0zDL\&H:bRb6|z.(N Z :0 $ z 0 &Bj~ L  `.8| ~n~v\ "%%$!fDj>J" H.:n$&zpp0F4 p fP F  T  F z   ( F r XD @f Z x  j,l$ZT, j ۀ*:xd`r\TJf0(b | \ b8 8tv j  J  (@pPZppPRH4L*hz<8|BFPrh2b,` n L Nh4z$@XlF8z,H& 8.,:ZN`0j FJ p(pVDX pf"F$b r,"4(.z*j(D۶< tb nxj(B NrB  X8 < ^ <P@d~V^x4!"t! D R r`84TBXt rF \JN^&B2@@݈>8xjR^R  ִ0՜BϦnPr *D~0"!:p >!, 4>,@Ff` b4b l \Br  R ,* (T@ d$D"&ވ&x(@ڂنxf"p(0rT D  B :0l $J))&%6' )>*)R8' ~"f@ nd \*pR:H:Vpv$8L>fl2HT vp ~ "# +2626 1r2* #& R  Bn\8**R&.L H r j F6  !62 F  h!#Z#,bL Lf& :,2dVH8H(: T@DL N N p $NFd.B  xZD bz&,@4ߒZ @ vNn~ DXr@ . @$, 'J(N'l#v  b  V  @LhlN,PrJr.vLJ:nZl,t  V@4  p  Zh*0Z!&(X)Rb(d%!rN4 dDPb` V*$DtTB#$8$"z!4H ~#0(v ,,)4#`Pbzn"R: N@jnpNB ޢ, @\  4\~ZD>"$z,%$$$,$$>%x%h@$"XX phj<h tDFxTnLjPTj^," <  l D   VxTx` 0J* ,  J$l$ P( ߚ@^.6p~n.d n^ bRЪ ŤR ٰJބ J& P JϦN"'(R$z,:|4(h(2 N    ~ P *0&dXNp  vt \ p   `x2~ &:6.LdVZ:\Z (t ٤2ެ*.Z >6t P X$ .: &X('PH''xZ)):)~X& . $~ HFZ<ހ, >ی @۸ݖD , \6~ t*n$-Bl3 f689f73/Pb,B*+*P' 8N~^ (fVTtJ: bbp>x0 0Fނ٨n: ݶ N|J`B`^"P%&$D,#'*&"( ,  V ^ J lz޶\: VBhLHF"f<d6. t^,vj@!T"B( ),,0+h4(t4!l0j( @  b , Zx D`,:\p:6&LF444 2`FH,$  6 >@!#f%&p&<''L ) d* +<4*X& !Lr, RTtdzhnfPBT^ 8 n X vj T ( 6 ^( ` 4  .*bv(x 6 R&>ސzޤ$lv^v| ZZ:F8 8 .T<fJ  n \$   jJ\N` ( <NVN HT,(2RZ  .:#D"fl  T"DJz6 ΢BϢd(\zFpv,h hDB~~f F!Nl"r2V"%'F p&8 #d! dt@Td \vh0 RbV|@T\$R 4" ̰8 &@~ X Ԝ tZ>#`h)4+*)j%"T`"P! r~&2N, F $ & t B,JBjB@v \ <~n X  Ftpvf4h4jDbdF rNjTt:`^l. j ( l  R , "  r bfb4& T:8BDX*$Xt&4b0@hh nrR&h-:21|T2pH2f0d-*vx((H (, *' "#hh 2.llX:j: \n&t("<4<^ظVݤFln\J  (T  |`>" &'$H @.v$ X.~f`jF.ߐZR0  "( 4  j@ tl$+'.|+*^( TDb r 0< h b 6T(nf0"j&8~>jFt2  T` b 8*% - 1|&2-2& P0 ,(< \&  jT 8N@Z`xt4! t',/60 .D)t&d&~|) B,8J-+B'4J!\D B*0 " :0`0F > 2FZn rlHt J 4NpnZ (llrptx,p4  HHtzVLb4|r,Hp!"%*&%"$@ n p:Td~ R $ttV  8 8  Nd J Jp0 . * L 8 ^  2(fb@<(:Xڰ؊׈֖֐6rBrp0$`4<" Zl2VN  H dBhD D 4H"8(6Vn|J24Pd|N4:.2*~Db|@ 4 "  n^`~ j `  d N& FJhPf `.Tf~~," b pdP<r $x"`%t#zPpHjT*؂Dpj 0 (z(l p  $lR 0 j@df x.(bR!  rV,dB ZF&$NjLH"bޔR֐JdxJFLϠ̼\( > ڼ b\ `Ҿ jRd"%\&b~$J"!v"Z#t !H |V 0~&D t (<T vf`  N "hz`T n ~ z 4vf0ޔ`ٲ؎ظ\vfdrF<׆>*j: vvj X^% 4.h~6&D>B B 4BH=$6"0 ", +..23\-( (ZNJ@>l ( Z^(8ۮ$6`(NtP(Zز`."Tzp. (Zp!l"D^!J l@ $ &% T h"V\hl|H,\P(0*Jt$(XrZ6@ x 8pD   *dxr Ttt| bR 6Tj .vFpPJnV؄X"|VV DL^T~  Z$%r$ )Z!(%>##&"4*,z+Z(<#N fXB6 rrXpFzJP`4v*ޢ(6p@^|R "`  *^ ~<$' ('n%\"F!dp!6"$"""X"<~@X$|Nv߀ ۰.0l@<Hf (B>4*x>L޺(XT^Xf\\:" F!F(b -` 143,42d0` . ,+* (t&# 8Jn6* HZ2"j|V6& .: @8z6 ` 8  L(2@~jz N  ~D T|J j: 4 ,BDh܌DѲπbVLRv~z ,dh  bF * .ZP xb~LbD  2:,z't$# P& z) ) #Vd\Z0N\:~ZlFB$J nl r86(~> ,>&.,)!rD n<4 % '&,$0!P r.r $ Z(B.ܒ ~l|8~BV *""$j D dzJj&,%+h'$ N Z < Z FH2r>"@6 ,px\.0&|$ F 0(!$d).N-5+h8'H7&!v3&,$>#^ &F x *V2 Vff< 2*rzdXh.(& X Tf^!X)"0-,)8%"d!#&<)(V%z d*` `$ nF*8zr\T"\X%"$ N(^. d6x0td"t~&`N<04 Z$^ ( < "h "^!,  !P#h *% @%Z#,*l Nlp*Z@::jF2Tbpb ( :  0x pF b4Zvbx  fPDh$B| <,vߦR, ,$B"8Pvv "$<D  . B L Xp  *  4 >\ $$6TtZjl2$.JrH8 2Db 0 N$ 2@4$tzRL&:^vHdH(HVv\4z,dr.4xZn D`4#(4.% :j **8|^ P N4:RznPPDP&d:d@J <4\2$ 6bN 2 F#"2 V^HF jvz $z0 j`fبݤ ,T lNv8Ǟ<ڌZ68ђ">(z*|)'4b(6*p*:(J$ ! F T"f"P PN>B | &RpT p X r6 L8  (& p<~\0tvtnZ"<@ (b *< < P: :H2  "8j    RNݺJ0ڊR~|٬d\ؐjTB, J (`z# * 4/F1"06,& !f  "B x@V f2l.hpD( jvZv<6dPrv4 x& ^ t4:b" %%"b#. ~\(N>6BX6tn\l(d&4T&2DJ&lR,L Xt v l$tN B` hP& Lh6Xp`N:J||fpVFzl 2& ,&t)0t)\&%( |R  z > ~  n drD@RVL 6b~\T$R"Hh2L$t@vHrnN:Zr00 >  n   T2 T`Rh2*dp 2 p R:~0nxݺv2VDZ4tL H \ Lh |  Bv"  | t\ xJdR(d<6HϚ`|nԴf$4n֮ܺ|HB .P  T >*$ T   `(  X\ N 6F &hd0ߺZv@X"0r& VL0^ rZ  J J *"Z&Z, J1:/&, 6 l   8t*Rd:B0hvF t@R:`P^2L |H L 6&4B~Hv   t &\"xX L,\ z(JdFj%(< **+<- .B.2+ ' X!jz"2 X ۀZܘntۚ TVjp\f"DؖnHp b|نr־ޠLVDz4  h!l .8$ 4!( #v&0("*P*NF' Rz:B<~> \ FDV6HV.zhXv\D n   H$H(T'|#!&"F%~(!,*&-(2+'D$ "",t\| \ 0NB~"~V֚~"ь>Մܪ| BR D~N4R j$n $()<(.# | J *  X`(ߖpBl8"*F*n :"Dv<J,xh h* p @b v%*,^,+r(%#>#D#(:"2\x6DX $ .0 |j,F\R6HBB ($\ & ' F&"f` ,Px$ jB ^L| hj@flT T 2@8#(0r-/"0\1j 1 2 32 3( 1.)6#brJ|V JFD$hL6*V|j>(&jVtH ,.>  z|2j&Z L~tְt֌ۨ:f&ZRpX zrb j^   b2X4. 2HD@\fR>4~Jr^. P*,Ղ rNldvX0ftzDJ$.Z| j $X B V ( 2 R h$ & f  p~<0z>FDF>~&jnNh ^>v` ! !, Z^6 >h#:%#\xvNV4T`pל0f:Hx&ވ`Vvtj0DV>\ tV |x  : *P@P `0(V  >\d<t~<<^Nnܘ&(r**٠HFӲ6$0 RvzLǐx ^D־ 2 R˰>Ԁ"H'%& 8dbP`2 |`.@  2 b $ n 8.v ^0 b B> "2 0d ^Ddb|ZB, x\ FpL>l @r8p  2DR nT,L L% &'&'d'0(&'z&x# V.&0P0T@ֆJzל& f`h ~& >* ,x/X.*R d& #, #2 n% >& v#jpZ 8|4:&0: ݨPltd ވV@FF b>b! l"!n  ! v! z" N$ &")*)T$ & `RJ($P&ޤbRT2n Hv P8 Hh   RP JT  .x Nrv8**( Dt XNfJJN #$z& (V8) .&f4! r ^   f  6v^\,\ B^"tJJ~"\Z  Zztt :l:"B'P)Z)6(&.$$$:&&v$Zt!|0f H^B !#&"8,J2X Rx,Bt^VH 2p$,@lNxXjzrr,P|8 LT!p" pJJ !(. 28p jD * n:l X nJr@@b2   Z$  R  ZRX& 2N2dnH@t݌jH"F  Z * $* f ~ r x nL~n  6!:":t xvb lVF>.Xޔ0߄8Xۼv< &: 0& ,j0 ' -/J0~.,D+*' # (D N xl ,$ P*L::8hj0xT &`hDJVP,<8Rh >Bd  NX $ <'&,$0 ^V hXth>X b.N02 `B~ `R | \@ .*d  vlNV^0 n@#J: T  v b *N0@P Xxn@L&dT` LL P \jJ $"j$|&d'T''<'^'''& $!P$< `N4J.0Rx8^ Nlj8B..r`T L F `| | 6"B zD @ x$  2lzt"H$vbٰ ~H B0 JfR L@n  H:LzT2V|\4$2 LXLZBl^r>   TN4P< D*.8P< 6. &h8xz*zNݰ~ pp$> fZ zDHjLvd$ bn4,$\x PZX|Pp:-2)Z% " ! # $v6#"6|DD.h` 0 *N4: , f8  PTfd4  dh @0x$j߮:< L$ۦXX&jPZp( T^, F   <`v!  r (0!" "j F&&V @>dԤ~Ӵr"ՠׄ8׮.nltr 2 TlXP.!L *2~84r9V60 *0%l!8 V (  p d nPb ^DBp~4&FnhTܜ|ߴTܔ&ޤPN X Z!"!Z` t $ >'v'&# LBJ NZNt@ p8vhP 4n \NF, VT :Xd\ TL~~Nz0v&&HVݢ|ߞNB @0  bJ8#"( - 0N0xf+#  D   DHT BV2pX2VP0j! %f&z#.VT 20  >d2 NtJJ$&zzjVH`dF"`P |.x 0&r)*x@*) ('())%!L6$ "P~6Xf"L*&"j$RD0   L f v 6&rTXFNr(  "L4b,*\@ՀѺҎH߈RPXH^> FF rx<(" * F  B :nvpD > *D 2jB2(pߦ$j"hTH N6 XBHLf$PbD`f(@lxRR.\4&XH2^"@ $dd fz>!# j$" @ bv #H&$` z j6f&L<*l ۈz("^46BH^BNdT vPX  h >^ Dn fB X:4 r `tBN f>ۄ ׼lh~lNxߞhҀ4lvԼ TJBۘѢjNNJ ԎBv`2ۈ zԢ6"&%"DbV&ߚfZxh$|P r R z~2 rp 6 `*  h Txv(* D t 8h& 22$ H `8j0P"jZN j  H6ljtp".<#"|$: (r+-l-,>*.$p2,* &ߘH|.٨XR(>ոBծHrR6 N l L 8|$ $,x0476B2jV- () 'Z *-., $d X,`pF ԼJ nb.&Hznެߐ~@>Fh n B ( ~$ nJ<V "$x "  n 6(z*f@$D6Z VX(  n!B   8!X$&'(#z&"~"<R2~v 0 . RJD.F 0Pd rP$> nj!Dz!R"!D%%)'b-T&v0#,2 1,^ '!H.d hFnZB>6V 2 Z@R:j(T~Z<\Z  0TJ!#"& 02~lZXLx<022*  ߀^\ D T,dtTd dh< @ fB(ZRtvLR \Vn N2"R~j&8tPRjP* LPB l:D*8h"*d*,!JTt zj~լD\ؼP|l@:nRxޢ*F$ >r4db| l, \B| | J>n~@:"jNp t޸` 8ܖ`F$ؔ4 x "Bnd4:"| \Xn" !L(**rT**+b+(z&$Z2!V !8P#*$|v":b 6 8 0 8z|dV P & zF`F f * t *06|. f Hh t~(nND@fphj $ :z   | :B Xt:(  *  L"f%&X& #zPr^Vڌ2T(߼ۚzD`^> >X . <<#,H1>z20@-(d$!lpDB ^ f: &H R. fh0~~ۂ>&|\Pܦ>ۢJL|BzLdT vbZ vNL!X Z" !h nVJPDpB.\$2$DbdJ*&:x۾2 l HdB0fhb ,n j$ TR @h2J DDPl4Z2$ ~* bXZ, J&h~+f.0.|* " XL<<$Hl~0x400rTx.J  p n0*Dl: ZFB0.|XD!(,+'$#nJ~V!D#n$$ bDH8 ߼ |Lbzr>Xp@6Bb ,#nB%$H"v<rTPj^ RJTVj2<bZL~8.XR8> rT$@'&#!| P"N p%T ~( )'F6$6 8$N(H`fP,z>* :r$4T P >Rr,.f0 >^ Z p(J ^62dH6 zVl.b|F>xBڊަ<.VX&04 & >rV  @ 0 l N(" ~Bn 0bpPVF\4| N  n  ,# $@< zz pB$j$$ & .$4 @x`2rX 6 znF>zphҎJbؒ RpXӶ"tƬrV rږ RtfpZԞކ'+ ,Rh)&0$R#$"f\b 6|x NB  X&T> dNzb| |  p " z(t  T | jT<D<.> ިP(XδtFҖtN":6z <   N n n| \x 4f`!"`!F d40 8`h<ڄذ`آۘrVܾ,@ nxZ!z *r3t4:2>#\B'|B%>n 9v41 V122p0<*t4 ~ b & z*\pN^VL&tBfhT|^DnHzr < r& JH V "D" LB <^n|"HZTZTVPLB\4ޜ& 6TH Fb  j RpP^HPRJR`X nj ׎>Җڠ߬dt0tZ bvzb"* "$!'x:(r$"f6f T ` J |rt,|NVrB(j.t"t   8 x ,Z # @&&&$ L$ "V"T $> ) - z/4.+Jr(R.%Bp#($Dd&\&P>%#` lbl28R:x4z*Tj t#8$0%f%$^##%j''$"P B   vfl``2ܚ2ۦrdl*N@> X$<FD!~!x .!$XL'*(~&l!`L(@ "nv,d<.\@hJ0v d \h 4RbRNB R .ތBrX@RV,  4.D\ FR : RN 4Nr8R >nFBfR>R0nphNb(@2* :Nv@ &x  2V8r 8t <2hHZ8 $ 6@Z2,bvbݦߔ(:~.Vzl PHvb <TLv$6*x,%| 8 *n޸( ,̸8rTpTlZx(^8p~jtRr"b N( d^J` bd " $#v @ ``:pnx߮Vچ$ގ > Db6ӨF24 J lBZf>F  $ $ ̄јt#b,(v(%##"!0xvl4V6N Vt &Dl2 b0X*v 0 f|  T@x 8 xtXNv p(8P bX. .<F>^0#Z$Hx#R#r%:(F*F0+@P)`$Bz H>vߚT84j\ FDH$ jRR&. 34pL41/V, ) D'%$ !^ b .PR0d`t,@D ߨxnިJؤ٤"vzlXPBfX Nl x T tfL pX l  NT , FH 0bؐVڈPV$bdx8V>j ~ Z~ N  Z @&(0 &B H.&*<&< vH06<.h6, J L#h% #T# d#" ""!%$`)j&-8%/ ".j*"( p 0 fP. Pb ~4LR6Jdxt$lrfN:Dd8.\B|DhjT6L"dL0fFz|Z:B#B%$"0l(:^,> Z80 ޺ J" ,pn~4Xd *6!p! H : R!!ll&,Td j t\ d $ZN*P^z>>B`H@tx x 6d"H" z(#X&(Z* p+n ,,L, b)>%P jj"z~\ .x>,(~>h`^X48d( F xD x  H H j0 jp r26   DX>bv\ڞ.TՀ8ۖp FhlXB 4 , tR d 8R   "d <^  F Z^2,.lh8BtBtHB6>dr0:JX>J  ~fRj 0X ZPh"Bd:,4 @ @p.> .^ z#& n"D r,dV ,:ۤP  $N>|"ӎD V(f 86pxh`T VTߺ 0ܴh tԬP%+n(-.,+&*H*t)|&#jZ!:HD44zLft`tLBf B 4"6"pL ݦ"~ j NTL *x `n~F #% L%#F  V Z@ x,tJ@V&dZ:bL`2ޚt"2J  < "8^f8 N H"6&!&@"\"B$z LR,$ lXnFNBVtV 8T&( dRR.0 $#* 0R2|0* x!66  N  fnB$nx4ZJDX&Xj:j:VNV$ &%"0 4"$~#!.*< tHb >TX\ f<v B$P%Z*&f,&%Hx$Zv"6&^8r|  4.& "~FH:@@,4:FT : t,V "h## ## $ & & &$>! xr*vP rPz\~0l  > RB4NF   f p pP 4  "x @ ,   nD \:t Nܼf8 ҘBӐغ,&,P8| t V f `  v0  @ * rT ~&xl~*Zߞ:چXܜ:j\R06 ߞxX z:"D N4`: | `~$ $`z  ^tTr\  j 0R4Rx"&X4z߶6"bB*rtB 24 hdfz DL $$8>ժ, xpɰϨײ,Z& ` F6 Pмոf'j,zx,P)|$& %*%$Z*# t8` v~4ff*dX@6 8@"*  ^Xtx",vJ$hLXzzjVP0B܄ߐJj $R`  r   " "6N"t#2%p&F&" 8LN bTz .2*Z׬j6dظFֺr@xxZ@6 VVl"@ 2+166bV3f- '#8"Z$ .&&$ 4J(jLXbThdFߢ@8TފݘZ4N~pB | >J*  f &> h j $"b \$'b`+-D,T$@V (h&\z. >,<^v(z@$PP|x < l : P: z "r$%>>% #!& :n2\~0&,*X"RNߔ"l "P t|,j4$Pp!D%:'|(Nr%P N|lF*^ 0,:8\:l RVDjnph>B$:d, $J J$*-4.-X+>N+ + T-r/ v/,&\|!,BL Lt Nvl&jP~ d~0hFd F^ & b B x* .  x|vV6:x`r:܄tlҾ,P |,BRz `8Vf    $ 2  ( 2 ` f0t.Jߎ. "$ ZF tX  ( | b" l0 nZ 0 @6ٶ*$f2dp0@4.vPDTzN84*<"@$4Nrn t B<2">&rl&$ #%N'>*B+R(6"VJHn(Nxڌע&$>xհ|>b 8Xt"0).@3f7p673*- '$. r% (+b*N$.. <  0vfl64 ,.rt$`T߼v40hB:8t" $v$ r$#r#^%f (+~)#x0>>0 8 &DdZT$TfhB0 J8 n  Z Rp$ rrfhRd8 R@(v&btzהt0ߤJVXTJ Z2$2"$ *Vߜ0ܞt`TP PV,2& h~VV r ^ t>v" pf$J'<(&$# ttN$VpX dj, TZb\"%fL''\`'V&&x( , 0R,2 /x(J v 4:&<t (`<j:N" (J " :n#t4)4,-+)V('J ' x'&$t@(@v~*&X<:0xb0LdLF6D"~RLt~R  T l r&dV`.f ~\|0 >0,^V>r^b` hf& ΰ$ЌՌ۞Bx:. R\v @ "R " 0  6  t0R p Z  @: >T"|NxLdPH \ fHBT"lh4 z :@  R 8 bR4 v.dB < n  D  .(|hl$ZRblZpZ$:*\v,jB  6 |%%   RT(8NުdَlPv|:4ۢT$\B\P x(>(v r \.X ~ "0lz Rn "V,~ p L~^~0L6Ծ^Z~Ҹp Nd *ϖŌ  2 `NҠ>f .֚> #%%Jt$~#~#d#4"pP f$TJ j\&|Tt|l H@f<: (n*  6 n P $(lP " , L2j`6* <@ l|rdP x>.  b`j * F X !f & !l#2$$( "&ZV &ݤT&"߮ߠ4ږH $ !' *T,V+ >($ \:JtL L P Jp2^ & `%^+@V.4,%6 4 t~ B 0TpPRXFxDh&fD~|4D*6Pp,Z P:R@h,R h%f((&",(!F"fR&8)l+2 +,*)$PRNh <TxDl~2hzxD "$L%T$ "pL xtz,r$$ "^JFxDzjl ,& R~F & Xl`"f:PjvnZ!!rV^\**  DR|@4DB6nX F H<  j  l ~  "6 2" v R  8X06nd8h06ۜ:tـ^b6LF>|tnB2jjF 0 * v( <  X B NFf2J^ @FlrVެzjF@nblx4t|hJT 2< R d ZX> N&  nz\H j r6VjD.TvL|B*&6HDH P vj ` 2 !0%B&x*"NJ t,قLx.(2LDjv.ddVv:rx@LJ T@DH D. T Pb dT PnBr n>Tl& װ^lߜh2:*4`ѐ n$ \ Ȑl D  bӂF^ D&)(%x@$6%>&8&#JTj8<Pl ^   z Rr  .x|: t ^6*\   N4b z :  ( jP6dݚ*B@P*ٰ*Z\NrL `8  > n:4x%X**&$"%6'`*,+(p& HB8NtԮRN\nF f D.(! )n 1,5DF5t0H>+ %! " $zp&v!R BB8 *R,:vxޔߒ~p6|:ٌ\4>P2* b ` Z2FZ"#!  Hr!N\$NX% R" dDhF ,~@XD,(b~n& 4BF bf..4 v: P8Rd H"f&2Hhb: |Xb6z8nL8h$HpnJ>P<LD `r  %N'V%0!( |$p )!.0T/$* Z"`$  >.BPH62BN$|(V&T v|jLZVJ2tP 0D6\D" & vDzx4 ,*:`<(6n@\xVzf8  ^ l$, /n/*R-pV*$(~'L) (- $1H2 0H*r!*@X (jlH`Bv>HtZ*$JZPrl ^^ H\ >#4|(@|,.$//.f$,j)r(&.$ ":80^*b>PVVzX<< z$f>N&08,(V"> p      |z4  p^~Rpߌܼ؆4zɾ.R((0@:R&Z(  r0N vR    $hv:&< N pdt | 0rJtdhVHZ~8, T  Z   Z &|n:H4f0ZN|ddXXDd8n" . j$)vF*$  4RV2^lB6pܼr8dbF hJ8VxF,D ."r T l  N""2 NPv! F! ZJ^* :(0&4܊ݶ(hrn0h L\2^DϞѺp 0z  $ hJӺٞh ZJFpް | | ",BZJ~d < V P^ 4 \l H N d |,  PTjr`  pxp RNxt"HRݶ^^x(\@(b  j4RP.f!6$4((++*)X,$2 L@ :fnvZܮPdJH^<. h ^"*21f589( 72.`d,>-H/&<0PJ-B' $Z\Vx4 D&LHbN d(܊:ߚ׊݌$J\*d  @,V@ \>t.p jf~  b##D l  Bl`04pJ*6|6 @ xhvڌJހ>H lJFnxT >R b X2 <(2 0X^$<~^  <x B>T\r "Z$'&N,&0$4"j52V,jp%@Xt< 4BZ *6XrP>@@:4,0 Z  &xx\4!&"& $V!v~|Vz, |rP >~ Ԛ׀ ~ `2vֈ4 Ōl$fע^H j f!^" ZDd|ZJ` p2.|& l<xJ&"|J>~   R H6 < \ ZPvFr^ 6z\H4 d4  >f   !2 4XJ *z   X^0 :fl~FݬLb.ݺ&6J~&l\8J *lJ&# T)d.2P3L0L,'J #!J ! V>` Nj( xX0l|TB$@V>BZ>".l,LPz~h@ Jl xL$4P: z<z~ ! t r * t ` r^ p`f8Tz2bZjTvDVh ~<f624 `^DZ  ,NN0j(z*NJdߐhBHP $(Rt~T"&X jR:bx`\`#T(f+n*0%vb^ BzdRl`FJ~r..$ t hT h TָD.<b&VT|dpX Z.TVz @r t l vH&V T<b"^ ـں*HN`0<:FZrDX,VJ RJh0,(HT ,d~$".f8RR<,@FNZX|BXDݞ<\|B$>&nD , v D<b nj&b.8 054* :j,` d `  xڢZ8$tp>ߜjDv0V,<4J F^6,z .r#&n 6&d *#@| V08b8 b R"͖Ҳ D`XLXV4\<"ʴ@~2 4t Vl 6պ߰#t*():'~$$##" btXP(R@8(z&zvB .v z fhRDT:8&t  D |B`    J * lBvfJ(>NHrް`.R|V8j "D8 Bd <  p $  Zn 0 r4 . &!"%'fV(V%. TPz 2P4\ڊ(>Pztdj$$z fl % -b245L^4L1.8 + * * ) '4 "2 @0n$R~rpl2 Zh|xݔߘ܎&HDN>`~*^X * 8FXv0 P$& ''r $& \!Xr n` Rtbzٌ6,@tޘ>8( j  F !&' %|& %"*`j4" >x  pJF6(V\ުXT4P\RH d0 r0L |V6R"! )!.6 1\$1^4+J"  TX l 0 & * `6l.$`>&ttr\h:z<$\ H0  b (2D%L)|+ )~%P!XljlL.~ >($"ht۴&6Hx ,T4LDt( |p,0N&<,$ RnDvn^(Zf .R`"R$X**./-,4&+x P+| ,D/0P .*%L fP "@ZlV"8F28&TXJl 48 8 R ^ :v4  8T  6:  B 2$^ZX4pN\" b,xvPT8< ` nHzJ,2FVf.<T l$:&DtFJj^l` bJz~ZjZd~RTp T fDX bJ < Zr4T>H4nd:޴jߪۜ:.8z86V ^^n|~2b zD""h $> ~(Z,ҾՆܮ H$^>>4,`X6 b 2 dN r " ~ 6"Nj Hp@!^ 8$Z#:! .lFftz .H ZDx(J4dv8LjnBXv h  > 6  6 $" Z8 tr $&':% !<(\ ې6ӴӒxװHذ ~ Jz h"*#,P r308:n9n5b1:~,z )( *t*'"!  &NBB.NF, *@ۮݚNۀ~>ܠvZ"Lz pd tzb P$ & L&xd!$f&N &P % <"6 B ( |zprLhNl>v^HJpP2 6T * v< :  !:T% &##""0dj 6 f lxr6Rd PXjZX< <X2d 0\jVzL v # &Z(@N)(& H .Dr$ \6:0&߂ݸ8 xZ XT@lP 0z2 , v 0> N 0Lx>v4 %)Z++&F*Z&#"&"v"\"@R6. >nV!V$&&'(X'.8' &lP%>":VlTX$XF8Vh 6  l nv*v Z  < x"&BbJ" Fd, TL ,P @\,$zJDT֔XֆP |4Dp  d \ Z^x|  $  hRBrRB  $b pxLB0z^ :J .bLl^  "*^ؘ\Xtf ` "Fd&p H ~ j(0 D(X.#^# 4dJ4(` >L* *n8Tfj Zxx\bX V | 0$4B  `Hxh4RLdNٞNLݰL B\ݞldLbnV . ^ t  D &J Flv66 B  x #(4((h$,:N |pHJP݌hڸߊ PL6 X 08|ThPz8\(b$  jxV|ܘ(lvD@xT <F2X 6 BBnP x f| (HVlh4.Zl߾ 8Pf*~Fp^ h@@v @$"%'$* )&P!>Jh  X jdp\lLl<rl rz , 8 d"` $!rN$@+0x2/(z#.#$>@&'N('l#|$t 2@  XRrtb##|^"|X d`:F6!"j#l" R(xFH:,z@~2zbL|N6 Rpp$: `%+./>`.+\(d'x x'( l'* n'&TnZPZB<,jTP  0 &  h 6`    Ht:J\8:Zb߼~vVf2>$2hhBPX 0x HR Zz0XVT   bF ` f bp@H\~z:$bP@0<RB.|~z0$ H z& " $B2j*`xP&8VB|.2D۬>BԢ6`d2,&V8* p N$).%` z D 4$xDl,X8ӂ֐Hޢ0P F0x0:`X z2 4*d6< &X|!lJv  | >%x'*&"f  0.Tnf  ZzPH|*4Xl ft~ ڞtʦZj$Zr՘2 H6#$L l ^n`  x$\~Xֲ@ R@Bޮb f:2h&8 Z D  &  xVR0 8 . J !*#<$H$#D  xl ( L|hlt 2ߴf .Z4/0+6 ' $ $%V%H" DXz,dN 4FbJP^2bR:r8^B jH ^!T"t0 X L\J#$N"8|vvB&F ."v4 "t۞nB.:^͆JnDr~hH4^>bB8 "b#tL^J dDTrzft `F ~,,8l .0 2^htpHV%#4.$(4t#6Xb4<-N#$ vd zhl , Z dF:$b&F8vV&0(`*b Lj> p^0%,h120 ,T'%X0( ,/10,\.&>\ D@x.\6\0^P,xp^ t N f| ,z0vB..fJBF,NFjJ " >^`<,$D t!! @ L J! ##" \dr R,:>b|2R TT`f*>Z.DDt6 ,|~Xl $   2` : F 2H~r:ҮӰn$dN8| rX*f V @ 0 h P:Bll D @ DN ^bRlZ~(`bL\v8 >b"b:p\vtV"  ZRltN 0h R F< (B:: ^P28@b^P$ސV@*F4@@p r\^2^2 l p$P(#  Xd" R x8٨pѴ Ө `ݒxBFVl~4ߊ$T.l(v<F L`p @6|v ,.|0 H><:$6 &> & %^##!"*H$XN( tDL0ۺ8RD׶t " fv؈t<<˚dx *ܰӂ*8X d#R@$t"t d:!!, "HN^:: ` b 6z *xPxt*XhT   ^ >pxZJ, * T h2 l  bdbVpvv j B L   xT0nF L`'P( d& :%',T0(X22., ( |P 2ن`բԌvlӸծx|~ҚӲpDV(H Zp'( .Rt353 ^/ D*%:#p$ &h&$z.Lz`0v.@@$FdVLV D4 8\Z>($#'X+>-+*% ^~  6z2f^*N^tݦ:~ |Pb zljB 8LH~xN h N zD*"(" r|.dX|,  F0 XR"r ""DfLX^B! n&`($,V J8 r x \t>pVNf62fn(^pn.( D >8X*(.331$.&,* X+6 h,L N,)n&#dfD4Xv\F\80vH p J  t ( D D B , &zn Z|@JbNhbߦzTXhVѤ&.0T@JD H4>h d6& ,h L TFh!6$"4FR ~"b 2%:%@" j&f Bz ވ2X4,x>RZ@  pܮrȤ:Ҷ h> ߺ ׮ " 4"F$n&x&|#jT!4 R HNFvpb~"D  ZXlvXުކ6zT\FݞJJt߾6bhN< @J  ~4> ^ x ~ &( :H r:4 #\n&L~&$  v`p ~$N٠0؂پ:tݰpX* jV!) /355F2h. ) && :'H@'|#rn^zHT8.bD"vV T:Ռ*8Vٲf6"L`ߊRߔHT~Vf|4 xfjt J h"j%l&\%t# B@\ R@d ,bDjB> J@X".NNfp &^ #\" lB T $*!8-.%z+#V$x n:  4D8:H\$&XߤDv*|l 42\ @ j$$2!~$`#j*R"-(P-z)"    P" <D~v(:,TN^h`jTDV"RX X60R ~&PL"|&V&#J~8 RZ zߠ(P fL pNBzvJ|X,Hn x > H h04hTXr($ LT^0( r#%&4v&%n%Z%&\&L%"Z8 N~`>HF4,PVZJ6TJ > X  Z ,D P$R$ "  TrF^4<:@2bX^.ېdlTh6ZF 0R 8 z8:< $t @ d p Ppvn $ V ::J`np`vHH2ݸ`6l0B\L\VnT2 D@| ^l* 6l nT T bn2` 8 v6lj:p<(R8<\XNRd>DTFnv0b  < P*$|42j޲jό:H|bl~:^."B`j`n j~ \ :P(^\zBf"^ r# l!^0H0@hp <\~> d 4 jZעزf ZX ݊ pPt0Bʂ&6֤ <۴ @ rh֦%()'fv#P >!d(#$$ "PNHPb r Fv8 \0DX  V68^|0 H| R ^$ rJ,^Z8 B6FLR 6v f 0||, J d < R BF p8:   r<ZZz> FBՖ :V҄lt<Ϧrlق(0R X 'l `/VJ6L983D.j + (*( ()' r  >P &``RPflDRR~L@لBJTR| *N (& !<V#!D@  ,&zn) >( 2#t TPD:R pp:|,n&~ ).Z&d x hN& @R `ZJ> bn `n  B$%#)'B\#l^  h#'Z|+4L-(+j%2 LR8D : Fxznp.|JXF .X"b`L|& (*6@V. (  X v h ( Lܞ߾ B$#&8# )^ ,@ *V#Jv \ 0 Z d>l D(v(0 ߰nݒ.:p.&| <  T\&*--.\/ P0 0 J1 ~0 R-) &!6@$hx `z0j6<@:J:  ND L:2pj^ x  b2 |H rP\h Xnzrp $ nrr.L،dbjtr.:*, b`d " B  B2* N< @ ( : "p hFN,xܺ:߂ H04$0 ٨pR\ h&  8B |t ~0h0,D@ZD`<pݼvڔVznd0B4( (b 6 > F6^ l "4)Z-' h, r  BRNܜטf&LN`^jDFNr$>hPPh &  pz 2   V"v.\~ndt<HPTFnH LFn HxݠھdBΖ,$ޖ\8"vd P8h$<h`מf؀d#b(`)>|&F"8 Td(jh:8 ^  LT H p(`4pF`8 B@ . > x4P\fJ2XNTpF.DblT^ڼld$Fv jv  r (H@zR$n!$ \  "b!p#t$!J *dF &LߤR$Z44f(4<ِܐD  (<b"tR* `/j^3T6641 Z-)( $) (`8&  Jr ,zbr:`\,zBۦpJZ HBݬRTH^NR 4&l!#`!0 dd`d" $x%>'(&x& $HND |d2n,tfT " nfJZdt 00,8^R,6  B~.Br" >Bl6 0$" !0 BRF: |"*VTX jL>r .jrP` DrVr  V xVLlp |  *  N 6n ~  T*, r ^$  Xn&L`:dD 6(0Z>z4V"L8r  l>d4h ~ * (  " F~ $ h <80.PhVL J.P0p\>&Lz V8*" b$  .fJPB^ ,ZPxP~LH"x4l F,.ldH f |*N\0T & LTR D*rx \V~Ј@HްlVnBtz8~n <TP< :   bp.vnR pt`|6D0 pt>VZ߬t  rxh&׺X ܞ Xܠ\Ff ߰*z\ݞdB%<*L+(#r `|hD>hZ& Xj` 0t d~ "  \ xR \  2L * X, @NNbn(Dx0bڪj|rpbFtӰ^&>NlLZB 8 HxPvdH!&T#h8##%8(z2+`^+'!f > \N2hz426ޘێlٮ0d~H$\ N !v'( + /035F51X@-bN) &'*'df)~+()H! hv $~6V@fjV$@ްZݢ>Bޖn޾$~ݚn Rxj> 4 H0z @ 8"~"X #T&^b(J&<  . (|l>ZtފP(HDDxV|f6" h X2nFX H ( Df <Z Ph"LRpjb* R,d  P ,N0\x HJ#|&\$-"*. ,V)(.'`,)|+,N,v)#"  P :xTBL&PTRRv.V^|`6 z l 6"  ! $ |%H 2&L >&%4%&b''&&&"''p%~!4X> B:zn ܔll ""b$ "$l $"0 *& ' %Np .L V rnJj:^J0zf:ߺb*0b &n$"$@ r""R"##T$<%($!:T|FVL 4^xbVr8.n6"th(6rzz  Z  X   l  *pJ,X>b <. b ` 8Z.L .0fԂ.\HӒ"מVT,N((:~P ` ,P " ^<$BN~Z@HL V tt2&Nlb,h40@X~.\hچ ,:xdf @ x ^ N" d J n @ :bV `Xܜ.ܒF<l v2 ,4,r@ :(x01L',*B$t` . \ VrNLѶNJtvV.ܖ֠l`hJNv4: (! <# <" *Z4J&Jb l$` h 22ڔ ή@`2Fٮ T BR@J˒& tZ(4J X Fx@$)*nn)&&F%%t$R!l$<:, 2 " . xD8 ~ z\ R *Z x Jn:BbR\`t2jhfx6V ~x2 t J   hn@ VX!"%T&((p(>'r#  N&x8X,HR,. 6 N(HL.!* 63d$8:>:9:\62/ Z- , , ( " 4p2T@j*@@`Hj66f`DRlPP~B۲008`ݨߺnL6jjl  &       2~< R &: , j rHrj&<>nr JN(>|x׀: ljB!r,$T!& &FXFB j@<B ^rJ2 N$V>j>  !2,!pR<(bj|&p(,Z2/\9-$<):>"v5Xp,>#RF~! @ j (tTT6lZPZTPx.b |0PXNf@ 00V!%2%#t R,nN#&& $! (p ^ , <t2vNV^rj0>""h|L DBj2&`dZnp(l$dv* ndbbVD!#% L&&V( T* +, r*: ' r$ Z6 LRlb2  6*0<p2$~ z ,( x (  X   R J b ,d,VD4  .  | l4t p b F  *   Z"`"$L(~jV>jߔ":ن*4|D@H&xnx(|*\ zH.:DP*   f'&# FJVhX & 8d jll| V0  DȚd<Ԡ ` TT$Ͼfd %z%~l"f VR ":#0!VVPj:NRTZ> J: R`BHh     (: |NBZ` PJ  4&$0n`Z

~.p"JJh b N"p 0b h  ~<|"!2 l \ Zj"$F&B'B#\t, NNZ^*B$z~V0v2X B! f*2jZ9; 69:3hV,&n j$ `%4 ($*@(RzZbJ:v^p(F܀ߪrP,">ݖ."6 |,  ZJ X&`")&v'"n"(~@ f! %b()XF)D%tb"|^ H `2 @2 vP"vT^pxd.bzh^dp h L   jdv 8RF, \f ~:NBJVղTԖj,^" D ^ z hbB $" L<\hX" %'$ N, 2Dx.T,0:dnZ٢jZ>^`6X"L$Hf8H & : 8N &!p " !^XbD v4 <&Lbj d L XN H&~$Z'% "t^"P \)$.V0j ~-xF'6X 8dv R>phL@2 `ް@pH Hp& B^ $"^*-. /:h/ / |. . .d ,~N*((%  F<<2`8j:lx<2&  N  h  \ X j   Z r | :D tvl 8N lH^<Lpپ*B*TXf8X d@~ Z6!&(`L$ ,, T v@,P 4\>$nf.~$RH\ `l\B hN`  BZfn^!b  2|v4! b! $|<x DR*&ݎ 0r "j .f^:VbZx4(T T"TҖ|d"RXl" t0 .VTڶ`" LD B j ~R .  4 \ $ z @P4 n z ` L j$T@ dJTx  (FZFTP`LJۮ*$`Ll8P& L :. BzT$t!j#ZX%% "*Dz x(b(6. nلZ^ۢPx8\p X:( D.x R0^^1Np2P2Z0"P- >*B(|'. h' %PV" 6 VTn,(R nhZph02"."٢ܸN:r>r$ '44&p!f,@lP z% )LR*&X)&"8 Z<| nT>(f`t&8&J2Dj*vRd D* p .%%B^ jL F V$tx+!+<#$T  & *  X,bB2vLBPBXp$:dH! $(&.6&0r"0<+@#  JLV , TLDnB 6N":XvBR 0lbD$F\t2 8px`l$vn!\'+T-R+&X"|!d"t $$#>xr N @R 4*n(*R | !  T<N $l:dr|dr8FfpZZ 0@8^ $ , 6!b"f"#R#4%%V$~"n^6 ,VT$\>n`x$0Dl": 4x0*D   l t p.  b  NF&JRj~* x^bפLpԘ nnb`r~8RF 4B2^@&H<  8` B V 4 D V dP ZL H $ L,&&d~ N.*^2Zvr$b..x$t2P&rn|2H8, |d>|<&v@j ^v64pnN> 0 f *"`6:D'n)(# nJ,NPx| r߮d*ZPbXR`^\$  t| ."l4j8%T*)& B%z&(|*B+v~) $4 ,zJ0b:td҆`~ZۜzF. 0 8 dH0 #T ),z+& 6>(FT"B8:2Vnd^ rhR8".*.^H,: pd4%f%!6 P"!h&:**$& H\z6 : 6h^(0t6.`H~8bf :   ^ f! zB~f&$&Zj8|@&>l <fT:  !!#'#+ *'v$#4%tp(^+-,'~.Bl 4fPZPP6N&`>rd.hD<(Xt6   $4H~rdb<B~|B t |H : `  ޲8n4ڦVRT68b jvj!$p#BXZ|BZ.$pr  :VtH(*0ld^^V L" . . :<#T* .h1 14 x1V 0bV0j0^0v/ j,F )0'#  4T4>ZD:vbVB`8  n  H J <  r X x V0 : N<( h R 2.XRfBҎ:Պ4NPdPt4ZxH B   n J Tb L| n 4nZ@fjxdݸٞږ$bD޺ڪxר՞4X*XVR|@4nt 6 0 b (Xr:nj2*~~B,.(@(߸^چHR LPR:F<NRB B\b h0F 4  : $*&FH"th6h rv4X46ޮ v"P$dT.&P B  , f 2"P#"XZ<0 V,~j! !. J ..V~ZBZ jdN \ bF0TH^ @v۸^Ԥ4x &pHj|$Vn!hr#F!4&Ff&` 4v |L2 HX <n4tn< Z   t :   .HP P 4`2$<,*.df\<*4  zt "n:$>"|x.`!"0%&!$ p t F(..jbj2n64h $0 vHpn X!,$&%*#,r!-+H.&*^ >* D h8 b " bJ J p.&VF\&`Fn&n(vD8(& X lhZ#4( - 0 .2 1R0Vr.X , l,X , + ($pz 0nL(f(DhtN6$pB$&~|  8 p j P^ H(28 8N ^ Z,d 6^j@~ \pZ"&*ڢDz"v 0  R*@r\&p$,|n/b( bh , J ,@bb4xڶt۔߀Zx< ~(>|z 8  , zH$n,0d v b`2   ZRZ.  R\pׂ@x^ FT&V ؈ ܐ NPZVFf&  l p"\ Вlb L&~6(&"$"#^F$~"0 2v*n:\T  > (6 Hx B P ~Z\xl 8vXh"   0~~>jf& P&>BVh2NN4~F&  R  ~   : T  J  @ Z 0 $F"T jFT2b\D V۞zv\ھެfR F  P@6&pb,B /1b21. +4 ) &'&&"2trrn pv\T*x`~nJ^ZTހB܂:(<ްTL$^f."V>&4bFZ X Z 8Vf! 'v +,+8,(X" `Dp0dtX~H|rfFjxz>:<`vR|   x 8 &$\^'*'&(&"!    : < X >L^bvhjl.* 2t8 p JlTjp"L^x"'&)T+P*\'2!N : V   R  0Xj(PjjR^Dz2PxFX"*`>N4v  nB!~##J!vF 2 D| bTr HݞDt` ~&vl \8 z0h`bh b .l::<fVrVFjh~ : &2$pbR< b""j#x|$% ':J)): 'l f$j H~<(  2b H V hP6 X<J b  ^TN4D z .  Hr 2^       J,flrߒfrڦ>2֜:یR>,tNHJfdT|x  n*t T 2J p   z 2,r0,vFr|ܚjپzB >bd$8lb:0T . . nR : F @f N  >&\  <V<~N&Lz߶,Td($fXT x D 8 ZVF!F( 4,, (^" P2b 2Pt Z.T.~ rH& *d60~ f vjP D4F$tZVV`\RԤ׌8H\>Rf|ӀR@LиhLx,#J6%z$6#$88$\#J 6Z4hj f l2x2f( P D2 nTvB  " l  hLn<zz.>Vb\F^<ܢ0l6 V\Z . V \ %~%$Rv$%&('$8  vp  B0ݼJvR4PBמjvԤ؆26p 0:<6#,+3bF9<  l4L  H $$8 >#f @$@"H$%$x# T4V\T>zBH8 j j$t()(N0&T#J"($x,( +< -*.$vx8 ~H l  <<|l 8$0>ߨBL8` J>\ ^6( D'(+j-F.- **'h '&2r%z#< \R z6fR0 8FPzvLnl  H v  T z b j v  ~T P ,  L:<  hX .066(<^״$nB*آJH:0ntL R .vh2,.L< 2 @Z(rdX(rx@>vR(Xp,4BPPf @  Z X 0B8~tj lF$ zln:Br*Z6FPLVܪ.LR(,:JD" VD( & d :#f)~-x)$lp*rdV6td:6   |D`:pD 8z! Pv b 2\ڴdN D$Nق V", f80& *zF ܄ Lג4Bb"%R%80"f(X$h~  , 2R  X  `r v v  VL 4\N N\ 4 @ Z ^ RJF>&N8R>RzFf .4( n x  Pf >B`vLVh  0b t#$#, l lP0DHHTޠFHٲr@6N4 8Lp4 )dF/*2r32/N* x' ' F*.Z.$D* Z"NJ &N @DߪdHL݈ڜ݄\ 6J<. jL "X l`< l D `"n$$$#RP 2,  b Dh(dpl6h(4P*l pnNr>J V L PR"B>  p X" !B$!'n'Z% ' L6 @ bD(bB$ zx|RDrn`\.V *x:2<~HTp6 :"H%!(+0-d,dP&<    8b ~^ 0 |@Vh ` Nfrb4>ZTr`zF ((0n~,.~,!p&'`& #nN&B:">~ 4H.\ Tf\ * :^xZ2d^~Rd F "v@|0vFTLpX: tzvb 0pP $X'&N$z!  P " $ j%j#^rLjj(,^PzL(V.ZDf|*^.    > vd r P ^ 8\     " >rV:rrdfbԾVvxʜl@˨^\\HT@: ,:R  :   *  *"F t  , 4x J&*H8 r^ޠ\6.dt6jhH`f^PF&6.~l(D XpXjVTHtxlF<n>t@x .&dd! N%J'.'% ~$(R# "*$)z.-x& l L \> H,ݜb߬`@@,Z<>> 2x\ H*2l. J d \ D > N 6pt>&$NT, t2:@njݦth6XTߒZ~0DШҮr@\"VHIJ VԔF^JBˆ vV@nVh >X0 bHp d ` hR r X"z T d Br  (t\@ || * 4H< n p $Z.f . x  4 *rh@:P"Pvf<N :0h  `<  N "!'$ N*,4)(&#d#"J$&((,% bP bbf Ll">B^,v.x B@h " $`p ^ hl04LJ@(6Z:XDtfDT>bdt .hfބ &vHd(jv:tD*fX r 86 #%F$vj ~Z f bt,&@Z bvN>Pl P*B*DXpdd r ( 4L`z#d&(l)* )H ,(* <' $^\!x"dT`Zp* D\00". $V:~h\ r4R$J$X^@ J@  $F| (p & J6|.lt v    , H V ~0\2p*|FX8><<6۲ؠ2*fP6x$&   <N   p"~"~ 6fV N:H(H^,hFjTf|b$ j r 0 6 P \ *"n^ .r dr@@26T0 RnHR߈D݂hXHPzvغ ljڴ0>`ђ ֠<&F:2 ۆ N Hd!6#+ )*,B -( | *>( 6d*J.(p2XX".Xx&$66pl<>z`l F< (!D@"# $% $ b$z $ 0& 'F%h hJ `~>tZfLd@lX40t :f:JD4,8  lZLzzv.  D$TN|"|4HD~&~׼>d& ^fJtxn6f*>  z*jRvb"f$(#   N$ R> 6N|BxL"v"XT>0z\  b^!n$N $r l>!$'','$FF!4l @ B.`tr 8, ^z ޢ ^fb4B#D'2*b+T>*'n%6$N%&6 (x'n$ : z r ` *8&P&(x.`rXrL* >&$)/ 42 8 :P8: 7 3 1n 0 .+' v^PtnXv\"8Lnv  H$(2 x xJ F  d(RNb \8 *rbD&ڨdlL4Ԍ^T݂P,.T(> 6RR& v@f  8*x F  v*v<(ۜܶ6$dܜ @&:&< D "   8@b"6   j.Z 0@vzjJ`:b`VHl`8ߚrވH2R.T\zH 0xj$  NN* .f'0-0* >@p Z ^LNh6 bZj8R"N\pZ(jZ, Z  L   60lN!X Zb<#0$$"F tjr ,֤<ݎ \ zb*t>ͼ<ϴ X߬ ޾F lԺfߦ"f&r%" T ( 8R~bV $(  ~H"Jb 0 , ~ n P fJD Dl"|Zt~2 V   8 N  @ d8v > z Jb `HRJb * 6J8 jL:VZtb$ Pf8J t 8F<!4 )/2*4>4N422`0d/l.<+ ' H t < h 8|x F$>v J l"h*^$zLڮfؖ,pDpj"ِݨtD R~68"( '+H.+2)4&*4L!0)#Z <0v`(F zD8 \rR8(lft 8"pR >  @`L4>jf"fjh  Ft,"(x+8,*F($!!"$#zZ"h *h4(* vz ,, * HRv&:(J&FX`.RJ 6RDhtN8^2t(0B:|Zn&t<F BbpT*F:bf~L,lhz2 \b^vZ &TZtN"z>,R.  b 0 (  R v h  b84Xv60fzN$x\  p 2Fx\t$ܢ8Zzؾ88Jt4~ Zx T$" 2j  f  R DB^ v n  T0,PL&"&0bT@"h*6 20 dhh4<: p LD<"f> `D Z,@, r\,P`bڔ0HJ<$0pbh( tj"h$ ")t-' 0 R T * $ z<z,8شtFPhvjlJJJ b .> ~v~F!$D r&0% #F<# $#  $ h6 N~bNלV@JՂڠ ݀@lѢHTT^͆ J v ׎F̎z%^*+)l( (^`)J)J'&%!lrNjpjHD J Jp :.>z8r:0J 0>r  2n\,,*fzxH H60\ ޴ | \"t.| 4  2 4 Pn6#2Z#$ "#&%j'd('0$^ f"  J*݊$Zްݐ80p.,ݘ^0` * j6( /3 6$684v1- ) &%$ b * P*6Ffl ߆*@:|HڦTن&f,ܺܲzDv0f\\ 0vt$ & @FdVv(" 2&~(6(&B"pD*0N*FlrHPpr>D(D<"6JD, @l^N D$zL&T"Z$ Bv ` \j| 80\4 &6 nD~2H NX"X ("N-z!R061$ h!L ^z42 B(XDnBnpTNF,\lRpp( n h(0tr#'P*0-p-- :. `.@ h. (.( t,l")%R"BR2& $F,&~:|BfDh|  ^ R X n    Dn8 @ v0JPjpTٖJJrRӬ`r,߮BFJn^*,  \   R , PHxD h 6 Z0 @ .Zf\j0XZ\8`J>:^vx ` . n\B^pht nz&4R@Dh6Xpxݬ^۪XܸpzLj.t Hx 0 N N8B'/f1\*x`  J &p|h*XNْ6h&&> BtR"N  @ b\!n: \LV!L 6""  ~XZZ z8V ( JH>J:ܴ b(FHX ٮfZ"h\2(!>!d݀TdF"  4Z <^v$Z, L @8  4 nT R (r@R p jv L<nXL*DLR,JxPNV v R4 ^$V\fH &\.V.#" `Zj#(|t-6x/JN-d'l4. ,V݆j8dڪbެ6x4 P*2t& 61n9?A@;6P 0,r* x+f+)"z Tn8XN<(T0L(&۬\~40lP4r&\`Tt@vLVB  *   F  8((N\ڬH$|۲*v60| :d Vxz *P08@nt %*d,x+ %: j v  tz6.t22p(@~2 b zZH N R@\2H`V 6N#& ^%# BxF>"x(r,fD.F-*&p"z!"""!dX!2:n*B\(h ZB ^4$ XD@!x$'(j$P J $< t \ &dR &2$2X@tV (r:^f&H V!8(,-,b"+*(' ( ) ) n'$(j^ |B> >(J$@$pt`Dxp @ dn&dH~ Z z\ h  0   6d  @v d n Z z,p2phFdڌhd"T>&8Tj0 Tp& 4  b (0(j  >zf2@ B4v^b>D>2Bf >n^@ޖJ8,~h: l f ~Zh0d`*(2trl:א߰ߴpt :,Z ( " & N l2\"(*%0b  0ݺZخL|F,`~:Dl @ n D <$\'.$$ |n6$` '&"b X4~Zb4 V^hD zZ $ Tf Hոhn V6 ؐzȸP.dh bڄbH Ͳl"d#: H4R "\dx4`D  P  0 : ` <Txz.bTj"nPx ߖnڰ,L4&j.0J>Rn \,0N f28 j!zB!R"$B'0((%  |&j ">hL $dHT&  v"J+ 168;=:<925@T1t . .R @0/ ,$Rxf^l :l޼݂hPR~rt$6,(4xx pBL4 : > Xhr86 b4r 6 : ,v  F|`l*8N( pL < XTF n b(T8^  x"(NLr06^tb\&>H(ݐ2"2F ~NZ$b:zf""!%'&+ &.H"p/,& 0$ D  H&dZhzF:4FJ|n:J ndr"("Z 0 ~,hB%b+N..\-)%j#j#Z$X$P#v!&@H(& &prxr(!#NV$"j xf BfP 2~@D0:F2 JN60R Fp$'Rv'&%$0$N$#n"z^j| d Bjv:Nr\hb<Tn  L $X n  : d  \vBv$F, p h X6^`f|݂VٲՖ׶ T8 jvVP .F 6 & f H 0(. 0Lj4Z6P|Tvlv.pVP"hDvZ6*Hz|D v.^8jf2x~(t߼4h*8 x8l@Z >(2L r : v8& D%++T$b * B,L <ڶ.׾@(*TD6Nl>P: PT ^rb @ |xhP0!$$#B prHV\^D6Tr<ߊ   v*2"t R ~vP*& ھ&r6ʮr2`ۊJdt^*ݜߖbb  RH^FN2" :frx6< h\ 8   * hzT  0 ,h8d nL 4z>xܞހ20N: dT^ V xp fp%j)2(&`%N'& )*+)t$(t& bV bx48V,:xPۨޢ~b*| @:jlr .&<, p167~62l,X 'P$B# T#" ~v ^L&xZ ".@$$F<6T۬(Bق |nR `nx H|`VF# # , d @" H |n Pt$~~p* vXvZ&0*n ND(8l R.(X0| .4l phB(FDpfT< bh >H  64!"" #|. "x$bj)!l--8)0". J@F ~:bvP@.:T4,*,,(:N D @6F ( ,  ! " R" PFlj "$F$Pl%%N#|ZJ4.. l vR~:%+(j.",t|J ph2d f!X"L"#p^# 2# 2"p 2l,6x NLn*N:2(` > ~NR\60Zj28Fn&DF0F R xJ 4 6 |D<`nՖpJ\>$dZVV   Dj N ( tb<    &xB4`:2JhRdPh~~ \ݤ$ݢ^Pj~8FRjZjp@8v\npDHJbfh vDbTNHd r^* B LV *4"'*L'PL j p  <X>t~4 62p~(p P$jNR h    H PV f< ! Z ZVVB ަ:x&>݂D6`,К8Ԍ  4.ϊ<Zv"ςجHDX,T >̀0ݞ@t@F| @޼ zrLH   Hjrj46xl6$   N *Vz^N F, .x ޜ V rVF~ڔDߖvN * ~   ~T4 P"b B#V&*`++,(.t1&".3h!$3D0,+% $t <Pb`(FL" B Zn $", 258::F7~2 T- )R ) )`)Z ' ~ "l Zb(LdTD ~dް\\,,՘L`(j۲6V(א>Bb\2 JF"  H >R$@0   z2l2$rn<^n6&lLT,| (4~2 |Jz d H"&!8(P Z `>"J(~lDH~"tJNp&p<^&4 v !z*!8 |B! %"*4!. 22/`@( !  8& t 20 T V^\0F>b:rXbx|*DFlV$hPv&Vdf~\Fp"R8$#l!f"V^dR~(00 tBn "ZB !<"! bFH!Px"B!$N `d "bn :n ~.|P$||HzBxn$2j8~JR>D` $` LtD\#%z%2,%l$# $ $ v$b " `>: R*<L.d\D" 2x 8b~p&& "D~`v ` z2 zpV $dl(n@ۼ*j"6BJVj8~R &6FX  x""r6h8@>"bNL~ XFjZdZ* |dؖLX@jr$.:B,RfRlnzd~Tn ^0hlN\B V4^ rZ * 8  n<! &`(.)) ' % $8P'>>-6"1 p0\'2D 8&Z߰ݐ8jX2bjbDzV(, PP n^F f v\L4 |pr<nN!"T T$ *^ t .Հ׬$PRjL ZTf~΢&҂,ΞǼX"l *pɈj \*4""\:  !Vlh.$~rV |d |2 p .v<0 p6h ^|>j.v d | j<"r&pZPd6@*~HJ,zF\ 0 2  :r#hD&th$ H" Z#:&B)(`,,$*b&~<$ t t. pڴJZJ٦.^ L#6) :.vj2 @30L,4 'R"h  F! 4  @$FVJJ*tl\"6h$H r(ހڔۢנXBnppzdl$@nV Bp ( ##`"|$Zp j$J"X(#&0""0V&"&h(f$T,  N  t"'($*  >,P#'+-)!:\F 8 6^8`L(\ZZvPJ >lr@ *b PvLhf@PT Zj8PPrZL  h ( >v ےr&ؐ\"4d"F%|#dfT"&^#(0j*&v@ f8r B J 8 P f*6L~zL$xTpP|X&<0 F J ^"p ( . 0t D1 0.04/^V.F.-8+@($ &J#:@h: 8HtR$r> f"lNTNB & \0z&P&J"    j r, @P\~x B bvV*(<"TT@ڔBӮ̶fr̒ע>V \R  Z J  @ \  D^ lz | V,:`2$vpz`J>`x܎\FR jz0">Vt |. 0f  6| L  D Dfhfh:t:6>0dB܀nD j~8B&l TJ > p `x\| %*)h !"b,4Z,`    R <  l0JVRh "< &! rR$xfV d<,P424ݺ~޸(>6۴X*^հ8 ߸rذ$ Ԛ&\pL (ׄӺ6jޒ$`@))z&d"!@""!(X$82 "@t,`| d0 : F P ^ *(d >Jn t<Bn f0 B߲^"<\Xt|ڈ>t,(Bd> jRJ R N 6 V~.  J ^Tr$ 2F Tt d8Ӛv2,\ՂNۖtRpd v6)& &/ 2b4@5&4h"3v|0`, *r l) )&'R# * ,&Nt$vFV(:h 22v.D4JVrz^ ~v| ߬ > xHP!x$H& &T%$$v&'p'0%|"$& HN:PR`^\j.. D NHV~#'v*6-/:0/Z-f0-0-* , +^ (%!$( lHZ\>LP|tpN^, h $ z F v  | ~ n 6   F> F NR4"jXFBR`hb>>$XRBP6T ,   X l t`\  ( t rfl  ~>8߈V\:"rntdb2*4*jn   6 L:":l d$ \xb8pX4hDj FdF"P0n`(Rhd(6TPb|%P--l`%p \6\ L ~x~հ~``L 4f0~8 P n$ ( "pX0RLTp> Dp&p((> XN,R֞zzۖ\vvL" H" *ܔנv΢ bѬ!B(*)&%.&~&R%f"df$2tP(0, L  ~    <D Z  ,T8 Vd   x 6>L B8hVz8vFz:PR 4  Jv `Vb b R^>r "v&#V!p&>8 >l(.ޔDܢnHH T&" f%f .467D64j1. +* H*^ L)6'RR# 8*nZ 0NފjXߌTߒ&~bp߆pvNp$~v P& PDF" !T , TR`   j \bxܦ:f: @|`r٘|P \@>R DR 4  \r,|,(`$&*0ݶ84bd Jlj4j^LFld.NL!f!F'f"(+F!,6*$. Hr b . @  ^`D8Xd6<.<> >  r(Z D" |& T'd%D"d.@!$&+`.p.-B8+"'v%V%H% %<$JV#|"Pn n@T $ x@ dvX~dtTL#(%X%$" | PBT RPl::`P*H D> !$ %\%~%0%b&r'j(<(&&n#.`& >6@>v^jrvR* LrR(NZ L|~4Pb.",Rl v T6Bd($PX٬J6ӲP.VδԔ0(JHX^br HL V^P  H<(>~Z6~  $,: TR>thzߢ Z>b~ h& <N"8t4>(dLP.H`*zfz Bf\8X@0b &L\(-\6)Z Db >  `phVӒ۔L8`ff\ ^ߦ4znV 8 ,V >>@0d6 j|!^ # " N4T4.&FR p6N"2ײrl$" b N:܆T0˴,f  *ߪҴ L^&Zv).)t'&^'lB(2&:! <\ LrzR $ n z J0,p6 ` . jf d J j t >Tl $ zF\ގ f vf0۲D~pH"  : t R X <JN l6 x$T&&% rhh n$lNٮמx&4PBRۨ(20\8fXR|hLN LF>h8%(-@3L66 3J. F*&%* "'FP(p& \H L.h<|zZfHZ(D0,H $pD!%R''>&#z!. !p# %\(:+Z8,Zp(xX,"z tRv@f24dvت~2bZp @ lj|,||zpb,D @D *V2F# x)J"x/!3^5$23 ,>F$z  f 8   Dtxz,@^jPt"pltz:nxBv, 8h X4X~ Pn Z ^!d`!* ~h X"%&%#.! F`XjN00tP , l N b&))H'X$" !0#'4,2.N*Vh$6F>8ZN 2zv,x> ߄Fd,BR j &*t\ Pd*~ ~&8(&# L<b !xF!Vj*D df,4(RBj@B8h@pRVD" 8  \ Dz   VT6$FHv"Dn|8 4 d *~$BBdR.<݌FTJjnrbXx @F2 h l zz  &8X 8X,.:v">" d`0vۄtݔN>2~X`p,JjV(zZR8hTF.d|T$T8dL\*`.>R8< rFrr | L #&F$4!z^ J\#$<!F<t0R " ޜrz&ݾ>z "Fݘ L $(&hr̔h @.>T X& ؎p"b"&|x*$ N f  v vr Z@x*  8T  v   . Z R  zT xN^.Vr$L0jzp|~P02: HJ ,R#8(^(8n&D%$&Z'")L*h'B!80^NXDچ(ټZJRԔ.&0Ff$D Hx|6& +.n1Zp1v/ ,). '. '.)HL+0*20$ XDjJ< | ^&DHpNN tf pHZ "l#8#"& b" "B 8$R&nf'&$r  8 j~(<n|H4~P&X x8\THx "< b ( $ B V ^ Z| @4hB bRv.d~@FNPn\ZV@V | 8.r0v #(&(4&B"| @ \: B&F>L$pbPR$t2^xl|Bh`~ * . (\ 4$r % @$"@! "%L* -.,-t,)'h%:%(`$^!d*~,( * Db&&*+)fH&>"0 NT" L& n* +X)Z"b  j\f`l8P""`F0RvPH DDxz J  "d nrbxT6xXtZv^&8֞ 2dJrX*DP> b 6vl$X.1B+ P>|4   ,~f6P | l8fP@ nR*޸dԸ<:(ߚڬtӒ͐r*J0 @2 FˬǞ|`j R܀6܈ X т v"N)-+b(%(J&l'N&4#,!~:,B \L dd*B D 8 V f f  Ln N8h>d^ dhD,&b<dhL,4\\RJL  Z  .b ` \  Rhj 6 zT@>tކڈNZ~x82t,l*DDb$ LV ^v|0!<*` /V23.1V,.& * 'H%6% $!*l 8 ~Hlx2dޘޤސތ߬",$J ^"&#V6@6P" B(r+R*T&rX! 4jx4~J~j(~B`$|ߴHH N . h $@DP6!ffjvr  t* ~0l@rZ^xjpނ܂8~| p|lx~B \ JdD>!%"+!<.-X) "   "Xv  6H0f b`8|pV@phl.dF@ zzd P40$(**T)j8'$"f$N') )&' <#f@p0 \6 V^ P" J4Z @ F :D~jLx&(V& zd,F`(B~|f6XfPV v  Xx&V4d"t %T&t&^'P()6**v8( :$p" F~.|^p |8XHpV   : " . FB *H f VB, b   lt0(BtJx("ߔݒ(zt`ێ߲Z `\|DH&6 `  *00BZ r  l  .p xz B$:Vrjڤlp:: ZD2D۞PZ\(p4d:h |h  ^D "6 >D8 . lV|` 8>TnX&4 T $X&Ld |LZT *  xf"&Xv-z.'z"4 .: N \8X(`TD،Hxl2\D 0 $t Tn hJfR6:x!` D!( z&D`R&`fHߒ`ފ Z 002NӀPN jܴ Znbjz@ʂ hזӼTͨ Dln$&%r#" !! nDnT0||Vr n0`4x& 4ZLb: H 6 TH ZװӞ:ޮ. J06Zp؞lL8^ X  4 8 L \ "d t2zR $ "x',-d8+Z% < |^,Pf::Vx2T^H*\ p f&PvN#B- |5   Xb *L!6 @D @L| bz ۚBd Tb(.JNN|`dHLjH\Z .\&, N0ڨք|0\&T.B~ Ff\ !B %H*@8-j +T t$$F $02r~؞Fق@ވNnhjX:pp@Z8>P8J$ Nb t4 "0"!t4*.$`'.(&)R(,%r!rJ:h|8<44 xJ߀ &48!$$"P,<v"8(Z \,\ ,^'<2 *NZZR,(<$\ $\Jx L B&Pn`Zr  < 0~ &hp'$N-(/L-*R'%X J& l( * 4*D(N"ZtL2 fPJtv hP r,t6F $Pz ,lB z ,  Jv lTZXdb t z(zF(8J"͠xjZX |V@ D f n22 z  ppP&$B 2 xLV VB^6FNRV BX`Rh|X@N8 bfF dF  j   x h \  R |6FnLLHޘj\   dHV. @FJHJ(> 8jP>&  x  \&   " ( 0| ( 4 x,0Vl :hbz*6rB ,z&.Rf0 d$ "b FB, 4 ^D<<& Tz Rr|(` ZP rL ~ f @x  >Bv 8Jxx&Br^ٸ88LXPRvh"DXb @lT hz@. @n v,0<6 ,!Ldv N\~fF(|,:RאjR2і &4 6@PŌ|B*$ LվX^x&N &D*+'X$D"d##hN @hfh B\\ tR PV   z D `:N N 2 d  XD* 80flRX DX<z2pTBr4*J rNZV $%N&d&D&6.'Z.&" &NtJ 6z۲ L؊J*~8dxHnt #( .37F8@5\1b, ) ( )*(B @!x (|6BH4fDl~n$<dHX\xHnbX<؄T" 8.\6zTt D $8&.%x# J" V#z & *4-,()L%~*x hB$ 0h6l@vDNp("0f$z pJ4 V^  &TJ& <tVb 2N"p%`"dN L@4d&T&"<^v^R bV ~0 $b ((tN&p%*')V*+r)v&Z 4!RF2* 8$VdV(0B(8V0"j x<8T,p0$:*((PL& p F~ d` &2 Rߴ ܺ*j6 T &l'H*&^#"#&R *t.,L/< L,&4D nxpt rZ*z$z *^T& 4t^r "n)d.L V1 X3^ 4` 648P9997 $2R -r)p#Fxh$  V8(nF* r6V,X  Fj4 J 2 d   J fT N&  :Z N pZlrѶ, ՚2nP(:&j40T Tj | F2   F.vJ:V V@  t  vj:lRJ~ d@BDRbhR@^tntfB*F\"0d * " J T >lH  d TH084l$L  2z >  >RjնP\*86ڪָX,Lxr^|R rZ|$vv*TN"&,`% $# "r0$2 &d'^'%  >&hٞZ2*h۸ PVz 0$V," X1 476974bL1 -*N)( 't $BVX $r&^>*\Hz*FNB*ގܠTVj`ق2ڢ ۔hr,6: r "0b 6! $X j&  %b  b >F,j4` <FzB(b64d 4vbhj"^bNL xRF8X 4lP@j4,x @<:~B0H V B"$(%#< b\0"$#( V @h 8f|z>Bx`\BfpZ ^ jthp"B&()))))~ ) (f& #,$Z" Hv6j( j4t&2 dX4 HF  J 2B D b ^ z Lv$<D`8b|>8 V.2$P|hHPܸ t brޮx"vDPt8pHh B B  `\  & J v  nj   ~ \&:>P&xpZFjdZZ2H,jPzt0J&j t NfZD, |zHr4~Z@~^zt8"8\@&h RD,J f ZnVp0|p & .&@DV@8*4ϰTV^@bBvl`v~B0j @8x Z   H|@>t#fN% #| bz6(b.h 06Z H<r Hbj"x@h 0" & T"&v'%,"x l v!:lP<` & ^ &(R$\ B TdZf>&ht8|f  "޲؎^`ގv$X r ۲x|ntzn" lL@ ` vn 2 x !2#*&*X)X+-+& j.4 , fZۤnۼBp"ݦ0 d l j2`P'<2/F z48:j(95:0 6, ) )J :+0+N( : BD@D*(d&nX|6>p:H\ݨپr .VJR*^ "X$ R Z!&|&tX"bn   6 pf$X j@jLޒ66N"PVpX  J p Nxft !(L(H ( F l<|H8J4V~,^VxH& Vj !J'!, ),+'X)"$4!D\"D!~%#)b&-f'*1#41hn+"  RV<|tb v*(~@T 8  plb @>db6* 8Z4|DtrJ P h 4 `X ZZ~0 2j"t'&Zh" R<"H(j+"\)4#tt >jJ>vP zJD߄$֌ڤ: fVvtlNP.@ $(pR' , . H0 1 1v1Z1810j.*< ( %r " ,\>6  6& &B*j&.H0j Pd  h @D Jvd8f* Phn  J l xRDRް؜^׼<ޒJZ:l0 ^jlt  P   RD zFvF4,|   2H.Xxv6n^V~يނtx@0*jn\Br6d`>`x|l:߈f4@ܒٜ`@,Dӂێ8J$rXD L .|pV $T,0FH,$ fZ  Fd8NB՜,ΌTbрn\.JjjNhd6 LbJ8Zhh d  pp4 8"f!>BFH l&  *#*$j$"H4b\ P^bp|TnD,pVrܞ NP (^V( x(`dvP^0&^zvt6.'$R-@.:^-):&%$"0.4Z8\4@x Jj r X4 X ,> ~ d. Tl" `,(|\nD|0p4fڸ.ڄ4H*z$( | & D&   b  >F !& ~d& P jJPZ؂hbՂF8֠آؔT؈Rb "8< ~!& .)&+,L,F+6 )'FB%# v!   B< VNR\0Td&NBܖ(,lLPh&`n ! r&  $&l&x$! L"d^\ z"nt@,2bX h    6` * V%<"''D&% F@p ^ ,6h~VnDTB,F*^jR8, xHFB@"#$\)#\,&!`,B\)$#<  h Nt  &  HrfD0&VD2D`\<LzBR d.>!^!0Dd zp" | 6pz " PNT#2%>N%$@###" l T  L 02(F |2vFJ&z4Nb >($lnHT, "l%4'x'`'b4'&% $vH$ Fnd\PRh jdB n h   6  v0  hfhh22, @f$6& XDfnF`P0VdZ.PH hr F< P\  . N @R  *t& H &8R|bxj2 &Fz0$xvDZ|Z2 \<,J.*Lf d: Jd2>Bb&&<LX (2&v(8Zn`dJX|R hH6b6 FH#p j D ,`<Xp8 tJն 8 vvXDV:jt*BjP^ b D,v"0Z&6` <pBx f8h 6` "r*(8 ,  zӶLxʜ:0x  ~ NTZ:ZЪ Z|%|2&#"4!< z"4$#>!F,,* 4rHH j> "F p> j$   %4%0N$x !.  Dݦpن@ ײhr۲\(, &`R R(,0x 7;<>9$5P1h |-> *) @* )> % H PVdz  x.rݐJX\޼Z.|6܆ߠX P vj Fd jXJ  4^  " %.%! FXJ ( ` jvr.~^4,<>\zZn :*'J$"!$ l(<x(Pj&p #b&b'Xd&T$"R!!*$')~)^&4 ~Z * \ d`j P0B>6l>^zN,6Z b&.#"T'pH*,+*&)2'J$":  : .Lh~x<2pl$4L pj x  8x~@hp&DF x b@Lr64P(v^>Lt4TJrhrFf`jz zPN.2zj$$ < n@.4x&lH zRb"8ZDb0`n` 4 :  6V<l<d n 8N.t86Jrߔ$Zx4 ݺ2DӸۼݦ60*^^vpdJj>^ *Zdx<P  !*\* R *h x:tjb~n^X8 hJrT`$ d L L`  p DXZn"2!2x  f0" L%@%z "VPv 62 N>6`r؆ N"2fZ j&  ^b 0~DbF T f 8 B  jNLt 6<0\8*8bzv-* H#BpL < p LD:XNHf(h0V$ښHr߼,ۤb@Nv* T J\$l > H(~f "n!z0 `8bP">tR^rؐۖZNdJpx|  T  r bF PT!#:%$"f\: ~ ^d4>tVxNXX`F~h|@v L6HV H |""("$ $>" x"!%"j*X$.$1"`2&/l(P!P b  pP X fb0V@z`XX~x,>lh NDBv\ RT\pL:8~T4D,b ^h6bPt&^V #.*Lf/J*101/,h\)' )+&-n+&\L D^ R  >6:fh*0 H(v*|Rz&n HV |"^(X!j!!2J dF d^F$&>4*@ZbXbrt( J & 2<  r> f Z ` ~N&  ^ 2* X J>rn |:*d:0߮ < fDjH^^~BR0 2:$*R&pnnt x\40R,Fx,4pBf F$RDFvdnH"xnntpx0nDz8$ XTx.x:.ߠ*,ڮ۸ښ &Z0~N"$|Jth f\ ($L6z@ 6> ~F  ZX(ԆV xb~:,`~:x0<֖~8ݖ:$>tD̖Z͞Ը L ۼr~R,:p >pR z6(\( B &4'<$v!.!#$nP#fLv~6 X f ~ ~l ^Bt `B.rn  N j Z6P  JXz4t*TD8>!v , 6 Z!N#,!j 2.. 8Vl,6ު6ߎHt޲6:n Xtll ^ & -r1B48 53Z1X/+x D)(, (Tn'$\B~ lPpN^D\f~>Rnx r~n݀ކ, RTPtF vh~ J6X$2( " PblH042FN`ݺ*F|$V@d( ~P "xld 6  Zbv:P" 0H0 `  Dv0" # ^F,~v!%)6$-`-(*H#@ lV x t8`$vp:@`J(`^ r  v   X( H~ .hFl *x"~$& %~""D\$^xj XjP z.|z"z#" &JNz 0$Z$|RhvLt L@nv8~Z@~p~ nN(h($0*, -,X*r'% %#X!2 ( ,f6F4 hrf848$v& P f p8JV|  d HD  t  j h(x\x$bzNv4R| bbFFv  v   ~`N~ r p~ , r : ( v f lB:BVfH4 tNz2߾P ":( n  lP(0PX F t 4pFJB&XL .(&$x:N@dD v bT $z ~ T<v F*6#&2#1'2 Dtr 8H ^FBތp@,bt"  ~H` B P4"d DDB b\ V P`bV<b&:`F8 `0j<4bH@ NT<$ߴTZͤx<$XæJ,4̨\Tז`r.nL XnB:x ~4 4p.~:\FBV 46 X 8 p\hN @`*x > V |`| nDb VXnr \n rNxZZvj t  BB ,JZ z, $&tl:$ n!4"h$^d'6))B)'8J$ ,\ n~~0Z&( bhnP@* h r# 0+0547:40, ( & & '\'t$  *h0X44n.lP> NxLl:ڀ"D>< P& >R6vlZ<@\ "0 v 86  plzVz^pLnBZ2 bh `ThTn* NHN0` b&rN| `0F8j6PzNz~ ~ `Tfl`"&f  %^!|+!r/ 1/&+%0" F Z h F (( ^|ZfN~d@"" >( p Pn h  Z" v$#V!X4 !n%*--,j&+)(d't"(~0(&%h%#,z r8tbߌ  H6@ xD2\ <`"< ,"tB8FbX\t6bl\nbh6Bx~v N,6,,0 $f$%t$.#!\ :! " ^#D!f|v nX>,`RfLXRz:l6 X  Z 6 t, z "  H^lHvd ,$ N L ߦۆb@ј4.&^fJ jND^ 6~T H < > F 8 t <0z  >B^6btfޮ@V~<jrܴ6n*"nhV h ^ H 42 <| R*6t>z nP0Pd24,2tv 8T $~v*(.+2# * N 0 v2ږZfڀH4^~rJ2(J V ~ t  T  p`   vHD  &!X  p R 00  < @FhtXj.߂^Ѣ f ؒ0 h &݌ ؐ̆Բ`#N#l ނۮxtHF& v F P , Dv  z P $^ 2N*B nR`   \*2< :ߊd<\ &d :$<Tp T4 ""r*"Vx# %##F&&rZ)Z,-.,.' n<  ^ڎNZ֌<vrDؚF.dP> p6:@ pj )j / >48276`41- +6 *L4,-T-F6(f FJ"8*":R|6&*@JܬX*>4\ݼ*ފ^:R@t$ > v j ! Z|!f$J'R '# bnF T L p@rnb`B^R$"2X L,< .d@, D2TR p8R\xF rx J(&rrPܰnflXt>T8l.h" bRlh:H.d ^$0"$x4&T$Z D0 2|JP $D l(:ntZdfH~Jdh2ZZl@rJ   p "h jX,: Lh TV:LP b$\VFR~:d~rr  $ HF,t|t!(,-,0(#L!BH"L& .+ -: +%XX  x \VVltF&*z&JlP6.Jndh X X:n~8j#D ~) - //`/ l.r , + + *v ((&$ RVtbd2F z,.vp22V:"RPv v N F   l  . P <l|^, tF \TJ8pZdn Bn |4 F >  j V &n HZ4 : l4$TN~v6p `<dh.J:~ 06 \ & T &,\~` \J<^ pxt"6,FhHf :ܼp2F0~^^" . z : zt,^T!R)+$ XN 4* bFt LDv,b"Ԝ8H~dDFzvJt",B v L L  \TVV` |Z n< v bx2 |>x$Bܠb Xn:<h^ tHHЦ8JҨ 2 * ߊ6J*^ͪ Φph!\ j޺FR"HB 6:t.J > ljlp6Z@H6 & $ b R . P N@rp &T . 4 .X|Zt`zBP z b$T(tn( \ X x~ v x P* j<t !D%|'"&p#Z @$ b XH8|`HNZlNfl L TX& .. >2444,T2^/Fh, H) & % %0$ 4L..6^p,,TnnL$d(VPl|($Jr2 x!l!">!X"R&|"$,"81!5\63,. #l  &.Jl x@$6"T\rz$pz>(xL^:4H2T~vt%r)*t($v pV\T :8 >XުPR J $bz!P!L "@v!#~%R$f!*nhn T 6  ` hfjJ0|PlVjTD x 8 .4b^v"&^(*~+J*X)8'&^'|8) 8*(.% 6:Jh*Tb 4 $4| Rt Phh V \   Xz"V 2:>F`vp8*&h.lr.nP&~ fHr>   * ` x  z D|Rz$ jp~t< 4 bXrp>>&FVLhLv 2Nh P@ r f"R  ,x&%h &v$  8R&4Hج.,nRt~`bf|r j " | 4pX R$x0 ~Z@txT  >p $B &(ٚl0V>P |ڔ>ׂbd\T( 2F :L, lϴXج"Lb$"$ R`v N! ~(bH>0x0"z X   Z4 V&:l@Z > r * D  t 0Lt : Z8t>8NNXj^tJ^^6r$@rTl4z T |bXz  ^ h2$^$b(( ' '(f*+tr*& !bb, jDH(tFچl|Trlz>ٺۮ2"j, d\#> )>.Nx3hj54"2.,+V (h (f)j(R%jNBP |ZN:|lߐV|>BހxLR$ Z8lHz  $@ NX,"t% '*(X$4 < & 6~28"ZڴzBR( n(L4@VN@ .pD rx  z: @&> T~24T~8Zn,xBdB 8 |:t"#" p!8%R)"<,\,):&# 08&8 "&H*D&Rf\FX6NpP~*v T "8 || X% ' (|&#!$*!."$%%h%$ !Z >RPdd\ P v6\bn^(:FDhV&D\,@Ntz >B :Vp $x|@j4 "jB( ~V* $ & t+N . P12l~21d`181~d/T, )X$fz \FVH&DVN|<|P* j | P V^ n, "  pJB<.  b,H \nrD@\<48r x Nz  X p" l<dz*jfbhj H:Z~DH`d2 $:$V Vl dl >$* ++# n., tbr x ,4@r~* ~8V`d $zV`|ztph$   Bl zv,>f," !| J>Dz"`fvߌn Z ^@|n4 &ߌ0t ^FR ,H:>p > bՎJ8#XX%# Hz4lHz p hp<>d,hF 6 | 4 r,J ^ JD|vpfbڼڮ@Bbt(0߮\n08 pDz&@ &  8 2  @V~ xJ V( t!" rN Bnv8ے&RHݪۄD۞Dbl&.r% :+"60@5&8863/ +` b(F r'`'D$&@!z <fn j>Rhrd@>ڦv8 dLbT0b*|0F "2 0 N ^ $tvZ " #~!b P T@ r ln lFX"V`ݶd:0.z r @*$h ~ ~ (<HTNX^rdB p\NXb tX`4DP> lj F nZj>|HF"\%.'V&((&! h( ~$p:.LZxZf:t<,0zbD2< LDBJ:<L \@pP|TDh& &40"jprT":\j `\ Ln4 <$f&8&6#n8 z#$. f<8 & 8"H "~62DpbF|Z" T R ,pPn4%)-/b0 00 ". J, *T ',$|!pp`fj &b8^*|`x6&@ZD(&Ld&R4|4z0TZ8 \" D  $X P x 0`  2  : T D x  4@ B D,4nVNF߮Xٲf^FBT,f*pv @ H J @( . \ tz | vtx v .N0Tl6x.4|rHb@,,f$ 2Hp@0ND~L~nPzTpp82 Nr2xn2N*`2~tf^r LX .4   FH X% 8,!0J.rd$^ h @ > \ >p,LX~zxJl2>b`d2|  jj ,.(x.~(p  | tVذjӐFўtӌע4h:͎&24B՞Vچ٘:ɒ j VL  $.| ӆ`ب%*P*Nr(&n&DT(\L(% @.4 x<,b" 4d : D Vd`j8j8 J *z@~V nl|H j@P< P<(tnFdx4pb   *, ^ B Z.l^ z(X  > VBlشZ׮ lפېJ޸0Jz<^ @n#2'n"* ++*$ .(,$t >dD  <\v 4LB8t2<ޤNܺX<0\@.l(ܤr zfD Xd\.   |p\`` `H\R,\hPNN|*@vD, 6\ $>'>f&Rl"f6 T4& r4r2^vB<0N|l: ^F  .Z \ * b <Ph ! 2&!*F!f. ./+ $8zLB     pZ&V<>48vnd:(^z|$FTp`r(PJF NBT&8#0$d"j \X $ . f  @ nFF\Bf(<:J@| V\d"JJ<4X6  8@P " :` N6h`FT&$(-00Z.d,(.&T$#"##\"6*$rN& 8jB 8d > p&,RRH \ `> 0L~@2Xb D B   RB L*  .|\^zPd^HL(|ߴv(zՈ8Zݴzh& b  Vx b  : : * l ~ @ NjHFbx0tP\Td.dZzFFl ~dBF*B.t^&~ Hx:0\.t^P"FBd. :L (lh\l)(-($ n~ T  ~r*҂p0&t4n 6jPxjDP D(np`Tv6R x"&%`%`! .". $> .BN֢d|4XD,Xt^ՌZF2˶x  "F$pl$d#hX#$x%$x8!h4:J"2 XJ *`lr N x f H2r@ $4~ &*28 HJV 2~f< > >lV Vb x D :Br  " b  8Lt * *h6:n BTN<׼ؘzڒܒR0j܆X:|~  2 ( P~ ( 2Z ~f*Ln%: 6))&"` n@L <>L V2~d(ZHn@l(߾f@`rB, n`lt "Fb#F"!f` >.D P^0>((:H.\.0~h6`Zj@2:@ L~xb*jn|F#H).Z-l/-")!P . |r n l@z&r0x4|f> fVN8  x"#H&#^ p`DJnz<$HTJ z   v~x2<&l z0FJH B8h>8f&*t&*::>42RR( X  | 8X<(<.::8|B$Lf R\v(L2F "`.  l f N  z ^ h R F "d*RxZ  \vbhVxܺ0NPܨ@*(L0( tJV t &D ,d0 < L  d* Z `ZHNN:jN ~ۆ߸HZRDնxr,hZFr&2 ^JbZ Ljj.  $ 0 h| Z bPV" " H :(Vn&00LDJp"zb8`ߎ>^tj &ZN t#+n./*L D.4dh  h6~r<وXRP\"bxۨdz>Tj*RDRB| PF" |VB<(" # h"  6 <P* F<`h~ H RT PZpfH Xj Rpڎ@Ұ̴H ` D Rj>" P> ."2# !0|$h~TNp ~ <R*N&@xF n 8  *H*\>  0D <p~fl2ގfLNl`**ݚךخݬ|Ljbr P^T 0 R p fVV!::$&(&.# zRf tPjj~Tt\N`d lV^J  b, . (LJ0|F.d \ `v VL RL2Jl޼(Hj~ :h~ 2!$%P#\ Z 2# ',"+!.-)^! X` 4 6 ~&<V~*F8@   N J d X  Lh  6 D  622fdπ VlpF(PBv 4Zz xXv~z,|PjH d<Pl6xjNR"""lVn$Jjj*R6bF*>N L   l X0p\D DFb \ z*rXB8*$(~Thz << 0 (z  J( 0,2&)P l z  L T~Lbي22TP~^L Z>VzXf X `&(0* xV.V` z :LrR(\P> vҺl@" ,0 dBvܨXN6fɺt~Lt> ݊  ~\lP!@&(Vr&#b"~"X!dn |"zvj,TP"(p z `4 N zPbRbLX 02nDtr \ v 4 ^x dd4tF0x|P  <& & \ 8   \F& \$. &. X ^ RH.6,۔ز@Z0 *d؄JL\fJ> \v|0 ,,P$p T' 'N'%D j" !  P2 HzT(Z|:lJzVD:\l8NbߜTTLjprv &^&d  h`^2,$6''N %"" H,N&dTl *Rth\4X@F2t NZ(VP( >H"$r&F#h V Fz &V+^& +'%!.T &  : h  4\22jPv^ ^.,~(&p > 2Jr h $!$%Z$>*`!+\)# R0   >6 | t6J:(:p~Xn\D2XR `Xp6^fr8b"Z 6 , ^ hJb",F#4L!N^ "dP#r":d"Hhn P  bnrP2X"%L*()(2'`*'Jr%$# .!D$H`ZfV 8 Rp&Z&x0l@:6 H& 2x~ ft#< &')b* ),(Pb'.' R'L '* &\<$d lxPRn :t&(pLVf$jJb<8Hx@lnF.>D@К"tF ,2dt$\ 0b |V N 0  " p p  F D @T :*TX|RB&DVJLfr:v&TtHdhDv$p  t B P R Ft \XFLfl\B\H`:|`,b 2t\` Brz fXHD"Z *'L/lh3-V t  4 & N DԌ~܄f*vޮ~j"@" L"tB&l x  l0"zT` \ r NFl&!< pp ~dLHX ~| :r  "XNzB D6p$d4.F*ҰN"<Ѻxɀ$ǂ ͲvvN$v"%h# #Z% '& # ,dx*@D f4 hb24L<  t. n  f 0Z@b >" < T^h  BjbF4d\d>N x\H x x x^0 .2H"%#l  ^!B#V$h$ n!<T zBRݠپr$&^.pl n| h&4"l), ,0Z6,9T7r4B0 H+`'$R$D |%P$d NnH$2B|ܞٺ Px:P`&Xھ^ VHr&rrPv J d :j N TzT (D0 4x@*~tF4|~( "%$!Bxd@~  flp`Rbb.Fd0bT J 8 ^ph6N!|%8)bv,-z\-* %0>*j. B  $H8B"^ 4|lf `2X@lR^~ , B FZxj X  v0~6!b',B,-J,R)N%~b!fJ6^><2"z N(D  `,4JpN0T: $ V0L Zh>0z:vF`Tnrnf`(rv` @ Vj ^ 6bF$x%:<,`/jx/-+ R(P2'L'd&%D$" hJ6 |6~H:z :Nd\0" V L  d R *   lj0 hz\:fhL՘NѶ, HxP@ l>$0| rrd!(("JD,. ,b* l <4XrbLxd4.v>Tb ,\npFb& J  ^.0,f $ RfT4V@f~RbL$ $۸ ژBJlRV   <Z<0B(%+*,%$ *LzT.0Ѭ`մ>n^P^dZ2DxDBfjV4:Vf r    j.,h6Jd D&\הڄݪllZۤ4@D~۸ |> <hڈTVp&&ؐ,t"z6 x&&#^v&(&6B$& "! J(fXRB\ ZD` r  X v  @rfbN >X 4"r  p x4zb 8 J|Pl4 r(r N \"x.xH2L $*f\$Tr.>> h T Nx^ T!$& ))% zb(B,PrLP܂ڒ٘$`D؄"ZްTL"D\@H"!)/d576J2v-n ^)L 'L (@p+,<T*R!>V TX @HD,z<\,>Dl݆ے`@NpH8 (@<\d 6! !, t V N\ @# :(n *d( @|j> h T  j\&p.NH\(0P*Dn(^r8Z t" v b &!>!p! "t$JH&j&#(.T HRJxfP Hf*^\lFx L   <Rf< tbNTJ ߨ*, tbB.R Np d *r .tb "2 R (dVf6ZzXxtې>8n&܄XٴՄ T4 , 8 tlj R  `d^X|F"f br$xzvLRD0(R,.d n &4xZ F>  <@dz!j!L *pFd8\x&Zآ rb  ,`TP|,0  x  ^ |\:RPb26޶nNt@ vJ4xؒ2N$ @p*ն ՜4tz |bfܘ20D&P(2'# dhZ>Lx60 P0 r H 8 H 4 4d vv>x2B,V dxv  x.0TFt>(bnpF0 pz D" "j ,2  , vb6Nl X " ZHx p FjjڰN8֢zBFfdٚtܚްd$"Xz$"8) L-0X3 42t0.-"-,+)# T4vjJB ~D 4FV2&\ 2x` V&rٰٔ6\h$x<@ $`4^ PX*zT~2Z \ NF^>Z8|*.~2h&VF4r ,tt&> N2rB R%( ) (!$)!) z*n+Z+Z<*% 2| vnpx 8*lT 8bvBtfPXfXTfn (n " $l " (^nHV!$v$D$4^#!DDn.@L2,< vL b t Z ~ JDV"V'+,+. '"( !$ $fp#D&0J | 8vpP:F0, z("H* b .T vJ F   | D8RZ(DRxB"F>X(~^>v8fl&RXBztxT*&r"D  p `  H   |j  J.4  "2b@@Vx܊XNܼ^ RP<޴n0:R JL D  6 $  R ~8&z \0*2HX zp`0RpDB<fJ$t xBBBV B  \<!).:* $rd^$ P2(|̒dDx8&" ~Xf|Lh<  VH Z Np:>&|&#( 8$* !rB6< 4\@޸> *XT݈b4Z4tL* 2~̚Ҍ *  Rv͎~!" P6x J dbZ|<N>l | nf  $h n. xj  b\* .~rJ Z <&xJZ@D(f h>, <j""<8r~ VB X.$NPd$ 6*"%(&%d')+,FB,Z*T(h &#d ' #  LR<<z~|$d`\~n4^f*2^Pւ8Jܦn݀߸*p08rRz t Zn:."$ #$! LF\b  4 tLTznDVZhP"&*\@.b , : " B2n :8 N #"Rh 2 \l x~VNJߦ$@z(|j D #0D!B@xN "&*F*\2X*7*(7#D5b/dx(Z\"",` ": > pHNxnFTH 0F|vt\ F  n< f"#!J$ \$*0v0x21|.x*&%~$'X((&$8 fV Z ގݦ( JJ2F ^>zp v 4.^x (<   DBdJ:zf2pB,><8B h :40HrV^t8|Z~ vvp@v4\<:Fp>T F"t B &  l X ~  x n <>4*B n  r t\@,V4HbN&2v*&& : R 0 L$JJ\8@ Z B <|@D`B R$Dj^@H.  L n Lr2`* x|~  H4>F:rll݆(ހr܎j`N~vfjxP N"H ^z ff  P V "<#xr N "z`RТ~x>$x\\JP42DhvXVz  &&  2 !N%6J&z .$!!z " 66J.`  X*ڞZZt , :<2FzZ >8 < \ޠ֒ ` h#*(Z(p&%t&x'&8$ (` D* D@" ~p  b z > ,r8  0V&&Bv4JN: >>\:4Bb(2v H pp  l H Z20 0$ "$ p XlN h"n$ :$j X l4؀.Vv8ڄP<ܨ߮~X" jzf# + 3(8: 96J2h,< l'x $ " "$^$HP:n|DV|HBNVHn*B@4NPJxx&F H 8B V&Z DD & L*4db4,< L^Ld`(ޮ~|VbH*ft2 PZR@J T~  D"lp * &"0\~T^RTߦ|2& 2:~P!J$ 8$$!%"   (l"Z$Dl'( H' " (P v:ZlZB~(R lL4b 0Z>  p\(bR $)+ >*x&v"2 "R#R$$Z$#tz:\LRlj&:J0hh 4 \TZ%'%*!~v6X 2 % '%,FR:4:JxH* 64Zr:~X L>B 2 b P T^ 4Z'-d01^63|2/J+n(B$!h. nh HL.@hz> zFf^F(`^$l  x Z Z    X zB.D <H $VJP^b`DRt>@Ղ.ެb<^Jx  HDfNVDj  |P| &`NVF,|@n 4lHpln z 6 ~ H <d. bv@ R2LF R2&XDnv\RB"^b`V:j f Lph \ &#'&.4 b `nztH6.J>J4Ҹ*"z@@B.LJ0p h|DJ b Z T  j `!dpD 8:6Vl<rxVd4 vd8.$h٤,& j֢ Z F ^$Ѱ 0Tx݄4ݜ6 $!D|hBlގߒ.< ,4 R: * pn ^ (x \ ~ H z  Z   f2 lL 0Dj߀6d$\V\h(Pj26R8 |. R J  \ V  b&`Rz2, ( @Zh2xjV~`v޸r>$XBrۜ2JBRB $H$(D0`&457V8>6422B3f31(\-'(: 8Nnd .|~2"j$Vߦ8߸nL ۚ4.ߨ><.Vj "8% %T #< d  l rBXLފ(ҜհHۂl0P*Ljl0l\>  < J  "%&`!ldd 2f N "@ n6,tF~ۤܨ@&b j|"V #Z L). n,v,r)# \     N6 P z p<"^"Px2*lf"NFnX  f  426F$F),4L,x)P%"T#%'@\('&#rP@2:0ZDR2tX$ n>"VT##$6#J!.~f, *N: t  6:Rp2xh\\R.hp B"$ !# $t$$>%NH&F&v%#p!L h$Th V*pdLjbT>d`     2  (   : l  0| JX@ | | NVBR zn^v\ \\~  < N" b   $ Rr  *H R : bxNJ&~@^R|0NNtBn:X`rtJ|b: 4~ t`p:6<z.& d(n0jdHJRR\ZRpTp2J |8".F(@ 4R%()!JDV hR VH0زؘ|F|D62\H~z0r2hT"ld6Hz8#$R!Jt "j xVިz t z۬h׊׬۴P\ۄ~϶N zʴPՐ "(6N64ϘЖ,!% %^$#z#t# !T8Zt>"L( d8 ( R  L 8X   *F. @ <D 2 4 rz hRJ>LN L nV4J `T JJ  6(  Z HFX02V D2  R !* @" (XF vb4zܦ8ܾڢ:^px*N``VTRj4z|d 4nx"8& (8 ) ' $R!$h\  fHtzp@l0VZ"&  |^$H,TDvZ*ZBJ  &"`#" H!!p%) &.H0l.N(Z jpv,!d "fL h ~zhdPh>P.D X Vz! j""|" V!fL 8dx0d\N dD2VpB 4 n ~ .F ND0 @! P!N>T,\PdbF2.ۦ, ~ x"(@NL&Nj 2bZFzNRhHt* z(<t 6>R:2Hdz P XHJnZ XP^"J%j%"^ &&%)+'2!6t xZ& dL&&0J&F> 4,*L xhH<,.XR& +X-J-v+^**2 ) )* `) 4'0$" <" "nP"X^r x0rdzD2>(,<Z x Z  "   <:4 : & vr$jZLZ.p>ђRЮԂl~0XL>6   pl  d l v6vD 4 > Nb>Xnr@$*܎@ :d>8ڲ6@px,H8`Z\ ,  || @ t BX 6jH.^ n^>bZFXFڢvX2~l *h@Nj  F`(46 ,P T b"z&Z(T&"| r0\ .HFx rݪ8z"((Ht&~BtF 2 b   <J @6D< `hbT!4!XP&xnj,V b.V*J`"ݞ4t4^8ΤdXD T" d~϶lh2rpzb2#*-.+~T(@&:%#B p ~JT62t8jVX F hjR b vv D p 4,8&$F @ &, r, F LF\,|\d@,@`06fpr"vvpPbt6&l4B\ \ ( dpF < t& $&&jJ$`&\#X2p v ,(МT>̨ߢtX$pbBjLNJp2Hv$>hz! 'h.3540*d %:$ ,&*xT,(((r 6 $& NpXj(n( :<<^r|t.$  TX, @ v#F6(T4+ ,+T)&$ 6% `( t,6.6l*j!J ,^ br",<r V28$|" &0~4: . F l  BNl>lD $ .N4nj82n:Մ|zPRT,JF  (  J"!~$&$Z ! Z B\hbސt`Hb0 jx$l~d 6B:.l,1&4/ ) vb 0 |x<, |6&j6tp<@xpl t*h,"l, 4j t:\ <* < B:h 6 3 2X N2$ 2l 1/*"v0dJNv,j|(.z`X(@ ", L   Z h \D & V *  \  R4>`~|6l.~zl@$&ߦTN 4 tL<  40Vr,>VJL  TZf8@" ~ܔ$ٌ׊ٸފۤHd 6& 0H P n X  ( . Z& p24Z X P<ߌBVLx݀HHX0^ t& pFP<b .#%j JVtfF^$V݆nd^2ZXTJvpjdbN8"$V>t< z >  PX $ n !T NHP (!$ x$!z & Z(*@PZnߦJ < BbB" x$F؀tT*VVߚ"T(*HJ(L#`2V`|$>Zl \Pnt&~~ 6 d 8  Pj bxTT Lt*\"TVl܈Z۲X0N2<  J P * f @:0T z *8 ~\ B "j"`  HrvdL\٢6ؖlْ&ިVV"F   f8t&,B0 R35P^52@ F/N +&)R'Zb' & # x. ZX@0 ~nHP2>DߞN, .*RvF<tz x". l d!( $(*L,|*x%d ^r~ X  (P0f2LTNB^P|  r zpjP6v\nT `8 , bZ6~D"H\4Jh|z(֤*xXZf:b t4Lj$&('%  4~D8JJ & 4JnblR Bbp0>x@.Vp~j>F*`     J *\&# ~)P - n/>d.H^,&)'*h'b(((|&~$" "6۔8R(~$ ^T.Z`.D 4 xh8:RD:t$ d\ &< `^|nf`8   .&\ b  V @ |NHx`ܘv4r0.$,T* TRDdn@NB x , z   66 h&<8^ @F P> TFތl6l$2FZR߶Z:,LRf`  0 'B.b3774R1^-) H( ((l(&l!n, F*\0h8l0@~Fx>P*&&Z: " Jd2ND": # " J D v T jB~p$Fܪz*4: T\޸Vx < f * vJNF!0&()"*%)h#:%D!    d8jP tvPR:t&T0ph2@$N ":,ZZB`" 'h+ ,z)#&* 0<:LݠVt*\"zvHpzFn>\z 6v np"X%Z$v!r @f!!H f| H  <tJ&B  TX Rt." b "$F# 4 ltR(Pb| " ^ L^xNZ(Hx^P$l6>nd2| d2 `B6ޔZB(b B PB  P t  d Xb B> ^r  . 66z66 F@tՔ*x^@,$@ߴ:ܪhھ^ڌH~"|l(^ & F$BJ~Lp|4ZnBD2"`޸ܞ`jV \vftjv$~$@L @l܄.:$pjH\:L x  &t tHlRl\> X4~`d>!N #"n t R6 dT@(^ dp L *z.X rDFz|jt Z& x f`,z2,` &@@֬ &R:%&F#4!.bLϬxҜtz.0P||>& 6   VB!"! P"pN) !/P/j+0#,4 "f(`*:Ԭ4J@ll<` n# 8+2.J8:@8<4/2 )R' )-hp/ ,# l&nV ^8j,0ެݼTdbrה֔ܞ՜۴֌jVx HX dH $.2F|H !R ! nfz. V(lTRD"(ޜ2>P(Lh v   fJN  "#!R60 V N8ppnl\^("|  rRL,\n8D n X#$#H#^''*# L6 (#L$|%)n%4.J#|1p1h,$ R T, d |  bRJh@߼r v2x\rj.r<Z(L" ^  @ 0f&PP t&)t)$&  tV^\TJ fVTZ 8~Xz~!"XV#F#2#X" "v~#t&(v(P#"$ BZ  t$ >l&. &j4zP~4HHXhtR"^0 2 * d^" 6&-0@/,)B&%L'0 J):)2'bv!80 Dr:|@pXd 2dB2 DB> 4 F~ `  $ t` ` j J 6 Vt|XJXnHٲV> DVNшՌ&\$XZdl*"X Hv<TTDdD  LP dX `p"^z"x.n6Zpݴ4ld6FB\b vj@ ( t ^ P j Nzfb 6dn PZrdR6XR.l`(>N 2~4F^VvR J $$fthf%4f+,&n n (J*L>rP|V  6v &,pzL6,2P  <^ ~t*XrX|x,$() :.@60|.( J nz  N R jzd^HlV&hPftdj:(l8rt,8 &~`<@ (l `!N $*z^ ~z f Xr X x @ d~"T"! !R Ft, :! 2$z%#h t  .h\*.L`>HF,$N r$ d ` h J"rR""! T >!"6#@"hpJ hrBX.v*~ ~pf4J2*ZJx6  4  l V L V ^P >* z 0 phB(r@r 4 ,T lL`XzpxDd(bPH@40VtdrT 8F^d \    tN z HZnR Z^PHj2pb"dB t2>*(\^` ߬lzhRr* , V l   <d ,  2 J((PpN& pB^XZ@*4(Z V6l  zLJ|< N  , VL ~0zR$4 ",28LDJpD0hB0"d 6H h~ > 0nb V |88.T*p$jH8 R$ߚۚd*d hFێ$vΦzװ .݊ XzϬ2t^ӂ  T l@լ F̨@l$ "nBZ2F$lz`\*th~ @!%$#V#&((H+&f+(#dP\ `fۄ*8^ز*F|vVD\ި#8b* ! tb * @hj\n nj2޲@4b> V zx0bX.2 p R DFn2 8&(d82*< H PhLf @P! "^ HVD4L"F&'fr&X! &"|>n`h<2xPXDz&$H,n"hl D p\2D d> v# $8b%$*#Xv""B#"&!!t":"  v6NlF: Xt :V&0423.(@$"8!z>' , . *X#` &@r8 ߤrD<8BTdF p8T,bXH .  ~ BphJ!&)(N**p)'% $"* L VDh~.V6 vdh|n~vzZ|x&f  <6xh 6vfL@4RB < b L(RvxLd,JPd&l2bh0j $D(~  : zV   hV  X 6&V\PNxpjںxH4PJR`*lT&V@vLR@ L~z  $ vVfZ $$JxRJZ޸hl.8T@\X$4FX H  R 6 0^%t,-"J$`~ vrPz\*\D޶`fx:גh~t^L\ b$f^\f`F\nh:JZhd>@ B  0 tb 6TvP H$.pt,x݆Vؾ*R FfH :H Tӄ P n. jpBn Z`00fJHz NZH@FpnDVHt\  ~ .$ ~ d f R@*<> t(< H<ݎ. v<vR( $ \x \ ~ f V z,dj p0. .T dR>t  xvb (P ( +,:-2^,n+B+j *V $* D* j)vF&"<88XX zHrTh\b.H~BN~H: B  R 2 Bj "!N*% D'Jh'Z"%4 |N t~0ZL<. f6z dJV VP*  ~ :<" 20nZ\:~ @N&X$Hjx<p Vpr<> rF.l T.!B!\"<$n0')&+b,)# 2.l ,P,H\ V(lX4H F0< &rXrt6:8JL z2#*$"t!hd@<8X4r \ 8jn߰ߠ D!pR"^ rD"f!!8V|$ x N~V`<V&Tz>"N8\ *8 p|rxb>JRR@LF N:J2:Xpfv,J0zfn$Rz   B z ( 4 r b Hl*\l ~ J<(" Z t(D,0 Bt<>L xR" N ,N  V RN`V( 4,hZN*^ @B"v|H8l V@@Z BX ~  Z f z,Z$   b  JV2$V,| ,ݦ`*\4l,n$ 0p " > F#"% f#  n!$j')>)% R 8hXf 8 ,\PDה@؈xٸ2$L "T( '4- .2~6ld86T3t /f*'&X' 'j $$\ `lx4f\ \.h"X.ܒ&^fd8~j, 2(NxB< tF ( d8b #b$ !$ bJ4t d:$:P8pbJ&p8$DH 4  <2 4   ^0 xB l8J.ߎb*& < tRh t# V$f"V l!X$'.H**D' !hV 0NF^Hjt66`x"(T\  jlDVL pT*6NFl& &jJ~vF. & 2  j 4 $ HNb FP^RH< <:. jd@xvZ 6$ ' & d< ,B<  ~|~jTdF"vrvBz0:H|n J 8 ^jb  V@!r8(|-h/B40r/N - \* r)4 (& h'D&~% " Lzxp X.<*nV2<`xd&    P T $J  L d $ X p. J n  F8  x b,>@2Jؐ&2fv$>:> 0, @R rJ6 vn j 8  v @VT l:DZ\z* (*"B%&& % j$28%4(vv-2.z(" f4 ^X$j \TxPz՘xִL8NBN08Z vzn46 f  X F   z  d* hJ L"dZ &  0j6 ` 8jLڜXقJ V,ڰ&\D0 n6٪аz4d v&v  f 4 zX߲!># J>JbtX & 6 P  $  ~fz4$v(V`B,@6L$vH B .,X* Vb  R<ܪjN @ f0@ނ(f :J  r": BDp"v%&#!T!#*'zj*0+("#r( p@^h0Bbٲؐ،XXۖ:rt6 fTf&>+(/ 1 31*/ + (%B<%.n%Z $" zPVv.LvfH\D| NߪJl:ضN*Pږۜ޲4(l "(4L 4  4&0z " #~" & L&jxb8z^(F~,*|H dH  n  h26T .B<lV, f @`$"|PjjXd`~:",&. &HJRR v!!L%\%8')':.&0!0pr-6'XX!\0j  F 0 Pf~02d^$2v RpzxLrPPHJ 0!z!Bv^,! &','% !0#$#8P!~zD lP bL6^"F. jvF:\6HpZ\  (pDxZ>#&&%#""!!$!bv f4 jR|D*>Xt4Rh(* R,  l&D ~LR\0N|TRT( : & D~~ޘ0FݾTDBFd`L^8x f  F Z tP $  D   @brBPېvޤJ4B4@f &l^ 4 8HZ:"PF V dl`̄Dǚˢd ׬rۘ \ \֚0؊$^D$'&$V" < *r "4JjNPjb H  tN~T@> 6 8zbXd B p XP. @  RJ0^(\T Xb8b> V `0 nZj: T 6d L  r 24P\>N܊֖L:VvbXl͠T԰|@Z<  l$ n*/V0- x("r:68T B!@ " @$FZ&p .`DLlPߺzZܸ,DrZ l"x~Dl$(D, +&" !$*D.D 08/+ j'<L"Jlj.4pP.^p2` n vF$&z#TN   h#!n%% B jx>^4&6nHD6"B٘"d"T*x6l8D B(.l\ vj r* *v$& #2h&6:htp(\h4zHh,r dLb"b ~"N*~Fl~Vf!!Dt >v>h&6Rt$ 6F Lh8#&(H$B0 0%`'>j%RZ: 8 pNF,JF4V2~Z~$lF>*ZHt X#2) . 060H/@/* / / / L/D , 6*nv(&N!f`j ^d4Jtb&h 2 f V   4: *tp FJ>B2ޒXbHpюNb*׮~4lJ2lZ` JrJ:,F b."Z@`rfDjB,Z 6ޔDV\X$R`J>P4lhh Lj   tT  *> hR"D\@J"P\@ ^   p\ Rf.jvrn$pL64  (nڰHжּn0:TzʺȄl̄>"ז>׀6Š, fӺ 8d>x˰ :ղ0(T:bLD޶.^< `, t  Zf 6DH pz ~`BH><Z" R N Zb > v&r>@P(P @<vZLFb(~.Ln2Bn.j,\ b &P6@B`Hp B\')T(DF()~,/p2V1-\'~H0 T^dPvB(zjh Ddt!)f0 5\9>=&=;83t /",n, ,|,() !\|0 4&>fDDjd߰Dp8>.<߰ݎԤ$Ղ~J޼f^&VL b b2 * 2NPR$tv4 hR:< Rpژ@߾T6nB pX*R r6ZbZ ,.P &Bl@4 jRbR p>4V* v. Zv8J*F"<$@x$#"(% X#j ! l!@ rR!\#0#8<"!PxnzzbJ> P 6 ~(۰Z@ ޤ 86 @,%2&%h#  $:)n 0+l(R#vX |  8V  |p$b\|r,f 2  tpfT$(v+^,h,*l,(%%b$$!tX\D fZvLl$Rh~"Rp|b&~z. 066 0 D:pB"t Df *P l8RZ l:t&\Jj~t߈|DRϐ<| nxL,N8^6$ ׈ ٬҈b6F Ѳ j 8 8.nf!6"BJ @٤*RH4 2^f X\ Hb , dv R \vB N ^^:@ rv  J FdL \ 2jhXLZD~rP hX  l8 <J 68 |!"*   !%((%F z nz*݈Tڠhذ64׎بXf`nt"L vx4#'R V+8.|.,) &(|"0z!4"B N#! jf>|r *nzv0h bvtNݬ V|݀ߎޮrߠX<Z8 Hvd l "$p" *8:!%H &2#(  4 xP zt:X~:n2XD |l 4   B  >|zJLb2Z>"r.tx&$d8 l@$`>vP X( p$"&D$P@ PZ r. P"|d2hHTH vVr 2 ~ 4vp!\~!Z ,hl  t`!x #$"`# P(X,P@nnbz n4ۺf &^((,+Rr%.p D&'#<"p. 0TNߤߎxhdVܘdLdBV V r "6` %((@R(`'& %, 8%%,%d Z#z f 8X4B&N,:8~h ":nlx zټ p0V >.6vXf2FPz  : 2 XjJ82hBH((lDj4** ކn>6lH߈ޖ̶ T ۚHn."͌Z R x4 ΢z٨v%&f#<rHz^$D^8R6XT"j 4 BR>|fFx* rL t F $ `x. *j R  fl TBD^0\ٴ֊"\BzL4z,,  X0,%+ /3z~53>0 p,'4$#.# # TbnbHxpZlB80x|٪܈܂B&Dd&"6zJX2JfP  L nb( n"@h!6*^ 6 B l &&TJRXb`\RHt|Vz`>vRR N ,J `.P"(B.00(0.,r+f("'P &@%\@#N.!rP l"BRtdL&f~  $ f r84 r Z >v4$hF T *:&^r2Bxr׶VzЦ^v` B~D:   \, ZN r B. . 2 Bb  v:dX6z fxN&4@j6xz,L^bFBZ@$vVTzr`$$v0  ^RXbz*\^xF,zTB:x xZ2^ZӾ vh ފ<6ߜ!\*(jD* 8)'&'L'\$pRVR0D^fVp6d . L B\rN   nR" 8  b \( p` :|V2: xzh|Prr@nLB .  >  z : \b  6Z^( fP& $d #$6! L& Zd4 Nވ*ނߠrj T\$ ~TLt'. H0B0B/,r )'r$x$% T% ! Z^@ZpRX@`&BJ(P2Jrp2h6z, Bx tX2Pt ~ X6l"n ND $ v .   r>\vtڲp~D*bJԄ vvPrl8:8t~! $"~,PB tXB  p 4z@d@\PxLX>L t 2x dR rB"$"\* ,4*D$" 6 ~ :j P pLx`\N*T*j:Tv`.H  V^x,TB j:$z*N.^z-xv)x$@jhV!#$Fx#| ht2 lR J<vL :$V R "^#!|6 N , rv|bx2Hz*8&^j&&BLt zv <^|N  6n6Xz D^xvv& 4fL lt\JVvJn f 2  LTV  ~ f r 0  r  D  N| f| jDP4~8bx4vb*&<>f$< V   t  8  n l^  \tndlX\(L\HX 6$.~tBv26v<hD:\Lr>~68ZFlp٤(ޔ"n&hTZj02fzFJ:lf|`Nxn%|*-,"" (  jF "0"Zx֔0Np2b:v&j (.J"T0tlT( 8rF~* 2:`b B#R$2" !> :Vhfd8l lz L4 |(ބ ,0٨Rʀ&PFT&ئ2ܔz$|tv|&".$$|"R"N2$ $"(F0pn@x~ | b0 p b4R|  * 8xzv2 x x@ &   *pTzF664jL|XR&h8@X2<x(rH^4 J  hNL ^bT :0fz   ^FrBِn*tԸpt6׶ hhn`~* %*`.H.f+ (b#r .  > Z~ L 6xB6nhP4t0*ߔlߠdlph  J6  BP!z$b &&# 62<,vj~D"BNޠRLFnBjV>tBrRR^ P: 0 6 DL v!x""N""R vR, b h~ x~l<B4r"~ fH j p$L$"\Z!$L'((t' j#BtL&>Z H,zf`Nbd*vRTxXnBJ2DnH^XxF l:Xtr 0| "!"Ht2DlX*h,nB 0N4 bhJl*t"# ,j ` 6$  :Tz.F(*DB~BT~F>b@NX6.2 ^ 0h | `h:$|)v,4H,N+l*`T* *( +x H,v*>'$8 :&2,  &\b@& 2nLVB4 t26   ,8 $  : $ @$N0BZ Zf:\"vv6^ޢ6t0|L:zdHTnxtT z l2 FNzd @ .   | T6 V ~lHT,Xn@ئ݀n,\4 ݞ6ٴxD ` &|"R 2t F B 6" J ,BDTb  LrHfb*xZbrTh *LB,. n  * jLvn` VfH! ,| <6@D>JV| 2@n:z"(b J N|,@x$j Ҭъt4 X H\ .b| PJ"t#D!\^ f B & D6 &R:d$bj`0$n&Z@.Z> n"hV,Nl v PZ JPVPj ^ FB0 P. R \V&#z TN6@~~D2*Lp4 Pb'2&/22HhJ 0 r  \*TZ^N`dNz~zt&xprp`@>` 6 \".' T/$ 22*j0, (%`$j$#P>":>`z4<.VLj\\@h&pLL R  X Z Bp<nX: R ^^ "TFpXLpVh.tv4V|Һ:tB>FfvJ bJ"J4xz$fb j*vBJP&BDJ0bn\nl~`zb   ~ D|  <Z6NF>( RڀRnZ"L@d DT 6 b . #*'J NN l:tJz^ ݸD2Zv\2V \Z  <z28vV *  8" >DN86FFNTB"\`&<LL8  t v `0 2  d d ! T#P2%"&V:&< N% "\ 0:ؼPڔ$n8\>Z ^ 2  *  &, .4<77p*4:/ V+" (T ' Z)<*f'! hLz`zp J&jZZ8"2.vx&6h Zj0$@t&\"P 6R!Z'2) (<$   p4f>R`*ڪ8~b\`h60֌dݞPl`r.r,B@  "  l bz N jH ~$z(Tb@ߞf| 4lT<Xf p6d"`N`T$0$$R-"%2d#5DD3l4-$  < D.@l j`* zTblJl0rfp^nTLBdFD L V j#6*|./H.*H'd%&\(*v,n:,r)|#@ \Z \$:V0r&PB@FNj >t< 4 D  2.:xdd:22.X4pD~Fd0 d V60H>!8"""R!Lxf$< Rj:f h JX< T2\Lb "   8 < j    X  \ xv : Fjl    \^0XTPB*d @ۚڼvތt2(&zJ,H.T^  r  >  ,  |z4^p:Fz8H.H$.hx`P  @tRr.V  d.@rX0"*ntF*"h4N.p~:p$2(R6^')T#  JF6  8 *(צdlX&2"XH.N6>"F*(p 0j 8`jN 6> $ % "zFd ~ ^ nH0  0X@:8<|.vҒ60 Tߪ˶~l l$NX Θv,%\R)L@)6&>$#,#6#FX" l<bXLF,8:D ^|H@F H\ 0  ~~L\  | ~blTX<"PF~,4<<FrNJ" h N l  r  ~\8  @ !Hv!p!F!r 2fJzzt|ކ֌Ԁը:X^ބ4T*4Jlp j~2 $ +t02565T3T0,-r p+ +*)@%l l ~rlLD`2^>6\F\FL>~ 4JpjpRbn (J "$$0#p8"\#&R*-b.+$% \Rv 4R~,T`vb~& Tn&2&|t,T0 ,tJx l$vF,0 zZhLrrzӲxJ܈v* > BRhxlX#X'$ *L) $ vH BR f> nBJ zlTprP J*nD& J* ZV\ Hrf p#8$" # !P hH$*'''&n%"6bX(B.  D  hr h&(~'$2!ZXj` b2$'&(V.%$( T8L&`PTptl"Td^J,HLnt~$trltFtNb2"|'v*+B,,,V + +p n+("%4"RZ l ^x4RppnFX0.H:z Bb L  <JtNL 4  .R 0 * (F *    H ZzpJpl ߦL۴XզdJ.ۀ8 j2`|N@ZPFp x `  H B nh6$t j N JdBN<`Xz,Zx4fbxR(.ޤn|ltN J4&<2jD ^ f   D2f|X"<  Jz`L<@6xhPVPؼ^ײtPb6T 0|  h ll@<: BT'\+(zHX> B H zbFJ z$6p2`b:pT. dP Xh` @ #^# , |0 z( 0 8 !&, 0 X fRz0 VjLHr0RV`,V8<ۮzND p#Pl# !n`,r"`dNJ * 6R L \>"V(nVB4 & @2  ,:H0r>* 6hn@ތ8,݂VR2<:٬.Dnhz$B2: Z P T p P  z \F D! &! &!P"6$p&$'&# 6 ~B<ܲF($T>ݰJfV n b. @J@v!xz)d0865886^t26.0x+r)d)N)&'(2"( >j$8f(V08:0, JBv !Xz!b zP 4!$< &&:%h$RX :X T : t@RR@dxTR,v.PP2,p*j(:  XjL6.Fr>$ Jfz0 0P.p$B6~h߾pnD,`nLآ:Ddv2H v*8 8L@"N&(h )v% x  @ j . l v(2,r^6Px&>>$f(vx8x^ tR 2 B< Fvl#n )\-.,.)P%@"j@"p"V#$#&(!h\b.N<l2#%T&'v( T(d' '(|)J*jH)'PH#dj rNh ~84*@|&~ vL4^ ~@ 8 hJ(f !H" R"xZ  >b(zp: Lt\dtjN*jLNF6$2|JF 2  :vpz\z@Dp @ 2  j( >d| F0xV~|v(Dւը^2P^8T:2"v&fb  j >, @:  :,  4H6b  T4N>rHR.R:<X,"L6 $rl\|<`TLXV   ~z T* HdD.@& :Dl^HX L8݊d\vb.\4pV(Z@Tpz ~f$ pj& %`,P,*"&lxN,Tx:ϾϤB(۶Z4zRߖ@F@fbF 6~d \!*2(X> h!$# !@$b2d~ VPxH\@ h\n`n L> $DZ,ȌnHX  4. N ̬X؜"(**,($`># D$>%h$"!z |fRTX^D:h:@Z Z FX DN jZH | T bzL\  : F>Z @L0 HdTPj4d>Z$( 2 , L $ `~^ ln X 8(!!d  T8P܊\܌۬*4يDTN @6 "*P 0R 4P7h9.8R4@1H - 6, , 8+ ( !(4T zJV6<0.ޠLD LܸxP8*v v r> $ $x# >&V & #   \ J \H$ >&dpL"N4V~>*,B$@ >H  @ , #4"&'v''%D#^8 >&b<z8dT2$hT0(JX&0 fBH,`j ^@ $2!D* `-~0.,'<!jX`\ 0 |j  ZZHn ^d|Pzf>v8|hB\<   D"bP( |.$"%4$Z"h N*^Hj< t0 6*8H(|\N\$P$ `*x(,DZ&(t*2`FV>:jDz\HH  ~:4NLvpz n!<XDFB\P8T N*vt8XfLZ!z "0!0 JDHLn,0t*0( d N&Nf>X B @ܤ|^ ~ pި ն |Ѹf,#T&'&.& 'v&#b,hbPb< \b $ T <<  2Bb ,   z0,* 6( N  L^nVz4xߘ ނ44>fn~b( .h N  >  L | *PZ@j2  ft `$$<ؤ:jTD\TdnN(^n\<@j@b 6^8v$+h03(3"/^**& z$ %'(&t4 ""rnZn(02vR>PhZB xR*\ߠPJh("*:z LX  R` 42b  #&'(N)(#Dj  dF< l. VdxH6Jz(DrH v b xH p @  !BD,hb&xHpXb>n\*zt.NXr ~ P2 &00B`#<4(`+N,\`) h#T"4 z  nx@0:ZXRD TJ@T Bhb \*ZnL H `lHvFHn 4$.$p" T^dn^&j8(J XZ(rpL d\6nh 8"(z%X&#vFX R  F j@*rr >F8j|dD R r>  4$(>&+Vd- 0,J*'F&& ' ^'H&#~8 nNDNvr p~PfHf".>Z\ `  $    X t ` :  ^h  ` h B l&@F0HT.۰b~"bl`F  t  tb  < ~<z :Z V|jrVVXֲf*D 2$J&&<0| p,  2  L@  \$ B&R H\L| j T  X B>.4 JVj,RN  2  $ 0d" '/1(>F `L.. 4f&T~<NbXڬvdpf$BfN$0DbrdHL@0<>6 B  dP*^> T# # |FTpt x2B ߌ hV @B*h >Z `Vlfb~HVN  hR^0  $&%"l8!R"#jj!F *<fJfBx J   |ft,dv.   n8< DX, | .$2 >0$v8Z.ztp@(2, Xd tbF   ,Bj'|+):(,(h(n)pd) ( '$~6,Dzيf`jض(ۂ@ܠ n8:\0~f bX T# *F/d1B2/,b) &:$"D" p   RlzX`v$8LRڞ J < D\Z\*& D2J zd V d &"VN%'v('D"6 2x*8 j|ZjD"l^*npz..0:d&`Dd(( "j |\l"  hV j$$(8J*r@n l F JbB&6~~b!8 d#x"*R`bD*`$@~'x'%`"b `j>`T:JX4 R < 8jbX8!$ &@%h.#X!$ f!$|( * N*&p6^XNh@Pf  d@"tZFF,~Tl,\< v v0@!D%D(dJ***v(^&$"P ||d>fJ 8jbJ66~N"r*2V^p r 0  F x "t  \  f: TR  bt 2xX.hpF|V&ܦؚN$jJpn24&4 40\| t V ~V   |  D* (d B"B4P d2nۄ`BtDݖ< ۂ"&Zrt  VVn ,v&@tr6"X0v^&"r|TZh0HLX>Xf jV $ z!R6"R N84 pPd"XH% $(R> ZD Jz^Dڔlٸ.^Lx&~hDRD  z *<H^ , jxrT2 8t`RPנv(J,8nHX F ,26\0NBd,vb f P  '(%T h0h86r ~tr r \& n@v  4 6: JX Z FZF@ X dL~2" rj42|80.//.zN,& :`^ 4\jr hJ~d H xtt)J*)4&>^D @L& tR 4lJX@ڨV88HX.@jZz<V XHHV&jRr: "j:` N 8(j:H$zv| ^,.xfp ڌjBJ&xD H0 LD!#V%'N)$($ $   . T bJ~ljppX`$flnr4~b l  F  hX l!\$l$d# F"H@dbr$@L!'+d.`B.t+'$$x% H'2 |'J%. |@jH d tD2TV`*2D bLX d .84hX"&)PV)(~'z'6'''%"d$l@B :z0TJj|6&DFZ6ph@  (bn 6rfJ N >f~" p b@"`hX"6N^ZբRd|H|04$2,xj  *l< n4    z  b  4 >X2@xpZdffވT8&J2V@8jXh X*@z`ZD: Lx*|V bF,~ ^~6: l*  ~L2 6 V!"B!Z  L%,/:h*Rv>| `  TPlL>X>t^~Rb&""\<& 8r :N 2 p^v< $ NL r tJ f X:z,L 2< Lݚ.`v . 4f:0v z< | .:h*ǤJl lڌ D &bв.^ 8j D0  f< N b 0$V >  L"Npz RBZ6N@^^$f6, 4 0B  p>f0't+* R' % &F(,R.,-(D.!n 0ݤJPr݀ ܨbڬټrLDzN |4 t">(X -x0BB08-*6) & #>|"D"~"* p!R 8 $TBF<FbvVtxJBhV~pD*Z`^>$* .>LH $PZ r ,#$#L2: \ $ r *v >&>"L*48&8*HX&Nr D.prn,`N ~ Pxb |:8@pl^V|^$hh& N.&tTb .p \6$R"z&j)*h2),#" h& zvL6T6,>x2(&8.f:\  R 8b`  |d# (' h&# !&+f|,&,*f(BT%"!! d^DBhV n p,0%'& |#P ##  ^ h0lZ"2$vF Rrt6`t^T<B   P (`*!P'x*+T+Z*6( 'j L) t*: &)<&R"  h .T@t4Lr6TR4xnL"   F  D~   2  vz0.6VnR   ~<2|$&*LZ>|վRp882 D  t*    Z h\x  4 vf|lFZݺ\ڂJl2 PL^$BJZn l |dLr  0 4  0 f@f * `t,L> ڂ޺V6(Z& 0|Z.r8LX#&! fv"|L\T6߶^޴ʊ,ɘ̎<0X FNz ^@n~&:^ f ,R`L^,BR "j nL(B:^T"$P~DN2 " 8 zxF Tڬ D.^ X\$HͲf 4"ޚvFB6*~H H ^ 4 f Nz>v2 R $!L#H" < 2`PLҠFѲ~`PX؞BLHl2 $*d& ,044582h. b)H $h"" #"V .HFVj 2 4vHz߸XV "**2.88 Ll* %,8(&f"" lt<H$x T(*>R+(" |Tv V`VJ( hd|xZ^t `$ "    D#R&J#&"$!zp  lND6&b~$޴N zj**d8*H4Xtjt*pX4n6  TlpJr ^%Jv)t* >)N%0"4!X#D$V$J%$jx"fZn>BF $0H()lr)((''TD'D'((l&"@t4j@0B> rtV~h(tJd*^BHhb L ^~$B^.  $%lN%#!   pv2`DlD L$PbTp(>f(nx:@p"ZXrX . <,     f ,z| fNf6TT pۜDxvlbh8NhHj: "D*H H  X Z> r ,L :  |XJD^DBݜRv |h.^Z8vz4.XFr$\p^DjzHP H^~ @p# &~ (% 0"&  j n(J&.zxT&. $,r^T0~pN6" H(f&ђx:ZPFJ R  ذ!P(*P)f' &~d&|&#&|P<$NX2B. j Llr4 X  8 | rv ht  T . v0~$`,  0.4tdf.lT&h b 2 @pR Jb l& > D    ,:t2ھږRL..՚ p,bL*>l|f~hFP,db^H F"& .$ XhvR~ft|ڄ׼,b>* 0 `Pd &"$z@F8$p.(F`)\%: pdd NpTtz "8D.>߲BL^h6$rh p v (| ^ Z%) ) '%#R$,',/V1>p1x/+&#,!p0  l>2V02 F߶8*> P4Rpf# #h!.& "b&% `#.B :DP0. < rZHX~"286vr\ rr0&  X f~L@&bH%2f)f&++)dp'%%&&%"$."b`F^D F(~8DrzJrjv j\|.(tD  ~ .| x  4  D &Llj6vL `Hh @٤զ֠R\fl@DBhlR  d   6 Ff F <J<j Fx j.D~hz^0|(&(z \ |"%)<'bHbF:&xH~N^>`@TxnR@<\v4B~   X& \ * L (jD\`Td|zv:z 04r~>p DP f:rDv n2( 8tբph0H xӌ.ߔ,  Ϟ 0̢p4L,#B&%&B"Z^x"b hh T t j B$ X XBz< j@.(4 f  p h RNZnےT Rr jjZ|\( .@z 6R bDl %z% 8!  !%LX)x)& Ft <DD8َ׈v 82l(ݴ , p&*,L@3\6v4&/^b*L%#V$L %%@>!.Z~d`J"vzh\t84"v\jߢ޼dL8h. <bx~ R   vz!L# " Z( V N `:BL@* ,0Hj>,TD 2H. zRp "2<lRL  \dt b$pfdVZl&t> p&x n"#"0"0  X"P%F)v../,, & n2 >pBl\z߈&ި@N N4f^xn`b^  z p &Rpr<Rfrx bb R"bp$%%|#2 @jTt|2 vf26ߊ & ` |4v!~(:,,* X%2! t",&(F% V`TF,*|Fp&Z N06xr T F R &>&.-Bz/^.J,@2)' &: P' '$'$` pxL 6*NV@F XX8rXz&" T @jbT P   L$vz|dZ>  lRv ZvX^D<vذ`l$r^6 , t * ZN xh^@ L    Z& ZBZHݜxvpj6Z&DPHZ&v >lB<`T * $ VL ln  0*frr dNbR >N` ߜ݂PF$\L8dt`pb> > FR2" (4*D< @4\&8"F"ZԢ:Lz(zFdrR\N>D H  bNX BL  6lX8"0v,&B 6vۮF`l 6P6 ~ Hxپ" b ޾ J Ԥ Ғְ*8Hx!~! T$RL"lj&Vf|LPr tj   ,~X L<nf" \4  XR$ R Z0:60V.~XD"pv^۞,׼״t(:H`&N 2V@ 2 4 P   (4 60!#HT%%#T . ,2NVR$`bݞݞ^Lr,P݂NTJ R `&&\%+ p04V763,1- + )x 0):(% D (   68$2jRݸ< <,@~؞VHhfn,THH> >*<l T Z r 8# &l (N'V N j&h |r|l r8dNvFbfL`0> |` F T *h>",,V l @fn":~B6tB 2.vZT`PZ$ f tXJ,P6d & jb6Rn!<$''z`% v`  rJ ~hJ$R*ZrnlJ2vp *FfFp:X\@:Tt  "  ^x><t XF,vTD<0,xj" f(V h &  N " H %(|(%"0 ~ Np"%l(f(z%d nlp&>. r F*d,d& j2xH<n". f *2TB`(r$,^')<V+,4, + *,+ 2)x ^&n#tJN|NB>r0(vVBdPTb8,4b` : (> & TvvTB F V  j X  F~| j|B@jޤڀ2.N2>."0f 4  ZJn ^ :  z j :  v R <D (*jp  DX\ J Rn0D~f0 ` v   2 (`8$r2`N( H: B8 !! 6F!\&,)$4v^~ l82ܮ׌ڀ$@RTtv4 6 < .L X <pbNR( | :VN^ $LJH<\2zlP Z ~ 8B $nD2R@N$ h zV XR4!"| ^ "$ "$$X & n 2l08٤׺֖<:.@| 4.\n %).1\1F/,)~ &2%, $ %$P@ fN hJfVH^j`|JBF0X2ބ Xl2$^N 4*j.~$<lz*N#F$X z#   d > lB .^88DxBbDX ,f< x :F6P b z  0Z0nP<: Bd.^h(t@8B \n N4n X!&Z(:&$v$%'*\,$*z&* pX 8 HhXL~L^F`PdT L:~ p*  ll h $| # t% 0%$"vB4x!F$B%# "R@ *\ < B &:0jHp ,^,.*|0DBlDNN|$ j@<"x0ljz428 xJ<. % * .4 1n 3 J4 32d0.p p,:+)lR'X"VLH *F:xLThXf" bx ,Zf $6 0  "4   4 <:J&> v:(v8p^*HҮάzӼߪ(2P Z*V xFv:RJRDLpX  ,VV2B8" l,0dnJRLr@L8"  D( V$ :RV zh b"X*T .X ߔH|TVVZڐ p\rT`v4n& D B&  v TP"$V6#(! d< 4X0JN$۪\͎̎^$ْHVp6|&h0` @v "r f 8" z pF2>(\PZFdTL @<` $\  ldݞ $ dV(ݪ~ւf 8p". 8x6܂Jې$|V((%!( r hzn" 6^ :J68* :j \>&h   " x( H. ` v$v  "d X2b\N :ې\>&j0l~Ղht6>>2, @6RF0@0 p Zz4."&%#"N#&)|X+f)`l$D Pl8.R,FPR8X 8Vۢ\*r`" nnP%h, "1406726d`4216 - *r) )*("0 X^&pN0h2^ld":ܤJlp N 2P D. pxj! ^$F P%N! d ~0 :H &Rެf4,RtrF 8 8\ v  6>BNNZ & h(&(<r>00.ܜ0V : thV 0"B #4!@"#<"$$%&x('+\'b.&/$/n|,f&P!h ~4 F0r: 8P<"*T6rx  < nj N tB V p! $ @%P$"J! 0F"|% ((:( '&$F""| f j l2 P$ jFN jPRH>.:z H& v|<rF"(TZ@>R2`r Z ( ,,^%\+"&.8/0<.4,)0 )(% "rX>&@> B@(dPRF@DPv  Ln&\8*2&ߞf62vfxn$\@J P JD~& (h x^rX vD^N~bn.\XP0$ffNB`  &@ v' ,'\  p D0  :T<ьx8Ff<NBJ&R2T0z^flh  B Pp T  . f 8 $#4  j80 pݮrݬl"\TݤVldڪzrf*&JX\vȾHJ ~nܔ HϘ ̢t*ۊ%),$)2%:\"!"P#!@\Hd J bN,| H& ht6  ~( D  bdR  dPt>n  Dv84L\Dz dD.n  <\r 8fL N.`~h VH \B,n&pT"rޒbjF 46&R-N 1 2 322x"0- +< T*&) ($fJ$~~L(n,dVڊpؘ(*ԒޜӤ Ԫ* bz88^:pT ,p:bJ6dXT %p&$  *v  F 4N p\J&0@n$x.T6l>L !^%%j"  ~"4'$+$!-$+!% dBB& lJ :n@h^L2zFH( Z`Xb86~ 6!!&!x)j .++&)# x vd ( (n P ~ ^N@rLdt"`>H`hj&0VtT^0TZvr|TZ!T""|J ZZP.. Z| $ .  &X"$n#!d@~V!! JpHrP  n &4f@(.lj hR0v< :h 0b >B~<0!z#$~%$&8 '&%#!6 @bL0jxPVPTZH*Z z  p  *T F~ L \ ~ \  $ 8d2TNJJچԊ<|&Nb~fxX z bbjXx n4 b>  F vDJTp  <.fDVjdFJ,,6:\&bzr>"~8<* Z V p `ZtB p\ :.|tv2*hTbhFzXp:r| (xZ r2>@\,Hxv fd:rx| r"$8.DX<lR4\0P 2@rRf n xxn:DPh 4^ ::: X 8^ D.hXD^ hhFٸ6~ hFDP~ҐfN ݜ ޶ |J8ưŲ̔ Ԙږ:N܎ d z D2!*),,*''<(|(&V&!>*N>Blb6j0L(Hj J lZL($^N P * Z^ ~(&F&d hHH B|N0vd 8`$Hr*f XX Z 4  T < b d Xl pnb$  $"#Xx"R 4:fR lh$ْ@PbLV۰2>v` P. DP 8"l) .r35T4X21. + (N.(` (F)'  @xZ 8bN,l20BZ B$Xܦ*ܖTzdrPڒ6TbrD0@2n< D N JfL BP $$ |(HV*Rb(!B4 .J"R tJh f2~. $H.86H.(fX( FR :2 (  X &  < FR pX>&jBr~ nf , pvD"0 2d&t |2N*H|LBT v#B' B)H:($ @2 vl6 | .2pxH~8vhf"$Xb R ~\ JP&  j! #$# !TTj4^#%|%$$#T!d^Z:X| BRj. H!l 6$"h!,lz2 X20>&@lH4f^r~ `p&2Z d| ( nt J<."#`f%V &:&%(%F % &$$h"V!&t&r" ptTf4L0&~"$FDj "0   h8 " x $0 :^ | (  z .6|zln|rPBP" t Vp  * t0 nN, "p( R F\dfdZB.lXv:F^Xj8J j J ,V tR *F"(b#>< &.H4Db"ж"<6j(^Rnfvzv8* 8xh   2V, F|b$XTzVlz0&8NV@` Tj ,tl:D ߰ @ jl۪h̠\ p"Z "$&r%" jtJ*ldv(j . Lx  N R .j n ,^* hT ` J TRt .$ b 2h@ۢ@Vp$n*ԀJDv`L jX~ 2 & VF dZDbT<4,ll  #p$H#N 6` \jPPݴHN٨$x&8.׊42< |X vftFl%^ r+b0D5v8296~2-v*)*.+,) V (>L\ \ZPn߾l|Xߒ>*B T`x 6^Hl r  Rl . h x |#%$\$L f VPjNrpPZp*hp8pR t| Z<h: "H 48f l 8B" PN8V$bLZ|Dx (TH62v\R V8J>$nXX&R!~#V&(>n'#^n v F x@0npp66x.(HT@ T2dlJ n fB2 `" PJ 66#"$x:%`d%z$J!fnj\VnF.&FR :0`tn "'b+-,)h&vv#.D"^T#D%'F&Z!L0 ^4 . @lrvpdDF@zx0X6DrV(h pT<,!`&*,-h-(,|l*& Z)d('%J"4tN 0D4:<H0PN`b8d,8lT , 6 0 x  j  2@2rnZT * bNF`H x*xئ(B&|b dx .4f8n:D~: H 0240|4@Nfp,*8X rV~"@lD : D`xl  LZx(T j6tjv<\v" ZH 6d X FBVrv $ '(& :!VRJ^<&ٺۘϺh66:B0xt@0JH,&|ܲ.V2nbj   $\ " 0 F$ J>40N8 P~R |(Pܮ& X| dT dv߀`"հ P,D N" <غHt#<*+^)Hx'h'j*|*(#*&4nJFfV 6 0  \  ,v r 6`jF|x, F( v~V$Rdj| 4 F $Zn.FRV"f xl p  6 n  60 B"t"#N&% "26~LDn:" j׀2բDRDD&\R" (+D,.+n)n 'l $4#$R# x%D'8&@#4F BL^ * FPt:p<8 d8|Lf (j. B>$$ j &4|.T *,(~nP$vXt06ޤ B݈|`l8z(B$  6(n\ T\>^ < TVjnN:>pdJ$ݜ \Px \NJ !|(",!"!" F"  `"!$%4%(%+B#.,'P !  \ p ,8.2 vr|*`&$^ h& : @ L&> |$0  6@(! \!j 2 z$lz&X%! b>0Z> >B  8\FXP>  L:#:$X#H*!`^::#jR'(4& | lT 824n^&XhjJhf`Dj8zd V r  dT`!x(,-n,)&$$*%$D"V^.Fp06xnpJ<2t hZ|BBl6.^\nfb 6 ,n . ^2dn 0$DlZ N 2lZxpXB׌Rjp^TZlz, L xp X8  pz   6Nd   b $ 0PlhPB($jj^V2Zln>n~ R(  & V~$l2npX$6<@8:4P @ h  R << . V %-f#`3 0f& H.& lB fB   J8t.ֆ٬LRd~8`6*\L:0.L`D: >( xT~NF$ lxHr dVhb@&P\*"6&RZH ڂR,ۄzdnh. ɘ, ؎ `( B.|P xF! &'.%B""##`!<8VhXd, $n x $ . rR ` 8 .d |th X L , xnDx݆"l $ jX r f  >@D  p"|,f p$""! " (@Hlچ8*ޮh ߈TR^ND 4nB|& .826&8^7 |41R- J*D(& % !* PD JZV8XpP RTH^ݬl@z@Nr|&&F~ &rz6>|^l dj42 h!` #@L#P\!Z 8r.F>zhdL nR.x߆& pB Pt8$@XnpnJL x,rx.   J>b\n,Vh$D,Z0"`v T   8f!$F'T*Zx+( # J `  \ r @  z `(Tp>tfhPvbbB* pH>. F&zJ @""lr X h'+-l-L+<'"$#0$:%%pd%f`$!LZp "&\Hd$`':(ZR&"$T,26"N0&d.'"j$(`&b&>8 ~Lx04rr &  0 B8#&b'~'& #F!6 Z(8pH B~Zp6N>0XLll f j (  "X(N<$Zj  L8vxD.h,.0PhT^ޘrn~`Dlp.~(f 0` * "Tt \B d . :J * T zhj*&0 fx݀ ,Z6\R(ݤ* \ӖTҲxԬrlLJ&  z0H"R  t*^R*Bvv`PLR@f,JPN Pb JB` nhN " "j 8 %+j.),L$PL  nn"PD^NٞV". .> 6\2\.f 2 < , &4f  RvN H < t n\d$ 8 Jv2߄ ,ЄІ *j ޲ ܐ 2` 8xzBvvV H pj V Zn<l ^ V$ ^ Nj \l JR^HLvzZV,ܴHhF|44r 4TL | p NpRj$%$f $x%Nx(4 ,,-L,n(#Lvp  2h߰t*H6( ٦|.:lݶ:LN2 hX"< B)n/Z3F"3/t+ ,'#"# P%V%v \ r RXJb>T\B&l߈ݬ  .݂߼`2(\bD BVT6 VV  !R: $Z*" $&6).("8TH  z` F @~l LN < v` D2!0\ $V f N!^#2"&"*.#,-(!P.R+%f B : p Z>\j&:8njv4<<:0*$6DZZ r "  @B d(ln!b2!< Ffhnnv 8&bN. 8 r  TD4!>(R,Pt-+(:$"|#'*+`)L#j:< r V bx<\D,l":RN@v\dnxB T . L:(h2z8!\8'^*- - ,+ *" "* )(&F#n \h T` 4<v.0Xp8`l2X"@ &f   ,     &   : j jvB:2R fnjhdV6\ bx޲`f$|H4R@*b^ V d L:>B V \  p  ^\Zdn.2HߖP$ڶۦ | N܄^`:Dr r (x Rl"X  (|h\^b,D p4ttBL(tު6^xVpn|\ @X "%&b& %"!:#&4&" >`NtTl,$jԦ,zrn~~b\vfP, 8t 8fF  l  : Z:V v~xz fFFDR"l8 v $tpؤHd$ڒ҂H|֦ j ٚXvdȦl lP(~ Ӧ vn#(&%X^"RdRFbBzd"Db~\Zb   N   J 2 :*j  B pV2 & r*P:ZZ>&lX8:ptV\ P&l 4p2 L B<N #!j  !$'(X&T Nj$ݮ6:$$ v&'nF%Z p:bdLTnvf vl݀pZ>tz:L$Lt^$ޮ2Z^(4 tX  Xv ` Vl,RbJ!.\$|& @% T T\ " 8& P8H.DnhLdhNT~hp>0 &Nj&# $ #@! 0!pz"D#&\"ZN &<jHDd&d^ *XJp"L Rf J6 &!PX ` P #B!'!*x+T'!b l B *r@ \ h`6b2(JH4P0*Zz v0Nnxj|D$%`$, L  " 0 ^Br8(JnD|HZ HTnJ8 & L(n@| h#(z,<.z-,< j+ @*j)Zl)| z(|n&N#(RJv> nH$jJl.2R"bZ.(4r^^F`6 J :v " pP:d,"nfNP\,Zz|d8x428|P  j(Nl^PnZLz, `6nF v޴Lͨ " \  B  r  @J*f  (*B@Bh jh nh,Pz,  l2X6:06lXr "f!2( N!#P'&*0v*V'n!f*rjRL(rdDP$ p|j "  2l^.% l*.l0.\+h &"& $@42x0b^ V ^vvTdJݤf6(^t> v"H  0 NHHLN>J ! 0 JDzNf *L|R $`J|   6h :v>Z.FbR r\h 4DNP 0PfRd(^ BVp.z~X<  t H L!\"!  "!%z"(!+,v*$  " ( .Zrxf&v&,|d(.Z * dhtfl ZrD"$,~ft\#%&%#B z  :TP d6pނ^ <.\PB4N!Z"V<" Tbh!(V#"|@  jZ4th 2r \ Ff ,D8|~F &),j@,f*&2 $ J$ # 8#d n"P j4D64 6 H4z<Hx>"4:>X0Pz 0 "$j@ & Jz 4f^ jfF BF`bDvF֚z8R~f.nblP:6^8  ^ x^>|.N: f:vh b X ZTr\4` f:۲x2 L.6 V HZ h F$   L NN.\0`<nx8F:rBߚr\4,*F:  J  *X ^,l#r)&) : @X<`F~8 F8֚:,Rv ."6JhP|x* &Zt xR  pZ4NV& *Plz` lFb"4p 6R~2&ֲNbʌl` j  ( Ҋ0!%t&#f` < !##r NVZ~8   & x^&NL 0x b<" X  p.D* Ft4 6B DN4.T pVjD*Ldn`Br޸v|2RZ~>^:H:z F> p L!8 ,# B$2$#0 &B& h@ h2j*^X4|TX,J <Jl   r VJN  :"$"\P`Rh  .dXDLD$h\hNJ( 46,. 4h :0 2VF<  ~P.B H!"l!| < ^Z!P>$ ' D(n Z& : vDT2dN&Z*T:F:vNXzVNPx8Fn >"bDN#)X4/|J2(31|p->**'r&%%$4" 0 R@PzV8d046jl dX$D L  ( D   n*hL* n 6zB4rپ4Պn*Ԩٺl>B^ \ *J4Pd@.B|n^ zH$RFRbX؄ p@v*:0JZ`j,.`f t  4^&0zL V p`@Jp\vb 2 xݦ&2ֲւ@<$J~pF2LhzVhP02~t2b2X $!" X j<\D( vVJZ hـ| V6 rpBB:@| jf~~ 8 F $ P0 \ 2rV^ lfR f* "  >pnv <X.ݼ~0 VtR؞$f:׾H& `r$,X  B ~  NTJ", 4    <rRJݎ" @ :fۨP(>\FZ0 J lJn  Vr ("!4^ !|#@& (\t)'#" PR| .N4~Rހ݆pܾBdZlJpb \4^#:*0 z0 5 8>7v4|/ ^*&4R&F' z(`&" V,jpjn"Nۚ؊DhFھ\LrހD.v>d pT\"!`!nv \Zvd!2%: (*+J*V%`n6 h H\ ^ R T T$Tl@j|F:^l6 > @  h L<" #@#`"!TJ Z.N`~|,j,dP~`Xbbr0ޖ@ n| B^RZv0  P$n ,) ,6//z,&T n N &p  |\&@"X<*&\B(|^$ZpLZr*TH4N`!(%&>&$@p"~.l|,n@8 , X6#(&R' &$$ PHL( 6#( $!N.v <tlJrDh::^PBJh6"X F TPT:ZVV,x4$&(+(,+*6(('|f'V&$^#Rl@L<|8ltNZXRrn^vl,Bf H jH Tj lD B F,  ` n   j n0 t :F<l^v^ ֪NԌfԖ f$f<.6px` :@H J bx V  n:XH Pld"` F6~>tTZr$j\nV"RR :\$F  :Z0Z@ \ P\t4^4VzN|* *ܜߢ6ސP۪ @jr&BV~n4 H|Z 4 Lh% 'J Ff~ lӒ$xѤT4Zz**NL>,^B&p\pZ  LTXXd *2" %<$ l h H t4L$:NjzLxjB` ۰ n( hҸppvT ֜ R*bR'**)6'hV& &&L&#N LX`(6\.@4D|d   |8 f | R *fBF݂(F64 Tݦ&lrJ:2b Bp Bh  >  L J .& "pn$%"J$z!h@Xb2^ܪz ݀`܎lB FB:dt4VZ pX& L+x-\.*-,*.)' n& %F #@ :P < H2*@rD0T$~0f``&V@B*( 4 6(>R 2t$! $>&8%8":F$  R b `>b6N62v> : LNچ6,Nv P&v 8d rX0@ *&^R@@F4D(JThZX."Bx ^PD\Dhxbp$~2)&,d,b) " 2J^\~ D| F8 6 d8f 6Zl`b*>tdnJPB f f D Jr#' ( z&r$"! #)-Jh00>.*v&$(%&(<(v',%"*vHZ (44.t(0zvx"d.8L42t d P ^F Z.:h*>V82|R,:DHd$X V^ BZP.X.v bfRN8 Lt:L"v.Zl:@l>dp &  ( & ~  |> \ 4Br&lLHl4F tHfx.$^z\<$p", *vL~  r&&,F$b r V <^Lb,* vN,4>JZ&&. 0 ,8| v 6D  P  pf ,&DT\d@ &V p6 T^n""zVp^ " b6L:8.Xf6 <R 8Ll,N~pfVbX݀:hlTֈnB24hN $zhpH@x @VV6 @|| L "R BJ(:."D" xb@. n |0 `f8DDZ(ܾrt..,l@ Xv:\'6,.0t-~)vn&Z%%$z!x6hzzB|< n   *.VP$&  . D   2rp <,>:V$Xl~zX\Rr֐\b^ PD^: V Z X PD~ F%'*F'&&6D&%v# f0Jݜl ,LLJ>Bւ,>ٴ4xzR| N" *LZ1B6 8R"62.,j**++n&  PX.JVLRL FDߔޢ>ߔ@t߸4 &*DNB4R2& "  "!N x~ "v%(l*),$DP * fpb,||"p"$L:|l2(8F VZ FJD`  B&B ^  l r  4Tj|44`bZ@J^ H@ Z <p  L*dHn"XX~n><2` J:L62@  .(x 4~ %f'&$":"# f%8 4' ' x&H #8$>p6F v d*,"& (v(Hj  H 0rTB \dp 0  Lbn$RH(TϬX"RF8lp^Fl  > < T  ^ 0F BP    Jr < Px $>@>R~nRR&~&4`j``t r h  V ,*  bD 6 v R (Rb&^hޖrB&Bp.@$lrX `> @ h "^BPBr%&. jl"lp"(~Dxn NnP,߸H߰*H>R |>z f 6h\ jHd6 dP4"F~" հb&rNBhZBd& 0 Z\ٸHnr̘ ZVXbp4 ,D H 2@DX!\%|%>""x:b>bhr\tB^2| T & 8L &   8B (8b@ H X .Vpf rR(j$8.vT  2 R | X VB b > L::*!T!|  LRh fz޴(ۊ4۾RۦztVX<&L0 z J jJH4& -1nN2R2$B0@-+ )0 ) * >* :& v zH0H4Vt*^^߄.Xd.:ܪ^hܚp~>txVR|   L | Hdh ~ " # !  `\8Z ^v 6bxXTzf@x\4p ^`n .nt F hf 8 !\"8# J# " $Xdp^tTVtJX L$ $v 8nx<< $'V(& d |x>nLn(bR~ZLTxZ:Dt^l4:lt|nJRX zRFrh4ZD"J:"2 8p0TBnL T80l  D @0:"##8V4h^j4 $ZHxtdJTn@t|l4R8R v 6<$* %F d()x'X%B"> !B"J#~#t !x .j (HN6~^XDHHvf`f,<4  ~ $ .  ^ H  *|  ~\  j p<NH$"2fPLX$x:d2>rX|f~hL> ^  2 \\dd Vx:  ^nR&p6X|\lPzX\d0`2ZRnfVB.rZB2,~R<`^ZJ Xl\rr\<&,p|8|*dpR< Fx&P(B(~blnV :8#(h&  &2 z\BD:hը׺ Z0 h,F2XDB<  r@ $   <xr2 x`j:` " %l &L# n! * `&tX  @~.Pjzی߆~4(vRξ|2 <ɐ Ѻf h l  "#!BlRx~8&~  Tb|F>*FN* :d > x8tvZD H& *.ޢ~ܐ>H0l thF*rf dv$@RRP\ :: jZ |b6^: nb%jt%D # B"X$Z(,l,fx.p-) !Jn l>|j4߾|N4 xDZ(8 l"*R Z0J\453@L0, t(D%$4%d &~n$ ^VV dF,VT(2rxDjRn$*ߎr, j,n00,nX ~  2 !T!&TZ n L Z |x"x.X@HZh>N f&FVBF   &~*| j: F  drJN,(\jLjH6< $ r L>qml-box2d/examples/weld/0000775000000000000000000000000012310072714012321 5ustar qml-box2d/examples/weld/main.qml0000664000000000000000000001573612310072714013774 0ustar import QtQuick 2.2 import Box2D 1.1 Rectangle { width: 800 height: 600 id: global property int hz: 0 Component { id: ballComponent Body { id: box width: 20 height:20 sleepingAllowed: true bodyType: Body.Dynamic; fixtures: Circle { radius: parent.width / 2 anchors.centerIn: parent density: 0.1 friction: 0.3 restitution: 0.5 } Rectangle { radius: parent.width / 2 border.color: "blue" color: "#EFEFEF" width: parent.width height: parent.height } } } Component { id: linkComponent Body { width: 20 height: 20 z: 1 bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 0.2 friction: 0.3 } Rectangle { anchors.fill: parent border.color: "#DEDEDE" color: "#44A51C" } } } Component { id: linkJoint WeldJoint { dampingRatio: 0.5 frequencyHz: global.hz } } World { id: world anchors.fill: parent function createBranch(base,count) { var prevLink = base; var angle = Math.random() * 10 - 5; for(var i = 0;i < count;i ++) { var newLink = linkComponent.createObject(world); newLink.width = 20; newLink.height = 3 + count - i; if(count % 2) { newLink.x = prevLink.x + prevLink.width; newLink.y = prevLink.y - (prevLink.height / 2); } else { newLink.x = prevLink.x - newLink.width; newLink.y = prevLink.y - (prevLink.height / 2); } var newJoint = linkJoint.createObject(world); newJoint.world = world; if(count % 2) { newJoint.localAnchorA = Qt.point(prevLink.width,prevLink.height / 2); newJoint.localAnchorB = Qt.point(0,newLink.height / 2); } else { newJoint.localAnchorA = Qt.point(0,prevLink.height / 2); newJoint.localAnchorB = Qt.point(newLink.width,newLink.height / 2); } newJoint.referenceAngle = angle; newJoint.bodyA = prevLink; newJoint.bodyB = newLink; prevLink = newLink; } } onInitialized: { var prevLink = bodyA; for(var i = 0;i < 10;i ++) { var newLink = linkComponent.createObject(world); newLink.x = 350 + i * 3; newLink.y = 500 - (i * 40); newLink.width = 20 - i * 1.5; newLink.height = 40; var newJoint = linkJoint.createObject(world); newJoint.world = world; if(i == 0) newJoint.localAnchorA = Qt.point(bodyA.width / 2,0); else newJoint.localAnchorA = Qt.point(newLink.width / 2,0); newJoint.localAnchorB = Qt.point(newLink.width / 2,newLink.height); newJoint.bodyA = prevLink; newJoint.bodyB = newLink; prevLink = newLink; createBranch(newLink,10 - i); } } Body { id: ground height: 40 bodyType: Body.Static anchors { left: parent.left right: parent.right bottom: parent.bottom } fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Rectangle { anchors.fill: parent color: "#DEDEDE" } } Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Body { id: bodyA bodyType: Body.Static width: 100 height: 20 x: 300 y: 540 fixtures: Box { anchors.fill: parent } Rectangle { anchors.fill: parent color: "black" } } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: off" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off"; } } } Rectangle { id: crazyButton x: 180 y: 50 width: 70 height: 30 Text { text: "Get crazy" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { if(global.hz == 0) { global.hz = 60; crazyButton.color = "#999"; } else { global.hz = 0; crazyButton.color = "#DEDEDE"; } } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false z: 10 } Timer { id: ballsTimer interval: 1000 running: true repeat: true onTriggered: { var newBox = ballComponent.createObject(world); newBox.x = 40 + (Math.random() * world.width - 80); newBox.y = 50; } } } } qml-box2d/examples/weld/Wall.qml0000664000000000000000000000042412310072714013733 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/weld/images/0000775000000000000000000000000012310072714013566 5ustar qml-box2d/examples/weld/images/wall.jpg0000664000000000000000000005271712310072714015243 0ustar JFIFHHExifMM*bj(1r2i ' 'Adobe Photoshop CS2 Windows2013:12:26 19:01:20((&(.pHHJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/pulley/0000775000000000000000000000000012310072714012700 5ustar qml-box2d/examples/pulley/main.qml0000664000000000000000000002471112310072714014344 0ustar import QtQuick 2.2 import Box2D 1.1 Rectangle { width: 800 height: 600 id: global property int hz: 0 Component { id: ballComponent Body { id: box width: 20 height:20 sleepingAllowed: true bodyType: Body.Dynamic fixtures: Circle { radius: parent.width / 2 anchors.centerIn: parent density: 0.1 friction: 0.3 restitution: 0.5 } Rectangle { radius: parent.width / 2 border.color: "blue" color: "#EFEFEF" width: parent.width height: parent.height } } } World { id: world property double step: 0.0 anchors.fill: parent Canvas { id: cords anchors.fill: parent onPaint: { var x = bodyA.x + 100 var y = bodyA.y var context = cords.getContext("2d"); context.clearRect (0, 0, width, height); context.beginPath(); context.moveTo(225,100); context.lineTo(575,100); context.moveTo(x,y); context.lineTo(225,100); x = bodyB.x + 100 y = bodyB.y context.moveTo(x,y); context.lineTo(575,100); context.strokeStyle = "grey"; context.stroke(); } } Body { id: ground height: 40 bodyType: Body.Static anchors { left: parent.left right: parent.right bottom: parent.bottom } fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Rectangle { anchors.fill: parent color: "#DEDEDE" } } Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Body { id: limiterA bodyType: Body.Static x: 210 y: 85 width:30 height: 30 fixtures: Circle { anchors.fill: parent radius: 15 } Rectangle { anchors.fill: parent radius: 15 color: "green" } } Body { id: limiterB bodyType: Body.Static x: 560 y: 85 width:30 height: 30 fixtures: Circle { anchors.fill: parent radius: 15 } Rectangle { anchors.fill: parent radius: 15 color: "green" } } Body { id: bodyA x: 125 y: 300 width: 200 height: 100 bodyType: Body.Dynamic fixtures: [ Box { anchors.fill: parent anchors.topMargin: 40 }, Box { x:0 y: 0 width: 10 height: 40 }, Box { x:190 y: 0 width: 10 height: 40 } ] Rectangle { anchors.fill: parent anchors.topMargin: 40 color:"#555555" } Rectangle { x: 0 y: 0 width: 10 height: 40 color:"#555555" } Rectangle { x: 190 y: 0 width: 10 height: 40 color:"#555555" } onXChanged: { cords.requestPaint(); } onYChanged: { cords.requestPaint(); } } Body { id: bodyB x: 475 y: 300 width: 200 height: 100 bodyType: Body.Dynamic fixtures: [ Box { anchors.fill: parent anchors.topMargin: 40 }, Box { x:0 y: 0 width: 10 height: 40 }, Box { x:190 y: 0 width: 10 height: 40 } ] Rectangle { anchors.fill: parent anchors.topMargin: 40 color:"#555555" } Rectangle { x: 0 y: 0 width: 10 height: 40 color:"#555555" } Rectangle { x: 190 y: 0 width: 10 height: 40 color:"#555555" } } PulleyJoint { world: world bodyA: bodyA bodyB: bodyB groundAnchorA: Qt.point(225,100) groundAnchorB: Qt.point(575,100) localAnchorA: Qt.point(100,0) localAnchorB: Qt.point(100,0) lengthA: 150 lengthB: 150 ratio: 1 } Body { id: floor x: 40 y: 260 width: 720 height: 120 bodyType: Body.Static fixtures: [ Box { x: 0 y: 0 width: 84 height: parent.height friction: 0.2 density: 0.8 }, Box { x: 286 y: 0 width: 148 height: parent.height friction: 0.2 density: 0.8 }, Box { x: 636 y: 0 width: 84 height: parent.height friction: 0.2 density: 0.8 } ] Rectangle { x: 0 y: 0 width: 84 height: parent.height color: "#DEDEDE" } Rectangle { x: 286 y: 0 width: 148 height: parent.height color: "#DEDEDE" } Rectangle { x: 636 y: 0 width: 84 height: parent.height color: "#DEDEDE" } } Body { id: triangle x: 370 y: 500 width: 60 height: 60 bodyType: Body.Static fixtures: Polygon { vertices: [ Qt.point(30,0), Qt.point(0,60), Qt.point(60,60) ] } Canvas { id: canvas anchors.fill: parent onPaint: { var context = canvas.getContext("2d"); context.beginPath(); context.moveTo(parent.width / 2,0); context.lineTo(0,parent.height); context.lineTo(parent.width,parent.height); context.lineTo(parent.width / 2,0); context.fillStyle = "green"; context.fill(); } } } Body { id: balancer x: 70 y: 490 width: 660 height: 10 bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 0.3 friction: 0.5 } Rectangle { anchors.fill: parent color: "orange" } } Body { id: circle x: 370 y: 430 width: 60 height: 60 bodyType: Body.Dynamic fixtures: Circle { anchors.fill: parent radius: 30 density: 0.8 friction: 0.9 } Rectangle { anchors.fill: parent radius: 30 color: "red" } } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: off" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off"; } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false } Timer { id: ballsTimer interval: 1000 running: true repeat: true onTriggered: { var newBox = ballComponent.createObject(world); newBox.x = 40 + (Math.random() * world.width - 80); newBox.y = 50; } } } } qml-box2d/examples/pulley/Wall.qml0000664000000000000000000000042412310072714014312 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/pulley/images/0000775000000000000000000000000012310072714014145 5ustar qml-box2d/examples/pulley/images/wall.jpg0000664000000000000000000005271712310072714015622 0ustar JFIFHHExifMM*bj(1r2i ' 'Adobe Photoshop CS2 Windows2013:12:26 19:01:20((&(.pHHJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/friction/0000775000000000000000000000000012310072714013203 5ustar qml-box2d/examples/friction/main.qml0000664000000000000000000000756712310072714014661 0ustar import QtQuick 2.2 import Box2D 1.1 Rectangle { width: 800 height: 600 color: "#EFEFFF" Component { id: frictionJoint FrictionJoint { bodyA: anchor maxForce: 0.5 maxTorque: 0.5 localAnchorA: Qt.point(10,10) localAnchorB: Qt.point(10,10) } } Component { id: boxComponent Body { id: box width: 20 height:20 sleepingAllowed: true property color boxColor: "blue" bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 0.1 friction: 1 restitution: 0.5 } Rectangle { border.color: parent.boxColor color: "#EFEFEF" width: parent.width height: parent.height smooth: true } } } World { id: world anchors.fill: parent gravity: Qt.point(0.0,0.0); Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: bottomWall height: 40 anchors { right: parent.right left: parent.left bottom: parent.bottom } } Body { id: anchor x: world.width / 2 y: world.height / 2 width: 20 height: 20 bodyType: Body.Static Rectangle { anchors.fill: parent color: "green" } } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: off" anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off"; } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false } Timer { id: ballsTimer interval: 1000 running: true repeat: true onTriggered: { var newBox = boxComponent.createObject(world); newBox.x = world.width / 2; newBox.y = world.height / 2; var x = ((Math.random() * 800) - 400) / 15; var y = ((Math.random() * 600) - 300) / 15; if(Math.round(Math.random() * 5) == 1) { newBox.boxColor = "red"; } else { var joint = frictionJoint.createObject(world); joint.world = world; joint.bodyB = newBox; } newBox.applyLinearImpulse(Qt.point(x,y),Qt.point(10,10)); } } } } qml-box2d/examples/friction/Wall.qml0000664000000000000000000000042412310072714014615 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/friction/images/0000775000000000000000000000000012310072714014450 5ustar qml-box2d/examples/friction/images/wall.jpg0000664000000000000000000005271712310072714016125 0ustar JFIFHHExifMM*bj(1r2i ' 'Adobe Photoshop CS2 Windows2013:12:26 19:01:20((&(.pHHJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/filtering/0000755000000000000000000000000012310072714013347 5ustar qml-box2d/examples/filtering/filtering.qml0000664000000000000000000000627412310072714016060 0ustar import QtQuick 2.0 import Box2D 1.1 Item { id: screen width: 800 height: 600 World { id: world; anchors.fill: parent Repeater { model: 5 delegate: Body { x: index * 150 + 10; y: Math.random() * (screen.height / 3); width: 50; height: 50; sleepingAllowed: false bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 1 friction: 0.3 restitution: 0.5 categories: Box.Category2 collidesWith: Box.Category1 | Box.Category3 | Box.Category4 } rotation: Math.random() * 90; Rectangle { anchors.fill: parent color: "blue" opacity: 0.5 } } } Repeater { model: 5 delegate: Body { x: index * 150 + 10; y: Math.random() * (screen.height / 3); width: 50; height: 50; sleepingAllowed: false bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 1 friction: 0.3 restitution: 0.5 categories: Box.Category3 collidesWith: Box.Category1 | Box.Category2 | Box.Category4 } rotation: Math.random() * 90; Rectangle { anchors.fill: parent color: "red" opacity: 0.5 } } } Repeater { model: 5 delegate: Body { x: index * 150 + 10; y: Math.random() * (screen.height / 3); width: 50; height: 50; sleepingAllowed: false fixedRotation: true bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 1 friction: 0.3 restitution: 0.5 categories: Box.Category4 collidesWith: Box.All } rotation: Math.random() * 90; Rectangle { anchors.fill: parent color: "green" opacity: 0.5 } } } Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Wall { id: ceiling height: 20 anchors { left: parent.left; right: parent.right; bottom: parent.top } } Wall { id: leftWall width: 20 anchors { right: parent.left; bottom: ground.top; top: ceiling.bottom } } Wall { id: rightWall width: 20 anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom } } } } qml-box2d/examples/filtering/Wall.qml0000664000000000000000000000024112310072714014760 0ustar import QtQuick 2.0 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent categories: Box.Category1 } } qml-box2d/examples/wheel/0000775000000000000000000000000012310072714012472 5ustar qml-box2d/examples/wheel/main.qml0000664000000000000000000002170712310072714014140 0ustar import QtQuick 2.2 import Box2D 1.1 import QtQuick.Controls 1.1 Rectangle { width: 800 height: 600 color: "#EFEFFF" Component { id: ballsComponent Body { id: ball width: 20 height:20 sleepingAllowed: true bodyType: Body.Dynamic property color boxColor: "blue" fixtures: Circle { id: fx radius: parent.width / 2 anchors.fill: parent density: 0.1 friction: 1 restitution: 0.5 } Rectangle { radius: parent.width / 2 border.color: "blue" color: "#EFEFEF" width: parent.width height: parent.height smooth: true } } } World { id: world anchors.fill: parent Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Body { id: ground height: 40 bodyType: Body.Static anchors { left: parent.left right: parent.right bottom: parent.bottom } fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Rectangle { anchors.fill: parent color: "#DEDEDE" } } Body { anchors.right: parent.right anchors.bottom: parent.bottom anchors.bottomMargin: 40 anchors.rightMargin: 40 bodyType: Body.Static width: 300 height: 300 fixtures: Chain { vertices: [ Qt.point(0,300), Qt.point(210,180), Qt.point(240,130), Qt.point(240,50), Qt.point(220,0), Qt.point(300,0), Qt.point(300,300) ] } Canvas { id: canvas1 anchors.fill: parent onPaint: { var context = canvas1.getContext("2d"); context.beginPath(); context.moveTo(0,300); context.lineTo(210,180); context.lineTo(240,130); context.lineTo(240,50); context.lineTo(220,0); context.lineTo(300,0); context.lineTo(300,300); context.fillStyle = "#AAA"; context.fill(); } } } Wall { anchors.right: parent.right anchors.rightMargin: 40 width:500 height: 40 y: 220 } Body { id: body property int speed: 0 property int k: -1 x: 600 y: 100 width: 100 height: 20 bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 0.8 friction: 0.5 restitution: 0.8 } Rectangle { anchors.fill: parent color: "orange" } } Body { id: wheelA x: 700 y: 100 width: 48 height: 48 bodyType: Body.Dynamic fixtures: Circle { radius: parent.width / 2 anchors.fill: parent density: 0.8 friction: 10 restitution: 0.8 } Image { source: "images/wheel.png" anchors.fill: parent } } Body { id: wheelB x: 600 y: 100 width: 48 height: 48 bodyType: Body.Dynamic fixtures: Circle { radius: parent.width / 2 anchors.fill: parent density: 0.8 friction: 10 restitution: 0.8 } Image { source: "images/wheel.png" anchors.fill: parent } } WheelJoint { id: wheelJointA world: world bodyA: body bodyB: wheelA localAnchorA: Qt.point(100,10) localAnchorB: Qt.point(24,24) enableMotor: true motorSpeed: body.k * body.speed maxMotorTorque: 50 frequencyHz: 10 } WheelJoint { id: wheelJointB world: world bodyA: body bodyB: wheelB localAnchorA: Qt.point(0,10) localAnchorB: Qt.point(24,24) enableMotor: true motorSpeed: body.k * body.speed maxMotorTorque: 50 frequencyHz: 10 } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: " + (debugDraw.visible ? "on" : "off") anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off"; } } } Text { id: leftMotorState x: 180 y: 50 width: 200 text : "Speed: " + speedSlider.value + "\nTorque: " + torqueSlider.value } Slider { id: speedSlider x: 50 y: 90 width: 120 height: 20 minimumValue: 0 maximumValue: 720 value: 0 stepSize: 1 onValueChanged: { body.speed = speedSlider.value; } } Slider { id: torqueSlider x: 50 y: 120 width: 120 height: 20 minimumValue: 1 maximumValue: 100 value: 50 stepSize: 1 onValueChanged: { wheelJointA.maxMotorTorque = torqueSlider.value; wheelJointB.maxMotorTorque = torqueSlider.value; } } Rectangle { id: leftButton x: 50 y: 150 width: 30 height: 30 color: (body.k > 0 ? "#FFF" : "#DEDEDE") border.color: "#999" radius: 5 Image { width: 24 height: 24 anchors.centerIn: parent source: "images/arrow.png" MouseArea { anchors.fill: parent onClicked: { body.k = -1 } } } } Rectangle { id: rightButton x: 90 y: 150 width: 30 height: 30 color: (body.k < 0 ? "#FFF" : "#DEDEDE") border.color: "#999" radius: 5 Image { width: 24 height: 24 anchors.centerIn: parent source: "images/arrow.png" rotation: 180 MouseArea { anchors.fill: parent onClicked: { body.k = 1 } } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false } Timer { id: ballsTimer interval: 1000 running: true repeat: true onTriggered: { var newBox = ballsComponent.createObject(world); newBox.x = 40 + Math.round(Math.random() * 720); newBox.y = 50; } } } } qml-box2d/examples/wheel/Wall.qml0000664000000000000000000000060712310072714014107 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static signal beginContact (variant other) fixtures: Box { anchors.fill: parent friction: 1 density: 1 onBeginContact: { parent.beginContact(other) } } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/wheel/images/0000775000000000000000000000000012310072714013737 5ustar qml-box2d/examples/wheel/images/wheel.png0000664000000000000000000000465412310072714015562 0ustar PNG  IHDR00WsBIT|d pHYs'׶FtEXtSoftwarewww.inkscape.org< )IDAThZml~ݻA icB"7EAg7FhDєPBS@J)u?h@*(!|*-27'GrZis|}fzԺ}ngyvfgyw0 1q'h?wa\s粔20ҿ#˲04SD~.;rx B/`9 \aa_0wr V_g=eϱY@ccJfލOK$ZZZ̾]̼v 23_p]`:"̳Iv#G,@QMDa1HDg:Jn0Njbg1 )} BT`VJ)u`0BD1G|> Bx@+*JyD P(wLX\L&{iF>2"`Wd w;;;@,3M "_DjkkƟ2wضY1 F*lR$"o~mD;V}>} 1*۶n$E:)^/>,Dʻ: P|>K%3h3N2)f>M\˕MD = CnxQ"?`YVD' VmR~{>hR۶"&h)e=Jauf^Nkii1(Q8cX Vm{;SNX|ZJyChvY6ͤo(g|V\x]X,Ul+Mf^"|9Lqd2yGJ23/p-gBV.oFU]y7Lf^+m>cm$3BLR~>f˲`8`C-$MMMQLsV>8|18x DtVJ4u^T"z;1RA>Ar֬Y _PjSSӌ|۹9:n!p DTizg2'MtƍFUU"*ED8qbաPyy R{a'ym:1r, i)f~)#{3̟C"U۪43ȇ|/Hie˔| Øm3lr*F%qԶC$^;">zg=eݖeK)/0QǼh4:EJ9@Dy݃0*@WW׍D"!Ma̼U'0"|cP`*Ü< @)7vaYD"q<4]ViUgj'|M+7g> ơ#Q;Pw# ߽ l6[2[vDK: m5;H> f:P:Iie>m&B6[u6}c!o;4;t j\cᾐ>`ajll\j|:_(8MXdϙ3gK:tqwbh|U_D4|ڲ"JDDip}EDH O9!DeY;::|>v9oq[̳T*u[a]a øR|t%2\.-<. T뽝qp2JJTHU'i"j _f3u3"80003G{Bh:Gi혲]퀤08eCeGKPx0|>dpD"ӓm(];{{{?M$;l-3oHS8ߧyC)|[ 5*]o1+p˶m^ڣ|TOl`3ixjCCcD4"t9t0lC){b*[OiWj13'QNgO $٠\~Yk,RN x|d*5㋉ț]')x7|x3J)n4ۈTgZ4":!8&c$)4bbd!":-&6)^*m@?ȇwHqEraE*cH$L@o # x4xmmzP>R{!>5S#D"ڼbLDPz.*!l#W}@fz/8tqOk1~˲"(-a`PdO {?Ϳ> H;IENDB`qml-box2d/examples/wheel/images/arrow.png0000664000000000000000000000161512310072714015602 0ustar PNG  IHDRw=TIDATx^OhU?3N4iBl[ьKcZQOE$^c/R^zQkKAЖ1߂iZS?Vk 3{?1C]|a|7)ԒbJ5ƭ~y=ap'nm6հcC=pjܑ'?Pk{Kq{s>Ly8q|ŸhS@q܍" [P'۫ pplD`wPSxo,-7ENt1&;V}]lx=}r nYva :mWaecdIgT_imY09p28  ,Mbw"&A6FZUs7M10J6$I%(+$SABƯ-n^G~  K;mGXxE'HC삉#CwjOC3sGq$XBZY}zgJLήne('S$]!F3ى^iPO\Vf֭;a]ށg:14|M)KcULQ+HZg@=5E4b_8d ۪[$.n[Nkr.iТI9q=$a Vse+y%L*[S(`Cd%0xi˻פ;>{}TPB{zjJ%\:/F_:7dODWOzsLқ̂"6# N=/V菞Fen6?/?ϟB.׿E?̗^;VԙZf%zIENDB`qml-box2d/examples/wheel/images/wall.jpg0000664000000000000000000005271712310072714015414 0ustar JFIFHHExifMM*bj(1r2i ' 'Adobe Photoshop CS2 Windows2013:12:26 19:01:20((&(.pHHJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/boxes/0000755000000000000000000000000012310073125012501 5ustar qml-box2d/examples/boxes/background.png0000644000000000000000000000070412241175670015342 0ustar PNG  IHDRr5JsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<AIDATx @Eq1J 6H xs|׽6 ?׶>YP8+/ } ˸B2P8+NDpxW(^ qqg/ ˸B2P8+/ ˸BDq 2e\pxW(^ '"8+/ ˸B2Q^P8+NDpxW(^ qe\pxW(^=*˸ '"8+/ ˸BDqe\px/n(^ qe\a t ;9(BѯPU$^$@); A ? "fo~_O??[+/_'Gp]wF/O9:d?A WYd/T&Og~kag{#k  I+Ǝ p<:1IjvMcLeG|}  L/c%Pȟ p 6IU9T%`:W,a`:U)\{n@@=9쟳 *b3yyP:T-9 8V:_ZP ?bَ93/G Kd.] gC/f^\m㨶+ ](`6(!jK@PS Dž 0%1۱ }G50a8l|B LRe_[Zr `؃yIMYNp_1druJ?eURdRdl W=9`P37Ji*sh860_WZV`,.50%Ns\)?dLbZc :ļrV.P{F|6{Pq2Q֫]\\|e(3te- m` /-5m_,X#\p{V<+fmr"W,ap^>h0/Ӝ<DbZ9SkCמlKNMe"C`K}طɉR^RoE[6Kpy?Xt,K+* }fOIIۆ"%-U5vZΓ?tA"&WY$Mȧ@` >lRwn08"QB 0j˦@i-nM ))hKuwcg{"ϗ%tpF/sn P1mm۴D q;K8vqfPjCJʫ2pYrna@{O2yV=I,&@t ycی8X‡D2< ( 4iLQu*PgLlG+}ROmiEem͎zYA S|Lr?*t.]sz_) 9F[JZuY݂DmH*Z_ܽ=5uz]oeY*d!eHXȻ )iu-k;ެb2s{VӡqLhPͧaB\r׌ L,>hh Dі8dg{^zi%b kydm%/eZMteaɴ? %͋HIefTcWf{moo8Ϲ{˻/Efu U3qd$ lvxcMIA#W ȆAR=Slc8Z/.uYJ{O^.Meu;uNɨaEM]R(zJ(3à /[}k"~rc۽Lӂ3qMϑ14R%V3S ]ze t]RCۣWU%Rx*چD79{*^{㨺s5oﺵAVuI\tKKT%ȟ˂M6|xǷ9+N"c;aVmw@Z. cP[ 4P_EvlT28vxa:ZhqMx]7*VVp̳a^XBT˵0-.ɪ+Lt^~8v0xʱ@0 u-7Gg]v$ !Yj{ {>Խw疜gJUSܻlEyޛz޼Hh VW.F"ePp "O9~*{h !܏6j +lwؑ^=I;fJ_"ݙ >b ~OM~jSB;jaP[M9_z>&:&[;zSJ:g5@:|Btvy,7e'+]/rȂ0-D8wTSWP+Q[nI 5Փs]e! VDp8Ƨ1qx [<]lCfGSWUcH_t$a^T[!oS> sS1x.|x]FH_||~` =;.wXtHZ)g_NF}^{#@Dq[t8ep0/m%ywCF)t*69^8BN;Ҫ{>&$1zg,O,e[ D'8 ^AƋ'Ho-]鑅 {Q!|;ۯh$\hU)%/t%*w߆Cm&g"?x쬕O,6o#ҞB6X>z>.\k;EvCK%p^rMۻf6Ievx:-a5;tYDi&v@?p:mtҶkTQ9+b܂e8%%׌yO|sdHҍ:tkxMeD!rY,KZjN 5ri{ S&.v]bEUiȘhkt 5t/:mqzU4)W]ш̓Xf,k e3]3tr(N!;LH9O +%}֚zKuU;ae žbqy8U@܄|Q3R@; 2 a҃v@aԱ)%j .pP6Չk8{/VpɚMj,#޷IF%? 'FHvC=:+\nQU.~(NeAPe6`\SҙR"133{ uB/G< gv)GC'8;~J{7sT$uc(ϊZ'_W3&{2C{I^rO/}͎Ft*GBJ/DPRoiIn>?T^\"ڍ9՞pIgv".lȶ`B& VɁ> 0Asi8P.N} w=QUAe>Ȕ 6d`%eݓzN o*̷v#E63/w=IjS癳1wF9F_˦7 8x\^*`ԍ&r3iw{TVNPH/2x%{9D5(0vz$aE%J Rui nTƀm%i;h/(ԖN'H;9&Ygz.Tp\y|42‰~RZ 탡+%ŭl|~:b]”u'X0TXh@`037N̖Y#eYW-TdHϕ셾r%(*,h0Φ;T ~`YM"d[wD@VJ@h֘ߢްՆ [& fRU$V!8 րmZ^flEvPսʆR:9{CAI}?aI7D%K}(_]$'8=̶6Iޏ GFÀA~ ][#G89w:rd-[7d 5-Ρ-m8%`c 84~`Z39c`hV$VH&HKyWD_R1l_ř3Xo +RO xVSK}@0ݏ\,1OSf'?a=0iALx#啌]]yCkP2$#MVe TKK@ykjL y[$Ř?,R*dO5["iuCjJWh0<&CnmfF `$ dF<}xc_'ch A:}@;W'|+ QRYND ZF]i7$PKEBuURUWEЛ lQ$%܅H5NQ.oꦷx:Súwp~Ro˴fą291: [E& =f}%}S%SWO' 650) joint.step = 0; joint.linearOffset = Qt.point(joint.step + 100,Math.sin(joint.step * 6.0)); joint.angularOffset = Math.sin(joint.step / 8.0) * 10.0; } Rectangle { id:waves height:30 y: 260 anchors { left: parent.left right: parent.right } Image { id: waveImg source: "wave.png" fillMode: Image.Tile anchors.fill: parent } } Rectangle { id: water y: 290 height: 320 anchors { left: parent.left right: parent.right } color: "#74c2e6" } Body { id: berth height: 30 width:100 x: 0 y: 260 bodyType: Body.Static fixtures: Box { anchors.fill: parent } Rectangle { anchors.fill: parent color: "brown" } } Body { id: boat width: 32 height: 32 x: 100 y: 250 bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent friction: 0.6 density: 2 } Image { id: boatImg source: "boat.png" anchors.fill: parent } } MotorJoint { id: joint world: world bodyA: berth bodyB: boat maxForce: 1000 maxTorque: 1000 property double step: 0.0 angularOffset: 0 } Rectangle { id: button x: 10 y: 10 width: 100 height: 40 color: "#DEDEDE" border.color: "#999" radius: 5 Text { id: title text: "Debug view: off" anchors.centerIn: parent anchors.margins: 5 } MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; title.text = debugDraw.visible ? "Debug view: on" : "Debug view: off" } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false } } } qml-box2d/examples/motorjoint/boat.png0000664000000000000000000001056512310072714015234 0ustar PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATxڼ}lW?s_z˅K_h-`qkatfcf2F%ӈ dDfb@+ȫP6h{vmiI.$7s~|}oX\Ɩw7i :OY w ہTLȏGZ^ڑcXz+H9~8D.L_zGb#/zV`+T OwL+IٺrgqR;)3("`K8"4jyl!Ek\rR\"K)21P i_0cM_J, Ш x <3o= ͍RjLē$LM|&d.@d @ﯳe/~X}I#0# ?'/> +j/HWLF%Sۧc*VϷ!7M, M0lf{nieuɼO>9.,6Ֆt7FBhw=MqsTgtBǑ 7fxRiT'@+R$RJ&P;!|@!|D  v>| :/MMuuR T@ AG298%-;p}G.%v?8p>'L9yN1OGTN(h@iE %>~HH|_` )%{ٺq(\8zՊQ}٘aW1AȰP=x٦eݗg4Za]3n@$bط \hz>fdPpMRk8x"vtCD[IENDB`qml-box2d/examples/prismatic/0000755000000000000000000000000012310072714013357 5ustar qml-box2d/examples/prismatic/Ball.qml0000664000000000000000000000121412310072714014744 0ustar import QtQuick 2.0 import Box2D 1.1 Body { fixedRotation: false sleepingAllowed: false bodyType: Body.Dynamic fixtures: Circle { id: circleShape radius: width / 2 anchors.fill: parent density: 1; friction: 1; restitution: 0.3; } Rectangle { id: itemShape radius: 180 width: parent.width height: parent.height x: circleShape.x - circleShape.radius y: circleShape.y - circleShape.radius gradient: Gradient { GradientStop { position: 0.0; color: "red" } GradientStop { position: 0.5; color: "yellow" } GradientStop { position: 1.0; color: "green" } } } } qml-box2d/examples/prismatic/Square.qml0000664000000000000000000000054712310072714015342 0ustar import QtQuick 2.0 import Box2D 1.1 Body { fixedRotation: false sleepingAllowed: false bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 10; friction: 1; restitution: 0.3; } Rectangle { id: itemShape color: "green" anchors.fill: parent radius: 6 } } qml-box2d/examples/prismatic/Wall.qml0000664000000000000000000000016312310072714014773 0ustar import QtQuick 2.0 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent } } qml-box2d/examples/prismatic/prismatic.qml0000664000000000000000000000431312310072714016070 0ustar import QtQuick 2.0 import Box2D 1.1 Item { id: screen width: 800 height: 600 focus: true // A heavy ball that will be created dynamically with the timer below Component { id: heavyBall Body { bodyType: Body.Dynamic width: 80 height: 80 fixtures: Circle { radius: 40 density: 5 friction: 0.3 restitution: 0.2 } Rectangle { anchors.centerIn: parent radius: 40 width: 80 height: 80 smooth: true color: "black" } } } // Timer that keeps creating heavy balls that crash down on the building Timer { running: true repeat: true interval: 1000 onTriggered: { var ball = heavyBall.createObject(world) ball.x = Math.random() * world.width ball.y = -100 } } // BOX2D WORLD World { id: world; anchors.fill: parent Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Square { id: square x: 300 y: 400 rotation: 0 width: 200 height: 80 MouseArea { anchors.fill: parent onClicked: { prismatic.motorSpeed *= -1 } } } Body { id: middle bodyType: Body.Static anchors.centerIn: parent } PrismaticJoint { id: prismatic lowerTranslation: -250 upperTranslation: 150 enableLimit: true maxMotorForce: 3000 motorSpeed: -100 enableMotor: true bodyB: square bodyA: middle axis: Qt.point(100, 40) world: world } // Debug DebugDraw { id: debugDraw world: world anchors.fill: world opacity: 0.75 visible: false } } } qml-box2d/examples/monera/0000755000000000000000000000000012310072714012645 5ustar qml-box2d/examples/monera/SpeciesInfo.qml0000664000000000000000000000733012310072714015574 0ustar import QtQuick 2.0 import Box2D 1.1 Body { id: speciesInfo property string speciesName: "" property alias descriptionText: descriptionText.text property alias photoUrl: image.source property bool expanded: false property real radius: 50 signal selected() linearDamping: 0.3 angularDamping: 0.2 width: 100 height: 100 bodyType: Body.Dynamic fixtures: Circle { radius: parent.radius density: 0.2 friction: 0.3 restitution: 0.2 } function toBinomialFormat(speciesName) { var subnames = speciesName.split(' '); if (subnames.length >= 2) return subnames[0] + ' ' + subnames[1] + ''; else return "" } Image { id: image anchors.centerIn: parent fillMode: Image.PreserveAspectFit height: parent.radius * 2 width: parent.radius * 2 MouseArea { anchors.fill: parent hoverEnabled: true rotation: -speciesInfo.rotation onEntered: { var dx = mouseX - image.width / 2; var dy = mouseY - image.height / 2; var abs = Math.sqrt(dx * dx + dy * dy) var point = Qt.point(speciesInfo.x, speciesInfo.y); var force = Qt.point(-100 * dx / abs, -100 * dy / abs); speciesInfo.applyLinearImpulse(force, point); speciesInfo.fixedRotation = true; speciesInfo.fixedRotation = false; speciesInfo.selected(); } } } Item { id: fixed anchors.centerIn: parent rotation: -parent.rotation width: 0 height: 0 Item { id: info anchors { verticalCenter: parent.verticalCenter left: parent.left leftMargin: speciesInfo.radius + 10 } height: speciesInfo.radius * 3 width: height * 3 Behavior on opacity { NumberAnimation { duration: 200 } } Behavior on scale { NumberAnimation { duration: 200 } } Rectangle { anchors.fill: parent color: "gray" opacity: 0.2 radius: 10 } Text { id: speciesText anchors { top: parent.top left: parent.left right: parent.right topMargin: 5 leftMargin: 20 } color: "white" font.pixelSize: 32 font.family: "Nokia Sans" font.italic: true text: toBinomialFormat(speciesName); } Text { id: descriptionText anchors { top: speciesText.bottom bottom: parent.bottom left: parent.left right: parent.right topMargin: 10 leftMargin: 25 rightMargin: 25 } font.pixelSize: 20 font.family: "Nokia Sans" color: "white" wrapMode: Text.WordWrap } } } states: [ State { name: "expanded" when: expanded PropertyChanges { target: info opacity: 1.0 scale: 1.0 } }, State { name: "retracted" when: !expanded PropertyChanges { target: info opacity: 0.0 scale: 0.3 } } ] } qml-box2d/examples/monera/spikes.png0000644000000000000000000005037412241175670014672 0ustar PNG  IHDR"PIDATxTWʶ r9 M9s9'" e@9g[ɲz<^,} @${=tuӯ>zՖ-,f&gD܂,ULn'뾳VVkVUY-_`ٯ 7VKTNj V뮫;`ٯf#orZe5W-M|d(j jl_ U_VkW3)Ђ7Ze'9%fo3uVomIkhk7 dyg& 03+Ct]j~F!(J-Nԧ^cGFiJ;gEZeqZ=剫.-~?79BìVb]bSw0}J¡Ek{,]Y&z򙸸/a>:ܸTHL9]e׉=Xqġ&ڠ#m&FT*wL9C#*TQ(Íov cZ(h9xic(Q,{j{mrH#t%)9J|fr1OTb/#s!w8?F;jbeR.Y;Q(̍V+9`d$ZW`T ,Xd;>ٚk‚6[cVUQSĴ8d %qL[b8Z 8T$ZRu7P{B4f^E9#jU&MC^C-兜jL3V&(E/h+&ruh4Ak%{]C5fU/VX$fcuiPh_W| *਩9eGT\מoߴo5(Y.RєdP Vbq0ᙗǬB J Tgx&ڕWUR5826Bsq-mkm#K=؅C%Xj ÅTLwp<,Ck+ DXGmȂʎlZ ͷg\iF 8Vaپ)RwBjNʼnFUe ZG+/suzm,`&hJ1ǥd팆C;}QC]vx??ٰ&Ux%Q٫chE6f`ˍ6]-dzmߍϳvb9ɴ:כTogD V/[mIG mq9hM֔iǎMϩǹ8ly&za+18`)ow9aЙ|^ؐ7*$LW"_~|ao"Cp-aV7hsmًnKAy>fߵ9Oz%&]Mˑah4cXfX"pL?HN7T%/Uk*Hy+\o</쎀Z#ZaLsb}6n bKLܛ\JV6$gG3Ch1E{Ahwu@4TiNݍ_/!-DJp/ab?YG-XX6Fg3q$8ikʭXcawgd)DWV_7t1&[Gjk^QU!kJX,c(ug ?RG}[j'*::M*5p%^GR$\ &3Ѧ#!Mp]e>(yXtŹT!l~WGԘb8^ $ɽfCP$achڍ#X F]%Мa\)Pp5ꋲ|KJ5:XMow}6:4~M''˫9c!"W rq>'銲RZNUVRCQhTS\n( (`+E1[0#'\>?Uְ,֤׷( nSxTwmn4r[:i2) T2XPP^MmThc1G#hŪ6fve)|p0IJB+VZ8C(b.| 3~"`I[d'cg#ڊ ~:,H}ֺ8D0kUα|˜3na%.g0NHHrJ͍`#dh!FF;^7~y';ype*d!^UP:Zo]Kx\BJZs*N51{ U0O'tآ2`r /5V;лXLdx6판d3D3 G)cp#7 Ix5;+ Cc4JJPMXk4Ql}UX Bw)H,6GC9T# DjUѬ"QË*:8 eM܉8;&J֝v~0idl]/B`Ʀpb(A=SDL 82Dq`fp+ ʈ0NC>˾&V=/?pHQ#-j q b.Ld*"VTj8!mrsnJ7z >gqǪqct{`>ى=[ X_BOrq/ģ\J赊0gˋUܼggG>;j H* `C.eQ -q3Jx_.׊.X7 IWn3#!􅃾P8v'} H3Q*7xo_ ܸlf24"*}quQg'!-8 W?C{BA4yE쑔F"Dq}=taBO~cW/O`7z?{|pz'ch+yV57W \D-do}(sA >IsXr@>cPn"-Q*XlĿ&ʅGDJd>,ħ$~m ׋8dƆi9%+2fkӿrvg:q?gDPDYGy#]\qs8 P6VNA/!1WĬ d%}`;oϾ܊_?E"F'Lf-R\m+H2 ̕c5FLѥi]M5@˙Hp &="a/*_/8Hd+I@$[^oW߹!zp_,^ 4y d"<3BKN CsSYݬVf;-a7g)TCj^/.zɆb$ S%p6;k2?l{_Ut[Ӧ\{=1Y珃u~(g*`}1ZA CC|-#T48Xbm%NL8# 9' E{fȋ*t$:`+c9:Yh7RWzaM*pD""g + 4vZ7n.W"=U`ʅt%Z(X*Lc*~wmOTVŘ#jb(|k*.`G3p|o[#Нh Ơ8I\?t &ۯ*]"QpdZ#7ŸwL\khdhHbݍb' +œILƍjĹA'_G-&S@uxE17d1FMD@9Va 2Œ1707T ]iNĩrtF‘4 l3`(C e?w^:TcIrCJ@ehe)k%߂}mu{3z_SqT=]—7q. ^FFRX{,geS)s3G_5ՙb," j(6BE)JcǸ*!}[=H0ӻ;a#kqwmN\7RaM,µKu 2`ÌZBN;ǹe8@# tdf/<7Їά#6VA.DAM|;.ŝ6 I 8PP]6 󧡺rp-QUǣ ܊C$DP'+D]40R-rhŪJ2GO ew]U7VH|[-C&5Wk# })tHS!kDž:-.f+g"ѥiyjyvNx%{'\sƔ X5ZrhAqm_6.H?JQl=PПu2uW}/[#<0%,Ω=GQOA(u4jt"/v峱ѓ*6Nltƒ4,3Q(*tA.KL^U3S/Vi:j/AY4׼Mf'P|usJ=:ZPUx HV.1őp޵@|VZck٫޾QqEryisp& ٞHG܍aKuSj5? <~wk~jáesAV:Orh@Xn)i`LDEF;cj!G]`,|jȍpb2o:J+3 !99*S1D;h'.XKMWtiqK( ЯX`]H\nvz=,M\WAZhak!E`5kIő( VZ =@ g͍p`];4[wtԍ޻0S󁷍{= EvE2^Ѧ \?\KM8Zp7 EyFu׽k! C\ `uӯ70(:s񱸚YEJ5\\AaІv`aLy')) OB{+|NEaO9>)A9ݕ8?_dg,,ǽs-*/NJ Or+~r9Hs8ߎqGq"Z4?ܛƹz)uDAxT{A\?Sn`Qa#p73q48M$L &4T5 XRںqet`BOR dc8zK1\$sD:E:bP qsӅu'YR9D_]r6J _}@/S:0c*w@?.~c-1L+ɐ_Hd`Wޱ=IK`M0M#%z ngKXLHcWu:vɶ&-nfiv#"Oўl*>dEJQD̎ΪCeWXpK #H 1hԕ=0F/'jԥqz8g&qr_"Gcu*RC_KKIЉ0X*D4oI?[II\s~ xrOc$Wquw5y\=pd+㬐$<4PwK]3Ũ6ʴQk+{K4RCW8޾FJW,(O9x-*Y%-6ƛ@9 Uvsb4X|U1XW:pD ZsQeA,gjq|0+MNUp9QNڸ# LU4x&KI  (Y# pE)r= EHipz< mYhHEnBvР*2jO䐷(A)B.H=gf(Oחޱ\wQkݗuJ_P_z{%I1ŞdS,F# 8'cQH}&#HMuy- QgdW\ړD/t[b}C< WkTH\wnD Tw4ϯ!;@[So(M RVÒ- 9w^H"B8hC֦kY-IRŶsr7g0t=p*gތHzݗl?m yw#i.̉HcJXr-'S߻\l"9d y1hDHH#MR#Ih5A.20t9q|1AseZX06C_:-q}(u !^rXl 1Dae*gs OtHƁ`w9k$lEg :TЩ"isc}e/ =yQb8 ^yEzT笖jWU,.F"&VI]:|o''D^| jХD%uZ_.sMl} Eɻֿr996w/zמ*`ɟ^d'TK:#|IuGrb+#t~A$"࣏ %]픑ENׇ&` I穆x,5b wWp*婜XAI<|o+s86&RE:c a&yrhWZsa v`+Z7}Edi36! Ad$kSQ(j9K-bˋ^u qƝht+Vy4JH^\:4Ƽ=ԵMNj.L21Id`Vrq8e$ q* `e<C3CwFD"/7Al;"&BEY;{_; $1KS9LQ <(En,Tk E+RW4+ك'ϟ?^{n9BV0_f"7)!ZՏL4zP%\!06A5NaQdᖡX:G ?qk 5bh 6spۦXύc8쉋m8EαC}DqY=6ޣ0NcREG'px?ɥI") i. Rr]*W(:ㅕ(4D)+q$\N*tؒue7>K?ևxP??)$_}paA+G8D nPƒ3.xayDy#+H `;6XvwgA)izzh ܨ0* CX}roS؉2&zmIZBDLݺokM$wG`#a/*ecqSSd "@*-jts^[IGBP)p~U8^}ovW># m8oT 0T(B.#'ȅ|9 vr@(|C)IoD\ g>0`l$ YDW--pxٟj.>pmR d#Ip 'w؞$a5/uL9m4XzsqnX5ذ5c 4TgTfDQ>BQD댳@o!K% 'tJ[Kaz-|FB;EY!g5ivedX6OraTl0QtGy:,Ru BWnb_oK~m1ˣ>89 7m7&!h7EQ'gwuC M1ho9٨V`O4 X4ܤ+Ɯ8@kƙ/\'g5+k\03~%_T: )XuGGTiP%yi=ӹ 5pL|QG˽,l\uQInAeӚthՆM@]%50Hgy 6w,D`!&d qPC'9.j| Rh0R$EkkPti|0blb=ufi W^ޢ`=Hu3{b0V℁k\LUC{s2mM>\<<]}D1 >@$"(UjUUQB~*j{99㉂TIm>/-—eb$GK] fc$碠zuz2L i1R"NVh&*Yqd;JR%ц8;Ƹ?Wo.VE |P*ɇz-ia*w@.6`BIhEp+Pz_T&"AЕ |P`T/]tgxc!)lc%Ű"(Q)D/DGady2E.69 ObN^ZPzlp'$kNPt5,NlӇdr7}<"ó,ur=u܎A?xq{1h13F9=]q9- J `bNKSLxIAexH>綛; V kSMb4\L%0#r?N0]4FYk-#1XべrO3x$g}uʼn.5TD]7RO921fOԍ1G{3Q$EFiʁTfb:&H'#)Ex-tn v5#Lo3J XO<0Clo&I(H6bg4zsݐn4gYAW4GZP$1"NFJyr#`¥+/ḫ#yV|N~͓2tU`:5bcLWT&`Uo&"q+)wj3Rg% 1D{Xf۽I3GG*՟F;Kd;hxr#ZiފF馎!Ra:಻;dp S\IJ=FH47%]/%!ӡG115}-5h!8&Jz7 Ef_*G=wx4{8`#͑2 g!k8I4GH{ٸK|9$DKhju48F$5;R0M-?z31\D>~Dž$+0;Eo#,蘠wCԓrp 2i`}C_ ?$PI2vSs1!!Xι.oNAu~tI8=}EADG0]Db(UQwcݍ%H(Br/ n)Q+jA'HWG#{HM,bɾ)`y3e0ERA$H.v̒ESv8O ZĐͷBq/"g<^Hmuׯ#nTq ǛuHRA h:?dk@Q$RݘA;lqM! T|F:ࠗ 9i:P҆}zפ0D}:F*L0lc}n(=b XQ,Dq tWGQ-o\ zWXK >J 1s#9Uq·0D)ǜĘ}Y琕5G(z'/FB0icUhϰДȉ1?'ju='Spb~9t%a$h9l:yEtͤ:AWZ]LE?'JU%va_\5!-kH.[#,dž*~Z>68?5Z͆tw8];J8m)rf qq [i8`iAFM54iVTa[:i4f@. cg:냦4/0i:\8 :F]P Ai$RUB!D6 !/wtꛚ}NN\z64qneyB\˵EWNyk*I*0V{b!"swK&onk ?ݻsapѽ^Xt/1xh0x}> E4pG&83d`$7BB104,3R g{p/"A;5ϜO$Q`Qh+"1sh1A :/.zQQ\0q=cr9l0EQ`z9EPmhHuU t{k&&jPn35>JVOꉅYʹtD~,> /B7}]jA7ޅvRAuDZ [A5 \\\hQEg,I~j^l-X)沙8a1fޤ0H`wݷXQ mNԥa2̃>Rcz(%t M))~uu i k\pqi_zQmRFbVp#)`,L[d(E")]Y.kajn*?r·; 3-_zkء=xݜ=>??X @n Kq1(#)RIhhMR?>LH5mҨ8dx9 ;v\{-R [%YK]~t8< O7m!h'ɖ_ud?mMGOMr#1 !z-QD bU ⴙ%9A*ktȤCD vVU텫y8Ro# S$KnGP;h7ӔDZ=סӉ~]@Kuõ3r~ Qxv[ʿGoWS=̾j t1թI\=vy i$㓉3tL;z?ڵymWju1P*UqVj~U&0nki89P mm%¼㮅@5) T5=VB0z&Q.;\řn_̅CK]6ulHc? Ԑ~ht?U6.,U8[s M14s}~EH =prV?Zij`f$N]YxÕ S>u S/u. ;rb;!K\Nl"X${(@jB07$m ՚?.1>dGÌǝB8FA8p/C "g-K%$z#g4U&l[NCI9 C s pw]^a5S$,.Jd-B &w1ǎ-eՕNhp@8eIE;)}u~ `ބiDVIΥ7 k3w#+>uTj Thu_|~Q!L*]UAؘ(ҪL%_uhc'IH#lՑ/ća~SIҺZ@BaN"Y#"\C8\x'!dIrLw,㷼)|qZ_ɄnX ^jgo^; =(&yW.5f~mј8=3hmz?މPDJIxD=.6{j/_d[$v!D|tu~b!ɡ8NPjw8[(l+/zi-u$ʚBN1$etG5\&SCӷ:q9v*\D41\H }ޛ?BD"q5H!V8ɨAX b=4zׄ"yta3 ~ѸEP}.JQƬN30FݎrR`JH #b۵kSSKlNwB.Q4%,׸J y\I5hHuxq$V`#u2á.ɇ֊T,H.믿cj$QZs™It惂kI^|b^R⇅,J0S|f z!/+/K:[@K1ҨNKw<6XH\.TȊ#qĹ G!U+a6ךⱘ)Xn CKN* H"?cx[`F^?:$4:!ƒ8YA~7ƢC1j)g;4(йWeia?QXp6=Gp0˒C@ XׇBpe< D{U+Pd\[O_WZmYnW 耳]+]zhGkn 9_= ME>"1L}%uMi~lt/'h |UeIB*\s>ttz"\ L-K +iL3Rm0Dg1cpz8Y&p5h+~[s 8XfP/ &N WUJݙtLj;XTXD-"V" mq)?bq20_j5N4Xb-Ke^G "}w.L"' gݗgiȾ}5y!p `M^[q@?wb܌ ny-o~flj5py8 kН7v@ԇ Q{C1h=6Za`8NؗcC$7۟kv/7TDؐ\X.* _2&W\ulbwO06f %a =҇ПvboXSt.u<=m #-o Ԅ&(^y_C# .N0$xc '}q|K MP⯀sXAn6"z. n1O%p-D,#KC%FXs} dhP kqg<7Gpc$U-Hu$jON 8qQg7r2gL?cK}cL)7ώC$<.Yqf?✞:$;ϚѡTwve is7igZc'e&@Y"[ \ܴX48yeS3Sa׏ F ; ~C@m4oww3gHܘũ}~$@Q`V"ŖJh+FhU" ,VP^sҖJch/FAq;CguIϖ;PI9fO"۠ߛLK_o=L:Zk6mUOK_wQ*̄lrēm8q]ȴ%%Õ4|v,Gz\S<5⺚*=L^L̕?QXV]}[ݴW{ LCmє۴$WW}]w}c.M#.aCv*MuX2Ͷ>aٯ[VW{"Ze'P Hx0P=$j]F zك)`VP4X$$ZeXēIڟ=aU,zuU<%ύX²,9wsG$z~~wծZw}w txf?z`G)}/ݝ!t >|W-Ppg2j$*IFe}o.ه[p@j٬Kҗ<_hWV|=`VK()Pi6cjK=߰̑{Q~y:P!9oɰ@'~]RB!x%~kmj=_25+]C)E yRm}_4|6|){UZmΥ24,}7g T(e BX27^_xc)sÏٿӆRiwqa DG+n JdDO lCдj%/㝟k@LR<_c/R,ńտzd_fg)@ߌ[գB|H7{!􉧺aVUAhT e{sR YVNWb/lb7ܩop5H%dXC)P`*ի${N8NA)C~bkooKozMEhZJ)T}TVqE|wG?g޾ 4Fͱ\@LUq_z/KZ!8JQx iO|i-ZSTU:;WPsĆb:`<bHB4= נ h%<*`9a&ɀ>=;qœLjM\%%$rAI)Y 4Qx6#J5ƔCaa7NF,+<]@M\"J#M>^MB!H0Yu sۉZlfe%Mu(B]2Hf{Ͽp4M1\gsZbcΟ3S]<,ϣi&K'l]3aEHͮɄ,+I84X Z {r}QFfKϲe"?q ~_?|ɰ37ڎj݋~ M{m@ˁUkZu{&0e Lj?|2$/ܔKUӬ}kea4\͠9y2\$I&1wA-y5M/Y^)S_Z$RTMZ.8Di ݭM lFf᱔D%r<M! 3D#v9ig <0c՘BUj2} } PkƔ:(% .FnMf9DH fj[-Ran-RT4B-:2NsTh{wei%ƾhDw/&KIqlMdz%eZA\}{aIn [1@& *B7a[d;4̓`[.~QZrAYFyA- Rv i4:1y}qb KólU>=4@=͚bˤI[G RƑ;iwyPe>j2#'ex^hcJ̴p=#Kj+:&!hpL3t0"\c =0S>/!Ru'=GZi24tB)Uo7!}f|w-\lcl1y!p1>N_ QReV%HOc%([;OrpQLܔ {qm BTBZdI̵+<ёzF*:(mô*XNJ$kσй 25JZRe=8 /18.jb7BID]4A9XFEeX;׻2ϟY>rIdPA NC9DROw :s!IjEih `ISӞB]8Eu(Z~] l r0,V$]/"J63qBm칄kunAIZs+di EW*(bKc~d^Ewt^`U@1fs8(^@w*Y[ $j 2Xi&s%/{=)!#v<'K3ǘ}T/LG?(2IObVFXK]zQ41GL)hZ?`w#9*Ezs2읃 !j?Be F rA 3uwmNq56QI|LŌxE( iЅxR8,h2 2!M%~Kgo٣' \nn-`T+GʘIS~4*W_Tu뿋KcAX)4#MSbLeCqmodß}35[{H]`e}~UlJ V,!iB 6Vsd3f @^Tiԉ| RF<|2q1zYn7ؿv 1Jx ^Uoyrs0I9$+tPifXr C)50ÞAC,Ch4t}5XYD!Bh=CH]'ȔdC3D,>>+bzG+n=)ю~tAgbkLXnRL;P7A%nL JHl5=db5k"OHw"V?tU 27QRaM4**FRb4{]f8EǤO%!hHgضM ] DhЫWzaos{.z6lP!"8(Yw3_ zkCT>AH?&EehEag ^S"t;G3 E9q Gqb,cf "Fs,]L"faĒO%tTf5oZyV(94>ЅPJa/Ϣr1S'Ob4%0=Ai޵ GW'̕E PDñW°F(U+Pmn6(Z5h3vu4Ie;qLZr)UHצsn;xug.a뒆(*w@*ۖ.Na#"U>psB}Dq`e"?RSUgc.F v*nE>5Q%k Y#"R s"H˨go!t]w1J6{A6^%xk|zJC>a0jdqa`jqjY7?"Y2{SK ?ollEu.wOifkҏ ^bk8kRliU3{kZ8y,D G#TVB2MIwADϸS ң覉8{rk^Mrr5 uAנR896o8|>勉oY[v@W $ƨ,SIp|X&EEd >_JG=܆푇~ollRh:FѬ8;& ],îTpMnd4F>$޹c>BcG?()v5p>ჽFplEɡeaB%,Y_uU/OIjK˸mȹ??44[tL?LBny~T+zw hm^Qk`!4Ql=bǴ-q@!2l] gxpsyk &Cm{;dQ?f>yȭ^¹4[0B 9%iJSk:_n@2IHw!- ^]G''9`욇4) lbp5l14 Q.ca58s [ .]!Hm†@7 5?='k`O]~`8P8ѿA+ǿ^~Sҹtg <7Kh;4^q]'o&EFsYv#[xvqHKÞT Nc |` !E(Tq 6A&Hr4]G *_UttL@fk+s^r(ћ5J'l W^X{pSUٷ?~U3n F*/, $Z>Y:$PEYu &!F&!OB_dhJ')X&G>0 rJ^DRyCZ;TF\~"`X[Σr+B{u$8̰e5:aƲ͉:H؎QRCF!&;a&V'CR#($?0I"&Ȣ4@Fdqx%I&.5-j5=aab7QXJϙ8e`A rhYb-0U(Q/̤BK(s<]!bܜ*ҭٳ0tjP%OcWװST]4PsoK!wm?i)^6mZf&q2jOy&EFΈW/wqKzm;mN.^jB҄A~- IC)vp\M5uNbKM(2KG1FO^+UP?49 sAx<&4""ee;xU|NN&L+[rIq8yO>G8H"Y o:3洢b"̩q:>Tb4!vPQDC-$[!~wrXQNNc塄h(y"YOA&B<05*2~A_7s_SΙ :^9ePJjS"0 .\f(E&Dʘ, d " zN @:ٓ`p9Ai5Hӌ<.Rհ ~HF[ ŃfzW!d.;]h{eSgK$W"t޺m`6ca7'buҜK&$[)7A AD}jZr=;3G4Π\ψ"I BǡPYJXB.QoK'~=˲o^GlRz.j~u= dA1}ö9<h-y0ladz`*ֈ4DV$Iqҡ<`{ޔi IPa֨fXˋX(OjUX7•8D| 4U°,tS' %j/3l2({/ y7J$> ]ҽ.FvLZggxg8{vd:'=٘A$?›8svY9B+*~ W),ZaFe\aFjQƪ٥ު2{IW61]gFRs+S(6v\^$McVG:,40 mq!bxׇخ q#t|`L(WoO {ۿ^g~G!O!^Ӻzљ=dO//Jj8Y4g%׈;ipR7aʶ6a {0e%#Pfoٳ-f0}bMzwbV`MU',0-!h5?Ҵ}` ZKsuTcXQ0GG\JG1O~iLal$3MT.\1 H!VCIE uFNϵKװwlvd9jQQ*'N&l_Um`Ijj͡rבYg%/ֶ nKIM = dNbt %R} CX?L0ȫ_u*ϊ$2 66$,/LmqyUu 0ud7P[>3I^htIU4 qihb(CDÀ7RQ1'u_bB s^&C'3<ʅtv:ؖ.6S =9p<c3?wfB  37inyƉ5k9Emj2NܣglH7L-xRed)%\AE1$XXE /V{vBAHADw+ڡ@Q4}&9365AصBY݂,N'i_\c-RY^ĝj>I#w昵vȋ0BBnqfFeQ23GUne1,tG}$%Zb'!NMA vbqBfyUG &YjV~B"ģCAJfdYa\n_\.IcSt7g]{3o2g29/ ]X"[飉ɇ;# <|,KdkR@{}r5B*IzC@%n#ca8ĮW02Ji!-:[?y\@wP9@3T%)%^iPmH0kjR ;۬]m!f|}Z!o;QN@h:P#{ٜ=SߒH3:%$gg7«Wa~w5iay.X8rWp(Z^]C&Vf4yjXGBZhBh`CBj5c*duun(:R$)+c ~?J4F)WgrB,&s_dd1NBZGm^rQ2gstĹ'l,Q`Wf;Ҵ\jSi_Ȩ{P?7/},4*#MFx 'mRۤˤBbU+ ²&svֆa`.S:q[b][ 62diN+ƵM O/`f1Uv[C94{*^r,/A0׋=vHKO\'YLc$kL!, RE!~[FA DLϳ2~(ǒjB Ol 0QN36<~>'MOC.JӋu*7: J=H2dmrsU \q<1a& eoIv9"e zn@>N 6kr*ed.66vK?aY448"Y1A2`aV4Yg9/3 Oť'dq87g_? kT!I|W,gz<[RS"l b Rc6/ ι7| *,Vŗ0qS}J4h.p׸{WSP,ݍ}Vt@>!3YvWio_agկ7ӟpw[J,g _c'_Un 2Jh< mJ2 bxd#th=W>aOBʲb-+7(V I.>AѿIQSS ~x׮$ZB`26u8(l|Q sԗJ\'3m/ ;lr=}do>qOdI¸? 9eLƩXHS\H249Qo) M#rl^LXe-fʸN-iW?;!ƿTʯޭ|孖? Q7iM -$EvغyHS1su'`OIeg#A:>vW F9Ǚ:bZ!xv3NڋNܶw2~a{'$v9smL͚m+OA^ttf A'tLV_|#ҥ:Ua2̇oB3pZU=fA}QQ2 [.Ib= q 讅1dUq5 oMp`oQBb4KH%?E;X.Ӭ:$ifQHܲ^bm{E pKVi)䪘ѭؿtrnRn?;nC-l0"  GQKYK)է)Jդњb a2FFP~yC)ͽ]2m .^`tyQY~};+JBF1z4\"<TRlQyq͍9U,#!$3D 籿_\I,Vd.KsbR?V5Pi'>k??Օ)v] M fpC1+ 7kS/WAhhBZkb1#݌\ˠZs%}Ao4U?kkF=yPJ(.mlorToaYR~.bB@)?Hv{8CV{mRJ+#bk9Y^Yu5eOlrR70lpJI( P$xw/%Ku_Y+aS i8@Ct2&iFQΗFFy&4^bDptE ԑo>M~i|RO2g7dW6ӄQ/oYƭ4A/$ޑ>8wo} z"گfklBhb-ɵɇߡT/a\ģg6yxrK\.ٿx/6 W)JIUAY+ԏ#ٻ-[)A˕MS_Xk6ww- !0!̑~F^ "L}w~Y%$GՉSߞ|+p3umr=bPҐBˎ>~#>:UZ BebVcd*nQ'Vcއ@Bec'_JO:`c އÏY!R(yYAh&f# `y#z,6|}ױ!`wPQRnst %GIK~˛]I>knv{hZYS/j`8dg,_#'+tRɜw}f0Մ4uj vVɳīt-1<77K=:xaxK;~{Ox[Pi·>r&ڨRmT!q1M}/BMi4O>i#`}*a9&:# (& vkhH]N{Eguyht"lNfRwdbe&lc<7?=OE-sAt3 ]:xl,V8ɇyvH>\t{0-YFom0MdӨ!$MRֱwY~q/@ǐLJsD갷52&nm:(AzOn 3Ĺ1ub$^rjד'.(D_WgòbfWIF6a]a,Se<-vwױ]JJ\'"T&uj5˗'h/XIBllӽ7=a!W2%!<ӟ~ޠÉ& RƢ] /៰p888Yic=8D>>W0 c&DhrA~PF)f`tn? &!Gsl7O6[~}5tCgX3Ey쉦iB 47[~iWY8^«yl]]}ZB FϦ(>)^vBIȏKl7c`;K>3Ǒ*G]r鿄Yg]Kػ/oh\6,Vvꌢ1D9{x.a>?VE!݉=XNd3 ,R68<^QHB6I*>NPţByk |LCEmv ^`3.#FiyrN4øL`-Ϯ}_H^L.gjWcR]eG]p6f9bw=swPn IBAE1W{* *\s^UYI,#gM9IvyX,(phrsʥow}GÏyza'Rˌ>S'đNw$)C%[iVZ4[s$$~,r2E:AghJ r^tso]gظ$Aer&% SRÙ. KYF ]{e۬ C+*[™oQ&(%m|亮OfBpkۨ/܆t ~df$*ԦL,#B:fȃ|Jf.#= 1up}_#l\2脔mVô ȸY挪'fn]y٫}VCFiB##,8%{nHO>Ԧ4+V|1; 42k*c3+Ԅ)UPb+k9~}~?XOF7o[9}pMBA*\c`ik<3Ev4_:^CuL|Q`6dgaay#QwчBC VҁyoiG?Տ?J>D7MŜHZw}ow M0l1f Ľ8^sK3xPI3@B":`٪q}wquУ \! [c8:h*=`蚆$qpdf^͔qL"n0Oseoyo>TnSgLM&@2\s`8<3H㔰gR6,=2#:&GM^8x AYTtB7ۘ/Ie?,sYKIJrF=S^>6g9%K綗xEBvGb au}O8ej5JK8iz. Qw͛~ nX뚦kyeYe2"&7\22#hѠè-Xu|[8/Cud }R?nl;4B|fGe9ioDD7&1D1SK]u&z9* ! #Lh1,fmK%ʋ5NL:5Ka$|$ĩxWLkLΓ!e@Qi@/#l4DQop\7? 97*OP(%x|86#GV;tuqߠ2W0GiA5dQHF(H&iN{-ڳ!S6o'5F⬙&w$M 4hs0&w,j36*IǍ/\ŪU=y-lMҿq~S|eLWhP;yݶ1GD%tM]\#BG4i[Ԗy(İ>(F(uӛz)P7XV$kk!;\{f㧰\p]6i +"805C' `錆n SC篳:_(,#@L8IԜWwbD2|àF'ζ&AXfA 7K @=ێ][Gizp`*Xۢr8GfLQR:w87$#,J؝+'0jՃ ]EҵnS6:xoS_3,;}oV=D4nTRD.uR4\wUF^-!?ZN4exm D;XN.d+f)r0gf1*4tɃfq i6Us.>w0H*@ԟn| #?} оo7/ݴf-+q怔6CQH'$i>y 8(E2G~HW7PYF:2P@HI'tzJ >M-Rrh!H\<ɉ;n/<,);fU0M SEVK:eZš]Ǜ©U=.ꦴA" [ur#eܙA(,6ʇ Ic"hSFWvR:FaЛzu3ZB\j{2ˆNq!Hwk{d֬10kEIqQYZR9"_ya_;n˛ߵ tMZyNNr&>j4BDŽ;hxD] XِO]#%BI$EȈ ql#34\62Lvg=`xo3~[踚 XD=+5.2||Ĺ!M_4Q$nwh1M6nqQá)EDQsSDQ!'1v#(J t]{q V'T,˜tv2k[ gFm /Ww]7,zt&4,q)YmHSHSAV &ĝ}b'T\z J`7ރ(Di#!S\\–]w[<Lۣ|,O~}|/5jF֖^z:57Mgw }*uTpgIlg2/)eB$da=GvX>sG~Sw[9f(% _E3 6h?2 bObtWא2<>hbNƄb&'{1*U|i2!][@% $k.^CL4޻vw:8%Eڻÿ̞}E \*5~EP(`:j<٨ mY RL]Y%F:(as b:YGYEfQw}Y 4nd_K5[{KuXkj48ALwvF- 5ڇ8;ho(@h:nNcчq1z>\x9ln1x@5T䣤B).M xř[$"V?! ]89ףXB#fZ,͛U|?hv tCڪ EoxP\bRqa;x<̐SfiC7훋߉N~(XSq@}E]iQ:ik̃,;~ҳh!cY9$0Z1) vLBl\ PRaM`Qd,+uFh֞ݗsgdc,H0ygs}<1 o~#[|db@ݱR-O^^ǰdKptI Ld'=?!p{=ddacXRɡmLMa448R4xDI*`.Ү5X7ft6MotAM*l E!3>F0pbV~JD '+X Rf_CdIWGR>Vcw))m E}2WfruO?MY~ީj*:AX pqIeHK`J(Ad{~`|ҩoQ)) tɊg'$q#s)q~#9w~UF&DgNzBz\^r4 ,ϧZ*m9M #Yal*m;w!݋JI+irUӤ6JHy O&&n 9H;AHM%Tzk4-mv|s6V9K6%cV ;H dnku)jvOs!-V&4̔<|Rb=U|V6t#>|ԧ1-i!Hn{}snVJ.BP)-Ԓ ~azs'8;)v$a$q qHKQɓٻHct\+ֺn}{L0,+ yY,VWOOv0$;R" B} ^pS5 ףFeam{vq1z=Rd a^%_|iOTϒ-"T4Ή/~w\G:9.Y !27l L*۽B)k*%S(ywuC-;=Z3a~e֕o>l߮!e,K:EQZMBv,*g*#Eӈ.%WԴR2 B0FÙ)bN/o T 0!?97D&; "˄)iٮwToh\dINYw$J6Bww$e3(2iɔs=Ft&lz\<@ 'p~yx|HI҃>& Aܼ?N)yeig} xX"?L|ˍSXRb0MuXIȵ5sqj|[ȔDvǍ^pҳbi ֠JZH%3\"!_] 裕a!RPOޱuAP 9"ʵ q^3Oxjr XB!cJC-tU%]x~PuAר=ba**-?P.aldH&`?{ёj>e wYxؿ{c=";t+nxISH~>}~r)(t-_ra)dzlmna0>' xN_"Z""lMUʗ{.L"8h@VIXHEv:IGhIxB0g'Nm^i&>+kDD B'I *q#f]}f8d V#:fPw9Sp9U% C>Rd#2E]atLk 膆i^@u@=pDL'Q+G(}_=\᷊}~ڪVF=QMJIn!M'76ַ{j70yi;mrNLS} -ZD2" <\g@dǘUH#pm B#Mj& &Uk_\"rU!VZ) %[fٳ:0:7\3c TUVLT9cć]@5R|~o313APuH ZE0SPICUt 8>9CC,^0w峉EOߗc>/S \K7>P_ydFL&_Z9bNvfEbZ6dnj4]25xV%"K薎$ZzuWy4xL$ŅlF wFzX4&'FX>{j+mY8#mg@k䷆|m H]A~w0 y`TgEAbY&f@Ỷu[dc 4VQn!=(5zBQ1;<55˙SWd_#X\޲2 X ʻ=HxY2EQ𝈸;Ix}f g4X;LGF&F;KyJgeBb)N6=$0=a`}TYJD".PiR9R4t^Uh^Ƞ" dB]۠j)sD]2Kuam;mAld4 ]Wz6Ei+5f\ʢꢌR"t s^2CㅨV'd޾gQqSl۾oL#!B)zgl90RFA&{ *  (04AVaa򸮋z %fgch5W52UD3-Afp>۞btm|iid%E-0&QI0wo%n!H)[}d!66s!O U ,M74`&.!IGEI-=j"#EH%=h;~k̾w6jǦ&Y>^uljS'k]j.~!43 Ri ]C! z^R:tE.Z* BC:.n>A6sJBj-: Z ԣ15?N@"}Oj℥)̩ɡ^DDqLB5>jfr l-z@YBTot۬>OK>*(2S16, Z= ЈP{ SZ+&v^XT5V&gn$#%I\O0Zvl,cerTb{Fv{-(f4@-*EFnǏW✾H:1biܥ5 Nu9l-l0,qEoCGzX攒PUAO8]7gc#||JȮZC(Qh0(R\P+nG`͌%a@MOȵ% ,UdX^\fadoۉ6P=}]޷26==+.iII츗_I,o\IlTڠ7GDΑI(F0TdqR(V'M~q=nPsȎO,.g0q66H1LfAܚ hnK[*e Pq>BEU8NgHU0)gt_RY!eVKE >{O?aO02TQlPZo2Xo¸J[_kѦx'aiL2\8Fyh M4-g8 }K'p. ZA(ٟcǡ) Dڣֵ*NMB<ςei ,@-W>Q!RGkw\XAm!ͮau}yƑUB%"; B:^89M9 ]XȿVuSiO#Oĝ"r(h8 Ba,ѐim?C*.hyEjr;j:Gp%eĉFM0( 2%41 @b ̤*(f ?zȮ-z0i6131_ŕ?h]h4X҉jRQQ}(HgÞCAy I 'b`ً_k(]@ RXtQtO5h62 Q|h󧽞҅12ThshnC"#tfva#_O3K2)Eֺ5~lBsBZuV= T8x!Jqxi(|ZE*>"i;:RAu M ?ߊ&|e C{%~QۘS]Qy㿢1\2% M6m5f)czc,51Dx~*&YnV{'TYcyac-ߓvc3I! %m!D~h, %yZbdV jjPs$BQSr 2Jq{8$05Jvz0Yn/z:NkG+.goǟX }55?]eHR\ȓ*1VgQڈt5t#tp]R"a(!t 璺ZsY>H7(l Wy\5j^VM2!qsݻT\J>MCL'뭠U4PiMQz@%qahqQB6-V pK윎ii.ckzd& 9f&@Q7"B8s}+5xk40XB碴׉#Oeh860 R,&Ik%pl<6Z0Z UEMdMCHEE!"&_ȟH_UW !\Ria҂\adp/tц|sn Ž7"Mgs߃vGL-d6A`B2pj[SG8D';o=ɘ:Ngf.Lz(dQbDLVzٱ V4}(BJ5`?;V2H1X.Bހ~Ng{mF?W~g=٭9)~-#qA3Y]`w#f`Шjc$n0-pDEukJ(a ;m;҅+#Yi$(&W\^^G- ^qUTgOZPAA6_av|teNç{Aֻ>;s!7d;v|(FvtpcIHsPnЫEP8L=UK/8w峧#}s6F ;I8ee-'ީE<U#Di7(fL.fwu^xׯ>ltg♵8|=~wWhfٽ}!Qpl}$onK9F4nr%$U'̛B?~sz{(<ަȬ/=´ŧ!v7>g Fh2vsd3vُiX:V?lo_٬6V\)^ffw-o7݊U(q:tUq%2 Ru'KlFG;b3koR_.E5z9V4m8(n}5K\ =n2P}Q^4ɗ'  7лË"=MSZ6oP,j$ jf(4GJj.ğ9m_2AKi*C9EEBUCDSSp]VWr*3=% e0#~DĿQbHsAב#UdEd1ԩev )|o@w#OQ`"LfHOsrc%ma~n":a'3i۶N?|~E]esRxY싫HMG-Tȕpl|M,j[m'__~=?n]M拢!CGQkBM?K\/aqqkZ,ҕB^އ"VWO!vNt`ֺQq~$^*f~|tٲ:HTET:\!ZwoI Dp +_V^T!O}|*y[<`G|}k~B*xlp{Qy TпڝL8/&2zL͠!c.lukw^rr %w|пv< ܋5 ީݝBDĝIENDB`qml-box2d/examples/monera/SpeciesModel.qml0000644000000000000000000000263612241175670015753 0ustar import QtQuick 2.0 ListModel { ListElement { photo: "coral.png" species: "Chenopodium ambrosioides" description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." } ListElement { photo: "monera.png" species: "Stachybotrys chartarum" description: "Vivamus libero lectus, sollicitudin non pellentesque id, adipiscing vel risus." } ListElement { photo: "hexa.png" species: "Amaranthus retroflexus" description: "Nunc diam urna, tincidunt malesuada porta vel, bibendum et enim. Suspendisse tempus iaculis tempor." } ListElement { photo: "coral2.png" species: "Vibrio cholerae" description: "Vivamus libero lectus, sollicitudin non pellentesque id, adipiscing vel risus." } ListElement { photo: "shell.png" species: "Epulopiscium fishelsoni" description: "Integer nec quam quis enim tincidunt mollis. Aliquam condimentum ligula sit amet leo porta eget iaculis quam tincidunt." } ListElement { photo: "shell2.png" species: "Daphnia pulex" description: "Mauris dignissim viverra augue, sed sodales odio commodo eget." } ListElement { photo: "fungus.png" species: "Carcharhinus leucas" description: "Suspendisse pellentesque faucibus mauris, sit amet interdum nisi ornare sit amet. Vivamus vel enim ligula." } } qml-box2d/examples/monera/shell.png0000644000000000000000000011317212241175670014477 0ustar PNG  IHDR\AIDATxp^=f233===iڦirbd[eز33333'fffF[,즉'Hr?ӟgkW^y] z9)Hjǿyyb^>A Hй< %`.ϔ>[|CѲק1ߟ֢Tgz2Av/?<^c-iH@tWD zɏ+8ߛ4@m"­ql{~*:86SL'!E&^LVN$olFgY,Ch3/O~%9I3Aj9QD/]xK0|GiRKQ$[ Ln Gih->az? ΃.w,*7QҞu*;_)?}˫+q~Z5ugvH {Rm/_ѐG|C}gT?=sjG7>evl}62qy&#y!^{7bW&;Δ$, \y|^ ϖ(:1ۙmmDJu{<]eZ}η|O1;9)IUqLJ/A+1WKߞ\, 0\Mu;\C_:( tb;==hD# e?ơ/^&G1SBE'"FElU"QG5 t18b]ufq Ǵw 6l55N>Wx!7Np=3p>sbKif7g5[t7%EkA[S`'w?o-Z]A`ߵs܊,.;K訌׿.{^8`sLd8 u (vx|"_' }3reB‑싂je_%P]+nO>Ίhef*ӪP^( En)rC+Kćצ=_[5`ۮC-ђ狮@ʬLX|g~)[D$$Z y.M GCL5zV叁8!A:JзP,ItEr&2`$̴ 4WI;Yo5?}^hCJQ4/#I^Z/Qz':[T&(KC2c (m"|NIWZ-~Eqqo{12[]{?b`E )Q ]m(wy&_̳Ǣ?ԁ`O6EU_.3uYAh&H[d9 鞈WGiKćОHܝoą|U$:Ip !?yyşˊ=ט AH_ca0BՈ9"W8GD٪EK&w޹Ƶ&g6Z52x%T>EzB.#@!ya(v@u;4%J~#g7c$> ih/Xc"MK#E( 6a!Fyp L{?4 5޸{:Pk3p@$kO/ղ)W)I (E{Q l4e@ ?h%?d$^F`)`!H[DGܜ3罕]^lXIK-(MqŃf(t5˫enKLPڀ8OT, {!lnL(R}/QRmkNŵJ\+T[*ݽ&X@I1ђr/g? ߕ9gZ%lNFKArP焛5keJ&efB$ر$?h'8yRQK lt $!YYWĉɼD?4=UjB"]0ק*PU[pkl,tO䋖ՠWSMz"\csOіSV5N|o:vT!)~^Zpp< `&? pCC"-JnXLJ=`&|x+<$.h >K_뭊6RO쓊dUCK?e9X).{Fi$ 6,X-i| 9H@kg*cpaK0;R.ԥSO]Z0P/<F-t Dd 9mE^[do)2‘nbMqm7ْ +UV d]emEJfo~7/>Oe|] ơ4 qPmh0ٺH@T烐@=D`i 3=w[$Y6%o_lBY $Vd 6l8k?gG/mXI@l=MqGQCml}j73=/4N^&( eSIe1 .H#SpwfrFZ W:Iuwkb3n%rSe =ԛ'@@`bţu0MY@~{< $qCyq ,NdyJ'@^奠t~a~ff#vj* VO=yu|y(,Zm #5Ā_t\IXV$LJOlޅ﹵PO{^Q@ ĸ =8Dq p]D1 QՓT3>}(KAE?R,n@>I88`\j0p 'KmZgޱjo $m-jOnq|p  iŁŞ<{yiMנ8e,/! # `$QVGis6b+}X(ϙay1^+"Ta7to/C~uHd7 #C>VYIRL!\j[& ꘲ t՛熋oهFѵǢxtg>:dF`;]Fn$ nc2]UP QHr;}צj0X ̱<,LBj ݟN1c]Q-9 HD1B7lpT}k3.4΍A3U1s?<ܸ D|swaV讌Bcn(_Vݥfbz\'2Օw-xhDOi3+UG~Sݹ7ꭊEsAL H*Po ݸ:^:}Of11LD ' YDk<7ׄt,hD!N퇉Դ&#y(]q$ Iڏ.:fdr藯{ m<8F%l݃I܃zյ$RdgL y`WI`LuTs4B1T7'Y"N`{r/嶢*Փ3|h:(C^1fk Ԕ M9 s[1FMA ylž' BNqeMvUebSM>X+J;PJF=*>&{2@yia>, @@6K)J6*@scΏApS a}b3M&8BM7[sp<1]Xk9&bR}1̙֘& 0f8XM0칪g4 Lcc+4@T4 q7Ě&vO_(Qֆ#nlbz*ڿERy;{h*lx1F쓾JţFiKzUqq@r-橃lw 4PB> yzOq@ngC¯LVǙg-3HNgI} BAV-ϸ mLHC*ELx;fjL te"&\d 2+&[ MCdu2߰M"&NۥsNF@&gJ]Qw:KÕmD$. n$ӘX$wM9Au茁F=Q${/=CˎY[s "It-7=h&3; 8`>j &6b_,ޥe%|Sn`MQ?RބjSeoBL?ben~?}iefW ؏4ɖc6k9UL)D9 ?Cp=ф \4]8vY/'`kJc֘h e X)9̦;s8g1]s7E@] V1Pf.Rl+ <&Z31՞Φaѐ;L){$`*T<秫Q#oKbOE)|L^,YNWFz xv>ꈭ 2z(FΓ,5!#PgI قi ɲ,UuV UsiJTG6J$ Ķqϳ"bc?bՑ᫇PSm*e+?2etmY|^bX E8l{9әC=?Nx$STȏP Ub P5=dʓ$ʭ,RdiuRJxnpz5j ?##oXTe[f9qv?y<Ɲхo"F(ӘnXb&f>{fS1X̛KXL43>Ҩb yD\hV#2CXb4DuIf7#w(I`]ңm: {[膚4+FKN /n%'b)# ęڔxGL?\wb绯}fxbﮗ~f5/8 9f6ZGm@k璘gI*+!n:IpA].J$ltVYS^R=T%?qJ(Orx y1u31a 5c&]XקjH^^:p"Ěb{Y{QZ Fb6%QPRqS{>灩Zm+JJasM8O>DVd4ey MQ֤Nl/pOZ%w (%aX[@|ruw/up0'S[L'|lbLWw]p]kJMMʶ" -Ŋ tzr\̽ߛĥmW?7RPKE9E %wuXIocsL>IxIH}{dXqvzt#8ËN@M*ݶfˊ$q{ o.KXG-g)uh iI6u.幝m40U5J;McRɾBܡ;`aoޕLte"3͙hFR*' R+[ it%Ic@>$xk_wNWN\i&g$awL,Ʉ[J[c(Nup[])@ UfGE-.n38 "[ʨ\}b}5륂 oU$[%yk3݈a#S.pP c1/#łVWq!߂|'I!g&&y/탱`gYV,ؚ~ɋsEأ&Ïn*ӼVN L2^E;:phS tINH"vcv*Ґ^'4r01RJ`_hA4'MSC*&tPQ⅒8YBQ %7EJw:lf%awj/U2Wf\PK'Ch1.iŕs n\$Y/@y2]4筥a̷*bDc5[XCnQ=Oo~da^]YmN JO߇|C2ڊ+icJf2L0E]*r]Qh?-T0+2WT.]``tg} +y&YO,Sat8HmO|ux;jB]u \=/ƶ,.qIjw%L, Myeig@`jӯn-uՒ,#@B!T.MKavJ;R'J3} rYnG 0ٽaH'JQh c tayla"6Np N*8 AtH(>TT81|]=kbb M䠁(;ܢ*H;oO@D3JZce@qqγznG*s|v|? .P8 V0Q@1/`ĻpS>YERހ;;J9ɫ\ vv\"Z3pFX#,ԌO!jX|=t) wԦgd_ܙi*Wœ$D'lh\Z?ybkiHine^0@Y]a KI sNktWv塷97(DO b@[:s}Yp S_#/rYh>;B2Arv> a|6P!ٸЀΏpVꮉFeon&'9JR<McOv%oC]w:kM'D9Rnoޭ1CSK+O I|cF* e"zRye 僟IX{߫$c=U2yFF $̓.rƺspR+lTy#lT`!fK1ڙtSvK9,01 sQhHAa FNJdRziMh%FrR߃D]] 6l0)eo(&qd)0*f:eV5|N{.Mwaŝ2F20CXoqɂmC[!@[eK2p ܀Lb#$K2}5Q8՛0KMƖC9fJ3;03$vAQzl!,G-\=_]ܕ""Z{|;UɮK/QP Kt"N5J,Ja~mϢ6Ҙšrir-R -01;PUmi.Rb "񲁡 ls]YЖ݌d7"Y{@tJ>?t Q:2{׻r^f293blU[Xk#V5bw!v/7GH.xX^K娈7Ar90ЙB8-:"Sϐᢄ]F2IeIdQ7:@} ֟ބʎN` @[Q6|k8ajDå `iq'mbNq7 )2 1tuWyY`՜n oqIkK@*9۝3׳1櫏=V %GY8[ 󈁴z%F !MA ibAJS%H!0_& Rv@' N'^HpU݊PIvz[eWoMI[!.5!"fjb\5|`>HFH*l!HA:)wJ_Is?:S,Бd3ڂHPQ?_HQ̃vh0;P=$e >a0 qmY-;ZVp+ERbBh 4Ґ$;ԥ<ݐKM7A\$3ENYtdz)Ti9V*0 kebtܼ؊"Z(Qv2HUͰt>Wd4FL#^B~+XO40l;$XJ9 - 4@ $/Ǿ~ ;o3|dБɪp\v530UX!7܆7Fa6…5}2L0>5.OapDNq*t|bMeॺ Z{a"9 | ]]i=vPS9ўgeCXrgoP&6l]|N~Іw<`#CvjmE!X)Fuvc`bL-M-oa|\rLm&INOW;*#[sMl f`27~~EX062hn&"VWGb^"Ij;AxBBH\+Qy=2",p#zMjF,few]?0g8@egbL 3Zp\EJ%-Vpmy8 1} kOȶWm;}?=d`,>4=ٱvHl}:6^!pFV`J ɀe@@S{r-pS>`/ 6:VefD7ސ2/#NEIN+u E K$$=gFFK(YpL,<ҍ*\/쪖iiQqc2køy~LŭzL?օ"d1C'!:gIk QB;T&B=+B elWrqcۓqm)$oc-hp;e!Pk0!m+9'pV du چӛ߄z2mˁ n~fK"/ 7b޽GUm'`#eS.o^5,C?`KĻj~ё4ýNLOVI)1 ўZk+?f'~09iR?hD^Y0/ tz|;혟[S"!&.'y,`8fֶIjKl$.q=%1ګ"橊|J=0X$7y`N˝{R|s3ٚAryڒpu9K=fFqi^֊h'6Կ*]5}=#ӃAa49jIĦ0OYk F,";LE`>Y `r3oB4N~;*l%mg#v4> zD!n|৷< qc ih-IH1ґ`Cg I 7_4?b0p{Ta O)3lmbo 3ߔ "0EK;$F?L&*[w $s%4e+eo2Q+D[:&Ӈ$>bVmJ((d%:Y")v̎vj BO45g1۝`cDzk8\Ϡ$8?&TP-"іd9<.00`o2f"_V֚SHa&|OC>As/Qe@fJg(Km<4C'HHDKaSY֢%;ߞ%3^8{yXޅ$O>g裄™<ֆgt\`GDMNW Ot;smiP1 #$b'p.uw'L"K0 +``k%nRg%13=y0p}'6=,Kdw.z4NQf`(Rm Jӥxzow?CcGE2l&)6BdC')S0U9.qDe6J 8B<{x2"GPo~٥tAQF)B)4&R7%-fHuG (I}H~&ڳ1֚ٮlBE#Cq5,O~3 [OE(~ 8&C'XRg^*G]/fCϷQ-7X' uf`quSL$~.Z^Zr9~t$>鋅)䊊̀^%^滏d5RF2D^KV[-t7! !!BV}8&/Y<3KmavSE.:kzLlu|=vSamZ_4@5@D䕖1ޜYiy8gx+X|17ٖX} ;-PތX}Dk(}N6/1F(0SPڜʗO71Hf>tʠ)w$e9?Zל,CGc+Pt:\:K")fZ3p\= f'Ʊ@n=ɬ3Vb2Tw TKkͩJ^42lILLkm96a5HΖ&pu|3@]FVm E(J|0*3ڿ܊d(d{luKj;0,WhuX|G6I-ׅHR_" jN&"];P#T@jM2Gmqe.J vÈ"*YQvN/;ܒw3td!1 uѨ#٪Fcqژ QUڍ".uݎ-lxgHC[Q.1ZA 1HAa2.홢RǪ@4mUܗ&uEkUms]5Ef %$.7DU4$<݃R~ XgBLw!:mqw7Zc0d; "2a JyS<4W?XF}Pkٚptc)3݃UNזੵg~ e+qQ%zu2Hu@Tf9v\mTgEt+P R=hwG6J0S<8Cd!,qBD:fsf5<;H}Uq(KrZ BaASn_ VB1fJEx7|GWUOcXS ~ˉ=ʍʼnb9(!'tݜF^ x_&VkKwIp zA4< :#+KtgqnpNBlMEGs?g$2=NRjñD'`Zs<_NCHKx VcʹAX S\7&ʅE1V:⠀\F13Xby |דG 6 uE)εI6N/DYRʒ=˃PE ]5!#Y^)Kd%d+#YqnzxxO:ޓrrF^ig@ HsQꑭ̖?᭯N?vtǟ_S|>X˿ek/K_{Xi9x!pr,_r[ީtTI\s .d>$×mͽ0V:?V;5I 9ev9 ]@2F/]塞m{D=Ѐk8iĺa}9ce* cז Hi"6j'݌7y{Xh\ʢU%S^SD soT$؞}>AiJ( B23<|T(/} 4ZV60U; C0'Vs%pnJzc ~H2NTfs~oc6.u1ex,.l;H #{%o H@SzCD{q ϊaH[4Q|nuW+Zaomd|.Dx-hU'qm 9۶Xǣhv$-଴5|TD%ޱM.Wl讉HGD% `.S$@,"%eb`ZD H-)*b.XR"d td`aF UT0#JݐZ܆d"U$*[%-Հ?`fw !.#ʀp = +EK0œ3ꮼ,&۝"P6Р07gj'VbWXw^63]*I QO}b"W}tcae ^$(uE_M*79-&[9 h";TrvVE 5{I+Q_N} rPH4BDQg紐Kŧrs}sE$iŜf曍@Y*G7݅f)0eQԗLlJXbKm Ԛtd5p0D(7ؿ#< g8].k*Kcw  wO%f_btb;Z˭Fs ҭ᮳J% M!X¥4T "X BG=41^to0q6m,Ĭ72%Jh~{mdglpa$IYi%E1Eiq+L P8WmbRGM%4i^ ?+I.^td;H:?Дn.c]|T_ʳmw䢫*eDyA(&٫!P&! WpDy誎[$k| k2aMX]2=f3YdQvF[ח<8TfG1\$)"(# ES_&צܘr^Ll}b@ЕdSӀM1TpMItԆ"Iug4/Lec)]g3] dsqzxsE= 3Ya, ::=QexN,샞Y<ڪc95Ga}#4&qi;GXi<{jaC 1|p%k+ouAdP\90`h_T Ӄ6q0MW"82O _کdܝca <VR캆(q~c.BKCL6%ڞxk]vC4ܴCzDITM潲#'sc5?*s,4ec)O>l=gtSOd`zkt2I QN7VI+dT/""HƷ8mCzɱᱶʂSQVJINj5ie1CC%S.kڏ#~OQd'R({$Fu9; i#67y4ΙmY<|8ͽA #+ܒgnl9~bq6:1PTDa3 {$~ňދ[B F0&$}q2+#ġOdŖ8,6yч P&NnA2rD$M&HpG51[WI|Pa 7}8 (}gU+݂D)X <VQM" f:!xmR>ґp;N*r`H R3INKQ(:Ě0 ՙ>_'6 0C7ƒMF0J)m/.xcuzM0V\EńMOd$(Ms L̻/4c?df { )>5HNlX,oK'\č"yui*c6zv?u,e$6DK" ]يkNi!ccS8HOP6]%n}HǭķpvWCh3r(+ ̡jНixԓJ5CM& `{.rb3Ӟa{ZH \`k@t8x O_yzH4`f!(F^ǝ$x%&Il$s (8awZ@{S: h^6KHnG*rTr9B,NPXp7b-g^ G3m@y/2$lL아 d$ 2Q98OUBl_28>"Iލ&xB4E U,[؈Kh,Dy;*`4WǾ2I ף0? B6h7JUѝfU|/yDHDHF, If*i+pgufAm_8xtw/孼Xշ x<,NO YqB~@cf,-DD3 B^u36my@z\Vq_db3=LM2dFy t S]+A% LlK7Hc+䍕Nn՟LA.]U1Sl$u訍C"-pgז}8 "`Y+0(LI&MBj}~;,ӓbGٝt'ÊLAc PގXsA)u^2{}6gz7 YQ|=<G+|*[htXKjtbFvb)󽹢D)y:u`z4E=-H˚@+` 38D~?OH#Gny2q(E9j&I'I;t(o|x7\jfW)=E eo⒀~\SAc41ޛiR^jxgƒ`e~GadR]e+}?8k !t і|}ugḧ7Q֕H tgΏ9x([(;/k|!:RqD"|4JG87M f#c>}%Rd6ANS(Vq05:c!vbe*y\ɿeX6"yu|+J{3T @!]K]/{.ImCIcJOKt9)cMA*0厶ͥH2`OpD~-Fׁt%GKaS erǐ\ uePe-E)aF EA[y6{яHS8)nAi*l#Ce`Y.;|?=L)5Or!Y*FW Lq?Ì̷7ᦴz7"񖰰Q`*dG6d_[m$sw;a1"01_ SC/߀MUI\l3{5)H6A1[C$,Ԃy&30K|_Dg&u?Or_JF zDs O6&1;M "3) SP?&3I RCU8jc8xx,ݙ`yl+4q|#a 5ް>oمc^-0ʃ̮d^dK6Wl} ~?]AUOuo\h>+泝=1;WzH8?˭LgۿmAGn#g%>Wp'P ﳛt-ƨ4D6.tgB?AW|•lRuQ7!EIVLDkzјdP=_R"O\!&ZRa$ o3y>y+k32Fa;#aeq0dy.+q䳄 4S&c}X :vÁ-MTݟ-b0Ii 6DJkIT*``~60*-t +bQ:uvĄs#`O\HF4 YUƯ/4:M2 y}=$smU1H 6F\_ I2*X1V6zGТZ ' 8 Iǐ`) ]#e$\zbqFJ;cdLUW]M(TE{%FsP2n0VC|ufUnkMImmtN7CL܎ȑϰ`Dc7k5hNrb;. 뮒?_clAI$I&J$:3c&vQŀU2E(' 38X+ǃÜ<S:R}yV7Ж΋,*7H΍`R[̚i):|tiI 3uqDŦ209+"[i>Y6֕o<\#2B$}xtsOz͂BĪ LsCE 93_qan l'R]9W.BQoMIF56u%]n# k}p4 L5wLg/ž*Y &˼1Awo]If|9 N'ʓH;=$;xY?~v0wYh쁆Nؚ$|_}/\j`sٟ_b-vj4pELTZa+y|L< c@0A@q<NU)VՅ 2rlNݍ& WzmAo7QV=iΆtw>POurc(RwyHuv"s;L:)K$tg2U7K S#hiCr`M gׇ"jc%P*(ITcƪBQa 2/Rm(S"lT'XjE)tƒAv8D  ɪ̋:=m$MET؅=_߃,esѢd0ZXuo>Y8 Bo6kЭLnUo|(A,I+ly>. LZR>E˕pO" IM܈՗⮄p3SfV@2Ѽ;ʵ MJLjrD+_&,4]XXCDQ oq !z$ ZDSm,M,23jX b0+LpjJ@C)T `lI ϲD9 ]6$.rЄ_&uI٣-%glۉ,LAb؟dXs .E^=5QN:PE[ˁ4S6sFal` o)Z"#:H*pGJidi\d#g847D<ۗ}6W:ԜH2S}ٝpL-T g%af) PF2_eV_їTom[ MZ1ҘsXTg.yت2՛oAWLŠGo CG76^P-NǢ?P;Mӽ= n2Ih*۬U8R`*##ꉺ4K8#'ܐ3Kj2 hDqK^bJ,NTAܽ O 8W֒`<Ҋx3H'9tr\_#JFHl( JG|;*paO>XjG7Ġ"ݕEnؼ049΁Ķ2RcַR%/О@IC59cM×g%64TOM"'rsn$OQ&J7Hs}$1,-鿤Ƒ^Vxtg?v~o.Ndz+J܃FH6aWʞeB3_'˨](GMG6}#W*MG\vڇW2WH` CUiܹ؅$^7HMm8 ",J֬5zAC6*e-j跎uvf5,/MTp27nƎ L'i۪ޕ\ k/487 nHPokq *jjYUdLuu-U(@om Hh%h)t@N2 &*dhO4e!>ɞdWP/Wp'i3Bʌd7S<| Þ o/<1e|6by]B&ȗ!7O4Ç|N'BǼq-Q5L$xeY:_';PiEq;K] 7EKIg(VdIg`ȥ /uUחaƁtcm#(q誋_dNm{FGQgT.q_l67 B~O`;SyUa[s=D?S%rFaKAcٞ\*7Yp N H n-H3O_M׎( QS}d{*3{롗|cQ!(wBF1Q@y&r0RXO6e% 2VjV͙(#bqY&F:;*yDgeV)N謎chSc2i.@I-RAs.pD\DJHAI[ {9X C'9B=҂3ŨӃv>v9Xs=YБ߂O[!`丳"aNY0 =PNa7j߇! 2L,,N`϶w9e#x, Vt.poU]O#4eTcq$*P&|\.GF"5T;`bƦh$6g~m|{?_If;ezD^;WY|3UkSKw/(SNc$M_>jpSIvd>!vJCSb+QhMtOu> BFjrv4D!2Vjbc!_n)X ^h, z =/|8yFgx`y&\0[X08{rU>D ){ce4ԒXH+W% Q7d5EL"ԂX;DiM&I@Vo 2AfãEXggon<(n_!`9SI9tyaV(SpI_{#CCk/|u&oN zr3\wԈ|HE0R`C$8k=X:/!IwI*-ǎ[ƾMo#ts`53e:مؼϷb2\dXSKOHc1K}ROLi' =\;yK7a{I4j De1hC/D2Vv"ɋ5D>Wx[q4OyCOe'5姤?~2`T`v.ƀ4/ dANm{>j=ֻl ;wDrj{ v";ڎhbBU%5u{.sJjo nXLDtZ֗AĘbSm{b3̕8kޞo䯇 >3Nq4;S٩$nNP %EA0%3}K\ dq) 'AU/ye;et^;ׂ HBy(O@1t=o1FBOf#gڪblh%ȋqB ]0GAӝ;#e@2Ob1њC?/+zi@29ռX;|* d yG-IZA-XFP7]}9dԴB`]8AXN[7]au]3Ůĉ]8lM[8kp5IK8؄pS}W 7U,vaͽt cyi ApS0r\nqV EmE 4 $z:.MtE2*bP낎|JQHZ)ei}"To6MBfEom n/6(с|b=΢Ld.Qo) ){^@ l[s=T(R dBkt!惭NvMĚ%LSesSit8>`fS ]+Ȟ[6 [v \;(0lt31fZa~JXSlq-r-DquU&x|``)6f4n 3E1%B-QEdLK87\ˬB 0Vɳ )L#̉@WH 4@A@bo n@ EZ#61ζ>ӓ_IRC_G6!o'ygI4e>|YH~ggIPj2eueb}%<?pѸg_ R5wL ܪ(A0]H1B麘^V#0]\2|]D5!Cދc|@K.O8XsQ">BH#3_3›=Ptfi`Eb8| K`]++M.T|\oƃk}:/O4+.06ʏCY@fxÁĥ竑;PObj3y`T/Ӳ҆,a!J}ߟJ}[3P _:}ok|Wd7W+j{ $ 0÷#4 $;ɘ twKe"816\ ag!}EeBxH瀡 Vbݹ| akMx|7.4sˬJX՟ '{ |c4JmQLkWWDe+#y: ` >fr+ÐPL"+'xEQ27a#  EFa$-O 3c5)BM1A 1 {c^hriL!๡ $UJ&0$öXɾ$& 5sCͺp/38Vk@Wfx):A6Wh*ك+KD7W̾d$"*FheEFțh9hH_ʿcW๺XT{2:d'b4 ľey*(=O#iufb3Jp@AA2u歉J.N`7ulf,;*Eu+ZɌ?uaދ|m#9mL}x$sYtF ^'HGmuAg0WcWm"g&6:V-;²;HmFJIgSq ;lL``S $y%6"}-`wEMqhB.OzF#-qy/s1# ܌W\{t: h KCQߩ$옵 4[;;9L2Fb TS߭vUH~+"#򞛷ɀ[[J<c#Ϻp~'iPZ /a-u#Cyk0S)3E|*떲H;E 7c|dT%K19H2 ߭:%)WWt &c+mt3bv,Kwln7zLvuj<&yɩ Jrא )!U/{?Ԙ'غC 9["#L1:08)h.GA3"4j}lV_YٞX+A#Z=YaUJɾ3w.@GǷi+n~ Hr&{5G}Hщ=E[O=u`wCy} }Cq p?Baᢾ :O\ĵsd#!$+k MhPG&_j3SY\gxTGeP Xj~Ouࡼ}X(&:`kQߚW:D0 ]Dk$_Ҩ}b}s{Jt^w}ˎuIIg 7#O<4!.|ɧؒcK-t+qJ;FTA}`Oapx=N o!*68 ޜ g2 m\WZl@cIL,> 4#;f`wR"A('wG08_,LOq̓n)Ɠ[('qV2)[{ǾWt[Wox(}+'eX;7ҝ1O4N$ .hxAa׻E |͔#'E.`aZvULGmS->Zbűj,n@Jϧ V١R,O#4Pݟ"+Ԗ7<%yv(AsQ;<dB0`cn(?RbQ8t$>?e)^ȏvTs+9Nz`S2{|CLDmKJGa^}MS M#mwPPinݵb2uS•yL55OFn f 8 s/ D)$*#.[=6%!S{hGF}^/Cpudy("#6.6Gc1(0; 5gb-Rwe&O"ԥ>Җ?5e>@iNe߇oo@NjJqЪ Cy(Ou@g[}H߉ 5 I1}%⌵JVM,mcTJQ] vwoyT҅f2H,cF;Jj*D1yTtD!=1H* `wg YV* 9KAf 2Lyȼ[Y%"|Xk{%WG0ڑ;~n=ձ3=6bVYa&a|dE0_ P4ACL1ɫ4х>gI$yVɟx@k4;9Q(&2Df+"8O^1P&ȶuFç>NDW@ca"Iidc\ƼpT&]Gyvp=</~,k+b-1HՇq4;1y[ $>316р_3R$ޓZ6h6 Wڸ1Mt%xcJL\@OGR^J@P:Q0Xx f0= &Z1-MuG9f]P'-V&#!|()WͪX{Ro]ʺ:s\߰uR&`j]xBLNQp2Bpn.pGh'Pџ8̍޻څbTd!3ҎO `\/3`,&|G-gGc`>(H@O]:2"PY=ey&in- Nl}.;ɮtTaW@wv{`B~u^ \csbֺIix0UšDsMHn_\ڲM1lkt91+߉A"ٮH>ᖀgEKo3%6dwFA3RQL-'wR#2#&0d.NT6miHf7_t*Nu% T"cDdZjf_]hD 4׾{ k"y%L}hPHW-LH-Avf)%nH"yo- P7_"'>|J6೙Nf!N@q#:x6<2ngm~ jOW1Ez2ψ7֝ 79\;́4-@{eGW幘e$I֬Gf/k(QO,e^'>d?ښ\Cz馉 Lh-{X*%5W37Fdp:pB+j!RQO *N Yqv&_VKXKi( ?L No!&fщ<*?9kxKSa$KćuUWg#,FIgƢ04`)/`?S̆_-sE"x^cLn+g i$5taA-5g}3f]mx#I&d {?V}Wmƻx{߹4c~FA*ҽȄ%?jvԊՔJ[Pɞ|2ɈEKqHsd S߭B)\ =ӄDF*Iqas{m}qzo&ZdG ֲs#EWeiXߊ>5^7:_*n+(JrH[6Q."1%l?Q膒DOpKԪ֍ MPzC2H 6 C)}f񃹪h.scMV'`}D~u<# Y(z6w؄`K-O }&{Z ߌ 2*,UNPk2ڜmoT*-a6 X9%kj9s.yo癎~%{&<ӉpӀQԒiG Z~l$Vͽk]"H@4SChH@ ƾCz~SxIvr;;蠖}!쉲4_b\`zgoD?P"GYW00W3PEbW?;Nz=SY1ߌn/oe<[{~f{#ʻ޲;_?K`6'{<4z<=uєA';}S>Q܎7 ,܍ p☻9!'ե̋t媧3:Il=i[Wv޻a5jBH1#A!AQ"Yͯ0ܦ1K0ڮ&I-+Q#AY$N cTt7h-h]sԐ3G_^aj(j(e&=("LaǷN!{'6~G C7ؖ>dҒ4y+}F޸o7xy)IENDB`qml-box2d/examples/monera/fungus.png0000644000000000000000000033143012241175670014676 0ustar PNG  IHDR4. IDATxwt\}2wz0,{I5*ǒbm^Xvo*ɾkIfǶqXtٲ۔,[HI`B:LocІ3 C-?3s] KӏcTXؘ{Pk*m_o.dY^@,sPŸ`Fl Hz(.UuZ/DŽot.ڲdɜdY4=azcڍBLب TQUb׶!AEz(fȽk˒e2YɲHPyHԊt]݈C;$Fcb/*KV`,* _sn޸U"ll U%j=X@Vp\Oqn_ayDT+PPk)QB}Vp,4YɲWX,  jPVp'Y2deyj DUā,s!+0YLVTn`Tz +6YfCV`̚ӏ=l<&aԕ&l=NL Lq]ĽCٌzTuVlLEV`LX*qRr- 8?ueLV`ܾh<ٸJ OEgѲ@V`\Cþϩ(7h2,5+Z/ߏU{i7ub/$,q ?*]IQY+3#,JFǐgHƈx#|DEZseYGV`nR[}ZJDDY@1hqwz"i%h;ɵFkA4~Udnso&)<*]JY`Zf_Q4IH&|ae 9u9: L$a}197DQFDTmApQזe M v RN<&0^dަEb~WoHx:oW;wBHZi]XNKVhnJsUU]J| H\=$0ҳY'jrMЍB Q%~Kľ@U/lA0nۂNhTͺΖ?YX X׻0) |"LU! Oᄍx 2 DD4 o}H긒sm:!i{\#3֒BG*܌`̝ؖeKV`!G̺O?RW%iIyw0c}5z)OjG"Ɉ:_vN21F?hlpdY`A] 4*|K>,Z,g&S;iشZNl7#V#X܈߯/բ'   !,f}{<\tqESD&Z.)YG51A $UX-\df-qkA*<]~twąbسSKi 7E)kEWp7p躴QQW-yE5^v@0{sD:ȨCè}34ڜ*U:~6\df \a,!D+AmK}3/wmQؼZd3!t) IӉ>o ^7|AxJKo^K^=$/טs]!ץIe{ٸШpH' [6>  =) ?Jϲdfhs}12ՠ#Vxq$f}-quZ EqWٵD\¥+)~ՌeV~֌[7QD)u2sZ{5Z{5bB#%jEYV`j&\R3.cRJӪ_46="+x2^%}5MC!Bl]{m7 ޒ%%ca*£1BU4n#UP&T $a;t^DK ftkٴ#pfN?]qWB)p jh(IsLE \DE2zU[騩A7^'JSDc83m'Z|gQ{.!j*!=IޭnׅshW9oD߲R{G:~3+9/uǭHj(`撝hmI"_'_ڠ!,ӧ^#`^"_OceA ~w!Cb%k\rZc#v&[%i6,:hRAnDC.s#V,2-9'z` ᗺ6+Bg<@ct& ށd&"!E9g.2a3F'#*bw-10@(o1]ME8p/£YkfZ0 ȘՂ ^n-Nh`,܄.{3},A; X(Jd$ޣhǶ?ԗ6,n`4=aW*˦`2Uy)3@IS$:,DU%S:f4e OB|\,Ap"͟'Rz_9XhZ *hElƿde~641DdHȜ[v]!FPɺӏF@be&\菁FfTUU#ͨE{Ocs?&Kp<"iҙgAa۝%շKmmgEX &~dł hAPՄG2ҺB괥J"#^]@7bx]c :/Coy"k#g+AX̄PTB_sQ7wEgVFimiƚ;w۹Eg.Cg.K1*ռu#*vL9bWj?z%yxl6b\`s3 /n6Fb6y S"fVnJe lB cւp3[5ob2IN1Μ#7׎bBoVQ~M!J,?>N!yli | kW!I4E$.yA㾄wba*?7{]7Y9Xу#ւ$BM H)%b0HI,jcg֫M< {]KIٙ 6p_E  xק2^G}S]?ƍ]4Z!p  yFQbqN;aZ늶m&ȈvDW6#j}"YgA[`W[XcgXz-%ڞ=/κFV`fDK}]V=1x 4/JN= ,|''=BB[Di-!7GV,ޱ2;xmF"It ae9K 2X?#qq:tr?Lm)FN#OnFV`fHþl\b0k]BB1f5SKknfK%&B4<n\(fphM?b`EùK &ƐjWr2aEM)MW?S'Lz+jѳmD[6F>cHD0$df; y@XbGC[p_Ƃ! /2m"{"U;k(]q;-h/ܢ&! xn*,F ws?F٫߻=De0eo3N[RKЙvm?3qV fON45FP{P/ KW32)|rߋ}íQ5?qZ}jz@2Ͼ|Ρ:{VЉx닲eDE6.yQCQRt].y`u?>(1s܂v0Y 0Y}UTǗ{|/M.~s_ȴzrsg7X5 @} O?&Sf"?#?.*o؎[Ʊgq frq ץ( !{]h,v4;#?`  d]@0J`"L,^C;Yy98}ѕ$OcnG4y9]?t{ٱ̩ L N+zeX/2ӷ/*? @ث2x9BнWQ˧BN8r޾xgI63hgו ֻ k>D`DYkiv$#rqNz<0D$In|ptDF(RNeUM-j~1 65E*m ,`l"}[ءlD3Jv/?^LyBKm-fk5Tc=o"7jԗvvHd)L< 7_, .{ELBHчLԧĈR\\FI;n%yC 7jE`܈6Lŷa,JTDC?f۶_:-ɨU-X Dg|ւFc)2j|j_F3P 1;G>[:dIb˰20m1-]|/_`oV ڭT2?«LtlĵoY1s5<{;8I3.dm܍6 QoI`SRZtl0`Z-Zegwp=|h)$)xݐb@_wYGi,3mG}(،{mK^`Ag gTAo} {ͷ$llgugzzǷkyJ~-$=i>Ú[jp8g{֋Ψc펵LT2F#JdW\IYrb3%h,LߵɼW?mk(.w/<&B&ctV)82vFj{@>S NJ )6FD;N~*~ P _<3sϖ[+Os"[;?e*AFYe/O࿠:ӌ}1^ֻz9M/s-}EAo>l"na2ͬ LC: RCA4&-⤑ܲ^A MLM߰B,274+*{!LhsSOZ|hC=ܖIVџpe^)u?sk]/Mu [w~׌{<7ƿ=s !,WԚRvhdZpࡄa IDATSt jEŹa}f Lp UܔN`H;qQb'uAUfrS_\N B+v)liio׳4Z2xCKΞr߬~5n ?WЬ{nMll<}6;׮ݲwRZ{+yeus@{!%Mir=RanŜQh.>voV1K]\45k fbG~MԗؾXcJvܕ&`Ej)ِu*l#tF]-]?q͸\y/c[vJƅF*.t37QO~ԋ9֘Cg2?/&{+hF\iXk_|c۞m؝d `G:Ĉ,gk_8@aQ>vG,J2K.K.6g9Ƨs CYŁ艍$4qf i1zU[v|nN˧Y-ıe7QlA}X0!hvA6ZpXřM| 6wGeXk8Ŗ5hc+c妕QwK~Vly6Z\zc쯫mN$A@Ϲ6F,h??rO ( x myVoƲjuϕA"YgtvxWpQCtD—}ޖoⵛBdhLX"LXk`,_Z;d8Jgy_`ϧOO_XM,AGuR?>=TUB}~_ǿx𳷲vkEFH` '[8ym3Y\~ D>s?8ȑI,u|A\Pzi:Dû &ITGAw,)QGqM1lNX~ ޱO~CSsC'9fb[yM="[0z[NAсW4#+^x7ogu7{PrPUaoy⇋(.fuס31}όԖD,AT2:Eumsi\s6{;>nF37Hé0+Q"Ĉ2kJd{S )EeQp.:M|?l3rǿ+"܂rd9mCă`LG?-5Spߪ_w$ʇF71(.-Xk3%Wd7xx?~|?rL`ݎUZ 珟g6oGv& P(\;W&Q .(MldKZQ"fE¢XY%ސ±γ)6i(fENϠWiz<I_ɖOE1n7MŷX\LzYCD3TT%g;0"yٗǿ)% vv5f!997~+o]ބs=YIDCZ^ŴaY [7"s R`F |6ϴRn*Zϑ_[8RG^j,=ou~ΞjM{Ӡ!ߠi0ӇJlDi!ߤ#4B"x\ɵ-y;)(n9z6z" r<2`Fe>Ї x]EE$͉nƸreiQZrWWMw2rp&כϥ_4"sCO?V b#-<.xONS=+Z.ַ2bs #9G3ϑG=׈OM4+gӠa<3EF-EFaF$fo,%IġWvroz0zlsS¶E' s4DsWc50 rV&:EAh,e~O37Bumќ:B~wIr}c4r ( οQmcƜKCՌXj4fƊՈBhbKxFE|hlɢC7j`SٿTKO0$ n޻~w3'8GSCW)u;&\)~0|9i[Ȣ@I >c1+pE-oRd;X_`T W3@Јx}4G%GL#˔88,)[cPq[-`ܰ{ E|FolC^&&l9i QGJ=[tlq)0h25?oL)0cH@Հ]9֚#]lew՟B$<ͤlRƵdb :ʤ8ƈϛ DS9S-4'\'K&;W>!J.RcM/^bJvps-=\nOLLhjhQe2$d=TMa2\9ŕ]'VoZ.<,#[JJM0b5kK_ .K,f/3 _ۯyoXYXa[ܴXLX[? }|b-z+ȳ3Fb"B(ݮ9fұ$a<4YoaHoAw򜟀/4.6a+6? kV'ltf,0$b>D5[gW1*6UPfmFˆ8'0V#{>6sfl Pw<T3QJAڞmz(̣l; ^Wn^WZט^ȚW7=a"Q:'n&hf|Eϵ{R[*EߕVq,s-u[*go]advO3oQc]ƚ̖ɮpxr8kl6,2}'_O\",fވ[\aamqA0 7 &\fk޼dMfM|pXC'վLiPKA\Ct+wX>E6S\]2`2zc/hMkpX. z/z!W'^fBxȇBMmͱpCpOrDivqEk{'o43Y,k9XZ!GQ aFLoZfb2e=/ pnK8w˰c veGyyԭfvH^n`dR˓ F|^z3Fg uh쩖=44SOb/2kPP41M;f!0:H1hp^pG}_yz'Z",[Yþϩ b3IOfkƳr✝=s*|-zYġӌW[iAS=]qu8@'C'-E  Ǎ*b';Y_`C׾,mx=AT缸FQ? NoX`nH4;)poLfN#>ߌ\cZECY3aNQOu8XWm_#f_~y~6fqJߎ]n;6?&8Y S u2%5%/prmf7Eu9)WO`$g`vSׅ#{_?e_s]UلlvC7ׇdD@9* -W.rT܆6B7YJjȄ3&=|BIQ\b " ´Fb*0mwX_`cn)H ͽ=^9qEsy=džnԊ-kȸ#sDcL&Sti밚ȓnH!ܞk}9v}J}-a;hji7:%PU[Țw ?ok߶ٳ#10ޮo%Hd]ip?ZR#(XeGEf| |Ik@8?:+YK1=#Y@_0$}g{QrcNvזM}U]B ݼ8FE"8MZI]8p=!!`JѤX/F2+\;u8(0zokF|~?:#ePOg o[Jسg%SFzޏ׺,vǨت$`73+ ~y`;1cϿw'[L]{8w!EEyq&K O޹I 71B[c*B6:{{[FI\hRt]@Qz#TlB,vXNƂ9Oo-ukW! [: O;Xgy#lh:sEݦ{0fll?}=>e* pri̊ aARF}^A+T;Y]Y2'd>96nd}y{̩aq"51>hb7ڙAgMX-[8sk[XI Vo݈$OY_{KhBLzQ,I/SFMA0&j$@02j~F22U֋Rd, P^\pBbFZLZ;tea#qYuH؂3Ⱥ-;@KǸxM63/tϴPbZa2rjj(v.AڪVWs#%3 П&$zĥ0mb r_ ?l;TWLSG.q%_}APc|wߍ(њ % a_/[\ i+="4hl䃋.B %&i:1+(ˍac,yE[ X̹}Ʋ=u:o^z{,q׮hR4NrB/'t:-%zf*J^z uk?$ X-\A7@UY!5?_Nw܅ʒyv36P,'焠!>4^_VVPC ¼rs9R[ #XsGhYfrs4$_mwO?A,D ⤛F _]j/9mzz|kK &>,TqCF5LkD qW(Y- ~=b 6} C%nMa3ro^5F1Lk0mA.o&t:-{'u')]sGl=GY5)ͳ~4-%={ď;Bs5ٚ~RCUͯ^{wܒqtTΈ Ec#F=ق G P^^$ک&/1&K[['vzԅ^fߧS.J483!l˅KWikj/m#=5FE0j%& I5csBr5Gs _A%m4|͹AyMnŰ*i~] ALip̯%m_][dt^yM`Лt4iyBm ij.5{Iei׮`˺:Rv^</;rv2ɦlqx:rlKJΝѣS^^LQ3r%v3;/kh#kpѳuZRLr2F]rdQS]@]m HQTKcXYCmc~gɶXs7@}+h 8& 1))va݊9ߔϴpy4'~ 󨭫a筛uMs 7s?j-Ιrύ?Upm*{oy\#^2@vK]9V#^?ζm^Y]]Ɔ þA49!&3vpT#}A{ SbMI,'M9 yԭ̧(߂ݪgͪ|: #x<{\ D mp$~`u/.0KU,fB^A%+0+zPEk&Y IH=̎[֒ydc*B~C.h rphޮ 56o܋>Xֻs: 569I.)5lk\X nݲf[,8Zz/eIg08:/N+.>|t3#vdmm_')}C==\G?7 1] ;2݇O&b}mW#X _d\VŅZT?{edċ^][gtnŘޖ~/{{νlZ(1 |~o.BܵㆳX >O $nj?a`XSGLxR3Qǰ7@c{/É VF&4;NCq{||Wo$l۽-iН}Ct1!j ɢiZf99ocn|pr3N]Eob(~Pp_}IY1|Krdw:L5Ȏ4iF#SVV`p0nNiΎZbF#fM5khڍ37Kʼn71tMۊlMU"lXh CvivXϧ F? { S͵8tڝWKF\].rt//XRs]הrͬ$h {tf_t:XSW/b˖ڌ'5,訶Np-<$݄ j )oTd@\3:EFqMUVXGEEfTȒ՞0سIɚV҂[$ Fii! zcyAwp@0HnE@=ƐdL?2#]l~EB CD J;-‰.Xb-U.`&2%%yܬoLL/FSxc<_,'b,UXWX0^.s2*\H*'jRƂdiO&Eu|b^ ;Pϔ{ܑT\uC*oO͠$+XՑ̦e.&RmޛG7r_wBP;fo]n-oRIvqdH3Μ2dΜ7y3^NđD-j-j-V}!\T\ dw}ϩMPȪ ǎDɃ`>R5M_p6Z)9h|<UļM06@Tevi:2>›rM*K݌TX>A\%BTx]kN.@!44԰iS Ż}k^+}ئg̼L\ؐ®}M[nSؿ\)iYL3,;I4C.e]]йh-楟@(dj^<.xN;8q{vqe$dtD0.&De ߔ=o¦M-lڴB}5-u5;Kr|H&bmwcQ Z7aL.7Fn.?!]b)"fyt,ESmsJrŰgf^OpCӟɹzdJ/g:Sss|_'4Mɢj1un4TK?fömmX1tv|Γ\zEAw &HL՘f7AT2 ŅÏ7\xQ@xh-KQZQZW|,5&]{SDë?c7;5+M(rKؿ{]x,r>ԕSbUڈ'rNwY6m[q.8/^xo`qG X$C\||?{uܛMɚ/g ׁ߽џ冧4꽔@ lKLy'GxVk1/D$T]As<Q]ҴoTSJ9URksWq›heז{5544* G\RGw}{ҕ8/?y7_HStv4E`dBi7aoA(S-7ЧF0gVsZY i&ka)\0I, vݜ]ϟ\4j#3zg?3X1Mr$7TV]Rc!TQrx3ضbH+Gޱ|?%>7lUa6")2w&b\ZQEAObLt";ao#a,99:g0X뼖oPs챸ggekNd5ݡJ|g+HUmP9TTT-l`Km%5'jk u|}|--dd[GZ.+H7~y?4n,߷F8l{V\͋/Btz<08t"x'nFL=3m Mݰٯ9дG(7) & s.ֺ-`b8g ފ}cw^\HMե?V-s}&S^j*|XZ<2+ma{dl9~oՂͪRv:pLTWG׏0Kq -Qnh^H;44[Xw~t{F#A:/sXgŪߺ;>VAlq܀"^T]z<d#Ћk@aB0nL<$܀TeXD۰ ks 36s̊M߯h}rs$ps j?ɀt= e^N;`H4F$ct܏YػcKN-/Ehy9LqETz]4@bmZBbŪV>[-dp: @(p,ыQv%knF,ˈ?Del%ۚґ7O} K!qhڧ֮UN{l3[}G> RXU. +O'04UcV lE6o&^y;{WL$: X$@a-le={܉B8Pl>iXtfj1ᡋOm8 K5'3Ru`jXYXS=[k1*I^.L-9zٟ;rγ#=x{?~Jpv\Z ˅* kBXX%!=ASmjg%vʆkoRQ_.#MlgޕM3:07)f`o (c{p`-SekN0!*HJ_jTe_kO8Ob?˼#m)Y}\c_X|*2 >צ%!K"Ju$(Iē w^cc++ڃ453;H,:!UWaHR 5jeA1Ms (/DXaGBZ̹G~XeYr.rzmx-)cm@uD9(&ķC{8Kϟ8DMS9[hRGms '` 0=xJH|IBO\qRtdl1LttL<2T%]el.\u3,D'A=|g-{&7fjZ\f!KZ<& gQ|}4YN=umn㜯`bxD&͝<%Cfל\$slGǹɇN$E3Zh C[aDЃ5 ^}l- kBn4aU;J-Ja]#A0ςqTlŬ?ˣic=jgb1RPřG֮eݻغGҫQx-K?=2J"~900"Sir}"% ms|(duu{A\PbqTʲg b"!,>'2727rZ2EKAK<-$(ILofԵBs?>u|5#W,YPj1$9as90Bfݧ`sMow<Bj"U~s4)dIg={Uʮ11hio]4f]-=MGF3}/gvJέbNCeIrЭY2޿$Ji j>P <;Fy&Hz\T8yѩk>l0UI$L&,+QI !zݜ9|_}4Aaj֦A5a?0^1|\2!D$rl!KG1ݧꔷUO1V_[\v0o,$TOiROpSyk0};|OTB#fdh2')qm\D,uϩ*+) "S3ʒU)sXLXK핉@I NY{{hv)x_SblmsڨiX&]Oe:us#wE,hhdj莚yt;W ʽK.Lz$ a'5Gu W/|w y~j->jWw'8^=w@m6[ЯOe$\SrAC{U6]ĴD z`QRY u,xۃ> _AKfm_{*Uǭ+"O 0}4  A5lyUٯ Mh.'#Ս_\>(He#$T?a&y~_ޒPpSf3GQlz $bLv)WoЧˍHL͆#t.WO'+xJ3J۷sqrzh$Z -aP`LW`:q2HL*waيes#Jk-*/&TQAR{D2l@4zAj~p'^=F4nǙ:.\eha;!~tS(^xk2ebB?0箍d)nDINsi`K# O6_ff7'H+PѕF4o>_Ϊa2<6-b%Qvdvr*!j&"N9lVbqbU/RUj9"|{h$c!L&Yu,k[Z&*ժPߴ IIDr_> ۫9ٿ6$cLz VEssmnq~˝c9 eZ5ps̡^2q%` ÿI~d OpL4D`f ^%V*H&+\ JX$/)Xݸ+pX _f]*|(6ML"SCy,s+QJ}Dگ,2Ҵ_{\ɤ( oဧ\hlnw`##8dCS<8ta|!Ny{羂_s|?=o> )HiH'HƂCcĦFM̦Ϫ+mrz:y Fx-߼3t*wZ}P%u": +Zzkؽn&6DGE)SW Tc8~ӧv(+/v@DQdOL4'_o=WwWڑ4dG޻L C^4bpyhڼO ~q>ywoYQGjw_HM޽{+Gλψ ڥfId Mptύ(6Q[YDV9Oj LGۿIS}ϖܧcesEnC$>1IeB,\C5!]Idck+V5w¿t` IDATTAh$dRDc z&r)+2qyغ;fooW>e[Ʀ'K|b'/.>Ȇ Ysћrجܾ+{Y2(EU*|jQ-9da{ˆfdsW-w֒29hD?u;mLD l\rL.&I0[ȪM-  ֒ -m$nMOž#%I{~Aig1GjEMH0ĬּUU|KAN m۶ ;/&N3B4;{U;|8-iMSgx0DEU<κ30[SyK08:gq;pM__8w\/#ADj hKa'mc| NS:jbcuFD"Ya]W[R?XiLL)ĻaYi'Pm2sR^)DPU}9c`xP$u&~ǔ,~$`̂FTuz+D[gyRlGRm6\λQDw.ߤui{wm*w^BeC`*C.F"Eb8FA⣗T5VS^.B=>{u7e,T8ē_jDb}2A"f3cu]c!I"h,+ːE$lyjSOO&us##M%S^jj|8VL4 TQLI"T7"p`/8>=UܲwmmMz =u.\zU]5n E 87cނ~t--US{ l g(iqHo@=p>TfFɖ&._\2ax]vՎ9OzS߽0sSe7u.{!*fA0 enl9.,b+&dFiAQl2XczVtZN\^qd`_|oպ"JDp;]kh@-QLI?ɤMWSioQ(=.&ؾZåZGL&Êݪ`Se) }^ Ѓs)#w 0̨פ2UcW{g%ʫa6Džid8S!oiړrt']rnŌQfS)pMLrOʎ DB3JRL"f{ XR)m8Jb9u-?|L*az wW%3;?K0.[ hJ%5|N\e2dH\~?3GP%NUq'L&bFOix aVɄl1:-lQsÂ(0t=N ~DO]%s9>C}Clضa)f8cA 9 AuUngj5QSY/:)2$#L Z/<"9w?/9̈́?ͥQNFՍ(X>Zm& _&Mw VҮ`^0 ӎaVQVf$蟈aLżĉe2s,v T"E$#Kg{N][Wd`T'J-VՊjQySll<;w޽8n  ?+qyclړV5{Y_ |@ޜ$33P;-wsgCӈbҩP8I4 dN(Sϣ8yuh<Υn6+w߾ܲ|״y|bPAzz"G$e u Pm='>c suug_-[ \UC =^bbװxv +eU^1e^ƊAU07a$KW՛46QYl9 Yh^݋WYi8=zu+33c,&tӕn@ ܵrW\Ip#T"Nee/_%TԬ2o:x _#]'zI%RTYf#Lpz βݕe"&ZYrDS1i I0ua)<ٲ-lԂ uuP 2]atdݷngߝ{x< ޻s%g>tߝ޻ 75B,\'$^/-ufh*-:tUIAkE)-b `nm@0KADWV LL0G-ֲ~b0?NΚ哋L ̉4`2Dqw"㵗6*0&̊bFVL^U]Tj сv c(yER['/r5JH((c#uBˉi7&A<r*Y/҉DC8sDj>~V"-;r9SXdl^ >p̥E p+&jUOÇuKH b-݄&yh:$㲔'fT}GjZY܏fae܃P0Ī,rOg-mX2DZ fNSg 0ߺ8CW]6FĢ /Ftz,j$&FZ*Dut]Qjr k:$Y[(5jCKL:wN3q}lZɵE,Dr1E`4l6HhR4i$ `;TT(ϟ=bw?q/#s䅣TWDin[u n{K]z†sXvރ$?To-+Yv{+>/300F1sff]c8yp$$&4l`nBaI%5$MeyL(#Rz0tbF0BLK:v*D_?qdZPZZ> ,_çM2W8]ίșR.-Lű䬔a]U9$292JK5P10{,F.VeF1Ict,cY={Fy>}~,uf +EcXd6mjeSS"fZhqQQ%Higwm7L~O_?-h2;KX{#COcő,˾Ҏ>x0D4. uȱaG'Ullq7?6 wݽ;e\h) ?:d yq"1ϟ;cl ?Q;/w-y  _} "=?Qj!֚[vYWGS=qYHjLGxf_ԉ>qk]y.>ҺjϪh[ SK =>6Jk\xD,p U^h5I@$[qUWbu^ͱiٲgsNуG龼pQMS r7H7 5\: h5@ьiA+b7"_E gt:c rA ,,J;؏H` Ua],ϽcKvo`}|cr rAW-F\@>>>H}0dq<ώ~YWױ6h ,x13&E& ؙNn^*"w'Β}L<Ek%XbVd7ؗYq2^}1eNyA5*Ed4U]̋aVzv-갲}=MmMYD?=@\hAe%PIZ|Pٵwfs|`6ܴvĢN8L,Vh06;%}{;UTZI~W;E.ɧOr⽾o:zf_V?-ZgÍRȦHN`zcmG.϶mO r7H2S¾;EV,\<~$i={+wg`-1'ČVD,G28vKi Y$ Z\Ͳr[VQs Xn,+)_zl1A46ΒIĨlj-[q"q0Car';\DQeh0&*%d]̾nCۆ(j>/]/}}1w㰭oD.km*1L G4Z pj[mzo,Bc \>} $p[^TRCDDx,`Vd{{?trg[YFeC5L뛏xR0 % tӂ"e6TJ u ygCH{eni-(v^"Bl+ D"Xjb*?1ŷO1;H2u!J"2>Bdd(щ1Rf(XH:Ҳ"Lm[(Yi^s0\(ct PTgRظO$&E`Z-(v>x0;nx+KKU 5Gx. 5qPݼdO c$R:T^&DEd Zrum$Efݾlnc?Sܹo7;n\u\zjq?D($t ##r|}(G_dm0%82y}l=pڅ$y=CSAFʅdRʺ+t{ Xne F`4d=(*˝|Zx=6xOǂɊ`N>Rh >"i #9l2U4KOڜ>6nKv6l6;8}Xh4vK矙 iXsoY g?G_j|n\^7ݗ lOU6t 5q90C{l1,k:Ұ84l[_(I\NFGcӆ-En>/uՕlhibS[ {lcMlmm-[Fb0H][޵JiI$\ ܗRk~ 1HiHtH/LK $kյTVu۰.]@{/Gkg8iĞZ/P0F$`Zn(+SZ27LFR(f) # dx8ߪӂ$DqʶZf[_(eU5q6_7;*D,![TuvtL0YHîmۀv )fRD֤ҥHLrf-w"+LAװ94W22ɅHLm5m-w;97{vo3o"d3$s݅Mĉӽsu5ߝˆF0-2>zEǧPjLa'T >˲cc^AeVEq܌P|;2W_Tbxx^~Th|j?y U%CoI΍4"g-jbbxxJ!E^+v4O]6'_jE杷r IDATiG1V )K ș*Ku3vи zNjӎ 0=cyjz半 (.۶ʱWI'&\v_}I1W]Cޖ.JO\VuA20B-eM\ fEa`>F-4nº]0[HuA` ?8nܷ0'8Q;Mq˾ CCL ŢE2UEV,$QblU6TS ύD +QЈ\#=wuV(I;w_|s:W$c}ּ=1ϾtW߸L[k_mEdbkٰ{}+GKO%Vd#z׳ `i3+_0~goOiRc0^T9 lٽsn!?^g&'{X$d^E/HGOoJK)pCI;jZ<筭&+N|q起D7 DI$  xdw|Ϯ[2 oug^zs8{[U@@bn։D][zȦ}VTd5 L9DER5BI8GAqkqqjoA\by{ LY6t}\TDvٗ_E| ZZ{xee+8m7C2ؽs'NuF38iD}i㤼nZr{CGJPj^ X KC?w{/ţx֯cr2׈gԱ$uޱ;w$cjs` I2\$&)2UmT5sQ d"$DDE5pw/ H{y+Awo2>Kav (.9^ڞfϮܹL2OcK=jQ$/]20)/e_$bD0 CKr ,w+hHbf9g ME}ynJIqv8u47-(gUҹg,ΒYoHJ [dz\~}̷oۭڽKF{.Ο"Ke zm;nkkaM?ONLo\g`Oj* {z4Fw0[G| " -(Nt0 {MiьI2VՁQ3h\ oS X_=ۀK2quiqcY d SK ̪Dd$s -W8K{\zr9YXFmE7 c 䫿,o>{l #h){Kn\- |#>q?Jz\`ӝsG "4as]9s.ǜcߞMl؄E6H׵wO{GywSIQl%۲ĎldSfIN9f=smM۱\$Qd")X 3`zL Usx$̼;y}YJj+9y*mFFVPGG[3>G0?xC\5ĥ[ig?NgC  mXJA TLer|sTq#{|HՊEz `Ww'#SK^]h;qܾ;ujh*ok[.7R=7ZUdـAD^`Klv"̯uc1U &T얹zbe5*n_+QE% -!ٺgǦ^{ wN<Yrοe.Dz B,Y},ڳk^GG[):L-YωĒTR"Ǎz ;̈u&T &crFz_d ,JLfIXYD @4a[j(~_ζe%[6W >JiWƪ&u.<~t7;V :tTWpwdJP IUVh\^'yLu\Ʌwع%~XtYܫ)}?<~޴m%@|w|`{,{駡& Eci!|,Z:S:Su;; 35;$! SuX@$  Fge5"h+`&ZZUzC8PTiioZr$rBl1H)Cf,q;(\J̟7j^^EEUbl #1g϶M+LߛxO--qŒǹ̝SqcLi͕;CI`br&{L(͕pnlҕ8].7:M\3-IUf4}/`> (;QXGUc;>ýs~r{Ʊ# g,(xƺ]Y, [_+wӯ7:0΅ø/b:xNEWCj^:-{~7X&hMZ !)cvޱvl6 *ZU#?389eJM r)YeQ EؙQŚ W[YHSLڀ5m5#Ģ?r.5Z]847mx3OQM\(o+ O3|=${Iznf_rΙ s eMDzF)~}/{L}q+,Bjͭ{f"?=ub2VO}"&̥2);;L~"X}y Wmjim)y+_p 038Gh|ׄbZdI&,7f, فH&nT-.)oA4a7a<j8c^JWc^w{wXW׽m w q?}nٵZSOF\Y%X,V0T`F ?ևhȃmg^|54|..F>L<1OVkVs߲[ cc9?{FgsO2 DKTsΤEF$Te"ޕN$zVe9Lɵ~;\b& W+Py!54G"Fn Gi%L|8㻷=BZ`JǛ$j Bώ3o;6"X{^$O년/z }}=4xǚ/AÛ?K]"qS UȉIDRbmWˤMM眷ƥyT:׏f@_gxdfqkh bH2rS͗B0<1ýD~~twnbɱT~Y26;% A("W+D8'1Մp#kD!2)Ǻ>k09BƑ^30P8E&dRdcFT"`k<ǫ^_ #70Lr \/|UfÚPĒύi_Bqza2)r?~_s dK㟟H"Fjtvu;h+70bւQj(nz}Sg--m<69'QoOTm"R2(FRd<9̀QyƧhHKwB|)+ 'WHЕy>Xafiӌ/~ u{|}-*:ڳcSx2+<#+܀T* 94Ɉ5$;wY/c"[!I=ySdY6/PxHՉ뵻ߟ/g[!bIBQTNjg.rch;;ikE:^/tJY$c<ׯ Xusj6l}?x@Ե*Ն2BAOQ 5UTttPOݱ%a&qo 0(e5\1ٲ?}^H&,^ü}qI}cLS!VSE`GqϣQ)0QaRn(˫R0DAbR 7wLŽC>kLm&"K7al럶YMk9.؝,$,|䁢\ozO|p;wrk5*Uji,K|og DUQts8MM'H闾zxkyWhP@޶.{'.?n3p@; Q/ js`[t03$ӹAOq_L(D!b1$~MbB_0TW`HH--SfnٟN}{#;:.#cPFj͞WNKqa*+ dR?g/޸A_/CTLiZT)SI:kh`֒e$< #;5>94*%Ó+$%l4FQhh4CAffgh[M,.Dh+hU ߾J_#hG2$`QYXocz!\)`5uմ47܀L#z[te޾C_jy;`&g #[2*`a 1pIJ/RN!k Z_XUMi3pH.e%BGeM9 nܺ+#ol<~ROT$X"]f[Ѷ+5~`l0a YM*ݛJ4'(uZgsXyhTJZjSre7QQm^{ϟz^zckG[;mؗ/X2TKDDc1(w-T( R,Bh:J?wJ9gbѾDsəE5F`KtΚmn͉Tnc~Nbd";5DkTh$D#2Geb$2/I|#gO܍ankIK_#8hCM J1V09]3[ =0GSGƥ\??H Vc622 c r6a--/(5Ȥ&V 5۹cK,< OģW .7? VX|+jk& 7B!BLhgwJ^^컕k79zh[(_g P*(4v "2"[|bI+ӚM45hn_s#D"QDEb|T +R+EՋSӋ ,vN B·-, <)qe QO=>HL>ZgGrec4t!͐vtv /R 0kr׻m UHSM;[hL(2)v/K𡽜p%\0`DR*ܼŽJٌ]ëtͫg/dcO?wG0f3D"*+r/ 6 ^Tp8${bۦLy&p$)!TW07^ߺp[w{ᭆէ<2kx#s=wL"!*! w#sP}"`Sp9%ܼۗv /LJw;rk GeYb4ݡVö M;aˁY䒉N:::r7 ==u97+9OkeR~#U+}7wcMU%8'#IT`,OL\Ds䅗OEc%qo|>* g/"yS*b1`7BIQIR 3rܖ kT,2݊D;ە\i_ryY{E#jĵwm*փTr&TD/m)G7nMҫ7%B1`vŘQP@=G;>xev2vMW=4y_{ [c/d,?͜"9V⹏)/_9eq LʳI`VÒϲ/@W#mM?#Op%_o 䅗Os**Ccҋʥww~z@)Ÿ1wƹw#73FX[6/R-C,,m̌qPnnE̕WȶYF|Dn¡%ޱ F#YƦ※q;k\TvF'#+d1$Y Ü~n^b)~͂"=V)خנ*Kms6XsWx\:Mjhi4PKK CaT.uc&nbuϏ椥2m¢뢓9 +r_{8SWٻ#]z ;ۛ7=>*J,4e|jsAf Es #|?<A"} X(޼sISnO*{.8{K^ (d2|RYbtyDVNyMm  1"Ih<y~ͽ/y/Q^OsG5v՗|QE7E0 OxN%M .QeYa uXRknjsz "XL߆L,#'q6p-%XD"FOSS"xRHTH D*`X(D,#1Rs* Sy?yކA[Oͭ` &Z ,FN$Ov{0/ѻqAVbF$bB(Zjmk`M Mrbos !WC(VQ>#f9kֿ̞ζ4$DE"|/Z;Zy# D"LN~f)HTr\ӥ+n/k+ך0U h{Z;TѠn_Ȥb>2lBNafvaD>Gefm4n0zb{ sME|X駏*TыRS/V[I>]\Ρ/P­˃$bUiW蕐jːtDB'f(rB˨[[&* B.#{ٽ<͒Œ3ʌnZLVPET"ɵ 5۵S+“G g[ }a eVQgG*"ݳ"s?x<_A Eo˳>>(䒄ý,ɩ,r1UWgK.C#:&S5ߦֈX,1ѹ|{ӚrE19?ύQ&,kty?xmt*v=1sfJ,Bz3I.ڽ˕72+ Э'(E5ǎcw3u?y>:ef^?7nseff#WΰyYU](؄$y;}Gtd+h5J' -*kNKb_0[k FߵToT"aOVvnk{| `$s{cO?"ZSE)sU:JyɊ2e݉b 6*he.*sJ8H~R#}"#&llҭ ˁF.ٕ 0gEZiVYjV^0L>_t7R_Kf[t0=3Lv~km ddNVEaD$D,ӳ.r"BC,! ?o`ȃ{J(Ht( qMٞwOK}|S27d@\df;+ʶC"ynƆ/p=a=E>/\g@=Y䒄V_":7T>v}]k$xpz6gA\!w$b јpNMoO+oĿ+30Ō#L(+V%뷈ExƑE΢V1C55Wx5F07( jkfg|#Y?o>/$tGĄU&83b-xm()H4?˕U d6i D.#.9|M|Oϳex}abr02 bKs ote[sl6 nclV`urg`&E.][x`_wsAΜcܼܠSPebM :ۋg;6s@ <~GILdTL1/+JR -m_ۆQ^z-pP(8~uuutw,|### âI,j y]$͹) !r›gQ*2cA^r@PU(A̛/h.we|f;۩.{\8baYCm_|8?x< <Tc'DQXG bxd}M`Nj1@HVTSMscjMFlvN|(ƹ]Wk*'a1D$v>(ܗLlFz,p*R!/.`5\nBv.I¥ $f >s)w.}y;/q Sûed2/ $$q- 7S lvC#LLSrr-mtli! >{%'_/R6ح mѽb`CPC,ڝ!޽ު=Ԃ⽛[c4ƻ2͸&yٿzMĽ@gHC$_@ `:tiqLJ EejkWjS1+yoiX¢?22¥q:ӻh$"z**.^OYe<4v]Y,2|wsv4V |&aw"J{%tz=7_έי'j[Dgν)leejyj_2H%bmE p~s]4jӳstmdBVh?{r^Cc\zsw.}720<΂hkiGODŽϿlZs :bJXJ-6*7,kZ cv=)LXG&ZQ|qz"d ]M_ }`n|nH8e5N* &ZTEj̴IDYuZ|` $^Za9Fx;TȔ2F_RutmG\Zbnn*jjݕvi?3>3ΦT?[lշb< J8oF͍uhԪaM =i]y!s=O^-,)J]=YJ>{{" /Nqpo'ՕkrzMjLݾ5+o L41FMFpQ[Vi#cR;\5M4=Wx:EKwIsSl@]}m`s V+sf3sssy% ZL \iYuoZ缛 TSXu瓤s&r.0ANuuL9p߅)r032r6_Y[Sg&6,{hwօky pev@$N ›߳X#+m`*-;JB6 V!Dt+ܻ7jbZlx^**4dLMZ1ڀul[y+xpX)cqzp*tw2YĘHcD"Q{sML&G&WPQiDQsXp7qy|~irlMj˩.gv~+6=te9] z; '_;0UW=n7Tsa4S.f g:+O@,?Q,eG`dv2( w}`˿,>QH$tUWs}¿\&R!r(B=䙊y}6홖QfzkwߋjZdo9!`Ʋ/3ֈ)Ӕ$$a'm(r|>hiiFйS dzh˽aZj+ άBp NQ)0UI\ IDATh CC݌M[U\!sY.mxS$# kT# 5DيTYB׎>1SOLeKkS:hk΍R$E^RǼ[) ) z*Dcx̥"jzˬqNzyK KbT/Im%0ksp: ͦ"rz#j2 }ٚ F;_-L;> UOB$Q-6 GЇJfkwwoClpݘ'RS1R)P(KBWo $a>2X={SY3res%׺"$ zB_[Y8>[Xv\7`[rvڌL*k /(0#dft"1*>E܉y˷6Լ'QWo#G쫫c$+"Z"XLR^ >GiؼQp[fy9⤟rfaNhc4η*H0{`"F<悑Lj' .SڀsXPW嗅ēO?pr*$@I ?vegq7@Ee3(/9\ M G3a΄J<cJ.npYZF,*567Xrt8ŲÅ˹>I65ζ,iYij0;Es['faZRBf#éFV`hk@Pid+H,IX=zD>7a0b$Uc˫jako R1H d#4o#U+POtnކeľMZSוp$ 8ߵZegDm6,mz*9-)Tw"hᨳd$DVⲜ8,v,lہFA*"!" h ʥDkS"?T;5C</K) V!+_I}C-ɿ?y$>Wx R)O 0[O?ss~oFJƶN>=&#FXD뗯suvuRS]t<wh7ތ"6+2z:9ξӷ)⟹V"ceg^O}+/@$u k +wihE"^d2)5&#sf ;݉\.O {wZTSζE pjc tͼ\%b$SդY ΄/L*:5B[F"cshRǧ~cW"@"q.th^͇ޗ%;5N+ 6AE/#5h ڗ" in@!ƂAb촊A(0" (G|$?y$[Z(ϓcomkdμBѫZdAۃ\E :~S)tZ"pC6Ҵ.Pe=-04XxV?dpdcME"R0&B@&஢l{4;}n۴tux7 HH쌙?d^@]S-`hZJPT1:c`0 h Rdj34+i47uجK,ѵ2\&ժ8`R}g/ F=[O7^X"AbƗP(jZ #n~"dr$\R)#@X@C$U#VK5%r$0qă Ac'_T*9NHjjUjH,F m}CȑVL/dҋa"fb$רЬp!Xqo>[7A˾gFlLg4nc=:`]H$9yKas-M~f&f7T(HfZ jCY걍r}ࣗ0"@1Nv43ow`soB&DZBE6iRՠ@O e\Lžvp{]Yf$&z7>r5bb"}=%͝H+jpݺDԿcA͖a,, 2?`GDEƸb ňD"H%B<\;\DRPZZwc;c'M&2/Kf&R/,TbL8NI۱{ww[n-JmwrAHηJ%p9{GHs y]ByXM<\*Uw>BaBɿ_ hg5zuk^yP H^+Q)&_Kp{O&ҲZM0bsK[/{Aʴjk,%#H>~~U2qKsR i60$ՀCٔ%ZKy6rGZLj*l8ƕԿ=uuMU1~ ļLL+&_zTY:}~lٱ. p$*& y kT_9})q汓9_w_-[U,գdn?r4ahzusu%).-p_ ]$y=ltBO d롵){ʔ}>wBAIHXZrR`¶#F^K.+ܹp1'QUMKK=4BnǠӤ"Nn_I;qA8/G J%e6[jn"Lڭ ̀(ٿgWp:jΜ.E 'q&RteQD+ ,%NI&xNcGP#P*t#h~wMO~)?G@@!`^r!w<,?̮_IAamO\UQ$/OoJv. } Ks*CeuMokkKh,βDzTaDQ|^؇A",H UHLij""CNTiw)/zQGێJ,h|rA 7֐ =r&*$)"t[%) zFT !CZq XX19z~={'s6avHE1K(j]\ (Q G2b(xns!?`sFŢ;/uDBa[{*:E7@m= e(JQA8Jt||AbIa.NNp.#rsM!&XS>4%'n7;/* Y7Pm FpT^A2E&IVWBmbE8BdhECmޢ q^ET*PO56F˝rዿǾs>g% E hVg ,ȫ+6b׉A`_$ћ_O߽/s.z|/Jv7!Ð3շ饗_}Q$!tnBy}ξt/I':Jnpzy\Oc_y&qTi8"ܶQ p۝$S ~iH#!],Fe! P?׫s6x`0ddzϏ #+7!E" }S큒B-Q՟zp7{O(nPOLtghb>'G4(nwBEJR&vT0v\fہfhX,TWWa0[2U&"m&6!_\d9f.9&WĀ)ioE"XqD jBet߸q/R{ yq-glA2 _?)H IW7%Q.Zۆi`0D8F槴lL犁(q]F;|o}  (F^/Eu`h5\0F>t213_(yB[m0:7=R ֟sTj@B6h0  1fy㧲G鈖Шp# H| bD:TN" O_gy+.$X#T5O\)õg[ 2*ie2ы׭K<552.7~"RmM!{opD[8P^홸hJ$rhOquǦfh|$ޞ>gKz͠!q8>~ $'XG8|~+׿Wc}.,"J#ZC?FfXt{8ZݞV\qye=VLrg=CYн5$J$q3xϏ\qnWp*A."O'I)jXV 5h4d1Q]iZȈ!"³(f4Ĭ_}&p8#2/#4iGLZs _CÞv>CF0޾0[XvrN$313xXbXvXrd:s- .[ݻQi444J%-I|iEK5RӪM{mm$&ؾ nACe%-ͼ{7hXv?=сb(27{rENOcyCLM8, QTJ{I@I\,izLШ YF뮍T SSJ3F^KLLmDBae._g>̝/mY5<r޺qYyMBrNUR` z8*tz܊mj? C >F+-M0f> lPuPR k0H>̉Q]\$ZB?g~_g8ޜT3O_tqZTּSOi Eqwt(052 pN!9)I0 zSB YBavҕF''L 6{y (e7\TӪ7ׁ8a|Q^f`p (빗nz0R0Y܆~g/ehd20˷_\OMN{ Gp;=h-!DkS񣟽@Fcہ\E,e7a= k0KY Z-d*`HNnؤe:4*%U|jOQQZ>w@0jd## Dtq[TkRҮQ?~y#Eʔ1z!24@pbs#n4v*HB$[!GVh7y?b>Қ!HLNbv; oRD￑J]LAC,2U ^DzQZ#F#rX,Ta64k!Wˑɓ1Xpu3CV.{{368^ˇY[pRUќHo d29Mr J(GR21-b\DTbb+7Sa0D~&Mf5Qa*H |joZIsSRɄdxhH$.hڔ#*zƋe hD)dll-X(rkզ1&HȯIzVHUYV}Gڹs~:r>,N`ζG.C8 Z+sÙH0oqiGP8ۗ1R"_(."j)4z51D<O?MŚp8-䲂;c8^tjpJ 8 IDATeP` -JO x171 ,ee 1 fӦj3'QLZz\^nl`փdl!A.xxH*LR#Y4$73WnM-f!CQ[XQjw 1Tx Iz.j l%Zƫlr3P `A&\nœT\Ge&Uerod KV_F9EuAQf֡-PfQf?NɀR_>D"Q{.fufs N5!wV*YlDRb,ӳwάǍ}`*+ٱ?0S3: i &[*e$nN}#soǃeU >ba/rɻB0ԃ 5}Pٰ-)dđ0HH{iJ4DfBCvjU"0} Y"Qcu<3۪[ AT4'&tzs0py<bG79x@*UV]] ^܌Rd12xrܳjIz' 2key!t3P"Gvi_ppDq\v;cTP_[!"hΦX, fNF-F <惭e&=-{F6$҆G$>8-]Jnʨ8^>˕ٳW``v~^R}y6t:ee rނ5s[ZPBP'[W*bKS,W0?:'P]UAuJ"SӳLOM?4(*2\v}`fllƌEq oBbZ |2j4Z11r+ &w2R]{:vD..y%*?ݫ=yb 5XN X`iBT&;wzA],C,rd2@%!I0 9=WI {[f68&u@0?+w8u0GAQopM`ek*!潢Klr[^m @1\vrwE0FVty?0A(]VU]\~}joͷxǰ'9UVU>ie$Oz,cz*-+3P][PƮLܾz$䒺H\kw;m- p?0$H<Ѩմ4O"1N[LΖv젺0;d7 102I/4rGc4PҘ%+U%d)~z޿V5OrZk3KfF&WPfp{r2Fd2d-/>s{+铎c,Rba廗ch4r[ \FCVqႯRmA@*&cVMA fiϥ\ Ν?O-x- Z;Od |kbvIJ]twu`Kz!!{/DTDB"i5 =LkR=,X C<DM]҂l͜?:2~_ZtwQWGD3:ϟ,"u6ܓ"aA0U<|d?myBpo0؁ɰqj4>d:r]o(E;8/A\ܿNO1h9J/У6NRUi%hJ=]Hgj΍w$SQimi>3PVo+` IRR*̳gRQVx(MuՌHޡ1kXk.Vȹ}HA#] xPUJ@0US:\'w8}P8Ƥ0%JE=6LF-NKKZXy4 <"\\0Vy'Ɛ< nnrʠ2X ȗ9v2M^p5L3'ߵ Mz:^6 sھ}J3DzYV["FP+(REM33xA^ <0rI KjlMtkatZ P]UI}}E_?3F~asRc`_jqUjakOFUmK>vt1O)Cˑ`*sEe bN'R4PV)86Fsdp*jj 2JC BX+qI"DL@mP(E4JeY<ȕo$b C{ Mu|OPmdJگ\[oK/h.Qd K$Zat>[=wۓtj4h500_\}bd, fd@~a@QɃ{)K#gSQ\mp{c[0o޺oR9tOO\9\ dL)`ݑ AΦzIXY1.N0OG,4D6;mjm#Ǣ MI?DCsB_^NDKXdT1I(]?L<DQQ;G$P!߆ўk!/HD,Lss/~f"]A^NC8ǎsx,P#Ї fn~Z u2s|zpk줶ڂZI{C(41=3C$cvz]$Ƙ$:>!Gq2ʖZ?%AA˘ *j/h$b2D,TkȅܚK,rg'ܼ4B) SQܚ/XΕ1˼\gvҁJ-V&,$ݎr&PP"z)Iڸ31\&?dzV;SSR~fJm mG1 9B?G?Dž]c,7~+νsZ{P(̋cq)Gı z^{-_5Nʼ&78ت9o_k}v_:ZcOr-- AB^K㸿~f=(JNg? .n}uvr1\NjQ 4:Mu?k)Zoksnþ2IG*RY)WV#2ˈ{7[A0dd` ?";^Y=r#E.*',܄#Qqc: ( U~ ͌s[2g'nQm6?jB\c|I@&2?\nD H0Ӊm]*4m%B hH4A453J᝽ŢE9gz.b0d cnIr,J1/,,:xsT>*TWZpnQ[8؉ɘ2nkKzYXv?~ӴD] 18=m:͵Vj:]?lkL9{XܻҪ´Zőݻ(淶p.Gcv:ij~!f'avrżM.T[hj݆Zbr.oO18`» 'a%ͥͱ g826/tO) 5y]V&! L ϻJV{1Z+1*3V#(SKBtBa^>qL..bE**x?t1p8?9ɥw :>FCs K\|kI?ޜ$>{N=BTж Y2,OaD`nrQwY ]u u1QtUV"tϬ}iLu`1iT38LWG%XpRȮ1j?\"D-qnx-IΒLCxru{{e) 44jG)i&bqXZ{5+8SOt`3Qbw,f@FuG1TUqcMc*Gc!f*Tj p Zv$Sf턗s\nW]jU*%'pwb/Z$օlags-:m lw[#: FбM۪b⦤v\=y\rrCzkE9; 0RNb?OSλ EձQc j*G۲Ƥ 56Ӛ]i?Ic+"I&u: e\Dffr.h+\V h /;'UP4 Iw_TGukSNׇ?ı0?|O= $ Ͻ ZSüZv<:D؟!G-2Rʱ+3[ |\hD"9f`2hNMS}5ZKz3Hf޶ @xfS>|T"]<;?Ώ,% [Sڦ#%^<04H ֛<ՙ-LMڒf%6gNǶνEvXЅ+eA~ek23NJ{a,JoeLJ{lx8ZI6 xy4셢c+D?=tC^ yܕ `ةc6e<7c~!IvϿ[ޏ3Z 'Nnc>>"%f0tLc{9wvdDts`8o=ۮhA] _ | /BrS1ckuh3} F3ڄH ,-*>3r,u5NA`{&}0͆lu !+geݭT4Q\UD(&0חP<>#bɃy]_p--Z( ZXtSJg|=D6Sϰs ?)XZZfqq H1RD365O5s7l2ꩴ[B_Cץ "pNۛx88edͮ^a-G Ef$ݿ~z ߴ&Vz$ #ZĆBGr09'tD79D drv1>:b+V)|}ưk$Vd p)Ө .ufvzi܅\g@҆ +7 9cE/כۗ{ U[x,ΥLgijuZq8o}d@ㆋޜJ\_ME.<";j`6< ϯ7o'O7rN-3ɹ|!MP(# Ipǻ763Z?ҵ%69 ]0ۭ kc%dq>1;\rs hk@$4JD$!B徏w0="@(HlfӁN$ĩЯ35 iQ7 xNG%$E`En*!0hP_ . ڈciy @ "H_z=U KA>/]uW3]١x`oD#.{ǟ~,oiX8LLo(o{u-,homdGS*CV|C#٪jtwfO2iXj9z7n399뽜>ӻYJ>JJ9w(rDzrջ}<O^SR_8ʼnd6ī|碛[8!LI乿jhP EDe?ĥ L:״` RǍ”eBʐ`$J B<B-^}!u(z_G~35^X kˍKy9p,1h ^Bd *,R44ڍuW C\}jmޛK兜b/Tx}~^B!5#Iҽӣޏ+ڪ1ItHA7i8T񱴸LMmC&UP*?}/ 149Ş-"ͼ`ktA:7ow};~>y}JTb~gkYlRDP ys,x}"&j2 FoLrunBNI&:^*<Q(V₁/_SsQj-s[y%*2eRrq9XXdzhQRQ"7wۯ?Rɷf\Lf-͜y 2=2=/cz %쩦PqVOL |8DE.c{iN^[מ]h4 ˮ,Fp O+2}Le3E.fس_Xѩ~g~vνȔ%x @"  v@6Τ#-Ed6-my:Ld3N%@Ga.&S$cw)^hFdY΅kO IDAT+P"ABUXDH"X^&r$QɮM"0RD_atLH7~:k.3͑822kF9@PhuFٚy)9Biób FQIz ,;"\`I՜eEe9쥡~<^J*LRfr0X̨4j&rzO" Y9nc_wrTA.MTe:.^IđzﷵYJzB18agwk=2{C\;̣bH=~PNt|39zz:_w~W?N%0.x׌HOшKE0/H6rdOgF RvTg~I7έKp`p5k}Rb#8tVF~9:.BƗP7RG1JN=dI|\~ R(D-G/eCBiϕJ%T=TZ 2@T(TJ{v`ݳ7M}Ǝ<"»WfęGڵmHVZl=OiaysRJ U*|3%ݑw`f'不 OuS[UCymn޹ȑRN&a(9-}r{ . ܷ9GWP>>E}ɦJ*[Swq<4'fWkG]0 YѩyN񽯽ɵ|.`bȦe:F=FpTĉؙ(5jFQДY?~2 Y]2MY-š>5V3_ {~ D4"*E,us<8ٌVWa4fӺ{3sdP]D0 tz=jQh4h4X**P`pe YB *%mȕ"R\}Ym.g1}z h4dgiT0k34:C $K.^^բTȱ4VtXNmW ܨ;(/3xx\B.QUnD.Q[UL ,F=&I 7hI" Zv4R[g֊ٜmngoZ,L`۵#et{?fSzC9iRNlb&^NZ &ӌ n~N,J*k okƻ!jT$6R,F4 cD"g!&͹+7&seZ H$vS_Y:OBD8н '20n2E&U<BQeT`dd@(n:LRRaF։ DO/y4˼aJ%c[1CAɣѱ^A252Poy۟TT_AV.q%8H^v=蹓`ٍF8G8 `6] ݌K>'mwP5(59es{F{R,D63騩j+55uh 0\STjSgά@;6ّ-z p-^|l\kr @h H{KH {;6jD6=Vm^J){^ Q9r;N0;09nZt VeŅw޾@,3(\>*~k},,225 ofpb2#-HZteo3E7G/{-[͹WJE)iZu^!: 88>.ȃ,X%tKǒ?'H렷HECjm6UPSWOl$-Fj*JyfhoX 3ši)BAeec{|tM]\%%~413Lu=}Mcs Q(ٛNL(j֒uUf#چû}}~? liap$YMLNёCǹw yjm՛K8~n=.w' >__ɧ?çeaf}kRcY\&-CvcvvxL&.sq86nK'["#,.'3!g KCķ-i$w8YMqNb7ن(*2 Q:dqߟ,wbn0< ǢL󽯽 _hX$?yDurG0R,FHE! \ I(ڈhd׮z&7_7_~g^@SL`ԡPȉFc" QN4:%ef-{9VKmmm|rv2F#QM,]M,,:x񻯭@qI\&G!*{ol&p_e9T[3wzȺ9j@ޡIƧזlI `#LTgR)f9=kϣѩWO\'x60=ȥAD~ !Y e&cvm%Vdpr0%吞=HH`ኞO=uϯ}cӿ{)xѐcN|ZF K'nx,cbb"\j5555477gK0dzz ˹!޹"BAGWf3jeY4'C$rbm◿u.~DAj$`.[}{^^Od,?H[N,3LQ,ٹ#s<ӵznΖĵMNN11ҽB6YLǓ<'/EN2_Is.\Vm4ְ{lE*6?֪xOR_5Vlhy~7grݨ5m)gg>t2KO2JvgcٖmYhJDHdq}EUa;n.P E:{/ny7K$⫊\rňu}<̪l%(ŝqVVh3Ds$c^ly=?8m2e7nO|+ݽYl7nd,E2^~aY H$$~Rfz euEFFX %Pڽa ̌AM1;=Cl8\X9T:Ú7XҩHnO*8(^4jO4M 0]rT*zˤa>y?kye#|5&'Dۦed ':+!Hr(I*8g\:H{ J%]u{ܙޏ3.͡}%ϻKE #T*Լ$QmYT(vmZV|靼?=]tm,=mN4jc {lLVKKPoF'eWcw13sVpV**' c"s35"npQ?X0{ +^?O`-z%N36 &N lj0J,VdYD1KBe3Fu͏~oiL4[*6C^+HoW}5H}{?,wLMiuEVh:>J}(Un^`+݋AD"(߹l°>S>0Xt|$U1 e2YYZ%u*D-*ot\+.W !ZK./͜Y5nܷ&W3%ݹ%E*X Cel~y@(vR:3XT`rI+\oNh(s^\2^4b,[KS5c.Ι A"o HļS'Y2Hޛ Z8ؾ=yE7fa@NCPSˁ}ouhj-#>2=J7hˣ ^uETD8J#H&JȋbJE_mBjŃ֜*یDdQdTfvu2rEV]kLOβ*cIeov`Xd[[;l6&T Ʉh**i,>ZI{WWٞ;7'9q|?ND"Kㄽr 0c7gKĔ6M8e\r3csTZaLkSqz!K0c#\zT:)v?^B09|(= )oNk$&Hj8s*w*3 q4b3F:Ki&;*o֍duDL gۥ˭#mdf&oatkbZ엁ڼ^T{`>)%9nx:sggaM3#p57& 4]8Fz[ДQzw~h$/V[޹8T:Ғ8H$%#GJH;'/-W缰.s`d7'K%Hlzӏgt)z|i^dHr&K׺Yab0RDDFd$pgr|cZ; Hk[3=gd628ԛ'BI$sBQK{Щ =uVw*_'H2IB_J4"L'H@鹢Q~O!&U黑f֧MNf B 2lftwgc]οT&ryPmoSK O>o4yLOp5{\Oehd5xCZ5-6KQOL5x_qf 24*@SSVfY]ua\4H؏_zp(O(j8zdS՜&+$ ļ#9hGFdLR\VV4 f|z!F9fB:&*\fٵUyQ" p~ɍfcLܝ!La28v\ɉYN6\yb=;b{M$IW|&ۜ4 SUTB&)}NԂEryIͻ^Basrp:m}j2D^եN?nrP*:PZ (T*L̊e0R{pI՞O&$ˌ` 8fJ%>w|k ^Ǔ_ݚAXA J˷{Βd_C:OqsigP{t,|e O#p,^4.HY<~\nzڜxv꥿VC,',[dn|Fo" Y_oFЩ0[ME&ӆ"#y$€xŮrԐ||ꚌJzv,C.D9+j](TQ, IDATj?;}!+:HWDڸ?G6jD7Zܳ5U WfQI I&"$4zF歧QN*L=N:Bd)f3db^ZG.؝JeԘ:R,f U^$K+qvc_XʒRfL[ksUW~Lk[3OZZe,fZ =};g-il8J]}vgǹ+f21X jB=b|HI&tkc{|c#z r#DJB,̸}KǰjbܝZ&rD.a*=ȪR ZiQ!~aUG0@^*zLiԑɺK液1C:"l9#h4jl֓" Jhu ;X<%#T*Z֋dL9mm->Nk?=PGn}+5lBdhn.ycv'$'/Uo $i^:u>oKW.!cFٌ_y V-_S>s.^y ?ЖK=)K# [K!.~0/&scX *[L/@=r?]7}]ם^?!. ,Ku̸iً/}JU ~@%x4VVձr#"G0p=Hv ^˳$;3o( Zыfhj::ڊ% _ル7K%yʻoM +^Q <~J!ێ́́i\&Sl{;5P2$T}=%\"?cE=&x-Ϸ괨mCc9QUΆٌH4ε[3,}-Nݪw[׭ܸ'>zc-_{qTXD߿E[dg˜Ҝ*<" wjb<(:J;_u Zf#-ƲŨ=4fi]%a6Kќ&J6#}I~qCǼ]Fh fB( l6+(yyS|d|zyօ>n Pa.cfqA#;Y*IOjSF,&#uB47hn:ȱq"s\\[1HNdiayKO8KQ"_' ޟ>5aiSǟv@RY{,g ,^<- \*eh4* ۨyAc:ܒj"9-*0/%A[ 4Opy-[(9{~#O6 ']] n7H$$m2knrS1Zft tR)UA`c_q[a)/~>B[uIo-j= Oɥa.2KSnK!2=O$]i9IXh{o򊤤*M!pꍷy;64y;jw*_o.Ө@T,#DKnKcE{TB^LMˮmY|,O.,scjN~d/@JTвd"x~,DDhÏTA&QS$F.p,.L=cmNnzd%ZAհ9 a[o{u_`Ö_ºl0o2 ß)K2޴۬7\kFȕבYiP齻$H3fճjSĢ ,++z-N8z5$cIAP`;_̡@TV$fYXDNnֽβ kKrlIc"(K+b_2bbA#`ؤ& (e-/Ia9gjn, U&07Tڕ#J*1 *"ddny̅+WJJgܚ]¨0jH:K8K ~%DI4> {GJ#q塽ی^2ŝ#iP|seJZd +rHT׮ajrsܒk{t.k7&ЈRKDyiBQį0]?0ql<3L8geiehOC:O+D 2Xɟ 1Wyț%VCv9͓T"Fu %%7߷wsh;y8ŻBz[K]$5q-m\ c9w͋",* ź?=QЄ"2KB}m%Gf5i3q{[^cہ(ՑggFGI>Fwmo@۪'JO{WFƚ0Jђ!y/u/h`l RęڰsۏOS F da,;6yf3|k+ #wkz@/Y(pN(/A/BۇUQGߞL&ٵkGt:Ly 7!r/ZXod0/7̝I\ e|7HyqYInOI罫57؁mtتh¬i¤22bNдZ#vmȏ-&sѨ蕅نӉTޮ|'QR. R/NH; mAbiB_Ře߂ &΍H̯#7cAAV̷oObX%Uw>z)̝IJ5CLJKeh7n0]ZS aAs=|칇Db[5>[La~x&;B.`# 3[ gTNGɔJ4Ý$.IF!#WD,*-)};vl4-nyyUA*"P<ŵJxr`)>iҩuPUL!,(8,VP*oZSs#pZ6:#PWaǂ!ܓsfYZ,cDf-N?Wl9HRt 9 o?-Fvח Bqfb*Y`@c']/\ݫ7}bP5(T*ԽADiԤP(`dhV+mW{YЯ{y#VCA ;'ܹE'd*北q:a[" m_磈bϏ*غ UzCct# q+\)?'I"͠(e'lJҽVZXXҩ~1kņXAqQl/Zs͓#{W̍3u1"hے||*%& b+tqucxolzm32 dˊ"h6(SH|l|wOr{8NsrͫɓO.a8@|k(JQ Jlvr BE"(궎E61t;KBXoԳ0q ՉASߌZ>Q8PuJLFY9{L0ҿk ,/6`2 ˋDbRs;ej& U/lM6CpޥLϬ2~kIG|!r)26 VsZ/~:!VwYgC׎۾򭪻 Ov-]vrn(& RIw7:}q ph>{S_(}~ض8錈+](K2f A-msxۊbfu-]m[\hҊҔpkIssh6F,)+ w>6d[,xLghh=}- r .f32'Y^Ҫt^ WDBFc+|! (!xs} g68ob[QX9C+> cu: m=j+\:Fi<ЁlZL! vRD8TwoiIIpx4&Yd&f2 6:ZXdm@Jtc+J3N`6t7Jtf_N@vau|uDhe#@.{:?yNF-V{d}k_(fkq:47G(g^'NzGx튯1֪ᾮei/Ni#(֍-oYɛꙔw뎤Y ePd"٬ޱΪW[d%z(jikw_$==^z LDQD)HC$թ|5:ZQ*C[Q̢֮XZ[70ՃԘ]m6Ar)|^NҜdK#Nxsߏjb3OFk*uuYu{h @7I ARyV=V X[d:HW>Z="Yܣ؜f1k&&"x*xAH&D#a槧i4*ZtwZ D7 ȯjɩ'I!hUdY|sչj(j-PJԠP(ݟ|u4`x+ zTpk5I__ A,f~1@k Yb&"LLDyט.3~95?;7;~g{ UDQDUFPj7  EZj62DbW+R$sLP\Ld s6H34S]sF&d=|r[ vjК 8xBx6|йO@>:G1C2ĒE%Zz} BzqAqd=#-${? l-MKl: wt_ߦ&8\|5BtLt:=p7_&"(pK`p%Xdbz/`orRb1S3{;Z߷EaLXq=vՓn@W赠$)B BIݵF0zV=!HtIw'=8zv+oZYqdc O ܐAwdܢ0eIFpZ ]G6-!1am=A?.3T3, J'ApKBn]7*luV)CH_ѿSƶ6wrgًm05;~g8lV4cLZ V$ViY%o;Ac#}l?QZ IDAT{Kkdl1VA%24,T򩬖&->҂VxK1_IFSUݽ/Qi7:TՋUX۽@!-iӛa‘$`7ݬ%lF{N(M.=qL0[-4wt?wٗaAV-f,ܽKsWbQ<3S44h$R^}WUK:&!nױojrI*-UPpmH.u֑>f.~JD#h5y }2c'p^G @P?ʍɔoVa4Ź%QΨ:[M'F.5m!2Nb&I:Vs>{EhM PM0sƽUMh(`4iШ,,=䠵SF8(+k)&fMTJ[nh,OYXG_U<t<~H,ʲRҩV)2㙙d=K:Yt.30X^\AZ.H Jf {Ol4V6?;GOGJm!h53?*($HV3,-DRH6nXcxpYۮtӑ۟;3=G$,z-ݝQd fĂD1K:*N[y-IҬݭST5V 5_D ]c9Фfe-æa=&_ ²r0%h v˶=}y FXTVV8;:DK'CRQF*'Z2 ?d.įzXMlRjc6=O7"zBA@F=б,*A%Xl""ap{=yrgvƖ-xzmO DX$!rE;4z]Njf$ b1OL*RDcYMUWIMiz0zƗ]LtRI4c(89c>bv9'j0r̻TjҜaSL#}R Y2{ꏟ'Jhq"u'⟖%l:N6(P FF]ߚ8|QPrQd1"p:tu:0A%@".}2#8p>N{gW7KENy5<zǗvu~gz,/`jzɈm$CdARQWbDc,h(:DSV5,z-js|i NGk0m"j/fbqvI6%ܣfR)Z Z@"!hrڽ6 p]t: c6CӂZ%@&!0D1K& [k uZ밀RI66m7JAp ( N *o(DZ;֣ oٔB!bXjuъ$ |)gSXsPs#mN SsQ<$O pk(N$^Z/X,܏~Įc7gΰ4Q< $H])*fE"Kaݥ|*9r!ŧX9 f2,f42ҚiBB9ݢ}mXZ,T2 mk*Zo:A22)SAlX)beFOxGK%fӤՏ$lUw=$YZ79̫ E/C?O;BmV56uF Ro2 مU"}FQC97:auB)}N%Wgsmv`4N+`Un![\pb^w֨ɦ8{ >E3PN/%t,MjSZ|zj#JMף-"AGRUM16n8`jGl`G J`;kǴtw q̗=ȧrF,׀fVɊ^%K0~s==zz;p6ۿ1/<'O*:7  X f[*-b&ݙpjj T7_F;&OR 勵wG /FDQA:%bsPD4*hP@p\˄o]JsZ>^9yc&&^#K&`1 X$bhS??dJUɊ"ȮzPk4t83K/1x cEb &^-Q%Ɋ?.@UId}!N[\Ft״WW!{u_t<܅ưX\z{:?*Sev*lG$z  f8t`w{W'dnv&vLT<@&]ېLvj#WMr mkֵVh#(չAc؁"{Qgj=ӪOvEQϣ`+A-bFmC̦̜%-u-w.!`?s_c# D.Ѷ/GVYEHU1R_XmfxJRA7 vL. EXQ92Y.m5v9rkP1fte;ufH RjL&CI̦ $\O+^VOǞ'Hga Uv]/@0J$syя~ ڻc}3/*{ׂBP!'Q75K-[Z#];I<eMb.ڈ꣊p"?/YZ:~kԇAOw++^,y~߁ 9Μu֋ꥏk,4f8}*\z, nSUZ8RыtDQ UP0qs(1"ǼstqEC68KB܃ H&{oє"Xҫrb=bϜK/HT)1uQmC=1\6K{u{s=m- =meEܜc~AN믘e9I_Z)d r؊`Z*6x^sWVr z|р Gz8}Ջy! I%f{A6"[P 4fL^buГ#K Go -߼jo3pfav^)W s [_ߧyxFcht2L&Y(P N#hnqh"jNŨ-l%ô:2raokֆwߍ̈́)C*ʧĔJA“dzÕtu2>9Z٪%굴v}`c6R2l!YEP*1tnox V_X'^3y䘏(߿K {/]ȡNzoJ]s s EFEAA2uMA?+=1R(Zs4Jk+^v f͵gM֒l:F,޺шO(.&^ &JUm819\dEp,I8DP)i\3?L(Fp:Je9H,PU o2ޚ7b2=Է;>:-T_Z"uI"glY/⢵Trc0_?|{\: PdV3o +-y>F+ 8w'\@ Xm3oߧ0zQ(;="*HZZJ%=(sS!VPؘt"`^yJ>z6qxoIU D,/'ng0ٽgi'6ΩTJg7s*-)Zmu=6; 1m]XNclpLZFD& *C`SV_4ƕE,:-LP<`NN"G2g._$OoFO>|>9Y]K3ZK#ݹ?`|KR)Do7%J"/v=ܓ?;q⓵kשYI2h4j F=ZeW] T.)eIn*W$CJVŗ>3^WQh{++ܹ=X]Y#Ri]rX3E"VC&18TPMVƯ΍qԂ֢L&`" Ĺ@O (*79 جz&m@2iTdK֑|zLUOU1\TiF=rMvR sS^wISV*#(&qt?8bF5zyy2K.0 Nv4SorevǿsWfL`ABUrH$RI[LӼXFx_z ՈղF"9w @#SHp3OS˽OX5:aAOc%DJgHۓ1[>4Zt&j Vu;1?I#?o[gy}|us`0%#f[GN+9O_ܞR]C#KD0+ ş8MpG%봬V*b+NbTS*# ,p\ Y*޽w .R4&{F7D3we704V9&Xʄx oXZ8jtK &V0~($v:[KL.lm%5܏ɎƖNx̅Kx70Psn&)55^xj*7&TBq^{/1<,g5f"{Q(T,իڼF-m嶍>;葫C1ЂgHxވ1i.6Q%'R 1[2J K*{f'lgBqhNX[鬗qH,9JZVS2J9F/?5).&z}`ef^xe~@v75ɮO}ls*+,duE")AozAbs -(d9pM AP.ŗfk*@qbv᳏L:|d>3u0Y4cUƝNLS9 %I"!}f!u%ו`6xRs8q _DZ8V°'d JS5S AGI=s;tl!{>~y+!.8MBiQWS ejfcVeAϏ~duo!\'57!in֘z|+㌌'-%>Iuj>pO+|^=wm(2/| mXb {BY4kYTk2{68mFA mO&ٲ)Է;|gYV`kFbݴmZ:&  l}Ib!@O"'Q(u(T:DQoXZ3>_KޜFfۢb#WqfdHD׮0jcU,Z\.,3tf4F/I#-y1l5ȵrZs4~.SNy[HI'zuhm5xxĿz_]}=Kg85URU_ިjx1YEeh&$P`JuK+XY6XJlւ޸&RZd1Lzli9 As|x1.D΍VXg/`V$2=Ws |'X/sܲg+.7\]&I˷P K'V˫r3ӞKmH9@ŤSmo/PRlD;+Ӯ@b#l)l2#䐀hD\P@k둖k&0_t} pjgRj^92+GR?K[ۊ~l7BԏRE>4U6[i_wyKIm #A**1l-WװUˋ(߄caAjSe% R=Dc\pL΅؝SOY c`8̲zv߹mcJ<>&%EfH+4*]bx".@`-L\AcnNwLpo]bڕ*ZdGԱrZoKtj`O+>I; IDATLiˋO.֥{hɋ#c*۴&^O Rfjޚ9a  x _3jlזa0Cfx?8b\BF 5gԓf:w,uTq`A1Kmj.)gzܺ?:h͏?-NuC֖i]QѠըtj_>E4*si6c" "SnTh9:ļS)Yֆ%(,^B\%gs gC[VUkەWBHq9V+[Xl⒩Cvj3>.xr䨓Pr-[9p$a sm{w rVȸOtD 5/ON: s}X̦qb1-?(Cuʬ?'Nv}>m(khq 2 Ly~pɖZ 1Lp{vRFWG3/Ҷ))bZqF"B F#b\kAr [X;_ e+)mSrƦk`v=`$!.e6' ɖQ&?}_ChvvDk{ק4*Ѯ9Ư(,@J'q^Pښ^, |drl9 iUn2ذaD/0J 0>K=qԥ%ΔbP+v^yoƷ3D\4.~N`knl/YnB8cp J+.wߺ';??"Z p*֍UURа?w_Nzj.lʿ}FB<>zsT5'vژhCCaѠ39<5B8"e}] {KX< Xz)lF-l`5Vu鉝_uOK^ucl[_vtA110 N9xo1*uFSL|M1j`|%&W 1hNzS`cn2/Ab.& FE-OzZH{ шrǫoJ^vliM{qP?qؙ]FWOz[O8I c0R[;6ұeCR${ضMe#@ QBt 褓Z >Oݬw>6([_k0^CRZW횤%/ȏl)||NhIȼ <0EkT߳ڧCca\s=ʛ˘d2em e{.ʲMb|kU0CsȖ jʓݪTmAeWGqViԄ-ʨc\HMu e1B,]9 q$?}A0o;&~Eys{3y U6d&.    JS! tjj [)RG"*\cnȊ<םlT} z\/cqj(,pw^#^‘t5Y/qhT j37IX ŖbHEިx'WA 1WKqɆAJw߼WVZDۦk)j*C\ܟ&qؙ{`[niM\{[=߻?3g)/uK[P(t4=={tdp4 ѤA<cfosʟ2_Յ ş\wsmd OUmBW9sATjSdꊩnH& .g} y~u9Br cȲc)b6j#"3yepc"H,xvT4%P0;KR!$Ng9M#a̡Ѩܹ6E[i"zN\YLLGIqt<99/Dh$·q>ujѳyĮՉblVj:T^}cز>YYA31G_co_TʤKiӿ w` P07Ѝ/{}Y Fz0 exƤSJ54L-HrKAȽROf\ݷC| r츜 RA|ӖKs漓ƺ"x&>|oK)+)@J "N$! wdUQ(hԼQ64W_{[ oCKS%B=q@ R7*xQ A;پNL3xܲǩQP),D"*P*liC~&^;s>)-v7SQt<>B PFRe"s ,fϾXF(Yy[ؽk#EBZ+r:`.trbW)lO/.2('hDJ83 Ί"7trEUz b1f95]thk5V`?(y@lˆֶO}漓WzO=H2DiLk1P(;]tգR)z#ф1i]0@K$&8'}7\yIWEa٢@| $ M͔#|! *;wP\K1t*QQCvJQg9 ~.[,cghQ_Nφ"k!msm(`Gryx\n =%%V=4P17cJ/_@ fB,)Nlfz:9F#VJDR }mחy@}FU`g<ؠş! d^Ġ>7-RIXwwVc)q,A-#WH*жLuq37x=>cKqٳw?:] ;qǻ(.бR2=PؐS aB b IVeV4T.+7y@3_K]2{,*doGDך^I3򰱹j]{̛rPHa[^FKu6/i,7±NdW^% q "G. g%.s :`Qab&<1p_;xl[qQU Ft:mZ[<' 8+웷n65$b~^qZ k!.sXys" s9B0\r@K}!p14,[{jˆ$qRq]ğ+DˇS E q MF,֥[(ݗ,3'w.cv~ŷb6O6_ F !t0EF,2J"z-.wno# G8I=4F%{0ӹmt$kVJKY-TWSUQԌ0İcr[)%h47 ZFūx~b+Ӄ'GO_ENWX[qYFZk*Gl}S45SX0_!e 3 bԨ}Fm ~|y\sV1˱HO|&J{=:5{=[,_$Lӛqyp8&-rL/UYL5 yk=GEExsvEDi+Fq rw\ 9WIL,坓K$ GDAwCYNE7vU=TU!z7'J\!^] F%h0Aevl|׊LcǍfNCS&fRɖou\s]0 ng } eJ::r"铙j(?˫Bă\k(ƒ7&]TExXrMREڎeY%]_ް/g{Z v˒VJIS|]*tH|@OgUn4f<ݙ ˄)` V G0k`O /HC:a[=4@+Ĺ~'="YW~y[;%!BKGZ/z90^]݈}7b87'~IU']VtL9&빒^#̊V﹞'Of#+JE^&"4ChѴ?B(5pokgwש9yθ35Yա,-CY^ *Sk`sY㧊~$I:K,|Mgw4}ƣć$lL: jK0~3Acޗ zH KwfC\ `,eL:Z5-3uq#ffHJ[!g;uޓGq *SiE`_?ḇŠ"jQALcEAL<)q" ~c)}?By4#u1@±3{xγ[2yV_̫D{? ,ݸuNl U V)xzj}Y:|s\WX![ Ó9]3b7qׁ<l]7%c:Ov64&;$ca,rbxzrτǁoy"8{뱚3׽,\Pa4K__O._{;L+@Q!E2/1oޥ!Dg?7丄Qz_欗,{j9 -8.NNo}(XEMP\p\Dj3y1cNДn(OsS6qΤtnݔv>K Z`-1>@I|03qY<ʦuą0!处հ ]=ػwYYVI|cHSq|HSw>SB1K!àR*LNeNbéY?@Vug2:ڦRO]CUk EO_GDvlYւPT[bC8Aʭv1 Øl茩_4_W: 3#i3W i2d~[9x4_ꪸsk{ d+ee!z~ -zq1oNte . \Ciivub,@p£A 9dtI~ߊ+FFaG!קcx Q~4(^c0BB2_ e M.2>)nUWVvt=ВC膍6?Ͼ:ߐGGh!C:w(8gD z/Q۲uK/e[6+jNZE706aʷ;LO~ʺjJ+ʒ_s*ZdVNMrsLxyͫ Cli-ĉ> (4-U WzY]> ,W'?HU} PnYiuŢ:ZM B8'8'P՘K`˺ rD"NN$"Fg簤5 PQ-`%`! ~K/UqKN qMTڍB7kIҷgVwJ``Ef#!ݙ+ͅZZQe.?qCscP$wB%K&m&>A6Wg G\W =$:trVAԫ(Ԕ,&Zj3(n@1\`gc ".'}giHuut;XC銡t" jl)qVB﫡̦~:dQ[HQx0C LB]\ r$яcbGS-eCZ?~/s? '00+2_xBBZ_&#m+Ch8ҟ|V39 ȕ+D1NY-[6XAsSՕ.|yp#yG~{p0\f[TWX@MW"DjPY M&T*%HUY1_I1ALΪ30|Jt.Z];yc(L_/b Vj| bԤfawz(R,GqѼ(+YM M 1@z#ĜNr-N'˅Mقxjbyσ0)q*$Ig*/rbEF,Εe8uu Dhmߜ?3k)r6vlYU ? :Nvߞ/rK:5kK*I_;T*1MI9h 1Cס4ȜDc3it8gGZRRl]NsX(-2p~$+Ɩ>Z]mO܁a6433HM+K0]ꀋ +OW$a2޾dF DLR4ɔZ9/ TH\*մD ;kRŭWiۃyWZ.wsL&Gj!Mh&z{'~T(R "r^>Ov3^ 4P˄@GZvH8\=BQ: ECTZ @0e "("1pLNdե<_>Kæ阘bhHbLbF 1J-AcNcC9ޝMWpk*==OLRESZv#Œc(+f ֋R Ki@ib3BiO"TEiET?QX?P(b1$L\w{c8q ɜyg W>l._l-Iq |w6ـ޸cHq!XtJjGB@x)}x?߷+nhiXj럤Αߜ@Nɖʆ hlo!_iΜ~') XtUǕ)>G> aunO^fCp&b/yP3Μ㷯H|b)8}H;g+(TH͏HG{F``}E@ tZ$xqr"y:L7䙫#47Vw.w;{rZ:ZPl3-o @ |Hs(:N^=oє d0/0{i殜e%4UV͌ˑߜŬRP@OS{# ټ׿umΜ~}{;޻t9=A(wur /$4cZ39zrpD`OՊ cu'q ~%_d8PB$Xdw9L$ZVZ[m߷A|vҵte@GAۃۗ$8!L-!l,fQBY? ʢtX~!-vN~1._Vl**yhUT6T,k,/[G3(mV>(F?-;=s/]>$&64s`[)%z/jKrM@ 1x+C"pwjX MsRO.='0pmD&_pЋ:5H\"2eJZ}~-9>W @!3N3S~ 8}Yխ,QB [ \_D^'1 9`:>;=3㜏zijٯ}3GbDϱwW]ev>!6>I`͆fKI!8(t:46 j5 UMLޜ=A^|+߰uw&fKbY\* Ch LBzx, yO "*+g2"D9Kq;L)(0&3v4+Y uEC^'\c\.:|!CJ VD:zN;Vsrqc zꦪ]zb(Ѿr͌W ݟ$.3VƦR66%? +Rb* "DGGF8N ?`{v޵&D9[,J}SATZ9KTkU]z?޳㯯w2EԜ'!(9%x쾼 7"ؐ:lN`VA" nwksK95$,:Âx "׹R(UZ$Ir+'*obצArx|<>$qx9vN޹=ɻ2zqO^% NMEU(ͩ3-3G+~l=ξ;0,jظLeN短iߜ]af6 :9Us'ip,p5Ԯm "ހЕK9g"̔_XjZV#fFݹON]o$ɭFy_!\=/0 Lϗ+(Nd:-_1Ğ͉z _"YFP # hҌ 04T,oymG8_oͦK Lo~۲yy+h߳)o^bfMQQkN`t:Z0sh+ d\`nc߷N~H!ї[;4 eqUgMIPWmhTޡ=xv>A"}:v 9[ILZIueaBh4zֲ ib3w뵫OMalL^Z-whU|73ׇlK,`0•vzo#o^՜.ѓ:o9WY8lj Jٴ ۼ3"<, qؠS>ZoPVMYd̀`Bkq E$d0pߡf_q 9))EfAM){wIҶRXAL.)ۙi]gn[V).z慄Q.)XװwiBoNҫg ysg ueAm$06ڶQ(T*TCRjeaf3yd-MYDg<0XWٙ!:5XREYUB,³?9jZS5*mWl^5Mu Rռ?\enώ|mݺ 9/ EܝrLɆI~5sEEt(Dfh*b#p %<۫z7ո۱QHG%W4(B!1"# xRS1'{$qP)S ϤO  &},TUP]oKݷ~"?PKs}9nĉ.y6*3^zlB\6nl_gqDӡYx*ܴ݀``˓?80S(fR\5ޏofCF g(P(ʭ h4\l1=M7AqD%4erLq .sj[S^b݇<%>LJb QBTR\@f<>>3scp{AcrbJAk.끨n"fuIaVxrS``6.UW_r͠lLWr Fgضe~ ƈKm?}%)R]aY qim*VșwJ*օ=}MֻGk^>qw_?5`Я+w媝b>B 2b1?>BlǸ`|˥^|ʰJ |* bnIzLwn3p3>9B?s*Ca4C#(S)RS] g O"DȪĥZ0N]Nz|sYv귉oQĔ7DUU.E:"#:r]DzHOǨ}Tc}6]r H_1#rD LC]a&*ʲ1?NZgsS){d2N҂]$Q3IQ'<߹oɂ#r\w/P(+Ay7ae3F -;ׯrv+uFtQ_ba\D6W6=?s2>x])"̯fR, stt4pe"a֍u~~5`6WUo<ȭw5=?v~D 9z yvlkG_]B;O'u$Wu(-dhL>;^'9w!յٹ:KQX 785[$C4&jAzoUTZ\:P(ae@"lG+Ӽtdb-5z+i>ft<}euR:l# ! &dbז3} ͋ G2'9X_"xCoc1Z݀p4&[;hZ~/ex˝-].6!o\*k%5f?O4}2["Gmw$l%F&W^yvp&>b"\oV~XF!I`3EOpNɢu,sliiopP: X[~T.4mN/yUsjbuE~DEֵwMLͧ./8̱ <C#ӉtZgcw4d%.W]>j6oh::΄OlSw4\)0yf˓?PIRpv-ίFQO$DFdyÛػ[TY)0ַG뤵3ݽBMStL$o^@}׍Jw+aN`Rvhn&'$#9pi|fXK.Zux>v6[\:S vVpǮJt<]&FڰvP/Dl mS7VMcf f*CaC#M !Fe¬g{q#ʔG4601ʻqV@\n\!C!=WciDem(.6QTlbcppbv܄g?&؎R4ֹ@il}Ɵwfvg/rK.$C$mI)QH#)Eku[ڏU?ha;`QES S @`uSזjV"ŢE]Dry-%9vf~!ޤHݷȣٿ)tAuG uU O@Vb~thGpm@pّ#ؽ0/vPm۞dj]Tl L`޷o\P[cxz C{PWaq:#%& 1Gsک^>wOW8{}tu5/F0>>g1|q\033Tj-G;vD`f7g͖w0ޛ{x &B@#忀l* YnB4 "0 [_$V1=S D.CIDAT|?xc_! 6sХ" j Y΅ΛZ QUA6 Sj!p ZE1rz^Cx;a̶--fu:ȸ1RH뱢%D~.}bRvrfE4BM)Th箅%1?sD:x:a76U΅hdٗ Pd52R!luo{z {>QOuiK5 BCFGחĢP|F23qh1H+ƦfybZpZ VAV$v !T+r<ե-W>_:DW1y ];?_ [&.4代P' ]t9ŒN(X9^0EGt~?H'7Vl~ 8sel"#c )ArCQ%8oj]%rSF<&ajTOD{s)u6J\|+o/,z qA hP$t/>ь\PUJ?C 򮳹p!ӏTiQs HB[B*Q-5コ~ JV BQ-ikx8>bL2ɑ oÃlwqH$Rutlb Ȓ{奯tV]5/.^H8(,(nwI$ pqhuñ7PZs @ΟxDfNxM\V-4g%|̅b`d!Z>/%D+GEKc u(0 0RNjI\lՄAk0􂳰FVdJsSfr&]YzaGh|dPqWW!4TUպ9GRx+]‰Y-V5Y NKlj]qM?&^름YԘ(g鰝 .v[6^(UfVJpIĩ&@Lt%W,VSX1S5= QuVv+p`@-1ƕD& ECK#30t 3u豍70rϜsG?5?A]?%PГ[iYs!rOv*lMHA@?dV/=@nn[_ i:Zyc ˊutO/:+G7^oFaȖx+k 44_U`. k[K Lj:J 5E6=zTy3gojvhn$ɸ{GzVbB0.k;o~5sƩZ@b$'@ՍWB)tj-6W ąo\fQ.fq%_m ra;fK2]9MWK-g` VP ݢσ^U.2p4ͷ,'CSs0\Ќ<^;[ >[7-*g4mUpבͪ~SzLB0?{sGaỜXB¥Z*誑^R 8|K0ك= 5{N2uG*zza,N]cyj )BZʀ5 GP[[7mճLS׊L|͘9yc, ZTx_09vD ?6KǡD78aۆbB`G|+rfih: cӠ6[:iꅳ|p!2H3?8Br: wٺ)<y! i1:Dw[nޜF-; ah";Եf1Wq½e_J6[ňaDD&"2D[z 2O%q ~2hBB g}},ˑ,aL̘G ~Džzo,"F{ I==N %А가[@TDաWyPVwu 1$Ⅵbf >kqXaqXau"zo./2de vhd|&H`}_(4~%` EY<#uw.Nl]X@5 $<ռ~`*pOx_ˑ,k~P:(ߚXdNfϜV% QP&1PVҋfki+W(:FFW(>O/*LqW#=KҀZBEN݆B# 8T*E0 CliSdff GxIìjf:{'DQ/] EtN~rٮTݘ=병Oo.ǾJi=a{&0LFåT.+KpxA Apv^\)W=RdSJIl Y_]yolan.Q%S n]7k,6k z*_D7Z<CKva \U09m^\\@ LLWsׇ#8U_*Z,; 9w_oP^(xSS0tmoFX >dl,4\B{RCChT hYa(~r\r݇: @Il_ BʿτE مc< UQ`~*K|:lFf(*K1'1Ȧ {HxE qzC{}51'0 km2&ח55QIB^6 ?<@)zX4rL``8$?< eS8y FVS"ڏATn # e7Ut^Tpy8Ly>'qJeq]k~cq avl"hu[3A {w ҩJ"\ Ï?V[KLƲɸQh+OihG}%4 H+^8O/;B/J)2aٟ09up,fWZFg;6f_pAYŬR^XˇV+nhyN}4dFm]PW -6ƺxn/ng97_낽gRPg'A(gq_`as14ɅYT0}NgѲILoVgG_m968Z˗vO69 VpkETסEF{*-V H(y;+&0 7^rn|2)өBuׂul:%c(A(EJ-#[yV}~\ɧ 5%j/x HhÐRГ=PABΓq`q5iܹYxSBz+[w;=Q"2B۷vvJi`Avpar6<(94Naom\%0aR 3rÌkvRqpX )`i &0c` cW7 PG>{) @wg10 _& }CmED} b?bƮɋA;(E;vL,Z Ĭb C|Z ƾk@(wd,=Ɓdw3N מ$}5tOܪ& 1wbY0D(CFy{1L`=GO j h;}C_blN+>,Vv{ @IENDB`qml-box2d/examples/monera/monera.qml0000664000000000000000000000320312310072714014641 0ustar import QtQuick 2.0 import Box2D 1.1 Rectangle { id: root property int selected: -1 color: "black" width: 800 height: 400 SpeciesModel { id: speciesModel } World { id: world anchors.fill: parent gravity: Qt.point(0, 0) Repeater { anchors.fill: parent model: speciesModel delegate: Component { SpeciesInfo { id: speciesInfo x: Math.random() * (root.width - radius) y: Math.random() * (root.height - radius) expanded: index == root.selected speciesName: species descriptionText: description photoUrl: photo onSelected: { root.selected = index } } } } Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Wall { id: ceiling height: 20 anchors { left: parent.left; right: parent.right; bottom: parent.top } } Wall { id: leftWall width: 20 anchors { right: parent.left; bottom: ground.top; top: ceiling.bottom } } Wall { id: rightWall width: 20 anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom } } DebugDraw { anchors.fill: parent world: parent visible: false } } } qml-box2d/examples/monera/coral2.png0000644000000000000000000042326712241175670014563 0ustar PNG  IHDR  IDATxyp\}=w}C7X $ Hjr%:lJLO%%138_&Lر^MU*)S3-EmKI$w@4ۍnTu}sO7|o%`0irsN)$DD~b0r'`0,B1!8AAN0Ǽ ƀ 3ͦ&g̟$ Y "H(&%8B u,c0`|Dp T;.L0P{!N`l;=*nD,B~!)n$snM'`08ܝX_fD-"*{ҟ ‘i Ɔ-?$GWzD"@)? pd0>wz Ƨ?ݩp1Պخp8ǩ= Kب0`^*=B@j2S= %I>?jz5J6 G0`5gˎ(m0Y`0&}MNQ<cѷ b$O#"+*jپ2'@F[>lV_6,0Q2_so0w&U}MN 'Gw]lo=.SdcLz)E̮(|G߂TTR Qr5^BX'Q`uqܑ-/0`5L(0+<;C5:?0`l&kqD:whs9dn>d]S)ndr҄6&C1aB@*w`oUFRŵ,9MD~.si&]/>'9.v0`L(0u}MNA8崉>!^U- tP/XH(f2+D-寱L,P ,gUx/Ft8jP1?=7G#Jo F=K F޽eDBV/N#-\F}N7Np+(68vC +auAЮ 1"m3"[7?`7Vx8T6rݝ\#]pGw6q%ebh0Q#zAȻr:NUH!ޮx-ۨ"\BD vb"G{\-<( l%?IԮO@fk`s=055ɮA*LJ Ōa|0VيJ"*NR~,-}ar_6tuk3B-!U[N7HZ\G^ Y*A0`,Bc>І+'a|@[мC4.׆f0ʔ훸@$+ e gXpU=pf8E.rJDfc0QB 'lvJ u>RC1-k/lB&S}x9XwA%Sfa HF~IO9^_h1bu<31# WFl|*|thEc0EVy[ MّBc ycq䬊B.%V^iqb생#h[ saAepLIF2J! T xˠ +QlN+FpÁ^|bBeJ=r TpP`gBX-,F={zx`{aM/#Y,lJ`ACeIYepT4ԲP Fl'!g {1#ۂ3  -֋ "6[׋32M9ZC*rBQe/?wo[Cyyp¬CyhT\Vs%8s;l"L6rNAd,Wz" WyZ C M7& з$\+pr\ ;Joodӓ ܸB"TB3,s = zs*.>Qט&P`0VQ`0*p.C~5M.GoK+ [-ٸmA}v>v `1;T/T+ lGQ=M8f&_o! sf8Nx&Y CfQ`0HɶΙ(9C}%hAφ_:\nMvynxU0|n#1\:;6.  щY88ގ*F9sci1'7_Jwؾ4߿ۓ"صRVp$ S&J1YxF`B_KY"?GC1k  F%(q}IfrD'"IdjX/|uovfK4ؓRjtUܞlK+rydz}V!3ގ(yR%a~+=+YcY?ž6PeQ(L]`2\6aZ,IqdyGIz()00>0{)prP )I|lcۓ%y `w}wj HDzFu^U P#65{9"(=qUII@I!9Sk (0p `c gS2[k=5!uA@*}.'Kmfp:k*2lb2>u0m7'  ˝G(R @@,`a=ӫ{s~gz3ؚͰa X]bXkoCuLvb[ങ UH0 9wY`rH'bȦJgG\=ppEc+.SE27i Ƈ4WP AD WCz1^_n=ho+ ڵPn۰oyx4ăwwypaxVW[Ep/$ OL(0z>YUY( rw]}孕T$ku=UAgw=h/9^LE>Ǔ|b 8Z>w޽.\05 "6SeEO,lMU\8l2u$t[0+`a$IF]5KOh(Ħ_P9"?7o#pIWA5FK 6q) 8Å7k*9v)\vYVqIbusGiFZ8J} cugQ &WwEqjc, xXE5`B^}"@TȒvmYR ",zPka*b* p)RG&?7w SAk\[#3i_ҪP:زӇM[7L`}>;ZhP5(˂n47DDiQETY7~,&n0pUt(?>'!8daXz9bSY2);oA"č1Ӂ8zpy.Y )ȃ73ads -DC)S,6#.;-&8&9`}Ss~g& dYE`,8!^bQT`O L(06<|r|J=h+B)g࠸zS= Kꍰ&}ObxpH"Ě[4'RC1L.pB{ ߙƙW} L^b= TOMزÇAʭ]Pg5bKb`ލ4\*ؗ LWՊJ\O L(0 (p\"8~[Ǫ'Z#F><^OȒb nGRĺ`Vz \߇{<]6H*o0/O*tmmßۃ`psH* 7ine0h0 iQ]]@#)6'.qy;!M8Nuu).i{@8P%-?W0Qr#as`k2nńTs6#f09V9Ӧ-Ă`I#X#ALݚC"Fx.`RNlmCs ~/)'#<: P[nqu5LWfY~r2Dz ^f5PS=(|+a;zGߢ/7ZJiRm~n׌A4}~7P*Da4j_LRBRY-;B.w{uh_\CzfQEIDå"Iy.~HzGQg̪łC%׃(Uh֎s..ikʂAw2v&9t8LVvx}T'xѤYfd+H 6wjZ$%\x{J!XEΓW9ff%@By&2[ZmzA'g5kd9 (_P%+?H5PQ;N9ňY]k)I%"ؤpX0SJ%2 =k15NArrnBhU ULS PSAS+ S9l[o49L lF[dܭLRwMwZ,Q޾˻вcU-Žۋ׮lE T,Q]۩ (&temE.VN̋ή>IsGrTt%1÷FOHӉh`Lɬ8VaB){ [kE,`5JVux(VGHב" ђ@FRlRI$r ^ ,Ǣ+"˭c+/$PL*E@P#(>pz֘ sE0fQ`~ Um)N0y]JA9<=%!_±[ XT>v} x'p{K]0IEAu]\ ÿ4F9T]4{W¨f#*E'8TLEd\示ISt`p+@r'`Z$)p IDAT+vLqsh%-(FqBK^(6$'T*_j0c=aB<b7 EAۂ#bXoWݟf1rV 9ƅiRqj}p+0ק9MfpdC,h0`Rm~LUjLj]%,m&Uoz,*]HХ/Bz0jY h,j ZX =vN=<;CKQDdgva& u6WhZ-jAyccaVZ̢D,[H&WZ[X6N>.VHy[LZ Հv"/bb۝DvNjTkIJ̦K^)赤 ̄i"c쫇4GpLoTL~ H5!R#9d^KB&b| ܛ@!<5  u ƚ%&bG?p/K`/-omG2aS.ZC0[4[/N Mx"+D ռe+i#Gð4vXZwY Zbb_'ƞH@ -NtjsIRqiE*E2jK-3/y{m&D` ,Qx,|l21Ba5  5K]g8;U-#EB\< )hюˋ)Pm 7Ua~)n$i qH.WvLFk߮YdI)h2#4l,(,g͔ dCU tqc]CcsmbRcŸh3l(cgIܞI" rI*']4ZcuPj¨`tyCԚplWMZQ0XC~w!NJmn6>7MTQ" X3h8X\-HNA9-a[y2aF7' l5aO($g KeIsO?a~"$FCW &f5I\ ,rT$0e^ eł 3X"0۩|<cqer w  ҜwP`+nldY16fU_pQB=?g&ku_ȑmS}K*liDoKy$gSr h@6MGd B(QLət!VFoBd;H#vXlM{O(0HIboPxeDA%fR=1()hbmɟ^ߟuCrդ h Nhba=g|g,„|(H0lǖ[9bv8d8(e,2< ժ+3?C4kC6zlƊRR) 2)$rirTk hbat>QISi%Xة4[EO|l*4sMNBiW+QIs@Ѽ`Fp*)ޱi0XP`4>X( Pٌa.9H3 jb~$ DoGavY kI!un}=*U, #\`\ #;)Z[ 8TPX Tm )=6RBAHЂ[%B=4EPF @JQMciH hI%~Rc-`BPu/OK@iD")NcV` b19]fʣM񁰸N˺)2zm(3I3!f>ZP]A*2ߘ[#IZ.)蔴DŽH1!j"c2-Iaq FC(9 wvW^V ș!7NNhSN_6=!=R"s58SP(|PEHȣWY(V`o-q#xvCב'/.iFR|Pc5_0`Bh(w8Ǫ9Bmw;KS#k=!e:X1P%&XHPEo-d=E!@ vU 1{}n/mˊ'{<{ 3n `jw jhj tш`9L(0Ʒ?C v#T[YNM99vӄm1v*  ՗@8>_ӱ1BѶ`1{b z[w=?|Pˡ^fBqĂaiq(Bi`}g,ÄaQݽ'muodDGOKu |tDž]p c-N xnlѻ0O (mg2(-k5A]C+f> XZf{8pjc9XX%ƺ!|AS7%Z`2Bf @Fh"T ߺXcTkqa6ij=Ѕ]Hb9o5SO!LԔR扂7ux_"d$qbF3aEڊ, edT-֋}yqcPXJd_Rv`+CN}p ny"9~t03`bw/.-= @(T|@zGٶ- ]r=52>X,, $e2`cMP8oYIEЙӺ_iv`K  u ƪ . LU<.AJ`q.x1Z05Tr1 ]3-ES-bYj.F,8aAW؛>wN08`Kœ)Hr-0aDSݎ~@Ne@Nkwf3R.Z`mȅEKԍR.yٔl\8=eۂgo!6Al$ Ygvug̈>.<Hbd zn.b臭\Ž*McǞcU=쵕XLbvZp 24sm𑵼!ZSNDP`4̒ʝzM_њrVCYc1N%+??tq/ۋY$|o. %jIҚ kfX(ԲFQ@m%YpX4/-RT]h2D#q@\$XT`_7udp.UA =~3a04pE⸝7[u"mˌCؼO}cb:):Mt]~HPfj, p'Ŕ-pT iN,XT` $WW8XL(0քka}y[^qGn âXXk ܛBtxǦe\p9̂((0V% @\@ՌxJv}c0YvZ:LZnM ,&cǶ] ]-߉jkKgQ};rZbF -FۍNeW4N%, en<_HV!+%)<5~nPJ)i+@ ' zYbIEj^9l}h)970:LDX6钇jS/Lj{,e,YEmR%k^/-πH"Va5AJpĻ+$է`L j }e`_ x*H{3ZCOh7#/Vc9bN!'u2 P`Is#@;xba g yd"arxJQ& uZqV{ MSʩRCDAb5j1 Rk•|Kc=h/{[`K -? $I?=^cJV3ɲ z Cڹ&HUgF_&T+Hٵ*l ¥*%N`L(0 $Չ}^|cZl\b n44Bz['b>93+ڄ~;핺,h_ @y݄%Ԣ %r|}d^zjQ;<2П.KX©Q`3L(0J\,;[9,^_iقkÃOnRzwI%2Chtpx7JK^E$-_?WuIg>,Ӄ0mHVpbk•ZJK\ͮ5[25c0%RL/ 8yDK;)pXo?YhMzw_ΪNn`P`4JO#t/Z 4 0 ͤqnNd9] & "-qCK"Nh!fp B4 Nb`sCuk4VH^nίF܄nLBSl$ z/zϤhmݭ rh=P*nx̚A5FyY DcTpV0vJw8„ g 뗰 و=V3 )!N1"t;Uqt2vBn_& Ml݆Iͽcóp-tݘ !Tf:jg01ZJq7Yg&Xbi̇rvah(X1x 'M>V=N9ފn1%ƏsX= &0غFn_, =uuxn8#U?oog1~%!x$1`1 GP2 l7`DP ϊ/lCFnh п&Ph >L }8%1 #Li z`10J@Mc=wAMҋ{w|Cn6 ZCAzk-%h5}h=5 @pHqˠ="ckwյg{#B r v[E`MzFt5a۾f쁟x{uOfE&N4 Pb`: 0YExHWߝF6h Lcf!I 3 "{f^bar4b&BE9<czojF_g嫓Hgom处[es@ Fm L`qf9a\ ٩ڂ2AC|fqJkML[jY؄59y%8"&$%b@AV4fy.KͶ_K/Q&kwˌ}ah4uz2vlS.#~H8^{ḡsc=ZZnY^ al_-ģiՅN_az&7/BOoǕ|\0{O:y^9 ,G)pP"r_y/_x'y:j4x`+p;jL xqM(ͬH4t&7թtPĊjκLPh (hdMnz=Doa7:q xx/26~F@HlI0rƆ znYH3$TUV*\(2h5+ ;̇{ pT?lx"/ TOzdC }95'6ZR`-pпropҴ9z|%%j+~O:"c%֒̄MX XE{|Beǵ& m" IDATGh<L9zniXj@OA f@E ߶j6X$ u wSۉ}}E[s;m4ߟII||=XIFiva4Wvlywo3^jznvG/Xk w}jxD 1 , [[؜ͰnYIKb Z mLy_‚) DhjbVl` JOu6 vuBȨ.аuRnw\+65,X/aYp3.p1/Fr& k>;ߙja}nF1La A/^0?@}/v׷Y~QQxc^* v.T&9(d־ ە3}"{ir <9&)-4{C5{- Y!\Ih >f%`Zx,T ԋO *nKц kK(W<KX9%lNnmjPzOL2u rqA B)rnYoPXG8NM a `LƑv ˳\F.> yL W79ȏD6GS6#b2ێٱ迯%ӥ`J(@ 8fƣ XS[mjw`l*YQ5]hE 4UK4{p,4lJ"k(V`_0s/ y< #uMfuHsGw_tJXJqYQ*˰6 [(w4xq&t5?w;+g*&vW<-5 W\n P@h!qqj/yEA^>0:K0GBg+֎^5ljqvY|E׭7=f m[ڙRRM(DG׺;" s rZ=9-+Z}FԒӂhOB #uStJwuX] ?Qd$`(9T$pr4^C)l1s\h޺]rRCB2uW "aE2@y:';=3- \}o\[_ی?:B`!Ewk;߷W} QUy&HQIx_G>(.d / !tCWLIc@uO&Dmp3 % 25ńo@*!?o>XX(9T2`~n] 8:m 4YY(G@/GNH+]MZvj+;JgEKU٫NWC v۴O4kblt"l l(Y (gXU:,L@]hiu+Z쨭W¡$@5 }*aP`րh(A]05"C"*"IʤɲnD G:˽(// <\8\pV߾!k!ªM% 8 ߥ಑@,ڲ h*ttգ\Cb\Xk8p'>܉f nzΏn MW` ¥rI?$5pj!"cߤ1s\۞ 2>|A]Bs|v^& @'MRYP2QE[x)go `?\T>5J;X{|ԏd Cf В(-i^@KI*B;uaiH [opdPn*^|,PJ˦,(itj`vz«غ+zEɂo6{ /{ R`$wN#_ b2hRɆ*T({XΛ!Sǰ;C#$+@*mdfԽ:ZҎ'M>f8A <AxޡCp09 )BL۞9=epRp-QBqC--CnNeePxאZBlV=;dkxxOiu!C""L<9Sw=T@&¹~x NH2:{C+c)\ Z3݅H%p*gF+dA F[TH1&Eģs"1W=?*Z-/xo`kaҧۚ,!"v?}$oV-db#y酤5t1BT.  Jb x*&?Йz~e6Nc Vz33΢U\á0`B:J`FN,ZjaD7!K$,iSYsyʬCΠ =V{}Q'zD_pj 0ص&:F=J؜>e733ص'MZVS,-#DòD`Y0ص`±4) k0!&Ș%s礷Z_n QU0˦iR8æ-jZxÈGLOz5J@HpDqG0Ţ'J P1)C8?!',kZdֲ0[l <4@Q|!nYW`~'Ѳ'{qʮ*!LVHt/0;|9x1# wFTɜ)qp/Ov߿)ibqf1=Tv!qsx&8* yi0{ێvfJ&'HkaID`vhq'3 2b9uuI'pH1I\ۮ0hƕX:5.B6P 1ښx$r |S~gG`XI[mӥN,UmqR daNB^R8Um8Z(T,jZ+O~@?(ܹSU0S @NdcJSI  C2"g cJ48k05fF6tM{9-\Dtq)@9 'މ{C+ᘎ׿4Jw5B˗nQP&v{#8@.1,TiYփ;Pd&}:Cm+tØHV@Wc-W'*)DxJ.K0?{iEˣ޷0> Զ9,C'T;55RN9T b(ⱭK 9W4`RK V 7R6NI^?E$rA@SvCEUD)LY´n$!B1 aգ@]5NŢ@_['d8ں\xq~ |SΆ'! u +H 1!!'{ š3]~p X{9ΝSJ nx+t! y(T\(TzmOK}΅iGǪ:4?!gE-ͧ N%8Sr$(9O&'79IRg6E]C {}%SA6,u N'XK3ܻF'ܡWlO ³pԋ Aj<\7 tV-tV ,M& )+nXGp.= ­/"өpcy\φŞ4LƩj` $AI9$<\[qgD >Da1D(IOӌAȣFbqQG0gP% 'h7f}2L^f iS7JmrK = `SLo;F (Ddl4^.8?Ah(hq`*{Ot|ac<ƏeM m(),B$KE* uw"ϝWឿ}vpԃ7>[/ H/c=*2usI3\;GB{%$ '%Bjåˑ Apn»*xGΈfQ s66E6:J/~+1;Z =BYۃ> p~r{/Vvn\?hyN͏RV[^AqxKc˅I@(`Dsgē0@)> Ɓ:`HV" )' z`y&^kdAK څ*4$جr)lz' ` Nbp0Q:d)U$c}?GpDy Gܿ t%]ЦGx+k1~W<%C@psN˧nxe{oo@}M$z$ڟGat7/K48ܦT~èbJ!ZbN(fĪ~ 7grfᶒ@XIm"Ae1 qa+å.Mn!MJJ;&z-eRk®vAc(ja҂WiG>э3\C7^Q 7ϱh5#wu`oR׳=ߐ;Pxp/K !pkg0ut _}zx-t+*rEϝYTbQWV0(瓄Kj#~jN}jѴPJzN0HB.b*o ˖.N$3(@$|wQȄiHrǡV.[lh׹rQyxT֍$`>nH$C.oOǤJ N}{##VS G3dS{7s L+8~]'}P2(L?XjMmX N//}G>|uo%tPˑc&p{G:p̹ |x+LEԶ'c;v߿ ʵdqm/\kDq3xVo\ ڻu~p)ՒRaUu8)Pd ;e**ƱU3tʪk G롭Y~ ($ H^Ȩ1Ph?f`ud➿}r$ԣ'*-^|ܯ6 BWȫ xa:Y*l?Z[IMڼe7yR}e˅ '(aYRggBȳp $![zapľ9s#B`1Jȳ,Qb-M1~B=S9A @ 74KX U".%~R%Ҕj) K8={:a5q5Xb+p gQ\ Iʮ` 0@.toQ `Ln& { $bDNi[ݮJ꽵y{Ԙ˂ ihϏ`:B`j}X1ዡ㳻~4nv;l>+ip>Ӯ3YِtCSBUI75kVj@Ϗ[Fyh H~w:7/O@ܾu`%@49R(YXlҊߴQ6A[M"h~i BG5j+m.Vڣ-4lֽ٫1-Fc^ `1vn-);lRЩMW@oY#C qMDڰZ ^)"kYB_A`dR4OW̝X[#۲G!.#+ZB)4F3rm rBҽfn^ؼ$D,{ghƔIU=V p8(1FW!h)@ v'%ٿ/ݖ?b wQH. 98bc3P223 H_p*{?{5{+:OePeԡڂzܳЪUD #SB;XPɀZh6SL>$K&_^ˇw%SAθȂ8.:GX)Zeq}-Ю$8$<%V.:5A$ Ϭx'*LhLůU1.k+nD\RSijD K0XGJeR`R.($q $,&@[a m1}s}~yQbLsr\ ts/Od%y7ђ$hi^ov`OG3F X ŶݎYhEM0_ r]-!tp & DJ0uڅ-Ho_Xj@! 0~~jV }-*<'o\޶rCW{ B\ĥ [ߑ崘o ` " ̀_ I7H2r'u9уqj1=êaU\[/6cQ즬tX7y)ؕP\()Me(*CKQ 5p @yo,3_m|;J:JPNSE'2fUBA ˠ>KAO܂,-)̂>eVfFj8Ĵk 1LP`8c@o/u=5/bjUbqeրI0[ ʇ\D#y{3dQ]E=MH,֌,D#è9NEtpXqO8ዡV%$ a59LOU6Dq\# Uu8T# zEʀE}o˕Cv>N/O`U zm*i4vn嫷 J;j9PX~RR҇*bW7Tʿ(E|}Zd@a 'y% qDZ&`>'c" jJpS[$/QL^̰bBo߬܂X&DIb0Ez0K=漘[:$h$D--ބm6F[]V.;"EÌ;A F!dV3`H,XB^z#k/C`QO1R!ʠrQPO  Wc *(aR ( e?6u!6 Bh^ΜgLeP){z3Lō5v<MB X4rG3R+n:pn.NdnAC2"pe(I(IK]|'UJRQ2Y> ԚaU)u~ttԱWvUO[ hAJz'c/-rX)BLTi,/L* DI~ð+AJ$2@ P*]ƙ6mF;,-,!)@/$%Iβ B@e<9gm'Rb%S*f(H8  3;}+6yWZ v V+/JOfFhѸZ,W$1uƅSp>ҙB7!|a`LSg\ 4ܟs!$hkԈD&5 B(ssTcy$}΅" -" PI0QZ RFKInV% e6IBKcDF&OaR 5@>87`# _$)U#$oe҂!D21.+6={аB\%xx5?Fc0VF}m 08/fvNp "VUf-Z,p{BY@kסQw7_׊9 sN#d;L1 C+I=DuOX 9.N1ՖnC#&'sa(@? i̾5cpǿrmz\)2YdT 2<lw#Nͮ[Noi3VKǞ._.a#,,FD_!5v < @QĮb[B׀s"fCE FOc(v= ^B͡%ep Wv= BEP[1 ,xg-sz_H.IG<-$+J@1[0fiN۱︝N[Y԰gH 6?haX@jHHPB-*s! ]m<`߾q ~2 [g>hd[2KܮP' E }u'!<օ(| q8X0Z]Qyg9EfHB&\WgpD*%Peע}V{mo4,`j,] Ąz冻  V%AhVj8Ep_e.iZ:+j`й rD<$`< ޖ[jEZ-'?"C{O9No_@=oQ6h}|E8Z`hm`pZGRs=2>@v0V$ɀY<96$&f Xo 0ܳ$bQ$ +"._db:!QOyxomYo 2ԍB byw\,l058yj8; k{"Ka7A`tnW&>F,)WzAO8aQDY֮,zd"cv\ j4̭n9 ~@[4\噭U>%~ Ala}kEwa"J뉶'*|7E$sbQCa$.V& "2k_\ };,ػz*5Zf^wa7ѝ19bsa͉΂r"$%A&.#AiWA NSL+^:Gڼ+ Ph=(N9 =6cmUx,eKE6ybgOO`^?Y G۠a5W.!S$]d!D.a{a9GY,U&˧dH/R i^_dHiMFW(@r ;k5% S_)3s)r$nq c즲Oi 1!!_zϠ7f! ʭ%/iJGmk@!O躯vg:y ?ˬ~!8  YKH8wz.ЯU^BỐiCc7kF?ЙphFP nuN6"3ki{KfWA*5k\8){EȞ-lDAµ+kke‸VǺAHqpp(XE {O;,9X׾[g0q0"t j*W! ?EГjU,nw.E>DC*ڥq/_~p=ZPȖq.ݿ4yQB%$"9#Y c O( J<o%5[$ ;Rmb<C8Hb/ hy苔DZ*p4Րx {>!Vu+Ta1^ȷ9_V ^͡(cq2?}ώ/B$컷3c^̌{[ZH,v˞X&G1;Ez9܎?GXY4 >#Oޏnƛ F*!8b'.Y_40\LU|r3}gmqL1ze(V%/(YEm(^HlrDN$hԊXUKҿUy!@Y^jb8BhvAoTY:Lv$(X ?i;# xB+Q 9ef`nm¬)QWȮ6 Q(o'L)rL(@ÅӃرZ V {CgHWH&_g@c>@0帶8o.K1ES)D{=Ԉh8 XY 6bnB a>h|:0ܛ?_p [w8MeK`~gғ<9b:asⱪ*3LLWBgI7)Fjå&&w?D]~H5j-Uv X*HPt&@^kpRxra׆@DH_yf@6kJ\ >7; F`~j|[ :N l(#Jd2! 2ιP]gBǮh3ZZWW8FM2Eάa\ōVtāGwz{Ou0tauJ37|`~] IDAT,I ;{`fC]{S~Q)?\/ yٍ=a88xa{[+mg#dA3rC0;ow#ΎcALE,M[oJ%#}$a#;]\pIȄ'! =(EWkQJ*-/ʇMB^Tg j)18u \ڲMG Qo+\ x0 ˠcZ`atyJvxL]5hfbѹBEH޽9Өn!&Q O`r4dl$B$^λ5 m S4'Y 8w9QWi0/ɄaJGY~XFWΟcO@͖x4V=䈄w1X) V݈{:"  vp&F Y(VPp&3[*I8b& Bo5fmaL ρMBj·I(pVO=bDaחyb,%CE|11[`n,Ib /z D)ז pR'ɟ摅~-jQc|;IԌEh7dO ǢvJ%o;ƵEUgf6%59fYDY,xYoI#~"y6 kSe8"~c*G1 vN8Gj-x.{✚ cz6u$ φ03Pn2hRb F17G}9~$-\=EF5Zmjyp I&b@4(,H]2?tU%"εG#Xeѿ!'|~Q}Se7]tW)@w1K  am6m:8dIFϣi *NM07G"w &V_HD}zzK&wᮇZ CHH8(b~N/bJ`( o{X)Bݏ@:>w Ψ8&}" aY4l!xkmRфrQ,eD|P`PorRt)d~| {0NZhjq'K3ؗj׾:a3c6<Z^ga!UBD IB&fY`sYŞ8 xͰD\c%\em)w}ruĚ7R`juz!&6g#/HD$a,qw=ӿ[; $Q_U,v݀&#&G|pOdOǠk{-?+#E^#B(,u4ve J` c~`У,&Wk=kq:%hߏ_r҈$m)0 >ό%Vtւi5DѼDPrT|5$|h-2 aj`SnDlH{̟" BT(D%P 6I1F3^ O5"E/L,BF$m3^j%64VLR$y /KhW{ey5wYI k47w]6#o_xn'=]V2DzsHC4< DLaNhP^Dc"b4TkH1Taz̋krTI$Τcsť7g 8 Uj4ﰢ~[~hh`q}c8m֞jg_YܰwH2[4)IdbBexwY$4.c!$̌DgG8x5C˯& ![ )V~Z+$۝_B9<Ϋ;Vؿ--tx76\ұ;$Y>@` aQ=$z ARʭbn+˿.(fL$lKe@($M&yYbgh**b`9XZbC`$AGD  -ly!nIYUá;y5:p`bb1)/ 9A=5z -$a L!{b@T$ ϳ az;IehTؘs˧u1 !LS1x2Z "ʵ Z14!X.!eVݸXLf =/g6%OfÎ/*yO?zf_ ~0Ǎn\z V55i(hFJ֡˲l6ɝO BJ5;_y/Re@m 1& (q(ka0d lyq_ѹg< /.QEղr%:IFNN.v63q;餝934mӎ&;kǛH%J$\bHbX JsplW}>>*6΀ {>c6u \]?=#Pj{X{16<{Ja9&07oսN53T@fbfQ32+(x< @5. "  ?_1U:QtmP:daF(>/pCz~'NA`v]S,.& f~__I,I"lP+b^d,m,?3\~[)`ё4 k$rȌ:9h&[Ş%&3" J g]ӫ'fQ-mai]M8tkwZbk5W QT ifnb;$C4?}0칫Νm8G GAk}49G'1[2h#qBr* otKu t:O(H)D4ZxY OD7GHcoe1%s]0G*"HXgqٴv\qWC" _A)H=̃y}wAsBf'l(v1 &9A(I"uI?Bx*~hNʵ3\;sckC*]>-^!X]xh2>~xsK0xdt5͈$8:'hU6c2%;kY˅Q{}Q n,4 @TA4 oJ4#j!lGxEu @?qKfm;|6?P| YcGSx&;p j]Txnn OHݲf;JEAec_b$,U"+n1y\hdث_uO`;6պi BS@0Dk -\K&_;Q4KR)HU֟PQ_(FI([TT_ce@8'];:篊Z܃J_9*= jRo|O&wMAUL\t &ss*|Jk4ω}8y }ZCb^[b.!Y1㬤FHGqh2Kfȴ)LN$OwSؑ^.Y_SQH-\LQ!rup2utT~.=u|I9\hOfOJ 6wؒi@QF([vDg!tW..DA.]: % (XJl9D'iE 13B M/eҚdZ*mA8}\h(Xqt:(C,կ qHOmS^172ZJO"2yMJNp(M/cz?OJGN%֬u zTG2j0|4jM4ph*e0I#:sy!J'&W\Y YXn,oik#ed(hnL-3҆Gx߬$!'d C=Mj.dEN )K@{)D/,_8*.Q\^W:ҹD3Nܔ +(ӺY0j YB#HF&xUBģ5na9jv}g88.i Yq8 q-8u[IEiCWҞlc>0'' -;hkJbO ,6BV!L ¿_iMBZo% (S4E!:VBSv곿>{\Z:oe2Isl(a\`sX@I4Jalh.,R(jZ;Ҳl1bpDY 7*df=GG5a;.@o(% q(27fiGa¨C8OB#TG e~2namWNgD;/Fw]7"~| miεE`V0췵V#CcXmA8c俱QE.M^,axqDAXC/b09zO?Ͱ IA.qN 3ur8&\a)fG:+EJ;ِ?-\N)z]2:9Bi|d6QѧGԧ~u>|$fM㥕'ܴDl$on&fl/<>s'ϥ\&w7S2q+>aqBV,Ml`=tToZ66Ne;tu;HLRORVa[H 3:L[H^g{gbƴa[KQF:QCN1 i*&,^1ϫk3K餃/OU, F"KE!V+=M>ORsGCoO! + 2blktKb>N@GKZ o/W4L﹮4P)7)7'59͇u5%' 49-0qskN #N)Q(_0/sJ\Ra 䤺!Vc"o57sja-vsZ+$ǦNpgb#Ѹ9+b&=gTkTC<榖nH[_C鄴ܥIB#-DJk>J]Qݗஸ,c+݂n?:I}Lp9]Qf]P |ޯRK 4v#Da2)jj쒄1?TPa:0TGe\bnD:j.=w%/﫬+޺W iXc^?VZA/@iH~kFȇ_nѾN!!%oPW16m+ZㅔBI}G{1}f!U!| IDAT01:f0>:X"AHJ`kbhU* 4Պʼnڃ8OZTD6uWh{;C[['.fz^k蛽UOxa(Lj- Tը8nqJj.W"FA`z#i/ŧ$Ax[GDGE֭~4M{ `_*7$}+غKAfᚢXm?ІcYXPk7$D`5S`=P\Jܳwi '0qݘ>zX͜vw=-ɣaC핛~)wUe"9طvK%f6ݙؓcd?٣ِ)7^0vDߍr}(OuR1HB>,coo$@8؟Hl3E(Zanw EERզ_i%$,C[vS‚An!tX\≻a Fbh쾯ȱ lY? Ď)BJ,'<.?su-AI0z=̭ucb_6ܺRݑOo:ƌ'޹K6?AIqDW k}k#Z%1сRөCGbG,Ɓo._$3's>o*#zUOB>kEI)XBA}^d+Qu<.ͥUF |)>ʠÜpVOs17{=~'%]9o4ZH`?XM}YBWnK?(Iv^?yyf-Q/w.t#?>k/}Wf7ĵѬ~o->)]W=*LHpן-iF^# ȴ\;Yzͤz6|jnzu(<_nˆ.:rCæD5lYI}82<5 1;}7{̩I.4p; :5pϚ5 +X3V;:59ptT6XMtEy1 7|Q 4~%" ǚ*nQ5 ШAɀ \ߐ!ش|Ok!KYq^ǤwŹvWa/X.`Eo1N^4cYۚ4<ܞԛ}TD{,*ܝϘȍB 7lOPh{AwwvGJpk~x) ஃyh\ps <&ߏ 1>_gsa{Cx*3IB2L)>s),Ϥ̰jumkl(&w;un^a)-2uzX,rnԽfg{'8g=S&O`R~p#/??R *P>˾-^(Q'gn[!Mݚuh|G?wu# %"S?$ & >e" P^L2~E\7ΆpgkWԺt]ӦL5*CNz%w?/IeEO$O'W/-+RiSAY pNF5?gNSpoT['Y|nߚIB<; &ג+wiO' La8 r0O=ϫoŸz&p~~߹[0>燐 l\RNC\ю\P(ɉ$ģM`ݐPyI{u 8Xѕ )Lْjv ߞ$HؤLb8I_񘐲w[]!Z Qo nqiI1XS- ɉJOHŧ&>dQ AԸaEvDQUI0?a7<$Iyl# V#coeHNDӢF $15b߬pid!cհ rS}9uKW#S wC3edpJO$!QjڛDrzP20D˦r7sp#ӓqVnM]Wu֛ęqw{k F[m[9u&{b{vֲgg -LQM%@Sl1OP}&$~@2޵!`r+eKw>*N "rHoZOF\7dZ쟥FMes@IbNIAIbS66F25A SY(S4ʣ8 æ= P~do&R|!A?. [0ȔURVt'G\,Z[*;Ys)ڟe;ȇ&2 H? ufttTcessS#.4XMl{ΤzTK~S'NbmQsi¿b2\N$[~!e5-⚸[X8gQܣISs1޷~`Jp[-Ls0HCkkص4zjF>ځlIf>| /#P_LUE! 1Nl6K#\MUlbtƶ_?/CX# J`./{Fl80?ϹcqN(騊~.}#5tQ('Rl؎ѩڀvo m]PJwAnO/ghWGjxdxyR %(bӱM:]v25BzZJ" Uvz֩ FI`it.mH;VkŹž?{8ArxG^ 0j^Z<nJ([B=UTHD|aQlpP`d཯9f=7z!}aؒgꛈ(x&zOo'PLcC'/[a`֩GԀoVag?@~ S'<1De\PD2dik%0eCSx#gtd3?D[SXV`'3]q(2 Kx/_݇e9L]MkVY)j_@*,MC hdvf;Džz:DRgcG/;/I%CKkwlc{ ꇕ&PcGz3k IH&Bˤ&9$ܟqCŋ5gic/JѯZI7,jQ >%-w2 PX#0.h`ۘN}*+ rFd!i Ts7ɢɐoV C94:sVf\0@O,i띠wm|C1ph5,ECDDRR}Î߽ߧGmM۵< 4. b8kGIEx&RԨ DZnE~G8n)O^v4puJ55yIp8 ƒAE0ǥ̢Ș߯۵]C*VQ@N3Y Vt"`VE?jHC^NN 梦jnƧ[$j|C XYHЃd sٳ ɪWʆlM2*TZZ1Cؙ-[t Qv[{(b@h'2%. yo&'QQ 4栱 a*?~ϋbkmmX7q*E)~.4(0ע3שQQvY']ya(`Iō 8"* Sz_fϙ+]MOHK/ ӯsݫUK͆RJJmԕrm߆ 1>⌹g1Wn[LHR ^ʾ#& g|]7[m|)^B.4 cre1 k^VYI) 4L)d Z2GPO֠# `BLDDyZeKv AѫK^̢U}>Qc!Ʉ Yڍ*#=,,16ϣ03G|~冑,,`kr``wi\=y;+2 k̢3"Aw ?M8u=c1eq[5ݞ8{FG2wBwn*mmUxxf'Q ._Ut65A)Jי]QZ""ƫWrEqI" B4~|3^:3t$y?!{Ҡi N#|+l1+w'8g]|뛯rn/~ :eLjvoczrH)3<.[7k4m+ +{1X{+HH22^G_@Jګ'O r/~rۿ~QUU}ϝ˸\bmM 7訢bo=*݇ɁhVsW rx~sZ= Cp_`Y n9=!it2.IPW^,  B"!d%)YP`cN `&seCP\+>J-2SH|j <q%D{(b{"mZ9{Sߔ[7N!pۺhTW۱.ҽ}/؝+s{z8j(*uL,jr6nwo)It%ńo|?g'(MiK)/N27B}QBUKY0{l5e{=?w.K_=ȂعGibԬʂH`! J;Ϊ$r?=y7 joև{83rHF6jMF2tT-A31aB|7.kkrvgZ͋JN]4<Ҏ}sEFQ\a\3.J[RWHes&H RHKK40NA9N <H$ɏ+eF+ 4&Z(!Q5lQz)%@(v[Ol.40֟'SՖжZEm5HJ󣨪i,ִ.K + M r~pK-gΛRY j3|?8G#bY,FJ"\X L~{MAY8D]s$]#V Et ,֢0"# IDATM E>; Z[35 [ 2eH$Q#Ay\~{fF\% c3$a$14Iau7_#޺wn,&>8ٻC4Y).MF F6Fҏ-TobH/f}Mo[% g~qGƄ߸kUh}3u/jieIc)=lml>+VF zޯް4.}Oɂ` `&[ 1(dM@)W]Gg ~)j$#&Uǖw!MM&r-݌`dCP6T5=?6,JTSǘ<1۽ڍ-_{r9d+Mptf3K ۈ8)/i!i<}I淾tޖx@e{=%9QGGr㗴Wbkr8uBeqzX&G1J%nv2S%[?_''7|bo!ל;o/&^CjYG1͡IfOOгo(VP-xPu^QBxtBMڬvr&h\έ{605c޴s媆‹S1фӑCHb+--6d1GQrlITPubst-/]lFOږyCa]kH9qX\VT2f4n]v 3o'-H":"Ph%gN/>AD2 ú{`^'[n/ٜo`./ı*H,ac.Nd}\`Hmv1"AsmO_BOTX C87$[Hà0hJ=GeXUn XtD+0& *`*SUKD@Y#]WwI6ZmW|h{_/%O| Һ 8}|S}/}J0'~e=~gAb;W9R Fsx ͥ\,RZd8::˥KhwWoDA6^g:=4yUÞlZ>٫g7Hx} T-D%. H!BH)XX;ͺ!ZfS ْDNhޔ DnCxh%>gzh9\1%zӚ*[,tr9ߙѦL.4kNYEBa㊅kyO>utEcsS R*| ͚ KqH;c|x-/Zdf]4'.l͜U# Ҵ;vbڑ ^ K! -U8ܩ>J@I#OX_šݲwҽ :Fp)!ro mey'_~u_!;#5{u>[4<ô:jB*?KdN}ڇeY dQ1`.0⋪[|(e\h iD TH1Xg e&,`El |a)D'5Pv\QfY|B||O}ҍ{|U i{lWC<gq;MqvOe&o{")QTXނ*3ɪm4+Awu+F)I#:a߅J.Q">m/?:2 W]xk6тML6#~}{eB) z& ";vo(N{e:Х1ZvDv9WO'ZۚTmX̔.2urW0'3(Q UP ?VpS(KZ7h=8'Z2,8odt|ŞgN|ϾCmr'FΜU\8x+KA (w;UV na'&cw353:tGpz}ESusy ]9f/_f^<# 7p<=;oVBm>^F}@[s>m:!bdOaU'͏|,/83Y)GF zq}5`)FADA p>O'IRYvS5껽 wrsrb] ؽ{` G: VrhǺKQ~N'|.WE<,Vz5A(Vu bf1+JWl@Ee6]BU^| x z+sq9} ޹5߿qP}c ?iL!6 zQpKfQGE$1e6IERDbQF0] EM~nxc 9BUT|jGb0Un-EIZa. sQ'3ubSǙ#z~@{Gug* 4R# Q)-Q\i%R˚Y>ݵѠ\)Q"U1&J(pY^Tɰy^ѨSqKv]ʨkN qSCLw GMd˰8,9ۍ44hU[Y u uO rN$eάd5' ߒMUjz|L^"16Wev0d >{oNhXfJgrZ:/DʮeמރaF%AJb1{np,`$F%k5(XA85}) 5`%5L΅+è޼𠏲 .w{>,"FEcC^ԅtj:?Hz<;/6G822 |pLŌObߝ Ҿb'%!Y%74y밆^C7-=Xʬo%W2'6OlCn؄MD]H:I,R$ ,wjE"畫}51̞덫_}yx%XY;} Sp~pR ok%Oͩ--woxr~A,$M'_}/GkLoP#5,\i\MޜdVJ3Y)B=>j:1D4á8V&c~~rN2x\ŬkqSY_)B[Qo"N]RgRJ9}ܪNQ <^T.J*T ߹®(D*WGjsDf}>YKűLDq-PZɑ?~{]wTuC!K†jra1Y% ^]mĔppa p ?JYDc]ZY Opz~l&҈B64}rǞ-\ia)$13LsN`wX8v\2+;ђ& xɒ]) kh(@0}lcp,"m`{ $dYu#0v&&e¶^'"\rt1ʰ}օьǕ9x;2<|R $K|'O$Kgom9} =l=RghB+D|$F;Lbd}J+# 98Aҿq$VaC-a,LҍRmI' "UZvGG4C$6|/GX(̤A},iIkj7s޴u!Da6TA2˔Wšu5FUJVZgj"D$wf67x~M}=YQShJ`p_፻r c%E4lijc2<؄hi P]M{(ɼA@Tu~ʸxq=" 6-%^E"YMDx[ S .JKkJʹ4:sEeJ9ErԘ(Tߧ($ZP!tizٶ5j{FC|8_wNڪy 2~<﹖p5zqJfhfvdױ894HUDThy d_γ[[" Co{a[s% tBYu1߼I8*n,ǁNp+nwVUcqW-"OTDZ(9܊l!{F0zbu!tLDͶR~߼ںtupΒ+^};Jٷ'ib1M7u)kGQ IDATOdXw QҵN*pES! ;]|W-a6gOhAdQZK|gA ,33imEN݇p5et~mE='oluFU6 >\8x"i:R&΅%x㙉D)\7ђ ~~l7ISח|?Pql,}Bqk%>w4E)U'*(A%`)+*^FB(=\ f~$ t0 "Q/|tGHy(dݪΉeԳo4&唹PXo5ufA뾢˹`p:Acڜ՟U9OXe5*:h1hO1^[0`-wRO6筆V{+# {]I!GDYghH7g"@Kj 1Llr}# `[VJ,X2ܲPX# |cɔD.XT>Hd0*E+dWX'7 jvY^8*8H %Tm\G~kacu+x\ch(IU̴.3(P^RhRKac^ JzAXB*֐LZ4Mls\'?u/4JZO7e'_"~  m[)P`;?s=_|]9+|m#ʏQǒ Ɔ84рE> ޴WnmWؐ#Q7vS\&IpGW|}u4,J8Ԫ=Vy@˳6I*2<.}cg?s:W1/d!DM#蹯x"L<$/'[p9F卟U8̢Lx$ҫLjiۡ%SDy,(5(1#[r&t"SI"Iq"SI35DgeHYCRyf1i΋sVŏS\I%#w3dy:Lx>϶05yZ6$uFڄlf;Dydksʗ$ܶ+T6ؖY'۴TB&o,t% c˞|b] dR=:g%ߜ{P*Ve?Rٝ{DWuah/lf %9Oq+14M!CQdex$ċ/u~3S, \fsY7/nj[iE<朑;jk^RP(zzLDіp{_yKѨ"E$rّ1<['XQŌjRe=mFO6l)rpl?oCN01.qɕ`EDzerkەBt"F7`[s%-ϳjK]^M|m#Mq;iS'`37Ho5Bc6h [ݳjq㸡kDgR&ZZ ,1*κo$6M8֭/(,S6<LRu24x v /`LJ݀@`wLa qx$ l?qML1^FB6I@gX .3\IXIuC!xD4>&Q,s!]?Q$ C!EfBtnP׶x1*­]P\o`cO80& C3:5Lf/k6YC=H"/ AG׳G0֨N}[%PneinOe]vmsrFDia7k $QU_6VXrş3=||qk% pSt=ySeWS> ;q5SD3D&bڿBŃ%iBdPwV*Lj%Md-DE#HfJ=E74t}s7ՄΕ daaHo$xo 27BPTrr2FI&z 3uhNɥ; 8 PS@ç&fD M_=QJׯH>d ,/_@]A/ ~gvD"Żq/2E<5Vf`r>Qv$k- 6nU!['z0IY#S੶|gt'05ͦ' FiX8"gC)۞:HՉJ2`9b*,%Izn.OD` kKEP3͏&A-dP0lYTif"T\&iАX\*ք@& X /a`DžƑ"ؕf\pzxh'6GBr͛+:0Ss.h!bc!:mtF\.܍nMn$Dd(B߿'W6[Φ#&/tTx4d* Ewٽvr&`*jM:֙ {MekJzƧ07JQHl(奬K<{eB"1 XD,efG%%^߾1xWp !}p܀%W58٘BUo JWƄ"I3?<ښ? ;csX3Hj f:f IbBQ`m\i{}Oa_ Dֶ%DufPV0G*j@ LTHV_Gp5f &u1D|"ݥ5 *VaBC` HL8Psv,|!Vh+ Yx] f,BeXf*L BS}5FS\5us%ή$,L5,ųDq$ њ}'u:#$r"8$_(< +[vx`yg]%> PML&u1U7 e4"ET3 R}3jGy0~j"0C9^MYiO17^ez0UPT Fx *cޚxDP 28V64TPYf5ST䠨(nh~3*J89' uO,@ E@r˦"̝vy!Jt%ah:՚,,@h!G& ʇyWgE-lE׻)npiٿx+-egcٲ&YX\>Ds]KFfRɭ$Zp$"Yêsۚ3PsD>/g dWQ ~ښ@îRj#/pG| v4 :Y\XIwP2::ʹ?Lo(~nPAcC%Vʜda=Vvn +CѕohitPMq_kQ}V/*c*CI%¯^>VLVͳ[X8+|aU!4A Bc&nM/;^p6==HXY[w">y 6JTJEJI? )oI_n̼> $**A6nu2Ҿuٿl9xgZ,erxOcbh~-T֭Jܸ ϥ3U4)ջ>Q8ǜU %㺒Do#,&?X>eg]a.|ca:u+ef ܘȕ BcBcag]2?a[y_fqxAՠǒ|뙉п^niqx4=XD5MfC6IYI''drhX#H|Bz GRZEk,7ݔٛrrHeo j,32 ❽DaGRwDrFItjY_Omgl;wAVD4kq}'L`%yڧ 'b?@|"7QTIP4GcR68гABN !_8OSˢhЏb6nwb-@J ' 1>}  x2@J}_ztE kXx_(T@AarZp? aD!*"YIǂ5 -mTA 53ʹgqoDCSnMߊjcyn}윻u%Ș/YnaٛU:;譌l99o {O$ ַPds\ǔeP6>0L:Syg_Ds?QIse%a-l(VMniɆʈBTHn&oQZUࡰ"@%?A0$L},]@RkZ B9\^*>FM"MT5y1%#IFؤB[’G3`1Yح"%E2%E2$"C ʑ=Ne8g&tܽ{$QHI{M1/^L(`2h=%m[TD*aBdQuQrU`Bf‚)eNHU0~S>i#ـzA\ <HjMEz{ѩ0ۊg=I nVb3Q\1 :86TE#>#> PR$F,4p{pi{'{?z B 'tL0v754}/ߋl[2dy&Q,SC@OD01d =B8ϕq~wy4ɤȸ,v[UDQ A U3^4( 8JLXeϫ{4{'q6I(2Y"Y ;%4۠&Lvf,,*蜱IHq5|SSʲK2FzL \?ƅ㴧V51M>"IvJH,j6SYWL#WOٶ F2lPcLf:p|(/c!̍x;{SL]"1qכ&[ `&Z2 Ti|Cy [qP If;c^y{$a*jP]n`9(rK+$H`/6QDž ۢ= GM1{k3W# ^5 ؑ0ZAl(W%&l[5AD푀~i˺8P^F4zۊG@ 蔖{(-sceht# #D<ƥS]qZK7&NPV塨ԋxD[&J~%{;*1|­쉪 Y$V6{-1) Y# ˶*K#o╱ KV)GL${]$B&RcMۆcWEf.u`pc)JP#l{@FDAhDV&,d.)UG = -j`p͜`:[$?3 qV4A$H :9cFim(:)*" YLF-$*mgGTE0ST⠦!u33Ԙ qPVmB]eQ 'i CUK[$ܲIe,Ma|qLv Gi«xR'Lkج럆OM>YhG6a)Bv[6KkMQfqc4ɈMv3UYl7O E DNkTt[ s_dY0.g~&"/s.)dOm߂qp+|xgEC tft؇`*:NgUnΑ{+:8+ó' r[ ^bςDEIKRUn.^vlR¸`WeĔX'R/7q0)Lրd0)敜)/@K-;d4i9eLU.ؙ>/hcq>Gk-sR IDATB\2̗$ S3sNMשU "Z6.0&Dvc , bY ƋVjX?&t.|.HNTq"޼]ֳ`+֔8"Mw{) ,iq?>5Qбcc%lx4,Dah|8I޺a`lV!jf+g.D;?W,[1Yh|K`8~ϵq(} K22nǕu3=n! 9)*HVZ>rP 纗쳰h|hcrq$3㮼E=VIII:A .͠ pɒ`w2E}FdA >U?B(h8P^z#'?7r~xI'?|*JKO"rz,fދʁhJQI{i<~4m^aʯ5Z Y<uę3%.<nF~vaꚸV,6dw)&oc}/_D1NDu58mJ9`2X̸  @0J¬㑫+:Xd:Wx<$=id sچeǛqP smт;D*MEA '{n%αƇgI zOvG22L&vqßU] &bq `GO/km># srJj\4 OsT7on z;ki=Oos:{SI5y}$}»H3`43 f5?E%SiYL30<3^YzV]窱YV!хr/;K<ޮ1&֥""NgOK7z'$ϳoˮfMq֨ƻNQsf48tbSTo鵏I@Mc)5U'QTzSIKI{|NvR|6ozbz:̩Sio\bD@ K^ f7/mp:48 x( cT0b_j?O&Ľ^km?+4(CӆbCM O۵q7?вsJ8A{9b5U6{o7f\Z& wj5^슩s/FjLr~eUNjrO)MAod6|e2(l.JjX20=̙~{(̢.Nj\^;obj*(dPƷƪ¶dj+]93ja3}~Q2%it3@jRkGRi-wblHtaV!I0H)b$5%|O 'w>չghom4X?,3v&2AwmnȼR")J(;KCXъBA0e 0jZϨ" pkH EHEr.$gFu$W,Y g&'p Qxyx`n 0"uzGW` gi-ʹ~)lao>ܿ`l6|K3,M3x"Mi!$Wb/ˌ4:k.I>"(˛tk|b= <$Rn # [yK  , "´ʌ" 9& -ߐKmN NڵI8+}&%<" aMmPI<g8ݦEcnfbD̿zUET/=7.K<>u'?)׮ V" CS]c7E |K2mv3__!{GzZf"ٳkl&Nf% /dr3X,x7/ӛ75/WpglJjrjyKs,(Pk`d'`1VEbY]XX6]=-tްӉ* p̣-oР'T?g1C\a 6$Hⱚp5aݿ7RE0#^CG{MMCtΛE^{K|JfZ gFI=# {h`.^qOn9/QH1$a-Kd|~X`x":+N[aCЕL=l<~&PMbI.L=GߦGKԽVHz%@׭mV<9lga5Rn1-CC25)_]Td.i=mB ,vgMⷾWmҲ**w>UC'T|?˿u4Y@6*W7Uxĝ DҺ4В]%W %6tj85%̤rӟ,k!6W^k0[X(hld.B*Ot ER08V*qJG+ 6c:̦q0iќoMl燩KfNEV?wGZj%1qi]mFXc}R+Dy$Pߦ*JA*21%h|VZْТXU.[b͢ D_/+& ?>#—{ _-h`pˬe*5f< qVƲ$m󓽢j}}`tHU,TG^ kKS](cc!|m˞ ,T(<3{n5=ž0`(0a+׷%4l΄Ĕ)^(+ lL^=Q7[$a4Ԛ7IT.(o ώtb¦T"f$.r~k FMIyo - Y.|eQmgdnӠ%&PQÈkW%"/]*UE0 L"㈼` t `c2X\e%CSܼ>ή-s:h\ԥNf\Mނ_? 5\7s>Ds cq맷Ioh %1of'|a]n3}h1nFlOߎ7׷[nGSu4ՠnG1kƅ}6*J3mw7o] B Ԅλk6 P+ϗFf5Wf1j4`~z%e_G:0VDJf9 ̔zd tة)7&Xz&QS@ELTRxx[ҿqWU5|mK_} Ϸlf77ѽ+SUŹMeo2fQ`#AW4[9V7%pa(6.dIB7 (Oϔ4SVD:S4UoCc.+s咚>8C1DdMu*1Џgo%Rd||Qy֊"W{Е1~ԔlUBxJgQ,ɅJ]d"/i&"# ~O@%@Q(W,<߂ZI9"&tPT`t8O,F'  `&H?UlǾH7 ewnL's?DOj:R9ˏ?@Ń-Y`d-EDѮ+ PB+ &Y`Apݑ-">ր$ȒllJMiF&ֿ20 STjGz|8XRvu.*<& ID 4= ;4;N6[VeęMUe'2'>}Lr+Pu&Nw1~5ǹ <WSrdco\K# A )AR`m \mk6jb3ZV.]4P(1b2|N%H.QK .& M.䲼b9A t=gCH2Q4a,l^Cn#02`4ϯ3S-E+"Emi#đ+p/ιCn$\^Il.pSmW^, I&WO0Mied5*IqXm86n܈S Qh0fik4 E3dhR5@p\ek= ?27p#?xJV rGrA6+!*Rz"fQ%o^E_ V?,M ͒wSmd F/(ν|D$HLmc>|?L`EQdEʼnެ;f;{ݽ>}y{oI\h+dGX%J, A$N:Ls1Py!1sfy]$ s[tO_vB تarjT$n7N,J;,-?^+t|(UR &UBeJW7;傷INx#XMA+P$r 'Jl}2^JVgW.v%J'Be )ğُ(.vpn='ڂ^}˯^$Ig2-1vVYM?\Fv$CKPr,QF^gt|EHsPc vAUK&!q/aNL6CP{-I;&R82 $IB>Z Mbp:0ce|`ڠ4 ޱG:M\iN Yq sY<@g$z4&~bBqO+o.Ķmɮ.2Lūe&&=-+L tiM4+*RRKhB`b,9?eap*uj*$VybZ" Jm*`7 d :ŬBe#ؘօBf{oY/ߋ5,B4!wkw Y ߾<`PE{o8/^}>HsB1"l%T<+ZcتlU?Op&rƔTfL+3W N} @vP +\ sA(ZR0A{$FFIBa+ͽ3$diQ)a Ȝ$hﶶc;|a^-^ GhPZSN)9TM,~ѳcןd]NO*3=˙zi,&c{*gO VR_:ps@=+|4[i̓ZJpӦYhċ^;6 |PH7 P֘u+)>#s! Ͻ& G ޺8={% IDAT i"C>oNG?8Bi!ȞR]:7=NW(ʎ _j}+5Z_ba9A󇘽қ`*5~CR$,s%Cf$AB:*%ۍ&MS˺`p"e1W13dt͵27/PUeBAH2*Sb`:Nϕi&61aUAVb^]0IuNj?+e# 3\gx+4~>\0HA1VBv80\_]Wp:A(@L,-DSZu ^%LRw-?l jK?ټj; eE>2*i9jJ .WТC[|P-|/=ә?3~{bu^cf6@kK%u5%֖ph=6[֞ڃb3yo˗}74T|h?E5)כoOÂźXo Tbbae ¥KTGbQtPSXP~Uģ[ȕB?@.IY\`WuKRC➈BE,PR[t4m]"4!|5Jn򷨹Ci"3*]C}XK@0ڲK]-JdkQGs02cxŔLs0m*B *PX8}XȖiVSp7 +LIL"yQ[Rdľb{vAt١=W MF9/?<צ4?/>#I<^=u/q3rRtvyA?ڲt,RV]G?{;=J5LòH҉RLN¿Y*K3µ.+U 1a\E"{6~6S)m(.WU-B؜6kvY)u7 𐏺(2.HX4a ($=]R -Zdq***O4]̮`vϏ~6,-$|P.2ހW(G upPZʍgkͪ|iKǜ(b7v5{ϐNep3ޓ(,1^XB?7ȼ5K=1OlmVXFn{{sደ(`3bڎָu{Z/֥=3sF\.6"h3MCu {42E;t9bQc:tD],N@{E)2˓4imXݐ'-jpg`R+.B$i0/{MCτ7%CFPu_SNuL,©q'N[yNBսRB팼v;rsDxۜˀ~XĘI^ {{̚-5NRC&s۷ (NX6Tî#;?E%AU߲Z0UD! I<[SJ,)'^b`(>OG4 6os>tve_xZV \Gx!5.-dEUU>'W%Eh`v2̉ɹP[E;Q婇 ѐɪ)')X6{h" *91aLOX)R+EE4 dR Y܎Eu,Jq^|{v>$k `nK4AD| .z G7wŎ /9ϻQ iYːS#m7.vg`UL9^|R$f)-wGIѼvJkOZZ:7VA18!i?`BK86e2w̩W^QȜ3 Β@}S# WRΙ AzIj3AߒPXd9 `kaV ;*׷0sJ:k7fbudr;Sz?Rb~ov <\iTU9ijtcOE,B`CW28%1rфC L{o~.oS]923t8HWT%bzaGNDP^Uв7!q^.bB- !i(9˱TāʴjiӒ@@?B<#$oM_߮~2&v[ m㹼cRKg*ƅnxCt|-Dт~ffW <{=e͐L b]}z0$6ɱn"Ss33u='+#aJS69ױycl-j] yX !{b5IiEln}BẬ˼^WIXɡ B`f6Q(dbZq@X&Paxݖڞ9V'h1n&;G&2&i2'}&qF,b|.C08Dұnqo-|y*6Rn$^=j zġC;(*J<`7nX M傈@'jUz-[(5$PUS`鹤Zy,d07*ܜSNy 0Pڣ e܄a ?uʓ('scҦL".ĊJ pܔ`N`gSeZV)i)^ uA M=u1C~Y'(*\5 -P ؝]HD]k2IPfMAqF)$vDх$2(Ȉ>7V%Ά$K'&8r9.3 NU51h,_iZ4W#'ͱWzG?vݺ4EcZ06;D Ip7ws{W~sb9EnI/xoj5¥i?u;S.F@㍠ - l:\a%E@8?G)ozO]sQ%ɷ1HXD[9F-ddBX ͱTDU( 3^sC1 #U˜?[cӄE ǪQ*7 m8)E7ͩ/XPj6',Y][j^2]=Ÿٯ|UayC&b.Y"×df0@ɒk*,N1˂H|z161=\ĞpXoˌȌEDw^QU>>ٻy&W9Fڬ&(Ãg1ڢ,rP.0 Wl\j=[X]dwTLz}EH)ED&3iZX`2dz pt7Yk8+ #;1̡C;-L5/ƍԣP5!F)6%zQ`. 1}-!p߃m Ba@ Bnf44V$-wR?8iY$F7 C iܼ5 SDy{|B|(s apSrM]w2i,p==&J/I29.g[O.L]^I_m}`sф7x~rW%;MD7\͗1j+^`> 3a7w8KD"VeY`N?}n9Gs[\z"+޸,qcnc~hP!cˢgHhK|cKK?[&ģ /31q:2&Eb§gk],*vsPu2$q^z{,3T7L|d0iӊ_dn4DqMGkc.ʹRQb˱ZFL]#02KçQZHx)7˹wSVy\4Y«H .2Ay#bʉE\oξ=:1-3,[_}M$s+ Β"/hd3x1FkaS^/|̞'7qեOw Ϥ6!Hb":6M2KigT Q"C&$l"܄nzQf~ŧ?xVW}1bjU4nuo*Bx !#ұ -3%$!FrF=+LՃ{p^kÍcܸ9d= SU(drz Vo~&}>6sfg>LwO(f3ǛW2|w_[4IӦ:HRKTC *d仈R$fÅJ&? ժR{j[(qV 435%,ggT8_70u}K쯣 eb F2촏}fU⍀1]H@NGy($ ͪK<|}Όi\3#즔\7TYpg1 +%>:ov]]IhA&۩)& ;Ԁ҅C)b/PTu(EFW4&ջ0Z-H`3,j(g;;[B/}b13Ql8 k )H"n=]3󗅙XH.5J̮[|xSJvHH<5(K,Bg|qd@KFHmH#nYMHxs8R:6l G2 lB0}W _F< ߷6{[VJ=! !UooPe׹eQ s+ZA1˜Ҏ#$]w6g}V* _hV Y"iyb[qPeK] 2`ck',FH0?U,o[_rQf<6f ܍(hf8nJєW Dxȥh܊a9?p|E #QMO)LaB[IXJ]e^ˇb(sT\f i<9dn]OC=-whTeQ1~:Iф}ċy.R7a֫KX;*HՖ?y p: OLl(2v[5rZBzb-[Sތ Ho"@-3aՄflN FDڛ3EGJ33Ly>gf צxӦp+Ed/a9-J\ EutDՈ]N՞Z"?yerC Z4ԦxĥPkʫ3Q?, G^|@02[ bU%sQ 8\8XvV]?A[f4|vZ3U!o|~}kMBuL0T0qIf賤>.0¤/ `S]4VOt7{WQ (91?==8z|w=Lծ`7i4-{iѤ'wvˇ2QIn!:uC^ŵkSe̜fЧq QR(qŷyg09,W.`ȌLDh.!͏'"S}~nzC2NQ\Q㈂<i&QɘEiUE!N/lrw8D&OL'#C(Ky;~{/$0[iכ5(Q~&{bӽH:Ldv˄jĥ1]ĺ gynvm BPUbZrULD44T[8ә"ZXOGt]H$L$szkf .`I,<)-S#`NF8Jxl*6>GA*'"p邕g(0jc3B_4a%sD.QX*' KލHUi!ojW{癟N_/QBa+ueڣ)rB/h`7o3rzä2M6(גA:^.R-_ηmP̏*GdCrK2 [6!IM4!D@<#+ْBmv7 M4rDJNeqb{|<|CA6p{s7F G #8+I5k3A: L#VG 1aI-~嵼c UN=釨=V)Uf:HMǾG*s_Hєf;}JC}Y3(z8oy.eB[@![j# \Ɍ$T`e6[-)Rvi!qh6W[gO,Lk LF)[p- #:BĠ_Z˳]쳂|j3s?UTV" + B/I-GN~4s^>{{aP2~6Z;1Mbp95?aV~F \0~ˇY{Zh~d'[@RGшRGoCw&`SI-}aUo68?> 一C$HFkBU(63ǿk˜EK T7x`OuwsZO+|S{))>;87j:$uC,Qf𧪳hwr27&O>ƶDM¡Ԇi!)ōHrhF7I$B0sx\P|Bƽ\qrq]kkk71}}#KZdŪˈE2 fmͪWm%G5ƇƸrkq`x+`{$Cs|S{ظBNS^c[C:f%,TLP{C[nahaύ-E fB-7 TUm#;#S_Ĭ'.>cx<~<~nu7Ϟ /^Nl8=7e1HL)E"^vx±-Y=h˖ 0N'wg\i#ӌLs7sO*t]1;K9^ }<W2\r疃6 8x7 H#s5)k㪵TB︕p5i8՜~9^ ͕=ݿcijꚒnvqR/~ܔ~S&nYe {BS\ q*!ּm6mٹͪIO7sY]Tn\JChQuE5=p,?~K(toUÿ[5k a=gaWNoՖ|s3jTq.g\e֞aXTITkzA65Oi[ϩ]~>J<>}<}|3sJG?!1b+ab>fd# ۬!lRZV{pHZTaU{~3Ga9vItrW6SPU x' v[@m: ;eiċj35__;Fx7 ľQR];Иs#6fUc.EYzVU4)?8經e=o#Sqݦ m5t #~5 W$I~ DRyT^ŁIJ (cmfnN])|g.1 qJn:FMiSx³(Պ.U]zPLif|cʊ{bw \~9+PɶP&+Eȭpm><ϛr;X7D_o\q-u;?1}~:BT-ҰƢӷVDž¾ւslt6#S5ivM`Knkc lȶP&#Or *wB.&n\_|B!r}x:omM[fëHYd*6CxX~Lܺ}Z> =m ȳIidjq+ݘmwl m2ԧk bСēϬl&Tp& fi{Bת՗/|Z ]ZW~ЬpӦaW82MGlhYL*cwnEdIQP47;~vB6ֈHpKԙiy_}&-gʝ$!aJѰk#gC(Yh{toOɥ ]\x;RGW.\UZ4@PeS :aPüxgpkI[ Υh */y*dj*_U8V2&=Wh\ f=Hu; ށ̅-fM;oMm+Yn '=ڑӋLtoCTP @ }Lۭ,g;&MzxjeT!IlbƈrYOpcLՁ#C`A,q8FfRUxf*˒޹(EYlB EN(.ůƇִgNU.JܙGZ+3p͖BTN:S0I~o.W[,τD?lO->G?#I|cg!Gx߽p28SK|cr"([ih.ksLDtM] 5 /_`r:v`1+_ E'tt&:1`e\KCꅋ|ˆ]ov1Зq1Ӌ(q3\ &\)C6} ěv_j|  `{>`֣_$r=M0yx}> Ѹ//,ȖĎƉēIdw2lNv?;q"ljG;1%"2ex$@_裺?WtD}dA]D/QJ(Á\"5ZFeQYB-0M㫂~uS0|  ˢ4`g-zcѿF;|SIv 3*Wa?UZfff,YaP (ļhSG[.ѹX;fijg \#mTX/  YAlF7.]1q?\p[+Om^]SEljdD ͑NEV'~kx>M>P6G{!%G;15 -Ju*ˠ&Nxš\$@kƲh ec+iic֮*$u@E,`= 5U'HSimɄ#]ZW)]cӜK. 0`~U3)w#mk1LxNʮ<|0qbT?Vv 9dr J۳ɛiXhfoM6 L(XkɸRXبH؛Lv1pnBV8D:,M3Mie{ +`> t΁m9VM(OdO0DKT5lPKJ ~5a5K+**~H[-kTa_U4)Lf 7q6+Ga5J2Ndj&8SuEB)Pg@X*t/s$Aᝉ$糮˻MP&_dMZ9έ8 M%"1uȍ)=#$LUS 5]>D9R~c0> D~zZc}_uOXS4R)Q2Ej&lhh{HP\JJ s썚X+%jӒ p,Uj?wPIC*3&ôLBU!u?[Ěf|Q0,'6 ?6:|_4Aָ8{vu9s$gHήKH%;~05]CLڏWDrt<1j"Cr|bBPLGӄ,&w6̞+.x)LзF]FC̼ l') YaFET?~Q&JbL+X}Ic)ΌV,-u>6Bn(w)I[|j`:⁂t( Ȅ{=!eDb"L|h$`T0IJ4M60yeڟ`YI2:yd4UGhy H7M, %d9 Ʉ ZL%B HM]{룮qe&3=$k5:2DR:QJ$ed,Mox k/.limK6Dp%4.aPX`36J[dlv;e,DR,DRLl|)u?܌׏켽+zs%[ )L[ >tՕ,\pC̞*V;džF#*C ")!geƕ2՝>|J>Ww*|&×cTl(P%XFϊbN_S~ZMřZ{VzjLH+: VU.JJ5ZZ֭$צ1%sbS4y6"_f|UlO!{ZjjQ%;AL[ L|; .`@ o17yτX'ܶ8X"U+dR$;/l$_:pYTfOhLLePә3 $ݲD]\#[hlm_oGC3m<9¢xX <%}JL'194tzpy ͊nܵ٢VKBArXa+WK=v_|m(ofMA'daɧwIbtxTr*bC7pC[L(ab߷|? R Yj"C`~!pFv7*7 vXKhhB#$ n6=v>߉mU@?ggJ/X% 4[`6OxVw*WN;j0`cLFV*.+=ep|b)XJ*w{+BR7-HSf#Wocfp3—?@@Q3(jh{]ʬ;ko[zXXݰa8/]fa(xr;-Brlzs_oBr%X^;_O@Ꭰفp$͏^ :#  Lb!!\9:Z5ziPA1xQ|<=T+pIH\,Q]&Sir GӜxgsWC'6S-7}+-n8dEɴBAWtr5񲭭[ز+l9KhjUBE֕sqhUa=xXj"å$xrVF?~5? p l!Bd1 Q մ>mVh|8G,|Z$p[u$_߭\S|-g$VFnD(8=vUc?P:'cxpxׁ$x<*юU ^VN4Sx^-6LT})~vC0#}(dYe|ζfue[]n;Qبfv"w+Er3,@^9RCmA~n7Cw0Ȋi)2 r.VCc^Sƿ?/l/~ znPqBĆBh80BKNzUܢ5u  o#cI:&"jٺ+)%C('8#quhrۊ%7x6A3x8Sa~e3<;OlqvcO)+j1.UvjfM;3i6vxk^,Shj  vvJr"DSf=_85a!B.M*Ga<M_Az!4g _Pov17)^fZbq` 4 % LͦQֈ*L0ooCE 9e+_gxKV`ZuwWOQbÀjAPcQTM'329G82jU`^Q׍OƸq+ G2[3zWqosoh3TWb,Q)gsE[x*3bღ˃_tKӜrB R+w%{0I umJp$v롭@b!Mկ_< i*jJs'G_g|fSaUVY3y VnuK_;A>=?_;qx|gd&7 LJJΎ:Գ)QC~=NuZW\͜7/ݿԎu ?\LA@XJa‘$uRGWU⳹VSWL1E`ëp!s|jY$??ޜssN DSSApس;4[4if,ɻ)_=XB'jU)蠔1P* n,bZvP$NZQ 2|e]ٛs|! CGuc{ݎw/Gk/—xݺ$"@;md04@Dh\Ƶr`X,JRnRϾmN+31EE-t 8QU{M0Mh%sY!:dz?L`A(ar~^ƛLMZ-BUtNQWWM}]8O 2mvinIV&_6dU2}$\vshZvm&s4C N] qjV W;%61{!tSxk<@0i-. <ڹn&ƒPLXki JE\jਸ਼򔶘]>7b9q9hJgHҨimY0C1A M%dY!e}ao7rq*z {;=4.j$#5"55h"rsoO|8N"f[Oݻsmr*|N7>Z;ヹMHYxIuC﷟s[ŒR /}$ob;< G/ǟ9tlų+ 4K֖`4QzSX2$v '֞k.{EJQ2#q>?O*qTٲ5!snF~XX Di1aUw!nz d~vJ۱쎐$ X4QYȕ l.'._V &4lx6C hA4$:|IBٲmnvOv6בL7lwǙn.k~dD*fn,P .b^LdU]qog `L5 z Nr+k[ kvEBWo-p%w;ӆ7+$N+;~e?\PNrɍ+VXDL/F/}og"a%e:;h 7vu+jފe>C8ԝoKWdy;bpih P}cf-iCB;8?@mSv+^KMa@ ͎ t70L=H9UCMx2'f%җ1IZm}"lf6SMDH27A-4lRZkGεa^XӐV5,Pe &~x'z `XJdN+ [>߄.:ptB4MlU6kWMl yj+ d_:~ɢij&VIXKc_|+Z>KoqXξ~+Cds|Jާt=lK@PXgHso]!:\ Kj+W w%{4t MEv(S$z~ЋN!X,X,"MLLV2﫨\RGI(vXbmӶ.'QILq׭ܝv-uto,wG"@]H3;%IbhbÎ5-p}ӓ(sW~}I FD+%P`N6wo$Y$Еu\<1iPڪ%L\Ѕ[DÊlq;qsq/8|sY8EK9ᅬoO+-Oѐ}@$TW> &xw^'\Bv}[6=JpU< TTM֭ZP^QSHX͖[OMcn}o}/|8wt;tkͨ_:_3^bXq*sǹŕT2:U͇ihJGqk,ԢCw3!1W8smPY˜ OW-}H)q{s5/8yE`y}c=)T/?Ԙ DL$YydwuUq$Ydߓې rLB}ʪ'4@t&aB8hV%e7'M5Jv&.dBpTwzVu救N Pӓ[jm[3=A`:VϏUQO , 1`5voc<.bEB1RiZg±k?`z䃷I6FY%17d8ϼ?iK*M},Dj&bVإ,*T&sp\ry// hߙ/x'g"a5mʘMMɭT;/<,:lfW ֿ{{R(B-C Z6Px:W YPsorjpe8I<;{;M T Q؂B]YSun] N` WK{P_nos=ݍ2fߏD{7fMXkק _||,`HSs (yBpPS땖 5j|؊6oBhiwOoۑ;AN3~r%_cw՝>dgop]- cIZF%kQ(kšDWeѹ$ _[cHDRFφ֙ I,BU@Hp,52:f$ïs8rB5sSUF(8hv͐[="!O3="2CM'T&Ӷ'7CjiٞI+ܹj8Mk+I:Sp !gNsk'KB1LDhyQׂ 2O*/\p'5'?>gN5`eеjT8kAYU8CZ0GSoqxvs|Hy* }o *LKYPiPc:NZ'Zk>Ihf垎&3T(R%έπJ/ M*ܹjgX$U(}%ljX*@6hhYE&k+k鵣k¾b "c%3%.=HHhom=zKwD7Mn&W  ?¡Wgx6Ѳv @C[3 \!H^2CK{yY24߸%kȤ3$YA1֐ݫ~c)pwqV ?fø\x=x=Hv c]eyHh='tКj܆O=nYMn6ÆjYB*f|p WFi i*wkaPqTu::]G{V(iEYDٚ?>h09!PMη.csl?\˝=x4S[!ɦ;f&&蜳(XD_?kw>jd)VMվ9+F'K(\wʢnG󶭶(dƆV)1N}քbgg⌟ny 4^7׾#n\wC6ҹC}g:3ŅZj yؒؒd\1EB:#[Zxwxe1l ȋ%+6<XbKL*C.c-rOZD f'~pX(EG 3[oS(|1XpeӨiDYYQu$΍+",Hve*-UCg - D|~'}eU$JBHpl_K $%8V\âʀ{eK &^g PG\j5UclKäR4/ ߜeG `|mkbI0~u#+n{"ǥqBf7u, {SZql,[Nz=0?ez"jZښEpv4,ثmkig['G2uOOwdr `l 2_RF~y^@tkm.li"^VS7 ;e`EL5 Zp5XipڱWdȋZz:U^Т$[{Qn BQao^Ű^! G&47ͼ^WN@c$/Jx.Jd>!YV>Չ!ɧwu e h¥C*7Zg8{p@֎Zj9\l Y_:c01lUcT4CY |/J1w%Jl|"@k%rK]MǺivg_#³sQ'G|&X_xuk7N?,*tZeuZvy~ @-h 1 4Q*Bd6Tx.I;uv|TEbPӕ~V#9ev}|"6Ÿ7z 'QU=ų$IGBq8&Gg9 5싿{FSSGUZE]P׺ /ͺFq58w j5_xnP }J Hb4 &Ol(52WM#ND*weh,"}Fe#Vcћs|T0+6-S-nGh{v'6D3d nY!n Z%<ȋLƍ`VAmwTK?GBAq%YE1u(jB%2bg&mu\II I~¾*q"Zo%sm0ln5|uU\0C:]%Hmξv4T;i pRmd asٖzFgvh:$hȚʎ;xr+-c_rVH"3)Xn'U {xclU{o{-T  gG\qN_g!)kj+3 T@+جBJb$قJ(^Vj"é?x ]iIH]'}w־y_ptpp8M^ ]f%%ֈFS¡psy -+mYQrW/Eyd6*~(`@2@/B7hJ5G8nA`"һ?iEU^C oV((x[MşlPkMJY C5_H0.[B, 0 AXbI L0nȐpVX8/_]{"n*_M$'ńhPU w*B$ 9ɻ{^(eF Y kYl[.In[L3u֎${D l^J}K芊ZHNjT/+$}g;\ _E?),ȦMΔb%>jNmmIFFB45zh/;nmCQ2/0T]/96tCWQ3 1tu52G?.Z+&,jR(~MN />0GvWqzMlE߷~~: i-R$vkq;H-mI#Ub !K6v-YDSL(X$uV\ V|xHq+5mNТlYgب+b%0Ie5"ZV`H WTm(,*x>=gQX%2%4v{T+unlչ.1UL " cV㭱Yd5ty&7<TWî-٠/$$7pvAM58]6qM73 \<_u)&MS* ՝ޣW'6moP5˲r̪sqwV{?Dtn'3 slF7J4ZghJ:!* "3Q  KN?Q4U;TY ;݌OƉуnyp#OkC򅌉a|212pP͏wb_X]bB>kip X ^ $643!^+Mx\ؽV"I)Px9 =^{iqvvދQؕ鍗*_OcrA!1t2ۺ@mlz!~q{B(` IDATkFGۤ<*Z($Y "Oj1+ OQa2=gUՊ$тuќ)UZB8CdV]g+|hɌN99ܹiMGؓ١H9MQSǸ39?7O iC3ӎ,9tx+37+*5V:g~f N jCtDBL4zơUThjپ=x4f`E>.4g.i".l^h6YFXXfcqDI&rZg:JR]ggVjcۿ,6sr߼?y׆;7Mr0G$8 8kNT4xץVJvOi}z;*ak-9B*WXR,Ȳ֞&JKHۆmj鏷;W܂`AdtMͱ$,1&+R+@ K$*jU,"V,t%A_ő :h^~=x+n,j{Iwng'pxjź:0qb]6TV1UYS"o}YK#N/X[2fq wZ,DoU ZEGh:M*/%Qv-?F JR;5̏]:kz5\\4}P8(f6i!')<ޥ NϪє VMa[gv0[1V٭ͭG)^g~xT&M1MH3( N ݁bA$DIF٩U3|%,*6rpq.ی|Dq!p\zM 6/ `x,x?ЄTJFv Ÿ?CK`og;=V]D&`.I?wBفgM:sgO $(Q$jɒ M㤱sҦ6N$ns'Yoӕ]M۸6io{rn:8i"˖cI,D"8c ,z’nl|6yB,ݠRQ4.)]OJ+IR?]3 ˭4Ҧ7'V&a &e\JIr)],W4;LPD!p"RK젘zcT m79 ;omTU`":k>d9L-Ep~ևxvH Pߗ{b?A}5FΦE?" 03fdr1>%V &3p,iub28 8lXXT6 NZ>@"A02׾ :"2Aȇi " ݈EgYM0h 5&V&l,\YU? -mx#>0dx3($1jRYKz.TQ}/⡽XSDX& 06'`qzȇ G>!Ofh$I8n("'ьL|aDOW1tyQEr}`jm9- & !8s jvC&q/ýtD08🪬 JiZT4݈h赫4 / b'Q?v5G,d^0@TF8^h<XM9E60hooC=IDR;~ۥ]rTa0㬷h Ftt BHb"M^;GC[(yC.)EJy"ܓ1 0jqRpuOѭMcΉU/Z ٝтS)`C681{*DvO#H BH.JQ>R$. ]K!F" hZ_ L~ fX Hp8Dx89W7&ZB8)t 9lzr@08Z؀(c|:+3&)DqDCq l u.i,K mqkh#CbGl Erah {}sS,,qUZ8(raf*㵙O p9'1춝LXOQvfKIE`Kc[AOSf),R2t,FpR PBE B#IbȼdZ_ʑ<=UOB4Q|F9A!F ikh%,ްٍW.J .Gq +<щ%NMvv83VWhrwg;VhEk =U$H4t y#%<&k1P5OV3&h)5;)D"#"Qπ?6]Ihs 6@, " 4uAe1Vp"A&́dR,$  mQAm68۬[Ιnýhۡ>fc$("%-B)npnh=&:/H$1ӟQK=P :wMoՋW!liY {F8RE( E>~&@'E$AAX n@McMc;Mc=M,oӕ82 hKQ]|rxU_OpO^mg\G4,Ef'ض;_yp8wLxOvv$}3-6t5ꐓ7@#I#L9>oF1j3xC .Z.ja5$@&).c<&3I4K֖I4ci:6#JcjdMv-ҾR LXD|[փ(?! @sk<ڧ>lHB \b(¦^s`그Q7޼cu J,/[`i؏\iq[-;e@'A )wIB!LGq(8I J;7=R6|oyF}r@`y 7zl,,](/ `\sb=E?f~z Y{}_xZ.m/"ˀ6PH2qv7b~&9#sٛ}i*&85M4-“{@`DDvNdD.dN_9ps$%8A$ݒ X^@lv ޘjD 7@sׂpmGgv}Ŀw[,mtCp㼕GA$?{p;uU\[MI"0`~w+Be~XB\|ǁC(h hu;5.`4C)n_VFP~-`KÒp H *]< (p"UMŤ(+}.05Y;6uR07Y76£dB)T($C,n\m.+ n \B@[/@WX 0x|cv2Yow1u=.FW:B`OM#鋡~k*xo;NSQiu@(I-b "x KHFYV^YBuB)[5 qPoy^JiCe m~3FI;.7`oʩz6v N`qA (}TIhP$i4+ǧav[qD)0Vzy;fH` `cJGʠpS>M@ͽ=/"wg׾w<~,LvRENyd\M8J, ɢ {p텋IB@3o]`a-2F0H!m"`@'“h\2Ww~bL` R-` "p/"H1/~QyKpH|oJUu  2#UB]6!8 $DZ m6Mw#N,^L ,'_G6Ja:;|K*ྯ t:a;:D_7^7VJ[ln٘ .kȈlj{RywZNn+LM8mʠ_nKۑ$y,Q,"E('1!eGR(^ C| A8cϾ4 'WBz@K^?/S%)2/^u1lpDnf T>шYzs_?p^/!d}'+p5-_݂\ԫ5Atb }룲O ݞz NɚW.7ˉh0T,KrӒz_ Űzm9.>[d l( n[Mnƒf$g[cuؼcCx!MI'|8.#+! ݏnA~t#aQ4} ~W0򝓺z\4aqס] |a~O 4TwY+w&wRai6.'}Pꝥ/Wd_ y{V+jP>JM>= .! >S9ZQce0)ʢ RB$(,:a~/(W\[h?ԭ|FlZhB!fCsI5!<,׾Ng_!fr4fۃq4j"c\ A`=HnO07@*VB ª }5I?.Rz/K)U.$+poaIN]RZ;B"t\40X {KEq໏b*z_xo\ =oOb;'+~vW~3,b~F[P߯](ߠǽgp,Q,Xh":>z*z~Zr#K?=KeXDP0ᣰb?LX4&M[% roD5yS~ޕp'u #Nzh֊_EuY#N]E0^G>;󠜬$o]Wl=|05z DaiI`Uhci>ws mIOV0ݟ!d d]Rd4 (Dszl=i}f%Eua"F٪ƭDnY}:o.UEn+$\, %'UI><%TܙS0/Vmx(5y} xxL,!j0~@CZOPY($ >K`mu$) ָ`½ !4*߈Rbq}=oQm$õC!Z+gU646I5JV-/˾cKO| >\e8K' \TG(maB{kwQgPy(z*a{ui5EJwaxU~-7a疫9+ 崃f lw|H䤵\K1o:5Ok /u᡿MdMnI0 nĎcsaWv09u{u7B0Ǥ!1/s#Yᯔ[<=KcUD٩{ʝ+M;P(l?ma''(sy_*`q^WڨIr~2(@ IDAT]_ŃMbG" ) _*\C߽yCcv{r`s~l%zb8KHUD ء(zsiDI z8:B`nyvbl<>_{GJ@ؕo鯼"EK.TQ(\嘦0 LvŭMa 9xi֚yFGDX Ê[#|<|BpTP~6B#EZ" + DyD ?!h ԯW"Oպڈ~-@2}^U)kDjaXM4w:`S.R|^(i, 3w j pį>VMA<v#2FA ^u*hUϞM9Q+kxӯb1& v?{@U6隐@^P _eȵ 0CʟP-" 3TG j C]ZCIś,ެY%`GFKzD Ě "eH>V P@# $=څmv8I5שp]\'p7{{b x`[~WE \<_ܱh~vM |6S=sn -IlM?$Wꖉk/Ñ[ryHTybĬNAD&~ח2R#vZ Ӛ]\@^rk:iVAT"lōꯢK>7 ZB@7q)E! K0Y oɆD4k/.W+  x4`0$ g]ښHhsCX7sbMB$|ryXD:owf͂C6u aCKo=h끣MNHfN,3eW1קJ =J̾c5SaoΔu9ʉQiE!A8B٧Da%i* ĹDaHI${W@#&;7@C_J^ 6"?/?MEP aXĀ IQ}B`Dxfzak;[Aتk#5A@$ IHduB;4h/m6}5A@BA)d&KoqNG_lޭ&PsQx/Y8!rpjv.e[q`IX2rp𾦮Bz2dsS $~:*:ydFv8 ufbV5U:k`Q0x Ղ4*$ w*DMdt5'h SqF.P(ƻ $ &{L3O"BɷC"h0G~-Bdˑ#aVEepyeUIPiJUg_|(mEǑBSh!0򫗸/Ǟ?yPSf$}q̾MX~؁ý^ 5<V~fAZں]ю$4-F - < @8$yzxnhݭƚ "!HD8LkQN)d6 7d3HFw ۚ|!8W|# nQ՜'}q/[QB$jQYX0Hs&'20$'{( Ig&BIW|+w4=g `1PIigj$EoŃ y b qؐa)a[HWQN`X\'3$6}r 14& иwzøimmOBd"\="p,P)^~iYxRc7.2[oaɯH hH$H7L<&(%"A,_w2N9'h1 R&͉!3v.̓2j+5 WFUN(y ˽rd`5P47kBy^!LfE SRԖmj*’FX{0-| x0?|.k"U*ÄO] 3+z`Z@9(akwj.Oh۾LTFreTgߜme= |$vm-E/y\c ּ)ԙۄMwC(:@Q䧖ǂ"PRxGGٛð&4 CK \RHko|#r@(x/"vhH?eR` ڤt {8irz8Pqw~#We MzJ`0@0+l EW'nF6"m\ YNpܚ,dLZmS⿳eґK?@|&SIFuz@ʗTJ@n{zgU6sGqK?%ZNx3 r15J7n H  ёWXDoWlC[P])|Sؗ\-GB ۢʑ/8]1wtsGHf -0m0g9$2,I0"`*EruN3N "ڊӃ 'ͯv5};k(B|^;0~z}ſ>Fdt>JRh%G8$\ 7mzTm#}Ji((Wp؏v oQƓHi8ZO H/5@0å0h K@ZMxFw7CpqPel((N͡yoh[+M<qbD `e~ & HHXNcɟ_[s/:R"r;kk&KY11ULfqX #͘,YhL iZ5^fb9$ mLg~Y =wzE Zd$,P.JJ{_B7'_tTbfy,t۲]X@>K "dU\MVѓ]\8 _X"(D:[+(S S\зz,TX x<+ίBb@ڠ꫰f|+ u~SQ!SDŠMpfw8/,6c{-Z!8 m\BTG;ܡKN- \jpŒ;JrQh'.Fa.$')@½kYE Uځq4zٷF{gyj18afssNJSpAȡJ%IPV8.Oq%Jt>|'~VF V,ٖ"B(}w$$8XiCIzl.yu6+ I_c/2[+D({?vTJV7@Y@lpmm[k^зӁ퇻s;>fADOZCQ5Ԩd fhlNS8g%C5:{3*g1@ZEhน8A@6X"5tF[>p- o!3``VUi u0[ 0$:I <] 1lL (35% z ;S(eKè〸08MOi׶ 8/+$99BKS%G6Pȋ;(ŢIИ"hpd3:!E<|}0Wx0UXFʅظ BpxQUUCRF˃_kn9 g=0-8NZ5`ȗ3['u/A3ë5Kr?q W$9g&Έخ` ۤH@l1U6IP"I!2;0[ DJD,+Zz85[*]_C @ZKXENmۍ:%l<&v+ ʡz X'݆nB); 8`Uڻ}WKzߢgzK?+;-/B^!t]0ioN춢qkkn5D&)ТuiQ3RP &pDca%MUJH"٨Hk5zߙ],?n dkFh¾'7q&^f3Ga P]YX9HfxV$,^ed"k/\y*G\uّёO#?ݚ-* oTYEc~#Ȑ"fbx=;RΓ (wՀmۅ>ݨoߺϣNI_d4A M(dd釣S%;Ҿ*؋WtG 0j"D%[ $%fevl%ङ1+`*'ݱ# z;Ǧδ@an6R;Ԋ\Ol5b.t4;C2blt:UZ|}fȥ5ںRRN})ID8ψycԎ^f>G 8;SQpfj7^L7z)-BLIkIp.pgڽ.-zPNӠJ\YWXNQ0t ͑d ߎ٣^UA1h~Aqm6;ϣpWn!\[zfí" n+ftojw-=N؛L;0d5 <#<<&,2@r6]Kf GrBo<^;鿜ȹ ,~6|V Y鮨EdJєyPc !rJ(ܱJʩ L㗐8 TIz7j8bZٹr+% dc%z.9=*L+$ࢅ̧nh lFl=Іa̎1L3G|Q1xX@+E|gWM!z(Ow˻7#Cȁ֢YܐoS[B$TYγk=XM*"!]r IG`gPD#eF1C{idJ\(w&EJYފy&1 ̊'0bDA$!Q`Y:`N'Ld*.b4c5x~D&+}^}R8Bpx󓊟ބ4Y.LD`qpXQM5w# %@ Ⓟhɠ?SW0%k I1s v"ԮWU 0T-$seAYDaT!@D$H, @$OMrb+%)T0W=HP{.B7cϟ<]ԸrbDcdd3 敝]|T|p(XOӬ_ǥy >/ 8Fp, h@oNC-@[lzJ{MoM z)vz VU(A%}ﳓ\rXi#*@Jvlnd!Q" ¹# .]'0҈n>2»/Jv5:[@ү&Z}g>ݳz%{i(*]s7#(`64vHX&Įl <?c|?.Q(8%F ܩK<.:UC$,1:4fL]czK~y3uU,t?AoG*reB>ˮ :BU0P8&-QrSO`]qW2 ;p:])_?;?z N%=<<@A$Aᒩtg% ËEd[Gv5ٰziԩ|TA ]Z$u7P| B7p'p e#!6ßM5ϡT#PPBܺ)DsA+PK Ë%w,4Z ߴAyu 9b4cQE\.XU'BpH뤊:뗉']]Oy"ο-*\$EdY& .Uvs;Ey@c/ JHB%^WQKlig~N#]鯼dxDI~Z@JH)Ō _*!AFBڔ"Pg7/^Z,O'R ؋V$=|qTi{۪j]R DQ;]ޘ2o>GN\?ԘX@{(h 84Z BW"bE/ wK3>5BgK+Ѽ=xxWm~dp7Ot]T˅eԪ S*h :3r[ry!8@bU;3&TN@n'0 Cw3 -.G!ԋU9+A)oQ\o-[[C. =7C ރ60\28Py[=Csr]y^w{DAdA4!0LJcvh Sg앀1p'hFU Bܫ6v!gظaL>ZXݻoL hU7䠬jPD!%ZD΋2g%,"𡰈fT^4:; jNy kw52yR((]@Q4lZV|A*Kq%M1{t&Rziɭ#/d؏u&cIߺǖG:Eܙfe%> J"ॷ'|Hi1”!R.hhIU)2( fJF*)1VCY͐r# ,5"M XiNbZ;^z| {@_J $\ ګF$Y9A@"[p -V)$\L`)pf(QH<^hZoDm~0VXE'0'$ ϣ<ڋ٣Xo汮S m L3DΐB&3ukt\{ױBD  8 DF;tduj)@G O ňm~ҩ B\nDcЉ|'+Ed"sZ$S.1H,Q&Q- HxI_\XFsd9K4t&@8e&Jw%m$…359,!E Iʥ E ACt"$PP/boDD2"FvQolCn :Fpx8 ʔLg+ h)YN$`ՑQ G[`qe8\I$HJ޸CK &|p_fK#'S:Q]|)kK@G9!B4ieɔ UҰ_cR, sg4C[+ Z5v WFG@F#K7 r-Br@r\)T=Q 0ϐ/qU`FkM 0  Yt.05q.JۭK a TQj E\[ZYN/P.8Q' @s-}ި(L?{|{lNLܭz(r5Hǻ$u2GHqbb.tcxBCj>w q2/h*W c/7ONXUp]6)F^"Eb"6D4p*0z)\$tai N?ӄy1iiYTp`"0oք" .]_D_w=s }|pbvU,GBv Rom=_؏ozeBvA5Y֕NJYBVB*!6 ѝC[D2`F4"3 JT<&bGRP*gƤuk? U eT A(4y<#. =wo?Y LnF_||ZȘ]}BeKhn0YBs@:LiCkcI?(MuhTH?=ݣ]- p/|ԆWL#RAK둰vwNȷpvz /=ǛqpHB3FCBWJ+ũrs6K[ii3$[<Ŷ%*T]lkFovdJHCiEE0q{vqLhpE@v:-98^J1亳̀Ux]vĤbmG2p<%؟U!ygUmGr\كrH=v]nѻk;N8Z_Z\sTAj醕\V-0N6Y25dQZؒ}:U2!6dv8c-8n7etx:thi`7v_1/f|n[wR(UfNUm U3 DBDe#y C[P\wŎk0M̤!gXXxq.}:&ٗ->I^tAʥj"_t['~Gtn U*K5le:\vC z=6Ѱ %|H8ʵ pz49.4GBFHb-rc" HE! c~.x܈M dd oV ՘p仲m4!N-7<v{G"1/WYFuZ9K)!f%dC;Z#sӌ2% DwJ˄uߔqY9TRmԝYt/+F3XqnVuoQ EXPh9$qlWHٛ1ifovq9 8%33ܬPOΠwn`=sl\ݗQ,f5Htgtv8]UWPx+ӷTNd ML/ xMSkٟ1ytvS0sscI{K׌-8?WM8B. =7HgV]4?P. 88W:xGs}~J(eaY3S4~{JL;-U*2ҶYOȌV%"aKի*/Ҟ{`4Bx*<oݿ޲MM'y)7_({_kn~URi܍I7jyo8~9\=6w #ԻN 80:ffv>O峇B ä:PG.a߆)Dk$˜n)[4:M>^9d!95hJ31kov(j^Ix\JA/$BWVM^ Qe">3;#۽F9H7xd&h\jPw9z7oJmB(DAxQ5>_N 9td.ͽu4{PJ]M;uǻ;ߌtuUg^VUX KAA%5Ȗ'Ux|:GiE,I6\W #U9$WJZ@c' z +~[W`eo}-V`],6&IwWƕ] I,-ET~{p $ ^Fu+ωn ~7;ʷU(݌I$x}qֻVDM2e"l%Z^T}YkՃ|N>LH^5yWKp?8}/oWkZS |Oqm8NGdt2L߼Ir2BzήV]:BQːIc%shBc`i96D6hQ.cd-e8\*'lq5n`.ILCb ; 0c:Ȯ`1X=dq`[=]UJ~XYxP5?rRJˆC2ϴ7GY`m{E\E*<ݫ=p鰿$swgS hJwO0x_"5_y9?nlR(Q)M` JŒ&x߫)qfEɬ0^ [D5媆o_-t(\QMdxL<:~]ѡ0}v!>"W2Jj7d]M;4pw4a:U SפP/o psvqecfj`tdO?^Jh|/ 4|'G"`UG&G]TDT0Tl@ F.35#3~c6]Z=GgU.=[\ ;BE[Bty(oJ3>d_8r[瘟S|W!pK\pa"x_D,wd|/+;Y 10Wǫzj0h4^g`ݮM0 vG#/84P(gWun@t]Si ҺtBjnF2諷}6G&}Yt(HOƯT2ryL"P1&scI2I)sߚMDw/K'<=·Q:i|ESQX"~_z)R|RO_$:)).0ía,"ӕMrar%@K]qB2kTA dGіXe$ gK2KB4MQg|u>WJy[?ť/v jNƮP,u~5{ l5D5=7~ya)Xwʀ[QAN}YJ@״5E4]%Ӛ6޺RwM:ÕDUrV wuMˮe(˜'9{,29ƣ)r\2DxE@F Z#UFa/`YPs R);"dxG=ԁvn'uMv)Fkj!1i(Ls ^ږ}@B[.pLhv]L5lDAyhOH#H Fa ~!ϓl数 R`={pneJ"?Gl7Z/Gi :4]pTiCڢY z7dHLnlM_}qp#ML|tte際5if;o޲oUdSa]\&2|k}y!#LvIsՈ^;HHH,.uZ,sl#q~y*xŁF;|$WdLl?{.?.ߪ!qfF4U:MHÒ|2L )L{%3mu%)!HY;K8SF4!Bm說ܜ]x7gYVQZRmE4Z4T[.gWj:k#`f[{3Padc.JI-j.;IM(l=RrV )yvnW H?#!9ˊzru2$]\:.4Je!X'V51'i^b)|KNAKk=.c-ݪX]xJ\F}'#˜a0KY,oli[,jjpkM>Chܬ-8[( pRr*nZ-JPϋ7d;f5XeWi4䮎=_ &~" ΄kvUFM(l!p5+voCl݁W3=xS|Ƀ͒dp8B^8t8xhQ(|nN*o &( r!$|* mbh~>=hrqTlD]{QRCbV^ >p"* qyuA'΅9|mSXα8ct1l.CH/<:ܴ:LdS\NIY{C npeSѬ͢%D;ZFBGѹ Cc*?uwgMGGx|:.c<7,w㮚㒣rX{~|`0gۻc {R.eIqj* 8Cc\^ c, 7ÔLFЉe:iVFnIYP7n1:8iJ"4CBkt*OWg]vQq0#WmgP"KԄ/ HЅ`0 dN8y? :іy5d92WwCϒ֪y&sB2 11+@V%W(\ܝc,8]voF SEwtpRk8;ڊXj~:ƇpT"/]-٠߻RgO4L(.Ƒ#\!LN&PKKӹ(]!  Mu4/μ9+ardޣZxW6'6-XX X'Tǩ۽nAScaz{}[M'Դ^&zQDB NnT'C魱.Vҡ:_~@`:UI|r;LxFyܹ4Љ37{?ޣ7sʴ,nτIdʯ=kɝaFn3K%1L;311[hI(<WE{"ܴV!Ův(&At!T [zj:v )Z5^06LѿK!p-]*<]mߍK &^']*n-2<>' P!2>,FS,ӓ\wKܼ9'J@沈㐢2V4V=JPQq ?jwɾ'rzx=f2m"0r.t#~ 3ilW}G[S'[t[!5,Sa2@$K#/oH$1]\Mgh ʽ#ʟ+“|D\w3WGM5R(ܣ̚2 Gx tt9qCJ ܴwT 40KDrqW@$Wktrs۲sZuF[wCnj//\ç: ŇL pio w4\XO1,MS&JҢHxsu eՎ{mHM(ܣĬBN2T9t(MXIK@،gv6EGOVA=$vH<59%-]\h 8| kn@H%r9y|'ﷻ /47x8qF||7X8wn r?2p r6~zGTdH8ǥNVtǭT Ҳc%a,;cjroERx&bb@JJ${ 15' 4cw 5]-} i,>zc#Z+kj??ćצ/=!v2iS/c* ;p)-`)r]u 5vͽ0E_uN\NNJFp'%ӿm,Lb4ÇٿKOHTI.gq֒CU(0]-K)J#g2~gT2K[OúGM9O#q82{%n⥷WٻAy-f7xhَ33О`~kp-I?Tșu7&u'H4vD]IC͡踽z^ _ **=.&tYPR5'H]٥" ymzkl5P|1rv!݊ӅI4 65OpT:Oh- gi NEke,=XxekwܽQiPbl}jQa\lPZ1+bߑ& Kt*pIX8Ch?Ŭ© ſW ^]XRyՄB]VR29[U Ghp95j{N !chBY1ӕUڅ+)X<`:˜C>mo];!S<\}mh~7D71y?^n>cbozcǺ,Ψe1csՈrlǶׅ+yN? yv arv-5/=X"(HigV{D^T[i&|_}PR>jڄK/}RUXߩ("UVoY~quag!%_+=#Sg.'f>C. U!xw޸ SbRZD@SNp2QNR¼foR"!S2~<^'tL@>Cb POb5pk,ſhmOTpiB׮F6,hRa,)0q;|SU].?{Kiléi< r+sKÍO?}ߗD%$*4lGu F&:VPin{cbT"K;ëxR+Uh4Ct.NY F4vУpt&# ^/QkW5Ԋ."kwfh|ɭ.*%Gl@gNG>;Gpʄe9*b !]b 7FDrT:p9HDzwgc?zj\nS]1;*.`r?ۃ'>HQ+iZDgh<Ty2{db!F/E)Mu |5lT/O2+MTӊWDJ;hmǵ15K)&j,&,zNS^'v0}E֥*[zx7;8ـPA$ #e?B>Y.S ,Z[`oмBp(䉧 bI LG6 c1Fd]2%d ni"UҼN>4zkEB?8ڗ0B|%M0Yxm:+.n= Më)"LI*%Iqc`LCRk tEdLQ$mgAx*/vyuKl)*+ۂ!JiˎJ8KT `>ߝN\ij쵨.gЋɏ(c3can@8f-Q3'aX7f|*W3wEp*_&>K3qsxUUh FkXss`٩8w3hdz`HWw/4!o*YZ( #0\ _WqgXt-,'ʤ}\|Z6ÿ9L>X'I 7 wc;C+&DiCs :mZ쵖r:_m"jyjB>;O4>nYiψCG Ch믌K?:y?P2 #؇M*y`S&TP$.y3}_W}s'-3aҕ\N/DR~?>VjO{Om}T'#ۈI"/hYYSW"-gvw]=' TUw3-ѻKwF g˭k(EM(܇/O{4^?ĩ)(#8S6^$V)S|riE$l O%V=iIDATz7J  t.vOkb¿9{g(?-g0Ŧy։IBE_dAJy^=+PoKtjuQ: 'ɊvL,Q#OM(ܧ|ɦ@_{4 R+ٌX8E匍&! Dej65Bzb-ь[ß#{%Xq E(e bWFLX$ЙGbjHXO@g%uh<^'@MCc1P"P 5HM(ܧ,* lQ|+nSG>\hEa#=S)_Y!)>~tDgs8g K(HV+YJS_hZ>p_F@VלAGIF3qa+ oc @7ߪ5Ը ?|[~ZB%£KEY4 Sע_ܘ?:ՄS߼+c,ch(P r" Wگwmo(Vw;QXhIKVI&n{I#ֻ+4EyAXL⨱ԄBE3MyMf_>ݴ#36(JvKL`$,߳p-pJɄEO%3j_YhQl'O뼚3/vFը |t}v8$͠c(*jo;C!'NgإKŊy$a tVu]cxQT bգ [Y 7ޓ ͨAP5PQpg-i{f`TcY}7%M,V |j}R='`XBaLopNP 5w 859\ەN!kF5R,te%zq  ͋@M(X7h;B3%7%_b^XbA9Sp˹) !\|ͰBM(ԨQgA,\G ~ y)/&,ָ 5jԠ&@.b~i.֢5g`u끍IENDB`qml-box2d/examples/monera/shell2.png0000644000000000000000000033607412241175670014571 0ustar PNG  IHDR".I IDATxYd}Z{ݵv7{aHjrbǴ n]oֹC{ΜTģ>97z˥^5o8qe!OߟfW\v̯y~_{t"7^7l!ýt9?cHۿ\Fx"qszZ7&ugX%V!mL{Z@H#$򕏒E#9^{|39CnP%7^!¡@8q?aGf'SXDHL^"pkBz2pcZy|h7$Zoٜj^I³H|4S[M>z{HK/yC>x—qjI!VũZc{h"@kȻܺ_<ػx2p(k_<<ǜ$(^ !:&`.Z@ts#׍$S>F0 fid"Qa/}zܑGwc* =afȜZ!Mh~8vY\|afZ_+čQZQnBHE.ۗSbv80a' պ0 w_"W~7wyi;gZmq&xQn턳Q| .ʻIXCBN[@))K9p6t"ZH}9n^;2غzs'{J-/OTi΃aZ _ͫ \yk tO㬽珧:ZKp=k򅙅CXHfH8j͛xe%J$|_3<>nKFPe'Қo>CxqOWTe:3T tO"1qݣ<6Jo -7eJp-y!q-(:܁& G0.>p(xOD s!^rpן{ 'pD 3TqZ(ܢV_cyyJU*bCfG6{ [ҧvR*BZˏKkg'؃WFfFN#DQ\<>?3ѧ-%1¹08Qg6_wׯX&"I8Y@:>0g0 7iVEn/b'ur.c sz[A֗&PRwg1B߲Uv?W]Yk/gƹs__k$S:4p$v E8 @2d2δ9?- ?bbs>9㔆PA7ѱ?aSzM".YO̡6?fooYaPwwi5FGhշ 1BX1 +?oJ})yQK=\lY@ؙ`|'Fyɟzߏq.~8Ewԑ!Cm/:uosaVG'`ΞuG/Qcpoow1H+kV ճ#{% xC6܅ C0b8"JٻfQ*1,uM +C"uţY]U$SX-`-GbSȋpbX.v. 8BG8"=+b a Hᬢݩ+DA}k &v&}QkZ+;qr%vfծ+,UrDEkEN] pLd_ ޸/||e ^w_M90s8bΗK^ ^')긁 2ZTX>,WGOh*&BV34wo-۝㠎[<5Q#nrPmJzHD_sչaIvv(͍sl_XgAxfFt(2tkJXR& lw ;r%쬅a%GI"A`';Ģ]MP%_Z̙xEb`h8 E܉ .]"3 {h5w ]+CkE d)'`3$*'}8nQ[!v!}^AiZ% Fy;qUE9,{+iǏwf4t]``Jtvv&]Cӱ\s c.G@k~_:JD#X_Ss#Ņl@F`e84om f ,l 6,;lj3Íuu¹叚 Vڹ閑e=M벂dGZKǁ8؞貚7+ Lk_"Szϫ`QXEJY@mvx'E|"66k,*0|!im~~Mڷ& G*$=pװ0 | ;^IT{;q; g#Qq'YhTuYIogcL+Hbo0yT+AT=OQ>SaIB&7EKob%ѕXݟyܽ*N,g|d.Uwgt,^P 9R9tNbd !& 41ݮEZ]fwcs(O]e?9Eɹ(ҪHSfXJͭ_9ĩsfg.Df: nʧ?}YpVaH9( qKBU# Si.]̎\zf7;lȭVro>Zuodţ0a"=9##W0(,"b =arv$AD5L%W^z v1, QKNy~bhWӤ36xHn#.qX B}1 *"CԺCop;VtV.jߵ9#إSbz'9is7qXD+c>Ҝ]xAn$s81lN;ˋ $ Va LkDCnIbgNƲ3ǨVR{XGMV|c!3ߏю-]"S 3sx@)`y踁i掤[?Bf-,Q,+i:Hsbfcg1 *5D<-'CPA1~%S G&fICd ,NGt +.-Z1m{]/BↇYʑ.#ۢUHU1" .Mu"sfb:;Ҩ|}Fȅ02kX,!ՙNTvTtH i5ܻ~[W^go{ tZQfm^"g6֑w"OQ\S >f{}A)J`[dX=s85k ;I|0"ҳն^˭<;r;i9{Z#r'!/ԪB`1_XB&[7D7PZr(ݪ$30d:>I v,\RƮhwpz+ԅ͏x+7ENNF2\yKB >GH)Zv…Tr%NYBaG~nEySBv6PXHOHbUpDat4.a wQٵ 4L#G؏+?ifLh7[vW_߽~ssôK=s_Y$W~@K<:+q$ƇCPs㈙ |JZI n9]C<>19JyyQr{YJ')/&_ޡ;5J!r ?+Ѯŧ(>9[ULxa|]ӠU@ܺI\ݚ8V1^\F1w_Ú*QMޛjisR E@d}G+mYBhz2Tn}LѶB iaSZj(F sQ&G#qQiG02kWtUnz'ş8tS>2[e8  7Ό=Wπ e#zAia#蹈H~ZƈvQapecC;v݉6(<̱z? iZӥQH൰aK!)oD:{8 #HT%XVbBۓ9c8256RMxX;VaW=\I}H){3̈́DKe̅{QQ@Ed‘0Y7|܈[7(43 I1Sh ~ڤ>Qwڐp@+4ӵzhqHΆj**Qad~kG0/bd<{\pqxhCdTJf3waDiC#U2`o?auL $p-]rYSdU iYOs[8@:) ^ #k13~? ը 8RM) jqDcayhvHa}Da|r IDAT61p$G9XY:mo \,GYW SiWr2Hs1;eO+iPT;4+#[^wj((9B1ٻw<_9m4(pkƴW{a=%w'8D=q-̅q5ۣv/03׭:D C ~tk2rLnyS٪WQq<9ARa}A_JMݺ+j(~\M~2*h?mUFXED-R$UnhdK+d+Ld愂Q8Э 7n}~ݫGkݫװxaz>; Ι\,% i'1Q {'#ٷN:>DgHäxݍke{YXι]tK3O -lNծCu|YMBa҂$De{|bQu#慥d u+8g2D>D-{o=A^mZ+jwG˅gq|Ƕ`ޢHnfy|oG8^ AZmAiuu˝GX8T_i`8R_WZ):Jwo5/~`LaA+vGEZ$(*h`fKXA@j$w̖#1͈N1@|U*vY̦h^E:H{iqa訂+7=fxaYCSH\q02{|0U_%[h5kwu4ͽ{ضfQ4y!s8 ~}w1MͤPX&n7DHPk<nj$k&8K&+>KGNUptι\D?FQ.Fl2Ʒ;s KԶ668 0,0(-.[dfzgh F؄56orܽJy`BVsΗKbo~|✹x=|纚HǞ{LQ,#*IUg셶x]^Z(SNؘ zaA9Y7LoMVrܙ|(dMN/ꘙSi@6׽(|Bv҉-萨Qʏ;Gܸ;?$ n+?{ݰllei;8<M"6Vbr[NUDؼy~p&G4E`TSuAЪkNF 1Jz >ޝՍ.->4;3ʭ5-ʯn|O8¨^‘Y:Ay {id{N$MMMl]dv*#USs:Dy_k5E:Lܙh,74 FO:ڞ:0j[wz euϵ/Wsp!oݣ4eC-LPPmKdB53ԾZt?>sBT>шU@[v[LsApzgv7E< ;]8U7Px ^k`E_Y0,B WO 74ϐ/_@n]4Tq]5H~iQǴ'~poLDLdN+nY˒8ΰm9I@8ڣb.3K;lo\=WšؚAlǃk%mpR\iZ(FyB|c kD@u4uZV'pgG#ABdq^sb*{uhwG*=^#rNn]~lw#ZE4vbrݴ sgc'-gJ鸶9q>Ѻ*v;ߝa C9*t!qDcjinY^ߺGEiqEUY˜m QMk2Jlj8aPq&^Thz(mc_XDɱpQ.;cLey3[DшNG} svv) n +a1XDbY/BEjFHORoQzlSK&QsDvS<*J{WMl!v$5q ͚vj9L+Ff;gĉ;o~H1d m6["J~Mν(- cJ^`fu>5!Bؘ΅Sc cm @ny Av{97/gwF5agP7^4l {ﱟd8 ]%ĕ>as:2[BJcǟuqb8kc:wBn I|4 U0@ ZM- zX[7t3YN>ƽ4uOV rZ8 ǿD2)ig|S->? a{,=Caq#In+a?Z[L#\s`=wR- 'vH+Tng T{iAxD0)Z[$WOEӬ>n $ #02H{TA&/" 6rթ!WFL8N1]Viob|o\E0o>к+z,~xyՔB0'V]I +{Г2Q\':>Xh@~ =>&\ָ;ԛQ*DErKϳ?0s:bNi+^"&uqf[:4na#A1S)0YW}k}jR݋x' t ^]_O4:S7G_cwڲKà8:/yE.ʹ9cJ443X(u6S\Qv")tcwڏYGsf_t>Mf#έJ ~Wr/??jF0jMj)"a$Pkdl3PJHg,̜fߤq\71Pj4Z>ZeGwR7Ѻ7hS O-Q30`f 8F`6QE!q; !ѝ;m5շ~ ZIv|٢RAb߻ N> %h*hI֩}1M`(bE֔H^QJP*"g<-묥:apIGՈCsosժ)PHBdm'Cq ~s0{\ӲRNZXY4 ɨvTN|Ns@(NZܸTv,C!l iѪmP>Lz:%8Ҙ8ܓBԸu-}T .| 򉤠yerh/;qK%qObB?rcnDe>М>1 B2P (&l? dT1.G]@(Α)}i{W׿i~Jjh&3" +'8ylwUj5ٮ ġGcwV" S`0Owvr-J)"ԉv5~* ӪICU;דRb&2 ߱^a&և= s3<0P)ǖ-7 Vո78q'(j$m֧aԏ7n%bm86誚vq7x*,Kq9 ߠ}WQ*&]erl%}Ԫad%rr X4 XN5:%@'8h{4 r }VH08 #2:%W:m/T6Rbݠg8@}ì+.}6z  VQ"S7y5Rյ{ 3ox1@Wz.؅02dkM޺ƍotia4Mu\ :|ۓ7.e5+&]wk`c.nf ."V@8w[o>~{QܽpYY:a//u|hF!ri(@`5_꟰Eq ի4' rŁ~7CǑl"ݱ-"Vf`{o"1͔xBlݿFJ^p!ɠ-A&Y"Wo#F_> }o?yPqLi,>7&PZIIx[eW ƈ5"2|o֒O"ؓ*$wVE@.s#NLpMNa '*-s0៏@R*>(.ZBX $uQ nw9=VOa "o`C;wiTvxj5jvl`0i=[:kN_v_j9#CadOa>U27?|vei QaHua6AU7gcZ}w@;Ie nQp6w{O8:+Q,/Sh?tع&pXا|Jbz 5?:D!0 I+x$.-SZX?Nh7Qqܦ n׶JaX&bv.QkggR_Ey7b3 mcSCH'9Z ^Ӳs"sF3{mZ&O>Q8epFlD;GE\'n5ҧ};3+Ld<2s :nd7$*^xX߹E>?~i:&׾ '_,kb1r3yWNb;fH!vo+02I3)%l{_j:ihUuXןggd y\7/[c8nWڠUc"w;v ETt"NP ^}:sHa[R>R8NR*Nj>*3$*hzuHM!!S3Ŕ]=]g+q@ʱVg 4ĭ[QwUQbz"{;uε#nV1isBRX:3j킃4">Ax{Ra{so[7'_\$+ UROB#7dQۋ,Z9vS4*~c;ߥr8SHIT$S,v[iS,!tP!l!jШū'AHz & R䋋,"Q04*@yk&aA]רpܵDQjOKip³6,N?.I-cBZ,!6Fԁۜ8cM}5{FtC8 nL./s ;鮒+>"QtBzB*Ӫ^0ٳ}"͎ cBGfl>e- i_8Mmz_}Gj٭SXX4{Ku3G/H(/,}F_R1M1Ahwn\y~4}Ke[|tȋGE $תٽkNYJE^_?S4atͰYB8ڥU.u+OՓFͽaq?EfXvSs4Ȗ֨Wn- aOrUgo:VrgJ ڿi V@ya~d<˒ Ed-U l{9u/dӕ#ޑ>OWvabz~@eBi8eWMDqy$5BKZsٿK|Ek71HHZA Ew?$nnD&G}ACzBQլv:Y8Gvyǹ֟Rl7ϱw,Xݕ>^БRbX֧rz[jQVn!LLwx:^>PB On##oo5cمv ^MqX QۣQ4%&"+XNEg."a1v2i´8'f Xo.pfz3Oh߲8R%[^=f:QSٛj,SΏ|]q|cjT+urc*Qث>Q.U5 *U6npX|Dm>77{ Y~?Ns:+O]"t@:FwU@PON!2X֧1\oaJ.ʖ{C0V9aW1, H:v+aPXhEױ/jWCNP(v/A^"2*`{6FEM<S _ꦯVcٹ^/4-RCq^ C{;7R Z^Rre!f,.K1b_b$ezkټ7^eO8\v8Yz9&8: O$ IDATn<>mT6fݩt]t1v鳏D8 %ڔ`}\8ؼw amL:BܺaXj^:&X;p;s^{wTQ>"jm]'nnJcP8oԹqkʮ$עC @͐Gby]Bˆ~T"@ljX?' *h5G{O]!˫+Wo{ةX_رE*7Ыޗa׾I܏ϥ|Z;z8*0f3U;By#\M@ATOܽi$y˻2뮾홝9$bH $$(4-YA `-KdEMRI8vٝٹμꪮkv'bz*2{>/Ro?K5~([ [~ؗ8Z@㔏( pV|pXTEq}V7jd3}M l+P#B Dt|Q^`w"ˑï~s~K$#'ί7 f(&{CW␎mܸ$2O,.ҟ}wp>hDIe)}kqO6NS:/*l\x$^5w*P(U?Yfs rOJ L-}ϬlP|pA\m^GNM 󼹹HѠXZ\RCǶw(G#aam.b6McX^nlwlukV7Y.!R%`,v5y+s﫱<;|Ł6C.S/|c6XþUZF Pw_A0DYFWOym[=Ml~eEo'y7sѯ?_KcƦ՟l}BRY 1q& o ۪ad{/z&5]xSr͗\\6i ;q߬n..=\Fo AKQ~'P A4;Tl lty7xcMyo Y rYL6Va-dYBs>Ǥح[i:ӧWUs'JaӨ,Ӫ?3Ǵv!iF;Ǒ( ⾫=P:&:V{osɍ}oӿ6yDw~=or5FIsN1 %8\vQ|ghfM}kM"{d`ZC!5ӧf_sRڸ"u #9PݺbOHFA!A+^z& \ l]Ea ^(2=to5O1(d%&J!F%{\e2mfT&S007WڡԪBVD_d-;t̷ NfM6b5K~\- BOHʉϰݰ6ʲUjG& SAJB;G5 'F/q%i\_AzL /kSQ$3bYIIj%A[@׾Ƌ^оgy&"S5F~ح/!#aNCԺ=T*%Dh u@Y3Y.J)d%ۖT}s`JLaяM&l,ʕCnJp]o(RI7zn8OcsW&ӊWJ\Wc(1:>23(ZT7mom7v"t'y8;pT: j:ߞz&HyH'I* X;NUO%fuU*Slշ(vC5^T_vτ>C@ϝ|Ͽ?rAk{ aPoı(NhSЩ+"׿t9?z C5<<{TuUЎg<"(7CThT^ضKusV86B&#f ^!Hw}8"61 ~++wpS$E'](0q~^s gfkT5i=sr$YRvw˞S)U]QuBuiG~a|8vpo|/[-HCDYE\Ed\!Nv w l|{[2EDGdCԈ*{IܥYypo^՗^s\ŶHx"OHkQZ+m/~,I2Bzē V:aP./E!1z^1 3 2E}m; {26I럀!6 $'vq׬f|#?8Hm[m\I1%q1g%A)L^DM$^'JfFzk'm}j)2qj4#OxN\@VmHVytGramxQHP x@qL0F>JFPȕean(pL."dGH'!]?׮t?VR |3qR^Q&~^Dⰼ7:CL4)\ ܠNcI˵f-^+l5 ytnW+gvI dc0;C1}E iڬ,܃W$[vJF0zp@e ƞ`§Ig^#RJg-㖕9&i7wʲB._lzBQVo+>!13SQuR(M.}Q:{}^!"&pj[B/L)Y[Tғ=I~q|tMv]Y-!twoW#0#Xer]92C4B $TCF8ĄŃssFgHQƘ[^lDqd#ҳk 1YV(G0[M(Z0z[L3#<<"k `ca@$kvEhѥue/IJƎ" #*1>qDGd!HNc2.T&׮uJcqjl,~ UQ_ıZ<􄩤/vDD|H\%-gnzHVE6)  A}5=B^鄦clw 5-&m00F.Pl{8 ɋG. Us3H$<1sVWwj*; -xDaN&dJYo<5ccl,d%%Wr"vʠl{Fv.l H1AUe._~_+~\h7 {a$cJ2SOS_S-<4CdHL!?~flVIN+R@t֮6Q4,zpsX I͠_$m̥jL~fm? UnW]XO~; y^rwY]d䱏&2yY,"#+49,.$wH[X.y(zz900 BoE o|u]zkVsVt=՞ JS0iQDnf{WFUE3Z7?=S]S'A؁xl ?r籍͵=;(vX .P,7SE# C*FIp(cvWEB$D7lUvf&),J$D9í芒3/c < ZGBa])yvD!⯂|A`ds6'`dz IQ0kuQDό@PN"l-ѥ&'s<|EFܽ~ QS.QݶrMAB)|nkKo>4ٴy{{]$eɎ=쳿@v~384W9y}γ`!NV0@8D%kA\{=}$MG1(FctctQz3>خqM>aonU9h#S,R/.,^ []{ g&:{FQvn+Гïov0??J`7)dSST ==kzY*"`7? $p# /JEG3[x`ZϮfF%ͥx)srruAfz /Nu4[x'P|ͥDQHxi( 17f{'`FD( aIv#qNCDQ@$4E陘jn^EL#gG{|pcj͠my&4[y-%C3Wl6Ar f mDjD1&fh8Nk_{J#bj.}]8ɅEx&18&fehlUf-qNBb2;<Ҷ+4 p{fE{F>0ĬW0"h{ā=3=BLDzjY9<3OSwc4*˸Vw٬1R p]-nn4B Rb"\ufKk35)gvB}kvߢ(" )yԶ[(I*J?HE!JHKÂy\L8IwͽV-"Jnj6Z4<üMUdYd~;x'8mVeVj6W(Ş'?ss A{(ML41] M͢ݽ~YQZ%% C|ǵVxCJ83qJS&'O_bw5٪oP̍aoUQ3\誴z[/-2L"qN\`tBGZkWGQzh =dnst?2D=e WFqbյ.#uYiTkzϒ2yU`6 dAҳ(i9#L/\QrܽuN_4cO3я8Vok59ab6Zn)?pӰP4dޕXAn!(FQBJ)a7Oq)Mt磌(3ϾmR8~kU;XoDp78,9qģ@D#8iA!dx:ndJ7<kStmٿIP{/~_~`n]G1Eh{ʤDG}Fu;óc( _6ER~k˳Q pQ$YՈ݅lܹj\=Fe$IHx6h./!F>c 95$[Y.:f\0ޮ%IzL荑cZC) IDATdjiPЁЬpԷ*G]! (F'0#R\(^G2(8?8ajF?Q@X[@**ctfeҬV6yXi"{;ijnc!YNMw_pG?7u&$?Vi<@ϟEDN#p7_5xEt=ke B?uo~UgH13:U= cAO9jmXM#gت6VLm%SsLa/3@RE 26yw}wqҨ׻ $Y%[f.8},F:SDʗdΞꨞIAck˘gvգM%.ׯtFGU2]P5 D:s쮥v;'Q\fmsǵ) >ͯݠeqM6-#Czgjm"TaT  y-"g$} NVw%ШUY]x85?OnӬ @FkmAKą{B 4qco <''v8Cr7qM  DeN?ҭXۍLi^yOբ q,f*'zkH\7@\CV0G߳~( ~Et]mE'AKyL\DsώRYMa7[LiZ j-T~S^l\ew}@81LhBۯ&寓*G/ۈ:aK=|C#ccLNuW$+Qtlr4os'0zߢ%{lx&G9;"pwj}]8Oyi `kOid&cYT׭F qQB Sp[豲GNwΗ*| c==ϳOR(u'SI$n.CbFPSiE($gz!VڦH/2QԻ=*iqz\!=}s%Qn%H i*E,l926ƙJr#H~b7TU(fьA >v% |n~o7G=[DAZK!<cţ($@ZpA)\J *<:u^N¼I˩l7nGeF#VW9vF1ƏT@`64; d =q;_qR)ٳ{yEj[rY5d5EvdzРh7dYQ [۪a+ǎo p%Ibd|Axq8IDTj4{-x\Hdu&unmuGy½"JƑy4l',PU*rJYrGu\ugl`C~L=ıS!̅nesƟqvY4RJj"JzP!={e\۪Zpկć1o%wȨ3.DtH` )N+W4QvTxnMgd9Ax6׫,INI$#A4cvEM=qwKϠS$ q}Jvl Da"|..mX8$8DCADa_x+xEKʝi Q?;u¨%<&O= ~\K]A$-ıCO—X 1 ^誆(4)j*w|Pu="uzd5㳌?uunvB|rjp(>~>6гb>_vc{<~*326IZv8t#&l>tqJJEq[cuHv$K\oV8e6)d+AnH۪[=4*K]͏+k(mu*Rcꇁ HrA$sn_=w $E"=lAJt ]ϳ۬1Vy o :n<7炈BV>ٱ'" ]Ge6NymtUC$t-(b/nuqL=!:?w^ a=|!?HcŵŽѣqE;v S"exR V6ES &O9delnx%\kL4ʛZtЖ?*vdci 898`&o7(SD׶Tc}Nrj +v,x*`Nyi4ɗKݢ ̏أ-$z~5}4Qыj0i[sVۡ % 6D0DQR8V uYZ~QWtMZޒS34Q-21N,i>DE$ȈZz_xe|a6qw)"[d8o|3/j}3^SM%jZ HTjPɘvAƫ]}h(L1 ?۪s y^җX[{?Mi29ߪQ)f wC8Ikwc3ӌt5r_nvc)>u0S˻7xH|YҺc/oԩ1S-=A&MfW==rYVyڂ#/.pW3ǒRn(!vhS31lGώgFsLߥY]8#Iq,* Yaz5B 눒gS΍es-;R*gVLՇph56c/i凯2v(ڣQc_D-;eX]5)ov(ãhsRT')x qrx>TFn%l f .9j[&*/IG!{^lu"jWchDQDs{q^LL?M_gs>/}%/1ʌvxVHÍ8!iVV˴Z=-=KiDa5Ql2 pv@#/Iidu-/2;Sv!+KLOtf=9ߑY0x)$0E!"K=o} k=߫9eN Y%!!}c8fͥAP^.GQc+0N׃/ɍuǀ#M_?! pıз.]P޹_s(Q+7͗=>ԩFF#uJIw_بY`7y/4M?o|cԪKpiw^-n Lwc'1՝"f@T.jKHx?@$Z 8xMjI i44[&ɱDeđ( |?D "ZDJ$Dr!&ZQ"](Y%Gb./q@dy*_!FeoơNr<"A,8܏X}ƍ8N䍂OsDRw:Z)4[cZ?Q?}oo@^~+ :Bl yN ~0C!J rGy8 (mdzolVJos6^[MDB.q30IJ#)mH {>KK%/<ғ "O}Zo4udY'xc@7"K2Y)*!)ir΂G:?3w^MHV;-fɵ+o\k+4(zcxBZqJ>qtwJ@*3C=ۯ@g$PƈʅFy<; ͍.ͪNh࢚ڃj-}_phpsQa'/O6Xck =ydn04vM2hك t1Bre XJ}#XwħəK_̏b+x_c9 ~}xC0$i('ݼr9#Q z{ nsoݖ,w{'\^/-xOBX;xؚnʝ?o? /FsfE;^y?Чڳ*{KDCvvվ‡:-'Hw _2ftv" ngQJ#C/]NƤ7629&ǣOݓxp{O(ZYxRy 3E0!! q3]a2-Tv?eZܼvj,VVyp^5Eϐ*Q;Ovrش2=ކ(( F4HCU{ D.xHZ@t'X]{vt@ns_QJQ22-{  |?|15p^} lA1MN/!U=PЏ'6WF%}95d֪TZlgr"#2ZJ$V8g2Lϳv~qFQ).'i~&#emK_ɳc(ZUqѣ'N#i+-FGu, &~-jDr 7QRȏNnյQr47f }N.lַ-07.A(xu*=y FZ$qA츈z<^B>S#lmv{YC]nR1J?81Z⋐'8ncr~׶ZD*"!8 I;MQg/??Cnaz2^Y!mt[rQBh5 E1[̝Vܵl`Lvw+!0ds`M/ I2Aн)|JH(09g|,ue؉u=nZ& CYrctDZmA"]&>!Cy(#Ddin=UXW.pX~Àz%kQTjD,<bks -eyN;rmZ_Q?ϡ H '֙ϻ=OԈ!o@bƎ]-47CY~lYFdN|l!|XE±v*1S?ۿW%^LWu wqRȯ/8*\&e޽G ^A=ѐ?VU5kZ(dF2Xu fE&1w.ggr}w0 d~t6ɅAF5wD%#톦cޏͭd(ߢ(+R,bCBjrfc7ndvpcIlsfTQQՈO+ k^o)A퓠Dwd?w/л)95w<85bf馇8$(?_mK&ތsAłA6cz%) A!(#7ktCF-aI)W=J'}XғÄ(.y{&[LNx. WfjGZ2qj8Iދ#N ~{$,RH%RQ?@(*O#4žW3>oLL`oln,cn\r+lC} y,k gzdA *!Iݛ) ftC*c>m}2#/" 8zQasc`0l_kysx"bkG$V@0JyfwLO g uǩP-MNg2l,cAfƂ؜|"O|o}fwj@4{s DNH77YK7Y^L/TLLo{)=A&pVyLC%4Z~*7)o48,GN[G^8\CY"tW{vl\}^?o>{JJc˦%9=IDUϣk"D.9Rz|reY,2>GGwM"w)M ַnYK=![4>2F:f ; 7soUI2^y0p$V!iPt05#98V6v;F͵֗ |_~͘8QFӋd s)5cOPyE˶gESO#M\@Yybj I9(D].("bzКhi"S8d`yrځAhct@yƟ|e<왅Ncb? uŜ[/umw-פQ412BrnL! |jovE)ѵHX̵'oJGǹ2"3ɹx}w}ʹ{$rBs&-"JJbTM6W`6␮ JN?Zjl@U>.ō )(iHWdǞ~V6$yI m°F}-H]B /8u!#3Hhn ꥾ jć6~G韠"jۣ0ZS:dclJFıw]HI:>{rxswX"'DR"A"$K;(aruuŪ;|v]*Swe'A$ A,lxþ9Lw;7, vߙߓ!5z׾5ĠLزgR:O=zЩS]a4=rk66e#ؠfl(EekPg&8yD~DI,'&T}žfwxmo}utZ{dqCKM`\ca=Zp&a"Q)-n'8Q~-[x^Y>8XOR6Gh-mEԝ13KRVShM3i+0t9_S}"4'NNoV#׾>?'yuuR-%GG"9:(ˈ)e8 _Bj(E> 6ɿ{$k!D{43o4]֯~巿J-haQ (/mTb۪T:Fv VO8m.Ү>绳B>fzbF#Wyyq8RqQ\o6 Opxe]ӏ7^ݐdq4==Ls˘0L˵>ŦJʌ4Jxa󄾍HҕiV >/cGV}MVѳgRU>]ч(*$3O޻(L\N'FwCx^%qO>H|T-_ql #Y-R//cUoK{0 ?W__\zp[$5IENNwE?h)2 g1uOmx+6/QټFq?l[? 9'敥 ,v>4]O}˗ګǀW21[zۍZHQ䆎eN]$m$Tmmy֢@ai ǩބ(Pm=˨qǝ &6UK\x{ܺh!?F(& 1eC!%p nѨ L"lxIޤ 7ۉ=((d"Q։GDȣ'2E8XzjըSYtP|E֐]3(ZхV`:>!CH8Bl{D\|@hrg5?a'raH{C5>G];ζZdhxu̕*81bS0`-lA9>K*ٝ豦ƌ}xӈml`UDCt*I!){v9E1Ր4 Rf9s'J1EQ'iþ?Zh 5@(=Ǧx_\_ik*)xv+TC㤇N2(j=-Aj.jr>;8wNwoPٱ-Rʙ>$+2oO~vZbpZ8ԫA;s#S3=f}_R]X{,L6HRNCj@ZiZm %hc*H$|bG5{A AQ(i=(w:>G{UҴE1!‰^J䝟d*Ei}Q50p͵zD:zrMӣKmݲ]]€?^y##x^E_ή`^-`K$HXD$) ,EF~Э!*hHuaZ펟$T*%,GR#Qx_~k?m;2Lx{ճʨԛ$iH|߹z6~mZ0  HD )1 )Z-J79V@,%BnRH/3w2OObt}'-w'ekcWx'2T/_dMeyٿϻo͕fBƌ3I|>d ׭o/$+z'=BEDrjyWJr;xN骐K9=%& 6ivzx|62E; w{ag?uw?ZOTulJl,]al<BXG Q!DFQ߈HrcK謃WQz3AT _'=\S_GчPFX j*o1 \ll I2XۮwD>AڷuDTvII @ ,/|ڞ9fh-0 #/zA֑3cyuLX$2EVG16oLsrSخ¹cܚ}HV3\6>'OO{vXGJ )*7AR8ݝ wwDzNKْ|ߩ!UB5$i V[s3gp{_Cc$s3ti.X"=շmsSC,-B` :!rЯ.n79[Hr@TZ}=1؅)zЇ5ّcQxߦnPUn]u۝ADBEui G&܊1:zAT }E [ou_~tA76$Ywq}[?xQ-jwM (eCo`֢n~5(#}u{N@YQPUx~@bk"a(d{vS^+-_>>|_x^A$mj\O=uWWpV3w_65^/~! sX ޑc܉yXY\DR2aR(VNOrNva\l_IJ65Z=䱧$,"^$ɧ&"H2uy5.=(PcCr౳G AQSw~QW!&uQ!hejk>((b_z}p@-DF3GZ p ۫8Զ]gvPT V.x-yoL4x~Ttko}/q1<:“OG)gqrUxo#"2Ć4aD}>Td0Vnru}+-# ч#oFKW)Q`uBg55ݍjo7z͂Kfs3+d2:N>C1f/d FNu^˸V;SEDIS@'%{Dh2/7.Jev:SN<[<įjwRY?~8Yw}ϼkKɫ6\]^(E+H%bev{=TU-a8v;5 e|o_[X0P5>zǼ%z {[C^pk2;hlg9*}A#6K~9G uzGbW@Hy @ܭۍDiho>d Gn}PEXRAȝkP`F}mqQs]{DY_ Uu97cPX2\rws(F B ?ЇQF#Pidv-֝NRtj[E:E8㌍oD!7qm{T`o|kwp;F!;F`mߧZOO$ے'ʢq$) EeI'K>IrW xI2\<}{ؒ 5ssM7~qj5JY<ԃ2W^?}1z)t$''w3I*q 7oXs/;Gqx%>~hm77]`35n4 1pVQ>^D" /9(}-Bd`R]~ڷcUG\XA%%A"sz_%3 +WA#$RV|q:Lk䏓%ഩBj$fa\pw= [,ݚϽ|k7/֛%y}Z[/o wg>[v3wDo[EmYKҥn6)Ėfw2MJTp]u(j:La6/W^"#A7_b7d-h"U*x_ĵq=F\C"{ă` } vX}-FS$7UWwu }j>WWópbЃ;zY eBAHO #v`!gZ^KNv-'2_%#(mwz4޺qkyʊN~i(CbTS4F7(?\w^T:y [3`ZDv GeV5XxcaB ,34KTǶ=4i(zQvboܼ.[[X_+5pq8u^^x7S& t~Iw.wl +SCwclGWgQX26W_DDIn@@6{}ֶ vz[9]EI~NzP^d-BIU?h ˜xNJIij3cQǿ'P; Խ-u:!5 bs8gEyrP*HZݬu5.pkԍbTۨ;y[ǶX[Xf}af>Щ ADNO̓uEenʛ q-.K[ Ñ$?C~gx}<<|k5*]{]IY=.HϳUu0ev$G-²zSzc1TJCwzNJo3 xoH|Y ڦ,$Y 9d$|\Hrjr! Mz1G=׭)-(AV7ȱLD!fB-B"y.١(j,r@Fbh\WRX밴xٛ*>9iW,5#QybC# ne4Fǧ!2Po߉3Y_]beVzSY'sY,qkv~]:{> H:rrKEa5le0y'zRt]{I>ĺ4zD*Jn^o+ Ʒ7 t#cz>W[aFlnvUm ܱZ߷Xg?uX -$*kTcCHvA)zEAķM-#"kҚ,˜>w[VIMoI$,&V؄}!Lq:rbs9K{޴벱#Oޏ|QR'=*Uj]_DzC Xpv9Q(d.005 LuhA+Gs}uLeQAJmjbxXW6wW7|/@蹘ufeT{GS:MeL;Nz< ~Us>}oyPb_9TvQ$9.?D),lpˋT6`O&6V$OH3?<=?vJ=' c|Oǘ>~t@罵µ]m7ܰiJQJyAҧwCUjox[^nDKrfZa% Yʫ]@~;9u%!3A $k|޲O Ј) 0onMbã0XTd9CuDbTXAkhwdoD/+:Mauxt vZ`r lzrL0jť5b1t*AYvU+q0ZJqo5t6=ێ(l~s`d| ױTt&͉xG9y4#Ww?O߅{(.]7=]¾r:W8u M?NЊ~ µKlnFs"gUIOה; vR*3iDI" w'wb|s }D1 oUz.],նj~F.>9$GΒ>i⏾ױ&?^}OCd<4A}1ډBR=?Ak l )u⣣HZBb!,BN7{3@xf%V~yX6{^%#XH7EdZhe-k"^k;7H bn̟Wq&ξI+V-6 gN%*Hʾ^ft|6pFRE+Ur8O~  N2 sܼ* + DqDZaT)l,񋗿:4rHTFc}٤VsH$T&UAoo$g$P&p] KdM!"[ERP,!. Rc͂zH*8ײqZ[eX!鼞ө,itJ*n8-]GEY?8׈uTj'>7IųX^`ЫyuxV,UKd:;!C%, 5o6W^.w_1mbPI_Y!N~J]kÐyHŮKg3uXUM 4=R.-Q.-Q-G.++XVUAU(iD-qhS#҈ 2V߾&LzwSہl~-tfHeTLmcKo^iDU2+ N*Nyή粸3X- b[ :{n'XA(' %'>7~j{a' 陲j8vzG+Dz $$Ie%ĮU Cշ+Ρ .xXKXV uD j,*O(ߣ?_a{H;6w,ٝ! V86B 9GNdYKqM\ex3)iIFG" ~i )=أ^ae&F2=QYZ.Q*,p{/e;lz^ОTܺıc Nc_(w+2j> UJ[Sy&>;z~7p5UWg,'|iǀm.%I*ʱX[YFP 3T%ȣEbl(;;Omޘ7 ]Hn"^e9}il{!P " yc}p6o6 G"JlK:U5 k OtXB7F'EO!*6YۢAֈۋo_fjzw87{ = -]n;L5 ؘfo5VUA`5ok}VnAS$OٝVbMG"T4 9>ʉ!o7MF !%?:G+l5 -cDTECZ|OC"i:vn#3- <H+.j3UYQL$U %"6!3w鳂{l O9}mυ*,^~<@*"[kXuCqr$醉ғ 0{stnAޤѩӜC\߶=o{2>fu֫|}kܶ*yZ:5<Jv A#ǮB 8iRոv"g߬h,*vJz$-YXiO;nmp]驶"U+a:ۮlxhdEE5BՓ;|};ߔe]ɎuǵEַX[x^B)mi8ǢRl<>R!.f8ddSCo(w|7{◆ƼBY"3=jg \Qn{s28֯nu/lmaծ u݄=mwMZ)w6C س֡j1?@z˩Q758w80 #a =_ۍЩᬿ6FyC޶pC+W::w`[+7\XAai ٘_euv**WKX0jT+U,5mʤ`>cY!UDXϒEP"3m8ϩ?s(>azmALn{q8QJT쐞92AFis3gw67Y[Τ*{DX[$ C<)8<'aGa;!RgBCa~8;Iϴ=igŪyü?|sR+o:XhjˮR(R(*:0u`2 K & J)NmcHFƣ F](Fmzo j8f)9Heo Am )=3nECeH'pLF0nijV!y%B2 顉c/*S{6M0AI5 Ӱkn;ݹu]VWWkxS'yI[) 'Hw7S`ej-Ukun\}c'v?ώ4Z HLT}y"`~QSUJeGxOtw0~ruGyOt"_IDŽOߏ>c76P,b(z~|]bl4O݌ʫHesyEgc[U,630>9*A>WY"<#;_Y.@:N5? Hb&54a4/|~?94I?|E$I9OOp wZQE6 Q+rȚ7E6p<90@U4RmIXM{.0wCRi_]ůmy &y%_qj(#w :A,k,߸>D"'cyf/v6Vz}zj(;NC"fc5i+Wm<\eqq[mF{;-D]zc0Czt~P+oRڸEicqyƧ14yRFw 0!HJ1\fZ24:׮54? =iFNssRXzg{8HN j꿏0 pz4N"uHt5w(mRGa6 {[A b\K< M6-MmId'ȌF3 '?9C\y_]#SgE285o׫XNZJb%DD"Sf)(ph_<_#c6͆w+1 K7IPcͅstHvϮ+qxaFǶ`y䚆# tYz=Sm+IV&4mmc /=L+H `KaջUhoGǶ\ܳͮo  CQ~麀\ { !b K9{JGO?iIR:Gq #C(jrCRigYҿX3[ NDZ(m=7}evykޛI}3s{fzvfwfvwb0 @IIe;HmJAۂ(ٲpChA1B2W%awAbgٝg>>􇬮3gDLLםU>l/)r~ӬsiuꙒS?ԩY23u!L1X N#Sk˴AJtրG>ɾǗ׹,.Ls6;]W1 B!쌉ei;\( ;dso4LTVh 슞ĵ8=cn0QܠULr)JƁ[ g[H~Fo-{&y>L=/%0Ο8RGAAR)=3 7C}c\M a@C$+,^x=ekmw8 $U8ZIQZ1 &ӈ`v@wGndt9(qךf033(J8=D Lk88,ey%Ә3}Ӭ<P-̥O} 8x7|:$|Nb6\ \jBRޝT+*+w)ܺ rPd3K+L: 6OZM{=t.Ĩ.fH͞(l4k3 uv!@ϙ>վ^:^:8wcqPY6?89 UY+uuk4 sEBAib JMɠf7o $Jȕlo2w*^x6$zj-1=Q$6¶Xjcv76pX usPl\ɍþ^ٶ]N~ Crd {dNUeobwsX[I779O "KYCy??}#8'J'?k.@T' %Y!vg9g"󹵲ɭרASC&@FUêqÛG!]z ^BKPiLSC6(sHxn{ Dq`^سSBHCG6ӭᆀ`7KǍoh4_<ǟ;y#H}2h_B{sbQEKtۻDQ <+sw4Khn!RjDit7kX=VuHbf9}ff\mtF!szW!rAѴ1t.eEeM٩9 gzF>/iI|%_G,ӁP1/mGNdOykqL+m"!!j3&!U㵛%r)s)Z3$  ]9 fY! j"'l9k囸;ju߂![$x܁M\|rygu$q4ǰ-MY8>oq}).\"r8 b_hޭ`t)/]ĴZxV1jwd/N;Xyl6ی߈H2y1![@V T=BP0#1EAQD2WQ{-,0ld9nH٧}QJzT2&/#"=i8yab(]F1w`Ra8j#7x GQd߳Q:ˠ0 D~Gk[-J{虳n kxw@ K-|7od R,|3#}2[wVxuM[-L4E t#fHe #Np*##߁'SݔJlnXZ8Z]BFq ܸ>;GAБ K.W`!7=(I]—5€0 D=;v5KgdDzh]n"2fk8!IR_$ C |PDQU 8Q1f#{q&ߵm Ckj/wߏ}BT_~*0t#0^I#}ZŽ땞llnDe3$ TE&ϒ -̘qR!tl/Zڐ|Ϯ>O>(k @UUf4S݀U+c[!Qgɝy]oNt_?߮෶Y²ȭ;P?(x{X^fyaC}#x Hr7W@{t! / DIBM$qb:9߂#˴݊vkwVX^qbL&Kucn!X#J*jbL]xܹŽ Y2$źVaYU]dv{a&yr6"a,Lޭw+޼g~?9J~^G~WlRDTi6kJ/!0fv\cv*{b!2TT*R%qh hU4} $dH#IDҤ3mը׶)Q4K F*cܾox^4&CqXM$c!Hjj+$kn?AzAq8O!^ `@I$pZ/4l-CTsH$s2@uh֪4Ԋ W*XݸSS:3O3=M@)X -[04T`IAxm|? <6 {Q\ ]쒍m6V{(=ÑA@ݽGG8/S ? _dfAA<~4`ڏJ[-_pwesxDmtWH"^*Q$92[MϠI*V{jL E 7G PFF1 G+E}QE GPC bGx~\/M~iM ×; 4QDt棰¨@-<OVTS3dfXxX&٢Yy.)KOS3AGhQ,ZܭN)|3ɤ0MӴ"H.5bBbGΤFĴlr}GҕFgp; 0>C⹋⨚x7n@w'_~[%W?|xG`Cxvmv{U0?GT1]Rx(J䦖%D˪t *t'JD.lb((y8i11YwI!8Y89?DU/=7K㾐Gm9=ͦ>hRI$e0&j?y3mIGz0|xﻷ7{gJr}%.^;tNIQ 4KŏT;Fi8LMȦ ݽ&OGV԰HR=dpQ {;]hq~=&bۊ?r"?{Yu|!C`kɭk~P 2mOvf}Ot!ےTHqފFQI$dFM6l$l{b ADLO|~*H2!kt}oϾM 1Oum 4! 5#qp' 8)>0kT+yXf`]˴i6zo{٩$Sο}x~NN50o.ՆL!E&9<|ӟ;mS:|N>dg T/S+q(RAbO W<3hxSظil&UfҴ*$D"jA,;E_$k Ȫjh(ډ8& q~ͤxU%%QDDU*v95YР*F%bX{Qᾐٟ/l~`Zn(#3s2!""f9ΗF SaHes\yjm-mYlms <ֻÛQ-5B6p*&{[;e?8|sEzPGRY1)2 0G5P@WHj1U;cJ<bpxtXRUϏBObJ T{dRӇ]-K%RfyGhp=^$F*!ru-d-(xv Mdn|Ea<|B?/g >KrɺA1 j9MB;Zsm{in/'q_C%RhT;DnLE1!)jUÅx?jAV%B>TW*8Rjdb:/BIM$U @0~gkD/̟$llN;Cqth5t-'Q]O!ێخi:G(zPy16V[&[{Rl$DB/A1DUx)jU;ܶ%*VoR-{,zQ@B/dq_@ )&zzm.8ԯ!agkױRW# s`C C@$V[~{Xn{wq(UvF܉ h(B:!S*DJ}9=p}?F/eZonmwKK IDAT &}ٹQS,թ[lniLrKb:~e\Pt"QQJ#~ L#DPEB =AGEL}'͘s pQR$1*Ef3?xhv&Q:2 (Q]?0##W[L_I-ڰ }o6ϋ9*F3QC9rVk4Z4'X( \I 9ڞ:v T*G#l>Av2吙 3qt^&_HsicN'")G+TjT"`P thgu͕ߎ볽WGO̢YAeaa0Mү~餔Wy$RK'hr='#!>-Y+=j9`qۄxcs5W9u%6-( MK Μ=t,D ǶF"# $<צGbcݾڶ] 1ff{ǣZv3XߴyY7>k"i%u*G"`~6"s;2Dơ CjP]KbBos-3݉>\G zG9 !9Iwݮk8(C`A7RMm$I,AؗHx0IV̓ @?1\t_‰vqmb3PUDB'9wfݒMR|gքH!ǹV˻}N g"hؕ5-yvn\p{?>ESHU~ 9ZqhI;^M(2U*)|hr TE´Nұ8vjudj\n0[$OGOH!VQ8ZH8uf]PU CI&c['i5꠶K a*<za~tE GGo_緯o!-wg,--UsӇ{#"!M_1UQ92ɩ(F{CTHa L<45,Yϒ?#mfcI\m~=8Hd)iD9k}*U&h+{BOw'j"3YDTz,wf5sAY.ӏFB=Gò|,˧VNu(?}@2c9o#C&Ы!(n˿Oyg5vj*%2py@>٨+}D;Ǟt$P5#,F?%dzvo]Hh5xWd=Թ)(^ 9)yQc_TdGTy1"ICR( mv2oOBg`li՝[Twn+/lG0v[7㣐05͡i4:oTD dM#4'޻>4j5:{{8mg\۶ݣ^SyՋL:H(L&$ah4fRfFEd="9z2WR&7YH %n&/}kx}+gc:<<jv 3a1PoR`2屧?}%}h( mR!VCK/[XcOz4,n+~lJ̕hN MD,q0gIL-|}II!ek? (MTj1M—/N맟W'N~Sٺ?# |J{p|4)y5ɉG?WDJ$fޑضMqw8볚X\?.jomqeY"IIEg~E"S]'?N h6Q"Q~P *z'y'Y!?K!!Km"I²s6"ovp>c?(ZϻF b`Β[z# ~Ӕn؇h%R3P6o!*:Xu|l?fd 89L]iH$FN( jȉG狂 "=zoO3LXl֑h>t@ 4]GóVY%<\+[CwgP{kznaboPUaclP,E !NHh,-0Ca &vTD*Q]k @Hy_:{nMv] uC9ݍVDgow?d=K_,YYoRlo>04) BQdzdqkw QO5hlq<'!7,lM9 _M/|'n?Qx}/s߃QQ.m;ڨTJܺfGg qZ톮/[t]!v|,;7 g"L6O:W`}9͓}]_HVo]B~?G?=n*z NEqXV{Q4t:уvz*Dbkލv/O~S#Ϝx oU0={i{CQ(h*rbH!SH4!lׁB,EPL=^1&B#$@!! rb$8^@k :Q!%Mf_4*:9F~9 _QҲ[8 -2 -A6'MZw OnK_=~^lDnzL?QVgUHG2_6ا] 33$%&J-n޺owxy033gݺXnߵ*@H@$ѭȴAݨKu.O-fay)8$mXCqظ2k}AϓLt .=v$S969,"us( UL|܁tADu0(.a)I)~,ayhyDUABRRzZ2Ht#)%`<Ln1(OmyVvF5I'5Lv&u5W _&O,|_*=C<:(JNK7خUe]=7-+C׋I2ȪL:7Epp$$h ,֊C3sG&~'r =E^#\.˅cy;\:?? 2cQ)mS*YX\ Z+CۺAKYv Mhy5jS 1 `*U SEq;+Ba.ߢ,hw^?C]ğ!] <4ٓ ]AAHn@9S r$' <BK͢΢&cҊR.zK⢜@2(V-.AѢ9Ih39IO?]ZmI6vƛ ^PHU$+(ǾG; Fcc&^;\Cn=zWY@OГQ)%'5(U~8s$OIȪ"I#Qk 1yA>dN}~Y2K';L냂(eV <_{)JuϾ+Y#?W5F7"R,()x)wJw"Qo)lSwNiL$9Չ;G%?iMrf.ъ-<10H2%!陹yH2ѳz~QC:=79{ J=fv*YnxQ$&UĶr~.{/A{_QU8Xx"׾|lƝ*@vfqO\ς^NE_98wn*K!J Ab4įzdkhY:~S cd0.J;yE/VDԥu)dcόHbș3Y^}A屶C^#xgmC:*o`8Co slfŃrN VRU|.$C?}G9$ޅ,MqjQޣZޓkѯ9>n .Sؕj@j<$x9ȱ?_).#?3,>xٳg={3<1>6;ܓGz4h9Ѱ߉v J>m|?Ǔ~?kQg٭j2٨FC*!> nzZǻotAC=us^as-=PQ]<=g4چ{Os 2**b- w9=ǤC!!wHMy*%}vweSd!E{?B.&:(dh<<,s7X[ys+;6Vyߵr+|=hA+0czKz2L *:c賏3ȉzLCQ.{Q}ѠGO {~G4ݾ(D Nz76n` I"Uza!  S1y|ɣG6Cό/V:cJ6 nW=%eEUt\Xa` ?Nli$Ł>pO-p :Jt*Dl"I2XGr1qys^ǩn37g~m=4`IΟ&<o5{Q' gL/,ɷO6i Q>#];].a`"2F{iϥ\x&?T-rY~)̉PzP$q!Yb:@[pȦ1TvWiKR* 3ڝ4Ly{dfrR<LAiwJiuXgowT:C2$5CnVժ €KU|SQ[#͐}QGo1v(ﮪ'Aj `8nS H4$ }?aSF$\rY ]Dx}V0TC=⯎p;@M^ىNeThA==o~MaXG>}&705tKs]ۯ>~Nu|WסNa [O7t^g<>IO )ךj.pra0 J1X:/nf$N_`<+?2Kr~UE7X!\6M!5lyck˒ȅn^814ycslﴰO.=sK *&ۛ%V|Wy1NRvQޣpvUV?Wyvve$y@mbi%V7}x/:~/<̭q s@_6F0JR}2i}NZ!boj(ze6c8ܥc_,5\9H\8v7z\џ@v6ofqA8(IKO.AѲݓ3aVVfqnv\x>#F"]U=RԎͷX=x2{o_zG"?y"ϵe|3Ӝ0NVss;7(N䳏^%_)6yL%3?cT+޼&y%.^z|;>4mt#*뫑,P{7\H. k~6A`.Gm⿰#D#0u=NJ~ipPB$lEVNadNF!(BG?zCy=\eR6=mwG~7/^~_Ǩlѳ`w ]FV%fɫR=,Gtiy֛&o#> o}c,XiX2E?YW|7ڷo1;%WH/HS!;[ʥ;[O?u i#={s IDATJNu">ƭo믳ų$JRhAI۲35,bOIDO??Xk$t|h݅e$|DlÑbdSs:{VojT'uxч%|oTmMTl>2RTo8 ˔NZY.yHR =qv:ǮQ\wL-}8á ! -3 (j^ӟW} t(7S>+xxxCC|W9wa9 :nDM(bu~4VfAQ0R"7߿׿ n.*>0WFDP( e2VҪ^|;]{Wjiȋ!% >sģ"A<W:}vvxq (Bfյ ZQoy/"Cu$Y#>4DIʧ 62W-Sܹѹnk-RY41JͶyPAG }4lmn~_xc٨bVw5<: {0 \}\}ӴXw\bd28G#W?Kk;-˜]qË)fWε|畗xe.^z"B (e\xjԶ T(FFs_\.ryDۓ6F-5\aUDIC^ ]~/wdr#=) ;~W^` }S*ǁe6plU7FHu#=v6o%]3&' apIlwp>07Yc8Tj$7wD[){HHe:!.y(#tRv"mywylmﲾ+鏝bgsL.n1 W.q񋛁g[#r߶P6|"|K nz{nvFxXj` M,>[VqE@R{Ib("# =BoFgkhɞ`ʪ'3-S=b1?Z}M$ ?qB4ap6?xދN[7<?վEE(mRhza{/^bp&*jyקg KAjEquHO%tD#7}{ؽJYYZ7ۻgUӸg-7X]GR53?MRöfg9|MV vwˬ[N瘙ɓ }M"q89@DN|,;~#чOql:'rTup EGfGpJ=lֵw޷]N/#/|NާmRTZw:{?Gѣ[/fDQVgr秹Nqo;|Dd3nS-ܶ;$uOIOuADYCMUZ+7vBbc`:2"7\=ZcqUfN2@Xc/A@v=ϵټh,sg?߄Of\iD~HHgע]0y~me H8,>H"]YCz"nD充6F&2dUc̃ߊrZfw#~Hr%ex7l6F 9Eю8sogjys0~v~O~*y9oo]ysz ?X)q!xuʛ-,rʓ<ˑºk<0pnt$Vi I5U%Ů;LƴllWETܑ}{;q7:]r_ky^t[a F&3c 8 &yR),?I^xV =죦9Zj+<3u!JiZe#]8ԐgM$9_Yg=`7 ӄ(@i[Ғ>V*$ڎAޠ"66+EXM:hS  {}}]!OD0YY??:HD<S+ k7tn!Ӕk ZNB0Gwf͜.nqp<kW Y =K̟{j=%+mJ mwe$q:6'NpTaMFFL<<|g>?>Uo/~_BTVHcǏD@X^-?0#w>7!JOk$/knNgXدntJgAqC:IR-ZP3D;N-5UXYVV; kCI:xN#[ )L3Zˤ*{hQ/hgW[9Bv6w =Me9T1R >B t[cfqp#kGgL%P7Wno`7-? g:Ffڄ Ixoue7VycՕNY+7qN[LOOnWhSӓ6x|v~/qsO#6|_lcqݻ6,Y[A> >JN͵v]ơD\C6KGcsvgy^͞7xwAJ(q 믠]tM_~"Ѽ6Fކ9vPis =(_iݰ<6`p؃V)|ӛ)lޠQln]鲗0-?lyuS1c~= "3}T ~RO|jwJe<_Î}4H|o W-o5ŷwU^h?QYh ìdy轏hF1L\/7w3S:\am}c#󾉤nt'RFʆ\u,Q:oO|sAynPꉯ1RssThW Av#a6'CsЌHS2HXI j$73>۪okE+uJet3Pղ 2FM,3ǚs:9~ ;B aXvˎ3:9MjhQ.y30u2ɔd{bU#  h&O !B7/c`v W'S⩡#fLGNlhf~9gtב.hbXshz*jn,##K lG~N$Pb*aLNylDi~?@S^(CC f `f|H^_k,$jyc؇Ѝx%(v]fh&1bCx+nf0; NfО k7_E7b 'jAPF45z|A9dq0aLF'ıp*.@*iyCf"œ=V,-7^b\88Zb-~=1fvShZ ~omw C{s]W̘/cf,>H\}*޾E:С3ܸ c,Jh14 lUVGR BO0Jp&~C5M K?: `[X'[sP&|Vk~lĞOa1>4BK)|kIo"B'n۰R)`[q';]ew~*J4ꎥ3 ZI=ҞAs,٩Ց膻tq؃c,c j *}ʯ ʫW ƛW_7-JNCү~/F>/WFaDf-s=s -64PYf,=PmB+/D!w߾IXgWq H_$?7~ 7\m[9@uT 6euE IR{;5iDI4 öưnyc;w:ExCoZd#SBg@P6tRT\ni,޸IE ױ#Ilnr|n^7^~Bqknƀ?٘Wܼv[ׯ>;${g`\x};΃|3wt}XYj-͛TߢF]V70 R h+U%=d;`Dٴ&`P=zTZㅏ>='.oY)) UX2i3-WX7=t*N[ZWb_={ kB;FbbTC#.<.|JPvfPaƆq+P^xҝBxwK)FyX[HcB(C= k+yl<v\U^=?; qov<:t?{o_^ߏR$^u"nw7hh85^,1 U ne~`^wcTBE)i@nVxWXZXr뉼{+La&Ffj㠟=;Fi&(#l7x7R*pAq•oP^Q`4Zbeǭ+W%j_gS&9N021}Ooթ`RxՎ7( XV zwf+9w$c?n!uPm}*bmd464b]4#fNэ@ԠAG6vW<92Pnh/PABUnDr$w[`ӣuл'N /8w$O)|?"ŷtDq Aw?haHgFKhT[h]҈*n _L͐H8|1޺QA,W#(]oQ[{0R <߸ !R_;F;p~z?:6;yt:-.{KxRږdyCמY!7n$ށS q*!o~Kϑ[_ӬEVt&7+k='haP*{ښccmҽeBw96G*@.^;9NLg"IQ.WyG7y{?W$]qkY^^͆2wUG8h@ HEr!;0 vct3'f[-AETTE0徟/S:c]"Jz=W J~]%SDtߵygn-\ fKB<ݽjqn/O =V V[kKOLCh Q~֝;8G'&wESgNpl3iVex70=7\ȷ=V.019/O0>Ypm^y-x;p\,7n =aHVs(Qtsm4g~i5 ӋQ' w'u7 ]jod?hԳ;g*MFC}er%vLh$ZFd4t3=8AM Z-%ubFJX)T{T<<ɏۿB_t/nlTP X6(9%H>Uhc }PC89=[oc]Y#gObh:F|w{8+^C %Tcf7:gH$N$[T*՞Gp]'KAk`NK[) KTCiɓ=`v`ihX`-a+˃`l4.|;o}09PwϠRp⏉qxuCWBY$$k+=/WU!ƼڢkUeRUݿ633Z*S61b'N {35nd$8{,E6 pCs?^"mۘM $*RJ frv<ᮤ%dIp 1®R2"0'4ICI~譵eڝFA*<@F~; %R#)RGoG?Lf^'_ZVJg>MQ6 DfV#νĉy>ɣuTlbI#T7~u;uk*tn&;Dkɣu.Vjǹ}Jp?AkӨtV ko_csu s 4P BTUuY>(k=u  ~zl4,110xt3C:(xo]穟 >⃏G臬hn23 ~P!n3}|+Aets P(Q$֍ſFQO_J΢1T 0ڏOu7ABɰiCR$0񖊫R&B43T-rv?G&46SS$IĆAoF6*u򞅯{M4@7ld-+8F,z4Fb6@ [L{ QM 象Hz8rIN~:zxlٵAPSRܟz#OCW3@>@l>bȤTlᆅ,xF@ɐ:$[?$6d׆V)Ѹ)"|gY2;d5$R/o8>DWw^is;DW1M0l1¶"?!y+gb&Bo~;q5:=[u;D)T$Dʩd}nFvJ(X C(%i2,D9ʧ*Q˫ϝ*Q&]'$()noռ\%p+ԨE14 t]{s'Ze4RLu9LIBtߐ.v~x.?-#bjiW9 9aah$( >A) gJ/@26kTmҙy~Ŷ:e`k:Lq3h$5\P׬D{cCǦ1 /4]gxbZAn" T J ez(,#eQC؃ J LP^Gzkev#Я\O]'u]!FiRJC:m26f=mfxhǸN([zCzXHྡDCE}<~wSUhbQ#4>6jww+O3:1 +4l CJ+y%h"%=d]B[N?W.v|Ͽ|/~ePAuxxo}%6ֶ ЃL%f.gZ&G&)Hb8:ayþKGϻcX vo45a`%2CXa|˥;B << ̌T\S:O^N$ M7l -Bz,#<'~+hFTi:Fwg~ۗkkg8#6xY1#h`q v56V:XS?q%^7zTu.?{?%ZCf#~~ڬ0R*m'JϹK%+ ѽJ0̶y ϿHv+ͿK"q~/ƕKĬ8]8g_[ܾ'~c)V"C|hП|(){2nm$'bM]PUvk4yקRh=^z_z~a*?+j{L&[-sp@O4# 'ժ?جɟwf!MG ]_Nd-)BOQ2 Y\Xfrj'>p?k27oe9<7mJjjn xh;QcqRQE *)oawn${S:1]-wJN.,fe-tH5s!lJ)Ϲ3,/(66+8>iDo;m|aDWF89D5KX^Gd衙,ѫZӱF DTGj tlxZ 5M'ChF՛$•@)|WmhQ))+ersF4 PN; 1`3F~c'^]~ T~hL{+|ףqoRxJ,[mn&g0⭕G](' 븥lr2J-mʠđ#3w++/>ǫ/~0 jO1y hTI! ]*?`}eDrpoq"+q|*I1mU.f[cpg?9¡I`L~k"啗 kI"32C\f-ΜI *{!pJ䗯P\g/p?Pnm^F{+sw!ݠ 8勈&1n>]Ey`ePUZ i 'A1< ts,f4,9Jo AC v5x4Vwx#tR᭡SM`n Jon^*%($Ϸrv`wwaF ?Ք#.:b:cp 3THo..<+ r)o04s*Q@G=z?n*mE]R$l$]_)m(ҹ| и]-m}"^yn!"5zq}^ {C3("UxG*_)XMىd5O-w\H35HL? ۶dFOnCg\\R/qA1%l(!X:rnc#4Z#64L#<~u ;a f]cc -jbt3I,qXj;Pk)dP~kw4'"o/"Cƾoqx*Y])RD|q=8w;5s\}N=ϑVRz2۪n YB3")CY_Yw4ÂZikT\w*<3 rkW"AnϤnƇ|bM}Ý psewpKrCa@m =*~;_:+K}\D՗8;e{2^0M uχ! 3,O]/ef7 l{h7 Vz:{9_NagpXdM߹w[M;=JpV۾AP%kWH,GǬka6C t-l.UKC ƺ[ByiN}MY=~O}0cf;핗82Q0SPELJ?!%*WݥHe_E)J}S L,޲ϝ/aDy;F /f|m}T袙$z,c$LgBJ.pW>o+qhAj8.ɯ_d#{76ctjJ3$!0kr"g-(4H '1kqfbw 2PRtp*tx-SGβxP蔪:dOH(;xx|oXbiDx`vfe#ku`,YBl]Ab]7X-\\0M>3$+=FblnF@S-ⷕZp (=09}owl(ab}1C23\- RJVZCg, ڡ8J\ bIM9t;+|hN9[$/BZ֪F&v(w]⒋' "yNLXYח03=D2uC°AE;P" X~p(g[wȭjaion`&Oġ9>@rP)OQUF@/a|s c?N 5 qXtH g/IL7ͻAo,ySGΒY,̖ n-^G̲xȍM!:Q5Iin,?|tϤzimע6aq)u$t{r"hy/"oy;lL8ݐdX;5NNt^HvR¦C)R-T>'C5:==Oz '?QAJcW9^­p{Q3\DkZ4ZwN{͇d @TUDV n?*7r@>N1~l޾bt?s~gq_/J?|RG{@/H* ynGR,LM'i%-Taw_k \=˥t'|N=8{{*(t-CZ*88U'PRbctͨ!-]tKb\3-̉? bɻHPA+XXX$AF*,^}d Q" \~knC)ٕ>9%%6FN ?{ߌ|フņQbݍPGxXD yH DJEX3c6/ kJA]Y0u?N}'9t!8 H<c*k/0:PvI%[[g%[Bݧ)u>b9y"E(7Q* ,=F,Mo%B5kdWXr -t:~:q4frU5"gLG--wԩd,Ef@m,h}FgN07d *yz}19, N8ѺR66f1s-Q mhqj1 IDATC;nsD]d|cxoQ(^6+3AV6n5Rfy7Pʊ-䱁U5#-S+[Q%[']kFP~ǡGQg>1NZu!l5<431`31*3! ;f6?G$.+q7(oP&p٩u☞OL3a2zatsRDI]BݒGmD^mŪr$_Y-4mv-ʀ00kQkD!=?DJEPkyx0UݞHa$fЭzng7 ZsA^9pf:n|A~6IjD7ͅ_V#E=-+knuN@IbXmۺ}XD{L+1xbJ**1gOt;p1A)%J#LS$&e׭K㉟im܋i>NBW[X!uTz 6Dv=_ViF(>K"ٽN֚w'D.2*(džAC"k(!*%C*K] ,78v4KXS21 9Hq! ۭ kf(>z+/ƛo]罏U=vZoaPES,p =IC)(iBA<@Fr'Dr{bo:I%hYIإyL݅QmiZY0"Xb+]w1= u XNcS.ݽZx):!cB׍8 ROÀ+oLС8uR9ѽ$%vQ]6Rhh"a 8A2iQ U 2dHw%ah5y.+VW[c-9n 7:~ᗩd/u W 78ysa-Cr{t7e#LRʛ3%xcGYy7޼΃@=붃w-@"d|QXrz'c;*@=IC2A&=2ÌH[,_޼ }tz=P#Gv2Q)T]ԫbc4k=q8Z7LM>8~:3S r; AJ%Zٕ8 wp֝H3tn_~j|dz/Se!,ygwT2RTڄnQ!AeB[%Tr'i%] z/2蜁W)m֗8zu++.#3=!Cg1:.,ǺWMŲm*ig7+6k/dWrP= hG)o0}nPhGOiDʌL0<~(Qt=Nnc9A[X!3L߇<7O󈍡ٻϧh@DIA d0_BQ\sdo-P*Ts?>CFkw ~5r:Ljŕư='7z,~tz z Q"&OɊ'Ll+@PXw)oTX~!+H+|*0Vf&btl؉T`ܿMЬyJA7~:ƏvG=Lc%1vN C!-93Q2vեl/a1?w#J9rezk_F nAk.Pcc-PY(^'ǻr.a,:-<)o#>e֢,dtWl>tN/.u`yay'Dn hy̑9לH 1:9ۡ[6<8,V *AP}ͺZZcmo>S\E ?we Ƞs6a`: ʽ@)L9D(sE* .eS wG?{o$Yz=OWû3XD$$H  [َL,7|%Y& w;)͐,9 A0ӳ]kVn''++[UuO`ވ}~9=>uTf!-an8 WHeᢹh86搮[J tjq"Z9]|!nU[ҧrGEcN X?bDFܹ>HghCǷgٺ˭sp \ǃJ{6]b JqG:յEV$Bh躍YHD,\CաYoqٔLA>L'8;(-0?7&rxZ%Á"x?ڏsytG!̖fz\DžO;BhFy kJZXEr5E}7޽CR*͠I˛z&?^ Jl6$-o]R2"}T4е, Ҙto½ =N prBBhQ?b`f /q 5GPSRnezZXʑFJ~*+89JSXIc/3^n^gṕ,;Qt gza~O"CX=wf? ?7le8jO#0\~{oѪwG6f+$j.vMC!Q/u%('gfFu%ñhQcI@ӝޣF#yjaOڳWwyY}-,xX 3SXfuvBHk+%O@GחSzmB Z*=>ai9De[M&aǡyŗN_Jd̓Fv߇'tʕӚӲ$G.iW.u|(8hs@ZwȪ:#C{nb~9]\ҵ1AW7^m8zg?I0 g@ay0~<˭lxxm䧶g?6qw:{o23;f3GG}dQOq$ >i0> 1ޘy;w}Mݴ,}~B›o$wi0_!P/s_3B8CsȺ$ddn)tF?:v%Kןy".)kLVݘ 0Ȇ|؆ ^Fs]7?ѝUC%[)ҮMυ/}>ql`لmxٹD@N7.e忦/qF xUYQśl,ͶIRBj/'r}5$U d^QNƌvpZ?L0G._`->kk+rk E!'Eٗq,UJ11W+e<{tl~ϲ9Q+zi*_̖8FsG׳!b=`y΁ ,UuX!>: }Lߧح #·Qmr^?J'FE&r&"75? #Eki>׿=޻ygO\ٳI2gJ*%\QXA Q=2U% kƺI?tsi4k7)ʇqяYzlqy!.\{1 V_ԡW8zGj[7,\"w>RJlX_cȋ:.Q(uT5r^\X:Wᵶn'.OJM舾iXgEgv 0l4StpHuFZBnE04Ӵ8f!d %\J= lŨTtOAv{ذ yKpǫ}f-F s\?@dgo/@\=6F- 1OfeӬH+EUjN6#npZaXNa<1<]3U<<›e5 ~̓R]r'8y>LbE:jE8 =%k,qhi*`mv;(.&0D_[~}VVAlR]OJO: 3Hwя(dΗbTDZLxfTTTJ{rhg<άKR@{HI~e%\Jh$~92@7t>boX;xI+_xdY#Ј9O~ZʝnցG qBC(as!1;LbC=i1r[`vsixҤ;^8q1T?onXl\"qG2ϾiV7o]V /w* {{QnL:\<q*,p_c‹66L;I4m 0{g7ѵSwUxeih}"EMdRۜ2J觳iE`;{;{SZ*y (])qS/`;6\= `pK+Ti'(|dfXeF>y*ya#˱f"cVBm,o\B DV}ŎD&;aK I-8iÇIuq0"o׸4v+0tM v l<4kmn)fLSP0?*G0W, T<…I〨S Yo5։W趉ލRTa3 hAhn%x"> #8:;M`$8" |sl2>K埿L ٸ9D/ lK'nB=lN,?Aaί2: 9ڇt*H7yǎ@">|tF7m"2 4Uxrɏ>I>{;hO7tl&1= 5mtdTeuR/M{ T/ѮYDٌ ܵH@9hkF樤i:ФG̅`,)xđ:shJM4U83G5|}N̯Xy0翩 !I'iԳ̀88N>1>MM;K^)g' <7[~b?qm#Sq+ T0mM޴nI M})aKh:L JppxK4Mk |}*9aa\%nؘܿՋ@Cd]sd0f_^c1uV;)}=p/skRirzuRTpӾseKT<&timif(:ր,7;'ŏ^; /]K$V_' tf,{Buxs<݉a~+W{4M:"ʕ 0Ĕfk|!fi*N23ﳮ%4b8q0MTS5yafG#dӱfMZ7LSϪK5lڶm#zvG L$;[lmsY.\a3Z~{}4,ύV?:iA5o%0*BJH`{&$MX뭺ZiaGfڄ]dbV*Y\rPkPƪ:@a6Ivg.i*..q{f`2&j< j<@8 HcH"oI*ө TAտ7IPh&rȂ*,KpZHe<3qHfZX,rJ)>c%' {m>/t %B) ^G* 4R4H*~ ۂv8h8:;^[LeJs:%G,x m[# M^߿7ZʄKj-vvj,-Uzt!bJy%2Iܡ'AV&I_Ri#t0KkXMʘ`}ƃM4M D4[,dI9{s`vqwޛkrmg0pdC lln,.7}6/e嵶G2x5ǁJ|Fbmq54c\uh8 jem`D?2>m¼ݴqCAv6AJq:KKeN{;ܾR\_ei:q #_NqFwh 7Qk{Jxpgz#F2ƻЗW=<8]4ߗ f/?@"# N֩Vm4, {A (6?ΫxDܩH?»̛(k*gO'NYcL[iFXDAs£h.㴛ooG\ӶT"he TW0l8& |:QwG/T*< :dHrRGB3gѾ?5\ rjjj6dyL jalzua` $Q4'eJ<ឍM' "wftӦrianFCpq%÷gqf7"sJ*ch6{~DDnb/]c{'>. cνRu BPr0/CFZâVR2Z5L4)+8"=b:{Ad1:"U(M`ErYA7K`z#G0LDWWJ"<&^0QyoeidKO*<&9bneׂw"<й| o_& J)[§w#<Л`ޏBe}c^4! &8Q^^3ϲs. kXvV0CԼrѪ!=6tGhFoZWNp?\͞?֧!㑒o͏SƠ-S#{Da=T)cN;AOyӲ,-g>]arYY(XNbA0#2JeLcMR]Ci⑛ȸn)P!ME cJšRuт!&^ߋf8F{"B22؞k800?hQ-/&Zo䙧/ڝ62 qӝ!4=I6I׋ʹ\,HvҤG&ExHԆX鉛k[ɃvwﳾE)ۀ#:fSc8 k4 Tkl^0xJYY2ĭ:o![(-uCu@L4ݠs#[,:\HlG RPl ZGTQ(}pi m䘍41? Tp?3G<_!MBCP;谽OZfc}Ѻ_G&!ꙹj Л-'v͈NFx#ITli:sK7FD& h0ukRg }f>jF aj38Yإ,0 JXi2$lS]%jMo=J f&YIcXeTJ#QLJ{wtxIjRM h9yt_0l!M5*fN`TKT4f$@W"Y#MShz\ra4ʋ򻗕@}YIk Lw1˷ZKɑ-|Z\9߾M.^_#zRYhDܡQ&u6c :P˫.>A@-tFm5kګ0$RQq/AA㕑%g)±^瞜~H (}!6~0y̧pΔQwkrJ N=KԼ>bNyHz M2zJ.?_7n!wh߾}!Jx8%⨚S!1.lԋ44@tP8 0l~M?3Čx,MJo !6~){YN{L 3.x#5dri6:^mB)y0CѴi>Ꜻ nؼY  чLjq)?gkXNa-kpqZv&vJ0Y:Lf0b. (\ igUQGkac2,M]^~l)M;/NtڙuI]jBdXyHo@ ʙsz?=<nߒM{ =`aes&[{5ka5N:5薍$qހU]!4mK*4|$=TC/]>YXE3l(S@C2ZtTTCF5dzF"K >ḥFa:)gV]ؖ'w|PPIvEuDeQFwѭukP2!2ÔTV*X"4ךa,,%4$]I*772@\tbQ$r@RN{TW]Zb@Scҳ'6$!BwPrp`͘(w2a̜ 'Gh$}^è|#;45M`[H#2i*hYP )T8$zún,RiJS86d}Շ3ff%$gdm'T pYoiמaXvqnSGLgq/ݨ:U+<<6(ѷҪWW^НuǯH@Fmk5Ш,a(tӚHb*TP kk[[ܹ;R(X{zv wNBm"#G MHƧx $i" vGOF,Md*3& ZҜ8#dtyOCI]2&ieQRQk׮!I^Xr ~NS֟(5Kͮ9uGx|F| ˇ=b:)Ieqi'sE}iY=:a1I`-Lw/iGGA'{ Я2A/A*=YF JH?DM4̅GIE4 tխR`;ȆyDͬaj S#4< 2j-Q\{}D͇YSc)KUSlUHlGF2(TSxr4{VwVR >2MӐ$ML;&{ d>C%,5&!8 rUb5bv~?yOT>+gP"4Q:f0JghB񪂺+pK'zw^B, CεGq3NSu!ĂMV-ڠF6Y$2yYR8\qcE:lV]AF:~G?}B05Jk\Ȋ{4R2&no <)2Hj|UAvBr(,VAO3w~@j~kWI3-6kh9vB7nt,M[,-?~{yrF#$o皰YWziS?m|`I?^Iп |M7,.>ܻ񝞤tvc/3  qIFrfUDq>fEC?%]D%rN'}3Vƙ!5rb)M"+0O ӑZ'۽߃HY&kO}i Y\!j>@FӍV7Ð(Nq{M8>wkPhX7 ^ǿ)(U)}+lރW4@"vl{SS@TcHB]P 5C,hш%]t/Mzݯ3c#5äv'lum-$~&͝"H?{B M@&Нi!tN l6gg7՟4*;;j8YĦgBAQF RiRCmRy: NHyJ[9p]\"VϰpS3f D~O& qҔGÄ7Z96^U/c>xb_޽'$}E"UׯfMDLl WQ3'~֕*7R}I)bSaKRaʼn_tlSX.8 r:3u:=l[{Yʑ *AbLLe;I:vhMa(/n}c>Th'+xTH;- } ]v_i!q 't@u9VLit3K1CyQmJ r3\blM!/>xOk'/# )t3qU{??u%m?4!kd"SRVRŠ蠔{T|4WƦlj8C$FYpKĵJ#&(OLP##o@i5GKCN.õé`W֎/e?eZMsѴbwQE*¹11& IDAT0 4:fq_pJ+#28}S`ĦAӚB0WGnaIK ?MmL*UieV/q?y8 ?/mׄ 9x?>}"*¨%̰#fFX_vH\e2քqhf ,!t mߦRIp evTRVM Q9ɾc{(%g%fwwϿ6Ix$~ZT]}ff$# Ү.uS tgp7F,2oDaҮOTbo1@e?Lkqc>&18k+/o/߯R!EbhkCڨa9,l\MX {¥5{F]1wػKG3q_x[)_GкXll6z:b֑3gqSR"MS" kk4m#I2Zo Q\;HdPJd200 ֜*17in *o:f|[ufy.2Jw3%qQ9ǺaJ9S(tvF%GF_=2\7f>@|L?R'2_%@d,Ԅ"ETF4v?2,+C\ aw"9zc Ȉ$lOzGe *QZ{ژKҨAb6 15]V/t&Ah"Mz$ȰMwr{>ܱjKsA#%"I2€VF06/`'3O>&)XʷD3\8D!;7 ;DAY4svE^:z-z0(A܅k cI2YŤ- UiVIϓxwL7Bc΀=A*#  uN]IҀT#C/7M_Cӗ5 甚k$rX2F&B1e {0^N~s0]\N fFqwNWa!I5kʅ'  Hh| !^:29[,U!\.S^u< E-܅k ׈ZI=TN1~퍉C?}5])y0_'M=T΂+b/t:(%{ Qo_&aPj>/%IesWCӗno?Bʰ唟,A7f 'chv72qju9& bkݚĹ5Ͱ)._ˁ?#C>,}ۍs ȤVqR^ؙ$Q!"lȑZM*g~Iqs0k(qg$HpPZgWZxҕ|ikZϩٌq$vA̩eLEQ6cBAbdCOn&{Ԉ];TƭAAh2LI*i]Ij;A/(O E(c4*mb6)=ҤC2#.I&5jD)Cٹ˟FwV܇HeJ{seΝJJ`fĭҔ89ػ3_zzЌ7 qdMuz7U {t`b!n l^^"{'MXYQhv !|LDŽ LeZDovw/I@Ju*0(̊ddv@/!B`H'F%;hrH*2N4 f\Vh.MGCt0V!_$7/:ޭG Aç<~ԋ<@Yx^74IpPˬRZЧcBp ."8SPiZٲkԽTYp0nQ]LwIqLz_:F,qD GQص ӒF) 3E3vz!?]@RGi1|9*g 8IG24Nx4F5dT#h:N#I`YDН~?B-?@aub]ЊّN+m0U<7VtR E }2eAMqP%O|.#Sߍo%ճ簊j\З9/!4 $MDO'Uc6(~kUBP,m5ftC%4HM$IRPw1ry:g䐜C{Pʱ$d+pbG ;B"J$ (1e|dMQw!9#ꮾfzxh첺zMp k >!-E0naaP^z40U& po׿*垆yhZwuqƵ}{C4=t>d6d6lq_$4$ is(T_>DO$\ lhWS0^ez ֑̺OziQA6d)e{DR˞B<~\خ?d8 ۣقg`cV;-_J5kGSi(t!cGFvq.3Ku5 PtSVi^`2Q׽ H"̚+YBқ!C{:h!Wﴆq[B?cj;xތO% `TA8f7_5gH\s-$CV` UQ8<ݵ3,>n6.]!,nA ޴h)}-',xs7}=!k)0wIa;Xi"|6|xc\MR8 IHfÄH i1nᎉ'M Y< ><B[/Z;)p;C4Pw]@šcP ;#{zpvľ$?cG ;U j< "Éc (D]r@N0\Gē.w[mݛ!@ja!FkgaKX Cs$cZi7u$g֠k_(j8 ޼og> k=!`RBFU 䒹 `E;}"c Wt%_fbMBĤߚ0@S{u(!NK[CJV)90:i5h6$*d[$r 7b hl]{ ʀa; DboELhqwϼ14H<2s+~j rEڶO.ebvm_ThQ|no'uT@d@x̊-S!8]ZCms"CLۣ'bT6I\Y鬦}:sD@юA1M!heյчa{ڃs.;xL+ CB4*;H]EIl bT9DZ/$v-_e+Euc~հDv U!QL{ӐNX!]mk [\[A掍La2K&!Jb "vڵA V'\ffŨUU+2BsJJp%?<&`4H>pl_@:a!w{rm_\k Q8(̧(E/Euw1)}xy,r-zh ˪R (cQ=$YfڱFcN~vb,Bn0';3e']!P膺.ʷ; ))76,{e|<$s!882F_+" hۊSDGwV 9X{6\sB_onh|hzM|8$8ؙ(ʞ{[}#NR cqd{ y!MpK<܉X 6+lջY .{/VǤ(j'\ J̴"Qf5 IA%AFd xg$f)`o5(5!1Wp z096FtqǏCr짾MH<E+\ZH$;+d*Bq@8u>I/^vZPOU+%@m΃SlGgn w|/|O;aD NJ,}Y t QEj X;A$k6 I +OT j*ނJ9N;q"X`[ ?sF㒹,fEhCJ<}V&;MqCԶKF eJ!ώ٩6Wt2=H9p{+"paZ㸠U@;Go ѹI1 *!3du O,1)כ)8$!zR98o<p&"j0e8"N6*Udf}(8O\cK'BDI«B|_^(HHgXX{6:cZ;;`O8@lĬouY#l;QxXk瓹<`^l50w(YmL㸰N$IϬz`#(fAKГzGV=ϽE7{V9Wy;F*`4c%Ԣu(|xؖ$jk8ǡ'8bOձ?"B7[Ƕo=i&WuLjg"$S 8;&:YwβjA$FqϾ^ A+z|+HT(C"ع2ǟ |O!L]S}YKBkJVtzx+%):l C'Y+BXBN aѱF7F:DWFxb~Ȫe0Q-#-\˜eHó4La)PئJ9rx> U1(j HPyx\l6WэhZZI%^&+@2`2I D`n@@@VŃzf >h1h;Ē7(Tf^音o:ׁ >V lA}8<>VQ~U͑::]X(hj@<_`?ᡖM/ ݅f~]:\Kda ס(m&E*Ke>pF isAOF eXM Z N,]@I!ϝ" o$Ǘf`vpP`edCG!ɝ@bif#kUhilXEi6 ?#;E*YVUn lAº Ϻ ?IC~ܟ1h! )m\s9hsUפQ߷κ{\ٷѩ]Ǥ,o[c#Y096?l4*%r"Xq րmVDn O~QA>Xp!PQCL *XuzO*Hl԰ҨXEqvTX"} WVÂհ sy 8?…t.º fǟ8 `w^7WQWaZ"Aڀ`|Q(8[_g4C_/1YA(Q,,jsL͏˴ijHfAO~Gw8Tf>Dzp$yD.[l^!!JCF9 8vwaM?s+;YN#ZY { }*G1*M2ݬ&q.vP=,I 6%^ǟ28U0pl:j5$mnxvXϿx_i^}eQsHve4yGiǂ9`8&t]ܓd_c R 1o5,#;LŠӛ˱Zr_1``#B<`nggP<<\k)Q:E^7jY rWbeW/D$: OK_׉#B,;g~y8_b %,U ll3[p/pz.oͧA'8t GI!JO'ʧC[҅0W'?Vwη_EK/([B«5MiК+4C178k@dUB:wvBmmz5ܷu0*Xu@\5j^Kw|xGS<\ӆg:`^-5˪at2YJ2nKLIFp\WWeH=7x%| vEeGU% rO@0 `#'XCs<U#l28v`^} SpMX ÄɌjLT:}v$-CJ/8Iw0նϤ+³,8=E#=mm!*p񩟏 $x% ~zϟ33KXMl@% 3xy@`>{ g^uԶ }M͌C9רX @I@Nv3:X* <(VUCmk zU;% p!`x <{ jp 9cZhy΍[RTZ ,dJ`'{*] vj³Jv|YӀ.$d]AF+ η6`9K'?Jԣa`^|[|S?5Ye aU4v 3Hc]lI?v{N EApO!,O@=D$SbZqX7޸<2PHSIffg#_3.;7VC^娖okx9X\~羹qcО#z꼤|[  Q8TiY«w7U.vϼC+O]3'f#XQU\?OlͣAC%\IIUrk$ ?d?/T_y|pTe4l1 UEX2jBpeX~au X~sn~*`epV`.hc؆[^wwpC=Ga~졿opid_٣ԪePg F *'ssoMq23"@_B:.3p9!`X_!^,B?3fY 25!a ^Z !,rIMg?_>7r#?vEĬ:YH̫1n9g Dx0*O¸u=xsqQa @CtB\=z]JY =kJN5#ȩe63 P 6:hyT Sʶg Ɋ[^>}2Y_9c4ǍJHbO`ׯ]9@Ih8-{ԅ]! LpH 58 E$SBG>"_A?{[@D=eq]Zu\ԶѵX@wq3B<7 #oOHr0o a]ϙ𑻾ق0e@IbɄ!xvuNm mXz"#p0>4ʩmî;!o^捕OOe{Ȳx,:@,YP] I![6|\`w(lA鯖I] VCn>N5+o =qHRxPh <Ψ[.-#OHoN~=QK|yUV9@\b:deo ܸ-;;{J•CEӅ8g^eżjvx.<{Tm! (mnL쮊r8ScOY8X"#gA=rQq%L5 p6W\ KΨH+B}+&X{?W ̳q1۱,J~_.d5lv>0/-¡ff\EܷDGD(~񃪬s H@#אʨHeTd*1$&0w䑋q'>>zq#AK uöL&E,: Yi$ o#yg$g⌙2c{ْ,J%Z DFkuUU 6s޻MH$oʱ=k={$H$ˈ۽D"Y&dM8"A\ǿs5cLbZ1~O߮J$oH$&[)+#/4LH<KSˆbG۶`DsP}>ߴqCYn7.,6<4R4>ټĢ3 \L%⭚;x1_Y\&gnƺcw)<$f<߿*wJ$w 2%+Q'[ayxB+әs-#]o vvhϤ,136Ib1N6]6z ?Z6KT%SGwo?zW(Hn$R@I$?B&߁PHdh8\Nsh\Л+z翰%tO,ސӗ?\@{y,q Ye.z$Dy^T&jkspK;Kk AP/)ǁ'nƺ$C (.g/?ydw#_Df44+s lFgIdQ"JT.ҙstlr定SL[k- WV߳_I޴߾7L~q~lLI$wJ"1(^XBa6 vlo#_,Y/9]ZOхB7_s<4׿ \x()fZ)DD (.DŽ#x (,\#}8TkL Ɩ^Lq+?ly[[O˦vWΞXj]ZEB>K%aH%L= "XZLQZH+1A)_]pqxogб?^g/eU,7|nKG/u3 # tثWrhu-47J<D2R@I$wR@I$w1´v BRg$ gSoȎ0lgr]kč߻Z=~ 3/0}r铣̽;Irm"\nc,Kd޼$jc.^7^Z|.=t-^2 ]2v9 b"ɕ>7ϿkkH$ׇP]@Q܎CCs ՜7prwOֽfK6{S״&(NMm^SCQ^&`>ͦݭy*h37B9Q_sg9yξrLkc|˧00 -vl!e"@"J"K$4wrd1ǎG{ ޺RO) !%׺lʊDi:YIY.N{c% d  W,𵮱W>GKh l\h3?:Kr!oͫ b fOaܐ5J$[P]Ov꽰Pn vR׺zS73}h.鉲k^uj'M.L,q&H Hbffj4g9U759ꘝ>zjx񻬴[ϧ(fM6^<8k mĦcr7D7_*?lqsm R*Y[NǪ7K%,Η Tn ^g.in]`jrծjlH|S-u>.]%~[ׄ/FNNwzyMDr KyN|Jee\D!P!}Ru|zϔ ]QJV\%u%ɭC (.'7tE*PzMSpj[TF*{8+ 6v/!8xe{G{ձ\⪨Xek{O3J$[P]NXdn '\?gg/.25YkY#5cǔ@T--I=}Z M[#t}鰡/l \T =Y4LP]NaqozK֣cT=},{(T.4 B;#r*OpMzO*]1\9bx7r}C̬a yx|n'-KIun`s$)$UFŠxU+V,L[KD'f[]4ph{sZZ5EW!W\q!on^T]=.x:*$_-@I('2 UVgJ?;ԋ TFOݑQ z7tDrۑJ"KP/#WRuW[ 5Znu "==!ᰗt@|Z@ݦ`(JT_P@qB^pp'6^e';k O-"A/SpѧWm ҖB@I$w S$ɝW(VzvҢpU{r u8Ta7ѥTU/RAױ"^Z u:Q3's͉u׸kxH$w2%ń5.x,TEeojNC M_Υt9Z3LōYw}x;mx^=vG|l:xB>>7} ol x!׻n!^NO榓dk-^u׷+œDr!Dr) y4mX/?Vs2PuaZzS]kMȡr{1V:MAejeEYt J&Mv DإE\-nL vq;xwN:~;_>Sc>:u6-I"+J"d ^}o36?فY|fH,Na 1{=xz22v T !MUxdk?_uƢerd=A.H5P-@ZKއ;Y v8l qX lwSgavvZ^839?X;4 TAW6\U|NJ;vѵzZkSILּk BGަF_+Tŗ}#qLU nꥧC8U\cv,X"R@I$?CQ @G>Zڽ]8 qذǚ_'V ddVj*Ȋ`jֆ7wزKf*Ϧx/L/VѹUPa'qD|(6룻k{O|ܾr$LJQK$.<&S2 A!@ P0 WDy7\?U Õ\m=d<;ڪ2bQaMY ZAuמ_ɻ#EYHIJ8C^/OP =vEоdpY-hb!Wy5ZVM4^]Z5p"(h=S][UHO^hӕJlp4TMὴ֜_\c溽$ƐJ"_&7Dy&Hhiÿ5|IK׬Q?\߳ XVQy@l"gAyf'/xFDU,$qΊhNR\ȉj wۅ/b k'Dn}~KB^l6NڪXQn[q-q (h rS#IkwDMj߻Wlp؋TEѓQjz7OH$C$"ssM0>4ȅQƆktmߌ8 yHJsR#0{iԜU7v3;cnm4N$Ԝ{q|^M+O_;:]rj-mm{]XEOlk+ofn|ز" dhS8rO[mfbnQ}m|Z,&u{/*oT+ 3&Y- XC-0+MvMяO#\/2ՠ6TәH\թD"0R@I$7ZEIFyii(-<娗áR~莍iso}.%l,2o^gt&h26@u$vNߵn lPQ׽^odžM{ y<灝VV|$F_5(UtykMBu$cBPezm SlpU|k˖H$ )<&O^Zuɫ9]x'{iipy- ta[pX6{tyfKV.Һ67VђE쮙_HfXC\/ST͑3{ [B0(Iy 54dnrڱ+9{l`랮Lq?~gkH$7)$vTt!7&'èrMϏ}|m gmJDe%\qV'-Z\ UST-NH};˻ź:k,^g.8[sk>ƞ~?Uf> h`č}m"Wk, NS*L=f u}cQ:*OQ2 ]1ӹgߡ6inD"Y)$$d='.LCޕF)x?D*QDQ(}?ߏ?Xͥ71VM |OQ5*K|֚9᭩ ᲈdEͬbTTblxYATّ\5J!SVh X i6lYEE6[j|NCϮ]2߻1A&BV_aiW'V:u#d6MH$(fc2Xξ-,,2pG`>/=5PNz/_/o7Ͼ\nx6_I:A/kޘԸף١69V }`>;*C"Nd鏔O+6:7'}o/:>]!:leIN_D"&Hn2B[~L9 <.ے@[{@!_`nz&k`!0yjm蓽Hõx7X .si(+ UuPy5>X\[)m֊$#ocjW|x%ٱ8ٱ8v\]J4.J|J{i,+<zx"[ӹuEt&_QZx{}f~r=6(ïI%d O"\>uOqy`|9ڤ9Bh[:5; Q(V*^19}|r4dIC)nZEz,w5H4T!o8pn0v3k w8kӃa2*l\/in]{kO` (DrJ"(81=2N*f iN5PW.ϕB_W si~ź}Zr4J/O؍Ƀd:d RBf ^/b eTviE=.tPFR+lpXaKu#PS8<뉧ȮPx)ڗH$׏P-f,RN|* ȇ5?~Bg=g, j0 )ɃYݨ*G4}%m`J|wU%bY<-I,) PEZ X;aK%Q+ B-N(lpܭ G~vk/(UxLu/v':5GŒ+)Ky%\ R@I$L8RKdi\"-F"lG0 ET)cK<@Cqʗ39RjR #S JFRE\mQԙ{gS/_ONͭMNciM.MVkY\_\ɊJ5j5_WJݥFGߐxeoBMcf`c*ꉶC6Wb^ ޵|LAL10Lq-YD)$[09a H\x mh\ojk_m{'?qv_8;KǦ [{K /~x3_2=K8;fE}Qib ŵE@)(΍$(US7вlzT6J<% z 9~5>zcU_7ި݉˵W&}eG:B!gɚy:d7!Õ)o c&⸹N L!x_ 8.xѯZ_"H%#Voe9TZLU[F΃=L\©ц^\hXsCu,ۄ^64 S1=6ZꟌNb2 imEsiRE߉-Eq{.NPl&ޗ"*\ug8}V 568կN\7ow'pٱ{9 &[DL3{qD7"Xmi\>;ŅE 1+Kk'bH$7)$[S_#ן4lv ׍M׷F@fij G1|nB Wt{e\'s|@3Fp vQ2 &ljűUA-=-8= X S/D4BZ':tmLNaglp3u)ȡ]fּ-3u}=..W{J<1A8~zs癿< 19]=[۱UA7cQujB T#ѯmI$"Dr(1vwZPtDxSX.tfB8\|O_]&>A8-oDD%:)N'\k>,6h|adt*1<KHunX9V\DZtffi0a@%8ݻk-Fƅ7wy)˕sK3;t+ ^}}*Q$r3 Ng9o׺?J+:Ռ#gHs rW/P/%`|zLi`8m% cSYLSľ?y6;{E}xHnJ 1(N(Pi%FKW?9O!_ac 89ŃW/_hXX^I^7psy>y A`(X{ g+ y 6? jdcks[}V&3we:[I=C͎ =բ+`n0"0O}9S#k˿*Q!־@vX{Ԭ{ſCfN;.A!ɓ˖ pɓؼ꟟%w%L#n?F[{6˗"UL~7;O[p꧷b P||oq׷Vџ%?>o/  !cOy gS/_Ms!Jzm͎}_:ȟɏƘ:K{e7>M19ϫ[WfLLntf}ڭnP4L<^<ͤX 5n|K0| F)"$^oO{ͽEF|RPWGc=YNoax SI7\}ρ)l}J1_diǷ)5oo-10WǺ`gȾhMك5KEE&zC;Ȏ̰9|Y4O5/;PW-Q$J$)$w?{Qa*UJ1SCܽe;W3ݛgp`.xCU&#?yw~Dxƪ~߄c Qҏe= N=Fv'jKtСOܹnA94QO`|,K &n W/'WT&Ezv7t҄jl5X (&Xm]U#L1Wdrp|lfǶ}m@Tzh;wWne s-,Ʀ'U4nZkw#CGM8 H_Xn)/αn:n(\l=3(x|qD-;XX"eM4_jx WA@^AQ3ZF:W_WzHzvO@kFs%F (Yyq!`anRzH. `,},DisӚ^MdV`l;8"[(qn4tSC)GA9*l 鳃iiDe˟r3D>k]=o٫z]zwpZBeo(YWFkSz9C f#*׷:0؍Ta1u•)\a|q鋳]<\MXiZfv9T<"V_-e}{yy4ʡbQ|czv_x;&1UXqTTn:=OIFj1tqU=&>6}"#ifbX4I>[Zե8`_<M2BA#)?#4"^}{{"(J$tRJoSo-;ڹraS5hP4x1{n/ԩzV&fFk΢.p+&%gE^>AGw}AL,g'ƘK飽\@o. "M̝Z Wk"PXBD`1o`wk >{%^u0?iom{q׼O1Y ;YBŇcw 17MgMa[+R@In R@I8m0*Ƒ fGR dT2C<$\U x|.:{Zi\Kd O0<楁Ykjɲ,~-A2Vʅ)ξumҴ$6PvU!ט-*_}}ѫn|j\s 3|[#uϝ) :5[ŒE_ӷ+L Tpu(F&]flvgi{=+8L&ij؝*vl ]+'ChUO\=ޝ[H!ykצ,^؅(dQS(B!Q mX4u}ȍ0 H6,%ȯ?(>ôi؊j4YF&ca6F2^=D0cfb]/PlB^}!vuPmx}EAFgeY)inlLŅ lݍ<\"ȱssCe1v**ƵWshKž_P<A ( f&ӌ^Wg2azuKߣہ]`=[o ` N>] 1(`(VĻ%£Ooæ*="Bt|U <76p嚾7 ۱k 'G]l'$e捵vm64aՎߦٙ|0^J ]%)${~-G\=)%8`RYO(͛[o P/۪^}VڷvѴ)Bb./&Csq )Nc uT*S}Q%4U4%d{秊x7y.\Z Q 6mvivsS/yv; b3Yl 6U"׸:Ao̶mo ׼4l&Odl+©%BTEsG`㹧هQ,OYemO{tղfY<)Z%Fg%~opC(d }BaKTvE"E4y #P[LIsejx]*N$1mp @ж}Us]a%wG6zvz,yi`nYyCEul6t4:;OPġ/_ Q`jo]g{'=-lՎS9?aB~mJet^|e'j%(go?؃{xL+_1|^;?ƖBTu˙B2O1'6=AY[м٪ZQtsJy=Ťq*pt?|txv]H/'pخZ"HMN'LURQ7Dow|y+ `d~Jf4)- IDAT AX㨳NxvAP;]J,զ550XK⩾_SWG鱅*ge33]{7PTM]\AxV2ҸAv 9^jŜA.T,uP*Ff)f\;6W'$ѹ8gGxMUi;zP6ғ >mY?"WdPky4!lM.#TsBgLv 8i.4BKoIfG[JKfywb0 սڙz(p<}fhm VD^'v0Qn.!73@0\m B?{o$aw~9s@$$eQ!˔7vc;Lm18fvSJ%b*?Tl)G%׉i[KD$~߱L݃ ajׯT%bE 0l>~Jeno2Q h>Qv˘B&H;BCTg'e0`f1iAdpu:E$$l/LhCr F꟯R񄼸:V[xD<^kȪ/a0pWNF2kyR<2m6ZϷn4VŤ1D Rз,1Qy+o`l+HoU P]/5k]?iȤr'Qd|TT- I/' ~F]W8|*VV "d7UM,RQQ~D6ۉ; ~w)4zz|8,]8^dQ=dI7k$[+y y}4+_.D|m.萯fE+sZ. &VCw䨗[F4,n/Uӭ,Cm\+9ضKE^Pmt巖7H/֋EED?sotLEЋ:s,Ӧ,Pj)Q7*b+Hu]\Z^'R2+[;,ᑐfi[6SEReQ$E&fqq8U4܊Tt ?J1_nPaTixie*]T ӂpSMZ4gcF|tSx]F&]D)yhc(z[2P@vb J/ry/ͷfy>ɇAk©ia4JSa3#Ο2ܩj*ɠs*l)EOTxDU8> k *!4 Ti B:,z_1Lq+ <<@`wÃdײ-|ȥriYf!Sm8;XI;vQ4+asS=t+TշggSr=)! 4$a;{$UFՎAsla|k~э@uy9:/W3E\`<:qF-[E"MvP*ݍޙIsl*D*Kx،]uLE"P0:aM4\=񋒈֡K,4|0 Sv?mCDlӦ*3g>Bui\,Ӧrdc%$UR6H,śkdU$0#'؜O"-}6mbYBy|^7//&sskyv2N"44 dg?, 9L$<; VpU|@/?{wKtT}G*\{"DA s<ǭ2>&\~*tzB)>esydĵ+,, dZ #w9m;TL Id?QPG(7m^\k@u,*|LզBpIUZe5v7T Ikb/`VL") ծ曢o"2|">M iN18 ?åFBʙN|-IT"6$rJ`G=&B-uQL6`c ֚ŗ ȪR4E)P "J ŽKFW(:li3i_Y@HVnifnDǂmXǬX$WZ*(D NEP2K7Dã_@/@GD+,^Lq3K|.O9W2{zбmֹ/K{_txѥ80&+axԍ)qd]|ia|aOȞ޳edޝuv"cUTMcGQDPJj]6'&x\\>8qsF ?ٲR=!:D%r,K7)EA` @zو p kGjH1,´AbuG Ѷ}1~ǽ൯46Ӷ@@9ԿOutT?sşl~ed[i$n yqZ3ٛ~8S/H"pzlBCqT/ύv2LJ ̢vWv05͎"j[@y7Gm(Fwu{@B6tz< t&]^Goc`'FG;\Yם:CU4F1W$ʑW l&Tб]_+WҬ^m-~cY9Q{7>Ӷ9;' R'=/?r .?7\+nkQO=hfpm&z,a~b G25?ZDO_|c`Oq`6Uh/jȋUZ,ݻZJN#w+12d濿UiY2\%$q9*z}t,]\p'>?C3o\v<*&6@cZ6<6{PRuA'Z}VgWX[20dfq4H܎t6U7R˚FB{ϱo|9ߗs.c]DS B^N"6\5vA.Ov_DcG1A%fRLXs MEz}=G 7DY룰h6V*XI((smS'mBOP#~$7"9dLlsRl^M'bA)l0 =c=^O"T歪 +&"MŵtrV(YkY&+ё(c.+0rrQU\"mW?Xu܅V0X(ׅ`n!n^Jo5"̆4۶_J<~^"2URtwB^K!lG-_ fS >}r.0ۛo4.إ1ìlr5YyЙBgFE O(S650:mJ;;lEb">wI)q ~]V~s羸q\'Vn);ٯϴXMKV?c4e5.I"+2,14u_Cy;>ݏ+Xmt0@%ƾ4ク[^ڙ~7= ', y5#,[Nm Bnˁ;@) 9ZGlGf.;ڃ}wUI=#E9) GЏ(K"֗3h[3ώiJm;2%n,}ڧHNR!3o7ȯŪxr"Bx"H`OA\\Y$'ZN67֛6d>S|dfo"2u5ueYh :FʕzECjsRuAzGGD"'V_K-M6$p+f:mʚzs~+o9-X=?ɲ9DE9[` . ʯKLsf`8Q˳>4^4pym9S-p%JDq-N~in<ɡsFDJJjWLX"e}UDAyۅa$2n=|"ϵvbhiRE "UL6iؖ]*pHl! +er^':@%Lkכ{{dq<$JHJ fBV8} ɥ ۉaX\/Rk_;NPOY;GPOt|P]$͖OLz@qV &f޵4@hoL2Mc_J%QH4&֜9ӨDt l3:FLy={A~Dl~S0Nk;j{b#NWSC[ fߦnOwyڍ\ڭ+7{2̧ʔ:AIAD-' qr W,ȲŲl<;TD3nz5ǁSj ŴN9WP 6 .kn^e=DOn ݋'y=_A T[߼?? .pn#Yb3U-mܪűm{AxYo}{k Lh:ӕBU|54䩳=v6/"^DCVdUDɩe#~Q'ӐL#vM>9츶,D'tbMx񇽤6\~b˺R rf^N;1:TbXA,ō2#gJESͺ8]ج (%3 C'b!yB&\z@TEfåpC/r9SfH/ޠyHJf] :e=2D&gm`ǙǪF&KDHɊN 9͂6:&1RN*qUN~~eW7IyXǾXދ8T'tRLVI_ɡ]#l?zݨ1lY**R/F`o? 8G: M$BQ C~ZL@\򯏻_^^vmEc3پ^g9Dɮ[Er}>RW1 f!->'ΡNKܸ$ T:f`ZdOZm=,*"fNFJ@!$YȣuSIJg @0^:\ʖ`aё"XkH>_"3qh^n\'`F'ύ (t67_ujd3\d8fbtAr=ŶI;w˫_{oAx%_ЍVq,|wV0b͂LwVT.Ѳ Ӣ=Od~@Pә^N>"/\M,mTGHУߎUgn\HW^y<|VoS#O s+i2cG{Z("*2Z<zk F%dG4Ij\xe ).l2D|F8!={f odo4l r+%|A7}=sYX}!7]Ң" ܵml'vMY,KBuIS.kr2yOk) IDATmJ9#QjٷynR>PREb5]/1p,( b{s>իf>D_z6﫢q"Ut?t;r.fVjOI=N*[s, esK%LY4 N?,bA:4?2JDfٓAOf#}͝R-KcNX|c*ڊa'#=7ԏ!38`u5̻1T̓k5۪-")xj^Owb5vn !.uy3.sx/JÐJz/&KikIf%l7f|d*>'6n{mkv2?J0÷c~ҩ6Ca6+B2p(p5[t~osDz6UZ.uU)'B~ bPfiflVS>*_R"Ʒyof#xulFR _<;.n paYְԃ{e :WfZN9v|`qNW6q6x8582@dcS r~Z[s쭰*7OMf;p$?ϓOsx/S=O06f}%V20*dzɺcz:(cXɲ$;dTtZfOIןsNR92;ֵ,͍$(v;ރ$c% $R\Lj:+[1.^AbTT 0j懙۟N5Dϋ"+R?|,U03_-r zioun6`;'E7uǟ<- | `8s Dxn$E5gOk&Q9< S'+FlPq Cz`OE0 2+9,5E#dڞw;,|F}jVz8 ˚`oQ YXXYlDMݜ ;Rej&e(eDeR6]{`cG{}!Qٗ<|&qN'? ~n) 56K"+3U{-V{=߭z0FUO#=W"{ <-7ׇ*}^NA?]б7hB,'+я3ǛO;P3xkPNO/62T'[n/Hb Nyp.늞Y\R??o%qw&)8v3 Z[,q$V3h;!RۗWHޡA4-V;[. YdI?ZG$`LjeANKk?d V -`[͟ܟ^VMZœYK5ު"VR7s@'Do4WE +kZS|kυ ㆃ Q-Y@Kn iFrz땧uѤ2w_ik`]w"'W;!u"Ki,æ2lzK?Z_sqkV6X~qA(a"q)'?˂ wu]'+ 66Q.|P[) o黷X{u/ZN<wfMw,]ugBlj?rKa)$ EZ˰&gg <}iCjQ`֍ 7,[jP i*g(BgH+ܚ/r>|۲F" PO {(rt|ࠟ'ΎsmM&Yݯ'?u@r2v5z) t)M6{RhF+{OStnzzqfh}]!W$7iq"M wB(YN[|J!۰ iCC!u x~_^٢%G[m[Bt黷X-^^|نvcI<lΖ\8@Q[_wy E\O廓Yq{0g(#j˼}dn/u|̶bVqxE-~0ʟ4U}?T hi,ͮ}*\>WQUA..WJ JC=Ul&CW>bVXx 6o_*@5oj: WjOI*Wf4'r]?u8}J-&wغn }xm#oa﫪 Kd1Je,Ӥ#g{hWV>!;G2]#(υs )v?%ZYbKwM6ɥzva7k3 ʳ4kK-^S(y4]um\J4ׁ:D.e~X)JY`'>w`Hҷgu:$gjuOF"UhH Mb]!<`xؘHmjLF>>ei#}^7¸' %IUɔml"=3_[όQǂ:fPت㣔3jJo4QvHZf|@FiSA:vIR KLFڥJ$6?@ ZOIL)◧[WLf"/r;7 OUu 2ߘ{$PN }-UP.Y7Q{G~>;%ԻtǏk#៞ϭi"MĤa h6 pثMѬHvy_tFZ:cFܪŷl,Q'y5F0 eC~QE6ŦV. zyYnr8u+e R>g{LMfj>y>PMD%z}7idbdbxCa 2ȩnajպI ;gsXaz>u3lZ\ݣ烈́?yzEXG+9i|uKW@s~MsRB1SKRKI%\7Lk+z]:#-SzjJ88:/ e Yh[jhUpz*nNJ,&&B\PNs9?<$Jt:IKR\ROܛ] w7?7u{yjrZLj>:h\<lh_PS7ы:RkkN>B[K ɦTɏ7z7Ր2-;lV~I%-6( 4m9shC^J{r" ?U8zbg43&ss=`Xwҥ˝Oxm@OM]؊KN6ވpbg;{=u }i5խZLze&#= ?,F4ܹ)n8n_$9R]L_gM˒͉M;]3Pw5JߧD l?.3#6{^PC*^hy,%/*Ln@; z^k_$gCZpNNn .Ap".lknJp4DjhZ$2PvOәމ~xٙ8AO<>H+ӛL4YXF#v:"]urP !h623gp5 ;+[W})s5`lbkz }Xl/2C I̊+91y ?k5Μ Lm{RxxE6YdbBQP 03o.׆v~\tO>e۳EkXik/"SX-CD{.h"fJ2ga*L{#=GB5 (*CsW`P;S{M ALtF]OyfE< 8YV[$WRk=a>93\EC.܉o> /&Zv w6'`Gq^<^OCM%Y MlS*Cg#~|~7`AE56]j d^C7)vp]vrrxϖbK9[n'Ls70:6QvdE=tm +Bڂ|bvt)K;w:%@-ӄ|Q~/M_ላlm}/;](KU.|`][Xl_פ2=jL(ԯ/@*B#Z^g jD1T芧M]G0TE^߻Љ+E[%֜BC@s'P:kߝDHSx=r }o? !9VTGj;'/W px*$ Ds:{;XJR؍0z|^﴾ViyZ];F,2'(,^GUN]~x'GV@!_-{/?q_)qL TKَ>ga9Km#kQ P<]e*qԮ8}'EI932N:F^U4B]&G&Q,Q_8Lp @̄P]2D[-G|B~'SQ٪9gO mߟ||IROvH$|g HK{vG=.LdDirT<31Hٶ(ۻ2s5P]dG}msSV^" ;OG?}oj5yB.$Edm:C!]O'pPC= Eo}w JGUEYk5 6x7x9fomrV&x P[*F57V*H'v| H^3=ۜZ|ѿ,5f/PZ-psM~$'>MQcqdZ%&.8hªe.}2zpJO$LX Q' ".x(a>/R?GL4on؜M{(@Cr9W9ܖ+d[`Z~C?'>!xٴid5W,1LIOM/ 1{FscYrx}"{33DX? ^Zts,ޚ( lo=b{͍۟S'?ŬX8 |v[ +ٚxgCC7IAu/\ x֙M ٛf2ņrD FsQ|/0ݕ}/({g#_ TolsˣҟKpZ}345$XGd*feM6oi?bw6ӊTüNޫ&n֦3 gNv;C +2.5FB٪Vdm)?NG~NP/ڟj/nFNȶy!gm,BVFNyyS8] \y3^6?g~c-zZjDV%&\ɲtu7yqCOK?4r43G8~xT_8;A Ȉ-һՈ!H_ >w? ;$Gmi345 ¨h6cCNVJW@ ja)n +d'@Oj-fhM<䎴_9{~-b,prI]koZIDMX5,iy?>shf{{|.p[7@0e)` IDAT)J-l3r'ygڻ~]6o>!ѝ\*LBA8*l~єpBė_ s_~P@ԝCՓ8VvL~W)̽q 1+ʝWP {vIqH5 v$ꢨ܋24-Qj*&x@KJ@xW#dr'~!'gC֧\SO E*dW,rδfmT'm ,hTd("ߑz ӁEvU$ӻ_`uFnC!LiZ7Y#ϱamOp.1 RyӱٲU+BrKV3 8veI]o={C^&ۊRQ7~Z/"iaڌU|/*D,S-D~6%/8?F~t~' B&!63ovHj:\.f'6ޭO}Dⳁ43iIˍ@9΍O vFD8v6sH@l>'XXgQ(@8WGBC8Y{@ Uwo8@S[A!{˔J*]]U݋cGs aItYh*BajB^am:CNo媿ECj4jV* xpyK8"S[Z,z^HXn4:WO zYG/PP1"a<E*~p Tӥd%XdX) % >A&Q-f4jF0xMҙM"$wzô`s¤]ϼM,ǕD|04 ݎd}j.q8W-ё.nTz[BA$פ!>xH>C0*)']¿'+}ZS pu(8h;JIuY[ϑ1w7p֯~6{ BЉtǫƻ 3sX)X"j8|7m"p= 0<bv>pPsmOXչM_X{i:=^FX:۪{|wu)nVV} u()ڨS-'NUw aPt9DOĽ( 4Ʀ$pugT:tҺm*`*BV3 %Z}c:[7ol'+ט=uqXBSe7s&6v]G(&@}0p'+M|svqIlxMHǥ(lz_uy줟 2O‹sw.o̕a9}͉2mT Jjt#͉|`;H[Ln3FHe!`"q-KLSf1l8w!8!<.b0Nr4ywL "oy]#^2%^hiFaUEtE2?{:<@}`5kY9A3aUCp#!to;Tx(τp+{C uC jsqN6y()V?80j-xxt&a!Q+( %"05šCFuk蓮0;wݧ{X=RR]cKlqn'&knq'!9m ['dzc A>mai% 8 ArBJLQ޷Dv<,\ UQywlݎ 8vdDv!Qn*%SKY+"/j:Q =d3 _!C gʉNox jFMj'L+L_I`vDgO=a Uu;D[7O #.=Qq E4^$ǿ8<_#r~~&;N-.U͋i:W2TG)7GYHW9!y*Zwlnz?j@vzJY"XUK֯i?5Npkš_$19K1ʽٿO9Ȫ؀c9 gdit({E R4U;7GQyumԧؒQo򧯯n'LZݗRSSJc )=Խ/>nhQΕ٘M[F%YNl-XW r*%AuĬCvHT3Uf0^y")H-~HH%љL{g[Im{s'B^ӹjE0 UowBoO~'zݯOD!.¹?Vx,A&RMId70t&\N8%pfuУ626Z RZ|ݷb8Q!C4^3{39⍯}ZCJp?^Xs?=wyѩǻ[FE#3'٭蓦QdCӑ>b+in&Ȧb^3'o(EpT=vX OID[=RiCm wi[!gӿ1|wo%}7o|߳(ł8I@ڑ <}6RiD-fHV&1-PNק},cP 4:;'$1/Z%9eJ$l~뉺R{u2όujgDGR ,y^ )6{:EÁ@/Hc#*}-L|jjjn=EHh/cg8bdNfփz 6F6oy`$1I Ow|@8-m!VfohUmiR,V(1u[I9>v?Ś Ǻx㇦.(^s /96ox>JV*N- +v)L7 8u I"]]mjʌ].Gj|eM38ٔ[iU$S~ŸPA  zDW1 6"\M^x33N% ]x0 D<$P~x9O3{~:I& b=4>)9?f:B@:TS*V 6坕0ZD)S% FjFqG.'e҆y.!'J[੯E=G7{2p|XTS!^Q 0<+b6yq)7ȧ9kl`|JL'{^ÎZ2Jh,jqONR RA9ud)v5mFt/һ٘BdܺD{ j"[IV޳/xv)yڂEG3XjM wr@d)EDy%O3)6LZy[S\ffE67-#y,59,aG\C_ tÆZ32dFjEhCGW{Rx]:9v ϐLQ>m̏T@7 hjp-r <5;~Z[[sZa Y|М`82%4KCAh˷VpD$ ;m9\H96YhHfd%x]N}O:/0m]KtD h8D!QTNB@&xɰ ǺH^v]ӉES$2]|vC㷯pk2-phcyJG29|M)d"9ﴃhx,Gg|oio̚$FS3iwiQrzDo) D@ϗXޕ{7{Z, ,xZpH0+薢-qw\^`d^6U>vn0+1n4˼]l~Y"$E:eNY_gkS0<=.'>DUtTW9grza. C4Cuoc}rk|4TC!ᕒW^_qf<}N'+jYca*ueߘ'M2";oJ nlA;"by7R=űϵ餣T:\6l "ύIܔ-!d$Ml2Z'>U//ɧ ]UIޚ=ؘU3ߤ÷}jt+њ a 3WXN ϱ#'e}i߻r_4:jNdX;Fm׽Dx}/JɩV1Y[uj6QdEXD$D6 =S׸7uP eK9m[$VK#P[IB gm ԑNg_x^Vlzm3P?F*:(\_z@ d;'M36%^*9۾˿u/p|Xk m[RLGRyo\ߧ]i 7ޏqV o{\;>׾  Dyvq8DdS <2vX˒"7odʺ\IT84ɧ5M&3Q/nniх(k bVD. 7cv6Y&NcTB Cט'r~A#ȐxS0E&dS%nLm`$OH'@+#:DskLhw1f}ܟ3M~o耇k[opI$_`\MRҥ*4z#gI H[,BqV, f@kq+)EGMG'tymjs9i%QHw;+%F+5'P Q m++?1&k怘ʛSf¥\7ls3W` ,ԧ.sA.z|=}m*TbkRظ)2wMHZYCITE<<h%ԠiRd`UiףMS@V(34m9T Ւjwu֥nGU=Ez"ΡW*eyE-,ۄљ}G'u]0cC"kT<\iiS͝&v!'JJbIؽ\SNQ;m]FGiD,R 2ܳM!s_e `@m; eW?].{KkzYr*%vZGKyH&(;zcs* y|oTEN/>_tD `KТ*oı D"!x;v)e dXOl2}MevM &?Zn: B4a4J,M}2|Ϧ)2ȺE%@6&e7fT7߾-=!H/FYCYH`H?;N~i{NX<0o<5&jp$!&=+bmĦ,{͌zwm8Th$O`^ %Op{:(z|؟)<aC-RNƏ>x$PP?y_AD5R-xQ'%[[Nbڔ蒫֟vՠ w1)<}TGLןٕ<WI02F{A&g0ėw}j.uY~-@n,@;k(F=g 1̴ֳ]'%4HQR$ivx\|{_W_8fT8Oo_S3"{[XY+nd*>>>pR\57W7Qܺ0'%T$13(˻k qeh8}nfXKBcP&vY`j(Qlq蚎jHS ;<ݔ<.N'S>N/}Zŀv PwLtJ?E4n9lT nK" k\uKmW#6 }@̫, u wr*M'o93 .Y]Z<Pm+i6aEdߝFOCu9si<hؙ[/lZJ1g79щS6S,̡N=4M'oL"kMԐ'~$T愻Oe`paMb ۾N1YL9[@QWVg)aw$TM2 r"7'<O!o@mn{H"M{+_xY kFO߻;ACT_6`HsKW&Ot&Gt#AG83{-?6c]߳]75t}C{ >/H0K .~Q{uKC_n*)h`:᷅dz/l;oCD06[lWk'0/RI%#|"e.)td H.Y~HH͇6d3 fbhMkKj 1TmzzqJQH}U)X4Kǁ\HR] Lތ~aR "hxh"g\QAjX mV&% tu4Ad!2X) v%Q`@l$5 m!$O[n[5.9 mV {ER6 Be$T,;jiIHfhu}@PFv^MO?K!A0PZJysnk渤hߵQ*cܷޫwo/{^IC,"&/Pcu|z-ڭ8wMOţoܺG`B[#[ {~qVJY}wniZ C $ʧ@}ZCO ;4+fԩflap$I<E,#LOdTٺ_l=+|w4XF8mtTTW(L׏99dߝ&4C&7A )GS$[qcه"r+*gF^O;ݮsu(P2ESWfr+vѫ<2=n{PRtVbEV7JReVcQ ⑷}>mB&X:eIb)yw}mtv5s%n0oPG1$Yyf8zjn \2&=_[Džc*Tڲ]`mDj>)2.2Uas2q?j-8M'Ҹ^]AF]Wrc*ʱ=D8<mx1GWfa^"A!rAgNغ 8(rgx=6^oMX'$a)r4CZlA.xmb%y3ٖX;iG^E մ*NhRLTQmILH)]6E6.rLR(c/?jt~82˰{Fɜuڂd *jTu=5J*[kx!UDC8iv@+2 ʶ*6291? zaE *\f' $?L%:Vj 6(oB_Ʊ/3(dN_ z[(l ܲѐȰ׊;=n◪r 0I)U"bj\f?T(O(+켍vBd\~TCbe=Jz?>avtקH$L͔& 4Ft ]h]U_H28A[{kTD'k/&pv(' ;|v@J1h>rV@7qVm;[At4xQqȕH\^yy|>Nq Ҵ LV ZFL)NĢ9{,ϳN7V@~;Xt #NNCi 1Y\2hT (DAP3-m'$j0N-`Igڢ *A1 JeJ`<߈8lY lD:*}Q(U%ݠ!#khޒF8W&浑wXrQinfN}(Isu@M|)񃋧6rЍ/./b}j"3Z.K`3>Z<0ՓauxvFq93/8ia{o'|0d&G g$2tA_؈~N3\~kK |5(0+"Z˫ΕMȐ-pD*Ƙ6' +|!‡SPvRܼK%\#Q!P* Y$ZT [ʣT/~)8|{On-v ]'k}Z-ߕ<H5DS5.}6!<~,{+H!#zk b*4V*A@-qrx\t6h-lfd*mnL9b7}-3In}n/=~//oP5VP$6 {%O]b.0fѼw 6kFL2&EkrY6wX ۷ W7Tzo+bYn>ypJ"OӢs=k.$xD,ie,D=:KӝF ԯq.46 ?: Y~ Ax @ѲEJ@nrpU3J;Nv/+E:Oux&ƹD~||'P4݁/܋1?6+jwJ( %F<lEV*eS ᗟjw6/D/6ghx{fHhA80³MUB;n\RYef/-M ;mNNsy&k[݀$Q0P r..?ԕ C5UG~%e&DbMJQplNH$eE7JӼr.:vG*ŤuzH+kLpiWUM@6b@$V,>QELAHUK6ݎ@ieb2MP4YÎSp]r ZM{͌Rk YV%2It|7#;Npy/nF YCal5Z|4| CqyliӃhq]@ d}5cch4DngJ% 2qU D ۂ$ЭBmȟݡ}^x`~P2MR`"ѥ5~7]"=Vǵ%¶;{ȩ:ײ e`mR.jRreS_`u-'5pA飵5?l><7cE|!7ýػ.-0QS):#_X': %V`' P[aP}x "P]9 qc 㭟{pu;m q,'Q*dl[z='{C_ @4a\Pq~l1R9u2u69{"=zjBȩ|&28^ۃtt\@}nye2YUUwZ{j;QlMZARF-46 6?eA&NPU ]ױm$Ex}D>qJ,?MN!QUrYŶcUeJvɫ|t#YIәjq;R'E3i;z]ޘr-wxr.?77mdI^Y4 ӧJ$Sf`1[XtքF܉$0ciE)qfS15Q)\6 <:sOQR} 3U׫4'O%1ht;R7Yavɖ;5f{A_U>A9( "/;Sw'd޿6R7s,,o(lZ`|:WKHg0@pÝ>6%>XH2۠aj{_O{ϟl?s|$H)U8XjV=ݜm$ ;Zr5vA&8qwsY ܸ^'Έ2՚-LJkq:zr94$I+BYn{p  BU4n]?⑧G(jPJgGd"JYžp|gWCP ,P]7H 6y%X\^G#AޮH] @86hFÎ jm=đhN)U <.Kc'W4Vo +iJ%UVE\!L-0 Lz[-N{"ߪ2md;hՇP ˙"}Nۧ6ٜD.t[o.ިXt(oC;'K/%,o-_2c_cA|z9U> "LJL F Pd05k'ln* i |[qF#gt.e6'P-Lg+3t^ɋtIc\}grI|Sal@_M<|s'L/JDchp$I#rjAWe-g˔mwrMP$(-eF4 Lr8]{藰 gM[#ֲ2d@`N8>A3L*@b p9[Gj!RYA7b[\SOR&Rʴ؏Q(C׉"JUj O;!n D! !jkMAgYG2L˂T[{$gت{Pl~*׻,mojEHo=V3%F=`f#C7AA6(tU eܚh;;vZme&l}q( v A0$8([o.V,06SN+)5:2Hdl\<{pEtMoډ.nV 99d${;w.Y:oi4N'voRQ%o5T#5vE n:ˊ02SmDNkΊX6 v#]w E?+X>dE6s :$b>/.-Ov?^0#P._.4m >ݳxNjĦyG Xo7[%gn# ??-knRP}l f[zPJQXȗIn] wipj0)SRu2;4 )mby\\M&p)iL$#I kVh=bTv|+"kYD-RH 3/wQȕ e(X,F3={{DFF^Zlulin[ =w64 `ߵmh0–x`I+,**+52/NddUY =zbFY9{@²=~2b =t;:^6\5Rra  utTC^HjX_l2)&ƃȲ ZNNau!q=<ۥ+Q\5'H2B<ZyVubcA Vi,Pz*]fR#z{ _22Bv1kv">6\MO>:`{LpuYb_#>QV4 0<Ezn%]aMi[ 7$n .-W=˸uT0<N&?2UT}1w')٣ (kTkP"Dr~$W_f isw?p{,s}aq?[(=7u뱷p; O@uNoI8PeY.J#PEӔ>aIHG NF2!Pqȓ/wnغYll{{yv3DH "dBzR [%AiR0&7TZX0$hL(bjT ŬMX^ib5m*h`5['OJYkz8JLGC]WϟS(TM"ѨCT,(-<4חo1B˓^%bY]$V? g\>EQ$u=2E.0ϥiS{+A{%06HPcj@P:nWD59iE!*:;Y$IK"Fz~X*TPs=6VuI2[e*-sƎ'P-HHx5MQ4 RCdl!2;yvkR$wDmRq4MEA&L嶨=6&#"+ F 9$4 K,P0UmTheE~@bRx,lާ^&3L8󳤯L_Hѩਨ0 t5dD/ߡ)w,)KKx'LІ'<={oC۸k\lzxꮨH1 CbԎZMI҉d @mTu:fn8'ES8y&Χ-W~yUS_ݢ5s,5ʘeտyyfc\FjSi`%!uk$ˡǍnsu]pn`fY}elm98), CXWje2f8(W(7gRMBxy ?/5\QFI<$ٜJ`ue!!n aUY+vN!@V$&/%*erCUy嗗M;`ZsFͤRtiXu>`2qb"KT7'`P3=fG74 Z5Br ̦ClR.6ۋ{}t*vͲ= 19&39/:MA.>tUk/r۴ͪ;̼2Z"{Qfuӏ,HDגe$ʐ[ʖٺ[_flb'*(zh8 JO:I$I!=@kkĂ.t-:kp)B,&˰Ϗ]ĩlџ+ ubq鰳Yf~XD%UͿ<5sՇZCte~#AN<ȒI HtDNIT` W\u0juZ4J ̚+ۧY9^(Pu~X՟_|HyHŵ<^†KBA!2Efh !|{l_x6l^Jl c1lģ{eQ~ 7*S.5=>p`H#3=czf4k%s˿~嵟)w4>lUJws)ҁc[[L/syKY.υIM镥9?eZ.&5ַX-ƁHh5K'ǧc\1:z4=!Z?R]WB ]XMÕsu^7ТZAH8z2m;Y 8?`9R3c'w<%>$%I~J~ ν142}Xj·uw`5@8՟e4K u~x~͵"+P^DUc$ v2 b_9?) 2Ҏo|7{XtFG(wp񆙽INSv"_AҠ7`O=Afl.=5Q\:cAAKRWT+&F`@3nx_ 42 2%lק `.gsa@)23P6IMF uAdᗛ+$b:Ksa^`<҇lR#0Dp\cs8rr!s]L!xYktsSr鷪[C k̼\%m:j \ AU&Qm$jl8/;\NJ ;=V2%l OmUgVՔ.BXWR粧/,?@QZkX]?*yzhVp)ܗN"4E~'EV2=rV%h,&@Xg톍B:l2]jU)KDnS'T@9!zⓢέU⊄+63eى܎Gâ,Ú mlOں2pq" * Zm 4t>"Kl~8x  '# !]N4Oύ3F%Mo[.,mUt3㡮!ۣoV`w"KB:"#)A$tt> 1&|uK:!K 2Ce[.wDon0]A5.1&VײjtO|ʵ 1"ҩFd&Fr.INpyDp`ivZ"rESywE"Q_k]oZ6-niXfY"*J.u-6222{>%J{5f&\Ay CYU|@}'6\5 ac6lɊևG>+/1%q<%SCv4JZ~qdwVu[GM{Q+ydY1"c&K?iճk!$*IiM2i(tǶT+G5.3̺`Iw?kGV#S*)hXc_ײէnًg@}i~q9RW>̇tB Lffn23?&RF@lH^xhd7n{w!wkz*GTZYX[< 9Ą'Q㄁%HbSp?'xFK'BR~ߴΓee88) {IPOԄ كdFaQ%FYQqNR*+{η?9B|!Dd"@(eJh!|{(k>'H236RNo=ׯ/Y;4&|[w' _{'#NW.ck{4 ֱ}.j"+2\mꬡGUBi#2뎧W{]4Mԭ=*:V1 uv%CH\|sV٠* Y" pBJ(5w)i[p;tdsa6(NT?S}ߢ -'Cq`n &@v IDATZ)۲e}e]0e`.HTd2Nm]3ZnҡeSA\W͛dkS ͒Y#:4lej9;K v2R<جStI'|K(2*#IGFF8Hl/aoTOrl%ui'O{&G|.N8etEeԮ,1߷j sLPT8 >ϊt}Y)M>`5HU暬AA%S;,Υ*{JFf-Dȓ}>_"u-FZS:E%Nܪp[`a1s2YM:0=`2 ɟ{FmU &(쀾w,wB$@nr;yC-6V2)Ժg0=Av5-gT\T])VIyC񌡐B%B 4*1[i\x\F_[q6Gpxfo HؘNb`:Ox\,KD[UuCcbjbڕK4Ǵ2UT 1Q{.{Rak #Qk%^y}x2N>ԫ **F@h(;"lTvJߦNxY&4$KvbV|Z[v>(b]v_^B!dA;7,ej<Ӱ1&㵢evdY& JMa5 5jITV܇G,|n(H$\jʋt87 6ony|&OP-5gXC8@Z;'=7t{llTzJlm(LwjѬ/{a'1~g&]_O:=~PJ@aG|57Md7N> 3BEȃʒa}yԃN Sښ)j0eVbFv~hJ~BeӀ! "|Qw1T;lj"0Gg pU _:nկ?'x;kCHHop%cc::@xbJP#j:ϖۑ(I0TC(D,1 4bt<@8 L,q>v?Z!`(msMEWju\~/ .F*=yχ[5hAp**46H~pϑd+7)nH]v(p QrA­>y+f`?MGQ:e%a:8fpNP*2쀬H2MO?7P{xfHضxeurld4P f El`RsגE4P[䩶|Ro\ ~mf&׷O'`JΡhz-?^gRk @vVN֍y/MBBbO5NGPA\Q1ѨC8o L 3}t%KĂ+35`Ype"D]؏2mSA>Z>ζ 2EeWngg@V¿)ILOr;&J洣PٯkXd x  Dxdu!b$)J:`6bi*B,LW'׮&zP:NO04]#NPV$q(Ђ*#\hl#u-Ҿ,K 6ѹVtrk1&Ř~)Ad,gȟ]nTVB6]&"lu \Z>"nvy RB( w'pJMrXV1<)%~x6mueb S\|"I/plZ)\z\k?K/vuhD#Oͪlo,8y6Dӑ1|b1SO_!~.~Nub&I٫* 3@!xT4ZerD]'*n+XRUea`ɔY0elIUE0D0\p$ )O"$$U0>BBbƕ)1W/y*ȏʠG`*hWy'n~-[/~gPPmƧgk.tPqk~OY*tnskn3iTt4]v/,t]u+0gt<bGnd'rD ^E&u!Jt*V|Њ.ZJx#xsSGiT@%3ZxRA deE!2"t'PwH,>O Ⓝ=aKc1A<>{ɓlIծG۫RuO9,Èi$ΟLb{xpBQPU RGgqx`H<-#j\I"; ;A);̻Q!N4%Kʦ!GH9;O2sO)[ժB=!Sѷ]+M}UqO갃uOxO [~i }[&%U#M[3Y6 \cw+`k{l앚O qc"1ͺ?}zȯuKRSLjf$2p.N9'k y_Ջ&0;^Wt/H, y µu*hZOOGB! Ƃj*dNn/\eb1Ef# 57qmH|4EuvS 1hnK[ȎDΓ 3Z$qSDTWدQX:cGt9$Av y>B*J}b o > Շl= oˍhVMK:$Ԕ[`Ok `DZc#!xZt:]If9=FUAx߯~|[S-R,6ݭr>| EƃJ<#DatC#[db1E$Ʋrkl?cP;6V?G #(-bo=q<,'o ղ#}^1d27ncvo+JUP,d|rQT"E8D=aK鬗=p$}̶yY0v;.ȏW<ދ'l ޑ3y؃'DZŦKk?n:O,xgA'@BL B.MI}z$@~Wx; zT*[gB'0#hl*MC4K6ŝf<}vnۑ`TAЖF<2֐OYÄ!1"1[-a6 [o,5I%U(n0c#+J2*ӄg:4ؖCРZnggH$H"Kia{[j{5 NԐ~bP~[-#^ ;?~n&&<80G=E5FպGtՁ! i?<kZp4tr1o &mA3.yc>)g80)cB8MEjCnQ!#Q]I?jN#^'ŷsR⦋-IbKTTA\nOFF-̎{87T}^|[2v~L^|L&t!tz@TՕ2t̪Ѱ%Vϟ2qc60)PY@~mq`ւ1cD&"SajZ@5;w*5=rc{~E FHAn V%dku6UЬȊ&PkfȭW:SMyKE&"a#=[$þKVes.%P:?"OZDeM2v85)u¶]v,G >J=O4gqj]h20%*~uŭ7\"SYI%TSM_|k{m1c)aw1cLuZ u~◯P;T*ʕVu\nR*ֹOsHU>hud1bf. ]w٧L"Sq“1jNn`!G% ѯsG\#]U!LYbېGn&I'\q(" 1D"qp3| 4x{à"N6lpdS&o!Yw3;OYO7\w10MdE^dY&4Hd*&!]!xLe0T N":wʓ8/,(W4LHZ.1,DgbXMAq\:{A!TSvM^ֳ@ek:L8~-y!Lr{CO}ifʔ?<8]`Y:s1PT|P$ P*viz!2'FviM! Q[ܼA~mg_:;500=B=W- DCB8\\ػWoz4ouujun%elO||5}I.*ۘe4zw#}<zloM+MbcǦL2 .iP<'X Tm]*WIȩ#TX x\ic}"$Fy-HQ!*FU!H۾#cK ú!GthzژK^|f o~O^_i4~GON'F"R(h|4A쿿M*&:|!5+!:*XS&qtN#ݛŶT'BK)F N;޽OmﮎLepH:ړJT%M"*,号]Ճ OPO(-{F ~^5g[Dxrg16W{?[gw+7ps#'wvmqs3Ihqvթb\+|f{̼@ kO4 7[N̐|q@"D qdKRlH8~DऊUlCW7A:I0W,5u۟EiTUyv -S"#xŦjHE6dŘE=[#8$:$hmvo5-gcX.R<LJa?7G[|*+9\zzmԫcXEE-iG:@(b[iװ ~:x u|ݧ-,,wvw Jyi.djݯl+ETaE:[r'SO1=A9쯒p|쉐(%l? LZ?k$c*5/Wᇱkir\N"Qcx J7MUȣ@ jW_ <݃!Ԡ2YiG`xjv]]<(ѦuH_x2y8F`j*fd;C1_/$H- :oKo>xd4@HDO2b"՚ȸ<<􆈪 gd?Zg+1%È( 9ՠ5AY/5˭@uɝ?!ԻLJ6p}mӴYˏtS5Wp z-a'8cCJ;_2nؔ g\_|hԉvV)údvuv7wB=5 ~ /;_}CQu%ERG(_ƽM3|Go"K }](|^Y(#O8_xU!>H vZHqxM2ju !()T;MUsm`k&- i ´yg -n [U#4\^FNU$ NHG`"Lx)Ai‹qD5" ;PV%^#Uol-hmsQƳ]:fD~t?i=$?Q97b .Na뙰f $F~ʃ2A4% 4v$LwVekEeӴlX;OiIBhPǿȋ 6YP ʋ _y8"J*fO?a˯D9H$,< Oc2Q)Mz6]̪7Q9m0ȚJ╫4Ykwc<1q*fAmNub !6֟?Q*4vI;EJ#2*&;1뱝) NET.Yd_sGGOF*䛗>'\ щ~D;ׂIz!_ 'RU4)̥I&\ɚvA$+?rOaxP!{÷EǼ%8P){V,*=#kxms jpu] 4PLʇ"Q c`끇`:oU UX8W<'2k:TTv4S]%q.E(ullt?ͼdG]\B?fB^|:/~{|ZFVnߖ<j> @ro UiY]SanM\LNr/9?@pNHX6bM6&_zM%<*$E"6 8Caݰ DZG\#cYQ9)եkzg'1&13."ՉCR^JFtGeՠ"&&u9ۖK9S#PHvG%]"o-a ^o/[0gq"(ajaÏT087@\8U1V~Zsjgx&RSzpn+Nql~l}]c̓$;+[s_+kt7A(Q(Y"Xh4TX3NxG8bG8$kbdCcLjd6!WpH֍FյWeUg+5:@g-w{=SD nxs>ɫY!Uf0!!W[=m "'EisHHHI(=79n{E.˸"Wwm=vOU m3ه$AJ)JBG8Ow|*&S6ؙ#?s}{1-Dͻ//T5(YW߲` l찇##ѓHyb*ml_-_%"67;)>1?=1M6Կ|l?}{uOSS7|U,g'IB(&rܛOWvgEebV1hl[$Wxk%< gbW¢[SꦊnTVjSG "֦9X*k&wnxtL'R}$JREFF9AV%\'+䬍8~^xx(QwR`g[ Ua,l.c﶐<.wBQlq"M`'CL34E;kb$LNOsS\K]@XӱtĠ>$CO;}o)Ϥmֿ큾BAղV1)vGVrLfr2bvE{'׈wڗ5֖ jx !{DE&Dw#scmۉ!f_y=~5:5t<ġF_iz ۙYqY@Ujn;E D2VӭDiܰ&€" UlNTv}ҥWzT-JsUڪ\[ܓRYl=pd0 +J ɽ7jpkKϝc|62ѧ|io(t."KB")qFϞV n\^m"btJ8$aJj0;X7'> f+j(\,.-Jek~'o`kU\c@U7]Sy(կdGTOE䨟9]ް1\ K}׽ÝV%M2@j莣uޖH*YYDoڬ(R0UWzOQu 1&?Sν&"$뻡!EfiJ%OcduPHSk-W-z,kpx}dڳ:٪G)"Ҁ=!SBɲ,Rb}2-yϩfZjeͥu6ֹ ~7"S z|_yg{= |^89 On/YC3(*} 9/҈[ׯa5CjU{-s:+s\9"~:RGϨkcA>qb 2P|ҕ۽7mCjQoڜd#TWg*}"3\Ȳ%n<(/m},o'SA=l-WjܛK&8Zl '$G>tcnGL?\oz텏q)f{N'b#Miw'ЩG^̫W;:V ݶC^N={hBww9ə,c`-c@5 ›]R3%-=U4'QȰPnzu_@(L>76"7I"ՈjEvj`VtFi͙/e.G.bfq|2h]G*"GϠ8 6l~j+ E|ؕLyBT= ۦb:ԂaRl/ vYeG¤ HbB\nA$d[&3e㶝*CMFHŘaK*6sDq*rHo mCBBM]r,ӒGo;uw3=q5J3UiN5F5w(;"r[x@}('l"OZ<]bgY0*ٍǟz 6݊  P)'ް? !* ]'VheZlJx+dSTIF1E\ާK+VIέ3zvKK˴(l(& 25=M*026ZtƵ4.DQ:P=Ħ;Oܽ 6̟D_곿ggF7˫߸̕Mʍ-k]<~O'"gl,g7<#~±fRQro9yW [[SwxzDjbd zS/,3>Ր(֊i&ecV܁Sݪ}zP;O!45F= i3ALEb'` $n{m; ]͂qI9O]D:aX[j]+:EΊ;cيNdS ${8͔+"Lʄb4F3Mr 9&eɓC/S,׻1=Cop=2P T[5`ăBnjT%;6TCYw#U)CT)fyoS?l+}D{O5+R #崤lm}Wx`鏸|a׳%nÚ^]. *~,'ߪv}Ra CZEg 6[}Fz( =uH62ApH@^kؑ<d${~Kg>f„&xרhn^ɨhH_dƋm thZm콭 ". pA1$}5RiyOV۟#T# <2J-^("T\~\ݻw(nv ̣Qo,Q^sWۻBN44M8JqǏYUU9|k+ԪUTCtݠ+).ݿN-EAúRD&.Yo mrl:z#u2/y([e*S5^+E&]enq?S;DڕM.\r"e!XVr\P]xe'dN IDAT܌4LlNPìYdM z:D]y *aFWnH\Z1 |zM]/0(E{žl5U,oo^;w<4RDNMuOyuB+aj[nPAc0¹1"\ʵ4>L㖨T;~^z HqnLh;/.zLm,G~*҇~QRj0ϱ˯8WQasY(ã̪6/)CkkHEѦ($%JN~7TEXp=6Rh{Gd2trN2T ЙCxbA}Uh:+(TTAj",6FtXoyݖF~(.Sl*n(%JGl۶R*"tbYCj?zs N:ibOt^Zկ+3>`y!p&OZ/eTK:DZ>qZ|wo?a=ɧfÔC9j\; 8b9+ڄ}-Eʼn8J DcjBkW3&;7$Uf:9q'/2"+ ND lCx肍bL WwPю!lEI`GiHShiz X@j]Acwn~.~C7HKy#/#$G;kI)Q!,y K.F5dIAUݨg5B,_Na r3mqޙ۵M>>43Ò$/| =Dh_._+<7xV5u>cn>!t7/'8Q9mGk>ZbsB-uqDM0Vx#v-Y;Dmޟ}=;+v@i5])'K:U%t8WwyS.m[5Vk} K'<]+Z!M;D:[}\gԳ9Ե86omm9ze n A#8sj+WzaiE6 kI*<7+(eLTᭀL\(J µ"ڼj?c(T^ճG6Gk6.a۲y{3\?|6$Kns?U80^oQ5n~kqg׈L6 ^n.|d ݮ.#'O8t(i}0}!9$EdT+sܟPn8 GC;!u34WKqz F|C( Z zdR$>xiP`w v6mwkM67 :"29㑉F]x/7$w%PŔ֕@R$7DY,Ojd_I(,0Zņ^ZM+R*)+ Fd8mCL?}駏<_AG6ܪ7y/|8o~{yg*w%P2 ooa-(۰';Ă<) C3Lח9S"νr\$a?SgǨ5 " nݦ 8W}|[nň/e۩ Aw0uâbpn&pN(Mԫ[0È9Pcy&O6Ua9VZ<#T-"ns@tI*0mG3 þw' f<uơ _A _ud2-g:xy,9}-yPSS!_qDcՅ6!9<-bI|頋Mĩx~1UmiŢF:]r7HH0o~^B٠X6vOkT6mDFOT@t\4( x=:۬qtS{W$,%1ZQ+gx*eQ*ɦ򔋽'XÑJi.feW;}E?韛0 jmZ!zs!uR,r걱&VwڛLG8}l_M?>LIlG5YRy8ih&D{ :V~kiq +Jn&R%HHBm{aLBRu aҀ5빶%EddL݌C>RC3C{j/^~ .ͶJF5a]bF(NiXvDb&LwUEArcG;J +\?++z?ߗڿ]]G|\LJpMOcRSXofo'oU8ݮtW^\F#-k rwx<^PTx͍}21o){{yR W][M{8+AO(_ۦ8`gA ) e6F.b?*~Sm06ۑ<?N r'dhĔ)u71e+ʥ|Wtrȭe0ZC b` #S#> HM8"sHxHӎe*m48sUR7ygwUdh N^˱q/񮓨;㚣iRp"JN.q(0vSeioP)k NJ67:d#&NqEDO >.UrnEGk6*m ϴqȧTS?q LaKpSJ{ N(J^mPo]6qWhK%Pۨ+-On3L'FmCXyK=Xm6er%BctwX SLYי< }-ط?P)}?SS!neĩ (ZwnSabGdU]R"aQl(-^?3+˻XYNh-tSUҩsbZ.E' '#e*oZ6R˶Hb3Y-sO( F];P%:\^ĿIF:{̆4aljy֨/mvJ@HةpKSECGz__؝Jrrf~X; mU31 Ф|awϥV*7TndE8z gkDZ շeR,`)Z5pv^.]]#!n( RQif`m쒘zkYr;3g#JL{UԈa"'7YjE{O0N{=`1{y9yXu #oEE8ԋkvTs}&ްYj ٗ9t$gv`[d=h@<st>_ʏ^[#/mztm>1Z ^e>'.H&d"\i[ÄGu!/tR!^bh*KEc&th\ئEuD"W&]4y6lӆ Pea( r!L{oI.w-1/9$DI1"EvCP:Izn\dUFƽmQrBSBS>Σr +@ }Sę;yʛ,v!c r\G6^F4M/ wHDv>&XT9;zo,s^"! \h%~|.64RO0{o8jk߸v.$O򔔠GN2vzld{D[QIbj2\H-TBZm[=1t 7$Epy"μjh?-n0#ǚ%>UA4C$#<zXI ]LdUJywi` 1$lDBғ 6:W!HT&7U8ذc[QzerImG#&IrNhn;;٬D^nLH.Jd(D XT\ȸsn>ި؉B>2΃i!H>C""$pM?x'_.\j|3EvHy-zɢ (wEJ2f, dL>w%^ZY#>XL#fR+i$d7 = iaDV;˴!;}mkِ1KCLcD?u  {4y8[Wc1JVP: & e]g[Vlڣ[A3m~D`Gd3/C^t"["fh2 Ǝq%2! q7t(e,^]yL|鯘P+T[d׋ Uӿp rN:\o`9m󟻲?uz[L -#>FFHF{/ű"q1RinQ\Ç;cDECC]5<;hn\/۟ƉFހL^UWL$Pݛ㾛ܷ0]r-0su1yicoe>$_dׯq8.&A*O^<N EF),NeT5*{Tѓ$PCZL6oo0zfueXRkY MxY%VY~k#XƾrB%[,RLo.$ p•DRF08hS4^#\>&>vɶlՃ]΁ՙH{ ȍ_E~wM6$&vMJ{XyȮon"+ De*q VwUDXvѦqꅪ(p#w!iYVltl",ǿoCt4i. υJH/e̾ҟL"!rcM X`[k̽I-R-]Y>(@mj5}:)Ej:pl&-sk&s9TLp9aCi6X6BA`s3Jc亯l@0(rj1rԻc\.c;Fe?*כ^BS;Z(۴k|NW70^lD\Mvp{]y 򨜺tSԥ [av5@i_.`x k)6d|f *l "n,"qw~5oD!jNr;~bn8V(&J$TrkŠ,P ,j>#U3L^9EuICNM CCXcmcQՋ]mJkY6^G-]xSzldS}]2B f4i>uCNZOJx#<iFYBY!LnIVvtLDsm/CnWKփN2j&/;~Fu \G|A tsGø^Hg+scGώ/}.yVkS+"6c mdN炐 >3Q@܉@-;$ $A({{Hɟ_|)Ns:Ev堾 VfAjL]Dy (0sS,&bTMIS)s5R%rJ|/M3p! DBxxkRYU қ?6 CDUt {M3GTLӦmr8_o1™&(A1P:hٵ+(Sb@Pegq;#8v~CCYJy'go&k 4;ܣV:+6Y\SMamvWڨp BI~wX3B/KvQNUCf<#Ld{[6Cd|?~%"'PnwՈ`$X"s}/^!jsɶ9_/@IaCѧmi6n>%.7%$úY”Z` !g~`gY48so^vi泟ۧS/p@ɖ 0V-5ƃ*}pЍx\ ¡ z \IÀmhDi3>VrzzljW K^[iNħR1X[xa~dIZJn3 Emn;".|]vcYq<إڊeX^YpDÌD*vZEc~dpaةMR;r%FdKhӁ-De5@U(1t&m;Vi.Q$ETeךHS#Ś߻FP%U1 U x;V B"عZO;FZ!+"JtФIO[dz#Mr)<\+*dbE{vJ`}HjB&UEVDn\M6EeXl\_$QYh0FYK,ϧ TB!_}yC(V(mU VhBG?b0m-klY'(IcA ־{Z@i%I:o_!O}=*3cl|c2ȓ{[`MqhBĹp[6 P-a ffQjDD T҉C2]]{chS1K#*w~۴Y\c d?wuu\e[IFA#6F 3G/HЭ0*W^*|G&o#,&޹m #[z O IDAT[ejj@ңt9QfS/:[Kb`(;"~(?{Mv>QNVl\_.5b6B%k[hd J ;+.5tB#=R=|eXX碒y[jCE#*gJ, U*25뢰"gu{kG/Lr/!4&ΝC9ᤛ%S.}ry0mf46 b$f  e  dC~Qr"Us#^>;i/7mamPۄ#??c0j&_\C+:٦nr,W̿KwonAC v"QEFU < 8]|JXDA@l~WUkL#V4'Ǜν6K$ۭ"U POm3,:|?iB?Rl1-q{o7c]-H0r!]gl(IdJSno:jq珌)V4JU'ڴR7X^)22$s8ՔFʴnf3$ x ^/阚˯vj֋fQ-?5uHAJo(r3F/LrxE15-J[γ+=w5G(x2p TD(PBfbC?5F3b !&К* DqDP:ڋ@i*6c͘f?$̧fMwJH1 g.Ywڭ>sA>y2U;"ߣgo2Ј lpի$K)nEُb]Rܷhip-XU}?l@FbptzMx eTMM]f*+W}?~* e6-5dEO"Uw8^M찲h a7*ziQ]ky6m |*4^0[DOX^B0&D&OL +s2>ۆR$IXaU,CQ/(IZT}/Q)TDhx߫_}o`b"O摣1(-IFwGҡtb?TP*:VX7L^ˢt.0<ęv\SϞ v(euyUw6qgMMgZcVC?*S?j7~bQ9iS EE-Tm6H,xnQ(KIۭÈmR(St+ubEܶӧc$Djb_kԈWf;걾;aB! U"UD}rDʲm\ծeZ׊bb6΀."|1 f, H6mKӑҎ,a'ȘE>Sqqd72,uaP.(+*`؈]w7H8$j;b6m̗(f~**[Urws2ÕUr=e>owWUWU3==|zꭷ|Hf6or7C7B#;'? >㧞ӗGQ#7:2Ʈ#4Rs.mplMUD4-KLXSO 7 {pƀa һOH< 6lQ4 ŧwY𭋰U;{5 .]DžxdX0X8O^< "KʯK ,]|'c*kj&ReaԞA,dƒjfcL9`ZVEʳ<첍5GjP.X%{3cn69svFqMgdjnez%}KD:2Hjށ$j{a !TT& ˂W7oaCTZxS3<1\'s +&C|g7^ v4_a-p9r}-$*J(W7yJDZGZls1 AirSx,l{& ?"̓eeHO[?ƱyBGuOU ^c)Czfj\T]}+E/N Ƿ A[$'O}~zoyXT.[Ob8Qۺ$mBCm >xt3=]2_j7< Ѷ_\푥_zl W%l!Rung FUb*ύv%VȒ"KR4\˥GBꂙɲR@D+8GyfQ^cD۾p3ϝdpeѓ|Q RgYn2nW1uTɾ_YOYV;V غ>mAǷC=WG=^/FJܭEVi `b8$:U\'@7F`[ǭ{TB~@)7 ۟  Q-X[-`c;yYDz*0fь Bj0E!m+i2OO8pO_^nV$_HS4cAE-]-y7B|hCAaN汅%7}Їr gwVҀ0!D!]61Diò7PjXwmz+RH"-שuFN h חpS'@ZO$IHHfzI7SJdVwQ( OR$qT\ &fغay{4trEę"HtDx8NXufv,fBRSK4#' IKq (,̤eXc;8Ol m%OSGQcmK|'HEbMף^qO.9nl8bk wTD~uah=p#P Vo@A,XXY.H`tqһ8 ސ?lUͼw ?Ry|\y7>5]V Lt;Y?*˭%&~xzYWu2w`TۿhkT*|e8,ޮt[_"<ܪ2-v뉞CݡU~¿zwl}MPs3blU6d$BPG[5AYC#~}4NQ-չu榗D˻$lO";Vg6-j3]HG-3zw22fEOa:5PPtz\{wJtZNn|g3G J0{i۴ ezuYo4E-`?OzꝔeR+\D6 (I/? 'btx,noDn+39ɯ}wP޹1zCCi:=wgodyF< e1?[Iygo[Q_ ]>j7O1~|x+ߤ 9Ȳ*Zt|P<;o|'Lݐ-շ[QԝR8_Dt^Ϗ&{՝r~O@Ijm5Uzu^zq̊KZ6٫1K@֋ϼzx߬KʚE%w8ҲrL@t7*NQ̗YY\{"2߂Q^;F=q={Tp赘hn9mxWVNB O[=@Q׿~[G:US,ƶT*Ծ"&guG_ott}0*F );޻;@%ԾR8kٸC<'ɢ(ѕek:V3yyfOC=( j$2s־Es<1žoB w쑈 DGn;JŨUuۇ8X#*5m?HYn#5Z+a* A {k_R?#Hzrz~k+yۄ~+EB|3MaepOh&QJwQ_!KH9ma\$U"`iAH_̈H/F>[2wL$YzB0`yWRDzvv ~GfUr&GKX\7xl%Ovn0x\ { }P[b)BPFikxh5}-(n۰655.c_EpH{kv+#Sc w0JuUO[-lbq9-`%ؒe;2:hޞY+2}oaQӿzIe*d)-0 < goԡ@Ӂ#('Ӽ}7@lb3Vݬs,H&"UhV/W=-rߦtrsۙC*:~8ӲJYd?F8K\z7!8y YJ2v.SJW0*:@PEm_P̕D-}>絑'`\Qt;A .(qG}T ئIq^D`IUT%hs]+j.Q_ɐi7#P/~(C m2k~ᵏ**31@Z h BvpEn$`ͬ{WFNE:>8׶ S3lOoR-3Da}S=ꜵ4n=xV%:e.u{&4Pжlr@f3z./tXpC`/-Gcn1[!x-R ՚N&pRp]#@bF>3>FYPP˶VO_DTx~Jq6=x Ax݃ƽЗrDG{$P,X _>ُa;\X,\ED9pE0TPOVڿ \jv-U4q4b#Ch+ SI!B 噅"dkEp&-3}/ @O4D>g*QQ$OhKR)y<9}mjuy&½`rI ԰1x;z9\V FlG&ךhx؇HK3h<_y ) 8շIB/=tQhB5 X:#Pxȳ߯.{cF>}MU*xSaՅ L#uӾhA([xEN>SΙRVfNd uv%!lD" n=m`vIki2U*pH' $MY g]-Q Ke#IdR)ؽr>A"5E 5캟cձ9wo0q\*azy}ՠȩنÇ| 1'QOЊj.ݬ7 y0D*d%LE>Su1w1Y;+ӧ']~hѧwjh4m"Ajdt1r%J.fp[TE\[V5ࢹ0]0n]罚 xTfjxM xqD> mj@]*7@ ·>wQ.\xww hp@8$6EX/褯tOm%4= CC-$IVmDX>;L}rvINEH$!2ރR EPF]yCWE[B5-"~v)t66 Yۚ W]34"q<.EI&H#6@5B P6P]XũT|2odoVMe|*sw_D2ѠL$ -S. IDAT}G< F|yؙT޾gaHu(yav{"ܢ=!|;C͎oeLceRFkD*H`rv%[ xoF r%\ǟgԫ&$H 31K8ܸrf.>4kEnNRHmRNRI3 {%^2 ܉VT5<\G'[Dݰgu)e~NZֱuMU%_尒-i 0?Qj9 iJ'mS~ְ]d=db{ZVPb!pHTl)7D*D$J EUM:wtqmŽm(g Tf g Ć8:)}'ybUP|)T?:Q*[=xu]"pKOzpzT+0:Fa)$"Zog>btײ_nI'uWobS?G])a2X,FzR©;`@,P]5YB0"2Ps;4^5BRSU2ѨF<bh4N@KeFzxg/mOanzs.}qʽ" ‘ ZP% mT5$~gܺ40#Gz1M;WMܝpw&wyXP$Rw(.ԩe/ENV>Pv(_VEn".?xLniI$0uy%)H¨N.7Όt%Ow kagݺy:Zc[Tu&0Uw:sصUH:Q,2>i3# I&CmnS])nS[ޝLc^d\)?soX t<}S:>z~@ٕk1ҋX''jwZ.% _'VjbP 26ku*s39'Q'2'""NsE.79{J(t(q-šVY7}鞚ܓt:n뻁뗖Uh1bt8?$t=z8Ԥ-aX8צ&{,/N=]$Mtt#nqW(LG7P+늠 sMzTO֝ q@(((H٭XV0fP@A$uLkَѪ.Յ e" Dԑ!NwwGLE/HGb7U5,b׺Wm s[OU lahCuں.ƬۛRlnTp[Sm ry5캎 ]|*[ߞTf|,H 9r}LO]^ PCITIIdzai,+TMΓ2֙~OU6>Lq~g|vs)feI8RpOnQ\jDETf ԜΉ_~ZbWev(# $Pْr-c1uVLnkpS*7,nLPE)3}elT$WcdF<dy#ߞ|Ddˎ[w^')[Xٝ׃Y(,o׻f%>BҺ^6[K \ףVбMu-{VfIԠ/*aZtB0gvrm~`(!EDA@c)<7Z]loYo֞~ ˌn3y5-^)bҵ'/rqTwIu26{in.}in0rA(oeTi,;B(Grp{mi>?}8Vw3<>-$JCԌi9$mŇa|┄ /~ /V* p+rײ,xLUM8jǬ7ſ%7/##;IݟRӨr*JWyyJuN=cPT~Y>Q8@^&)m:8v)T1k6 6B8LrbW,eJ3"@*h!b{JsE{- MHOi |J+L4" [n~ۀng[@7wkIvdbD.S+#BU zcJH>_CxbA#U %jU#-mHb25l?Ku!W-)K{0SХDغlPvNb\d>7ű5ܾI4<4!x(fSOmE^Bӏ?l[,b&ׯ[V~B$01#VT Ei<"o+8ku(.*$<aU9HaS] 4ϟk{R[wX~=b{*F\]cl\5s,BBqt$ju01 qnR=Ӧ d/V}K:^sgB]w{@.Ez.r54 ӰQ5ip+PY|F' %I_PMJfO9iX VFxM\ɲ]}}a+yLE 7Bfn| rQ*'8|JֻiI'ɫais}TN%Q$[wΌpW'6[K\ր=6h9dv&PJ@E/՛ ж @XrBAxZǼ ̷C0b3YF4j^b]D>4{7kh/6N @oㇵ-bS)JV4-) p /=ۥ4#9"zU"s[l[wʤ4l!B}>`_L#ΤȭՈD5zBuN%oJ~-ЈHZC7X]fms?`(dcǗrE"nf* C98cn.k|:X߅ng m_"OŬA%oal1ʪHr@gv0ߜFyvJ٠R6X+B۲O Rb;O`Ѽqٝ4ēQl̲4w!T>%T!d|1H^G<&37Co*+S|zku&۷%YOx 8S6e&O!{+y*+-)c~i`G6>l[ۖ3 S{扪6@ I{ď%j'z(R]څǻa"3tWpDMw_E ocxK"GRO5{ЈS>wM ̿=G$b'pD:JO~ԸfkےT##mK:wt/?@4^.O:ex2k9~)v' i*Sd)u~i!r)?^OǓ!&O1}*59kp@@#%@o3G0\M9 %&ر$Z'( oNpiǚن@miyvZ?#68|şi3|HtOS|׭n4DST/eZD!n?  kBKjGWTVuzBp,ēhpC-JK)wK @씺Wj(zm=HH0(ӳ,,=i9]^'BL"Gr %V%(}/NT}ְc_7 lF^kz8~cʷPo@,[*R/թ xFVh:^SIg?$BȢAHBܞ^eyqڀDa²ch8ˋP8~aD<=$`71c<|0j_{d>X7GF` z[e}x딪: 'Iꆄ g듯ғPw ?^XqW1p.{PQ]ыzi)? rp2ڴ+he<Me_jPԗϡ۵0iSɔZ΂B8<8٪S$-:"dT'C~@ҝcCA .gy:JA?$~Dop*HPeyډJ)>⹯ŽĩrO/$aEEPe !*@kevR4}AdqgN6HrrzP.ImdEbs'8p8{\ i WN0|1Aa8A דpy*i^?{…֞uIM-u!P=M`> e~J|[bc5E靆!ڀQXsxx4t{P8WJv Gwiw ~iZL5Y"A {{tS{?؋jzG iLCRdBj(@(!h7#=[W1t{Hg<=N,דsrXI^I^bi!h{ 84cdQ/?f`{dO3I"GZsj_bWpE EI.3k{F_ΟyڀO %{pM/!DڑD'"P/IѺa` 75AO_>Nuz6yyFrHe_#יn>A ;?gmX̾u{Z!6O^VM Nz ";6$tkze<[/5pm)yIhZP 뾝?~}(tw[ΚuޣG Ƹ^'FϏEdf@3D+x 1tO~@+)@x=77O4Շ%<4]ñ1 P~8A@ZEլTs%w.fr1֋+q]Ђ*? _X}5--6WjE@!HU5_O[..Y)8S`OG&8h߀qnllśi2.Vw="{ BiS'ey]ĩl{DMEN#l\Տg}ľ`!{0i]$@xǑq$ >ꢯRnQ]*[y uhc g7+7MI%TqD9.a64T{[)es}Y0]$`Nl)B#(?A jԹ"ȭ8:roA"ZD#?珅jDc?}ȻuuiX^Y4&%/c(R'hnG-߀~wwS@zD"(!9 Ǒnvȭ(kԫ:}e hL~%n x1HuC|*IV0<3L{wʺ`k.Q^W#1>#HG'o{VHm5//*2ߟҿykc?WGPvɠzEYVUw0Uɶ]~K(qQ[:W:W?&MaO":!O|,<ޏ6O8_ӐҬjqOk yoB ($& wrbeot(7 @ -Eāy?ާHAX%µpgBg3늀#6^ T_;oKs$B2#++chS -h5W1bW3YHrK)t} -/H[ݛ]?1++ً_拰NƱB?\!i%;SCQpvoZR+Bi 3u(lFzztI'P[ rNoo 7Swh3GnVܪDN<5JOGJwYjuzVQNڍk6zYdmz$GNGN͢rukH"bj$MBXM(-n^^,<2By\ |AXn2fLU.ZI_†5_ U_PWH@OR!G A@u.G +-"j"U`d߉4ʾ+0dcZ ,z5qoH6a݅(pxwY$3;r4K4:_~o}@7  c IDAToVlr<'ʘj\o}K7^eOolLd6uL?u?O+|kfD%& ASBFG:N^l?[GVY$i5sns/)Loo:ܣ #jGPTfR'@XJ7wRdž9Kl/m-b:קf=k9ug;}9ay3O?ez&&R!stT6eҕ6-N$^b@DUQ'5]jw*pb3{pk:`]۰Y21Lh{f;sマk؆NS>(W'{QU2j>鏇  f~}ѧ'Oe['jkBBEp[S]Swʰ!44+܋yf"m;L0f!o8+Qׂp)yqߜƫ p%d2ʱc6'6E=-3vFEdr{CJQ#%_ب,\\@Umb=BbsP bQϟ@sz7g;$NR}}#m׌8 va߻Wxvs{._erX]V!Y/$s/@xAY, h\VI(d(D%j:NHt_񤰄6ިs<3U\ѲJdNkTNeH9T{td0{O8Q){&Q+Wr g'zZHT'aU[6}S4Ӄ|ܶEOY` j1ïۀG'$ kS5:[كs5_w;J#Ϝ"԰,L&Of5O&}8 G^x3W3t'Ry~c O5W%}-M7uI˔taK3"ڗ`x]ڝ4˫eVK- -OݾKGэD$qs 9G;3JER5_1oIm/(s$Ȕj{md9p2n<@*ڿj<A-Ma".Z 0HY1k24O~ak6lnq?Hn¥ѿӻZw->~2\Rj&sm bW'eMefر]0 ZF5O}(YL'h==ZDZLȲ# 7*u ssޛB)|r;&q"B=ڏSJP˵gxv.vj e(YKu{Y[PvS3j|ŷjts 9.]'_<+@\)bL #IΌG <_jQ-e檁hS[uP'#bo9w}X\㵟2.|Dz5=0տ}KnToGG'@&EU8nk'xTEk@L"&GoD,$Rޚ"4G|=&ƿF-yLni& !poYz)K9S;Ύs9"@/J,] |qJk=P jӷ$>Irlݑ G"[5 lUc;"Pdh8ߴl#R#/k؉D%B2I IX-dJ;xTg))Đ Rw3-p-[2Q;`Wbٿ7(;щ@5CQ$^xn+Jo) Dlʰ7RCӭц Pk35\#P9h瓀ۄKefw_K!/݊0nnٖTyG/H|qjg{3?{oaw~ѯ_@7`4mR)gc˻[9q#l%r76Toj7f-;>$ٔ(Iq83{lwFh\ħ ENׯ}+Q6za4AFu'~LxDβ[EraĄG-^z,Xm}L$R}=~j5[7,8O^L1H݁YL}[̶B;l7f;ûWx]MnRW/./WN˟:H=m0 AB%N%U?^\E_ z(j#jX4uD@zG%cHtU=w/XLF_yMQho]"ohx2tE%:޽0'FU|,,8;6퇳]Է.VYDYDT]?DmG W4o4~/YS/ |g ܺ:+NH;9wo( /ej6-ے!s]=&\ywVivLl"] •">V,qn=R{T>d#բIzg]z$+ؖx2Lj(F"YM]l; ."s/u錻1夽\H#l;I@LNyc9qIN7փh$zv[Er=~*0֞\,.ԋ'I_s^@;w6@.eFՅO6>ֿP, o{!#+'1Kt_D./ʘsDT1ʺ9So6w!V]4@Gia~^}P~V;a/FcF+E}/RXn' l=0;iFBٖ4&ňpc?qBg2ؚҮļw_q߲u[}R~Mx>3?%뉇!QUJ'sEx|-xveX9ȎKt9DlPE&G ⩞ wWCԵ)d0\ϠhK̿5ޢ_&<n-ou}Op/\=xW/;p/ j E/%p;+U.ۛ$vC^zt֏NT1Wλ݇iVИQ鿒" ,#$NcMM}+n>ٶlr.;&ZaY6WoMߡȧ ީ2/f_IdBt Fyfr (kPo!$b=^e,Yn%eX.^c-TTӿx7\73f4ߛfRpk/}dlugܽ1Ӕk%Ry{Q/^"|q4* ߛa`EWxqFZq JT@FِsӁ'۾YµE6Q /nMf?hTҔ H<ȅg\v+)U'@6bjo[n2=JV.vi;PK>UCYyy&?^H!>F~ Bdm#lp]!$wjmVb= ߛaͥK^t~G6r`T+r2sD _dA$3 'rl Ehrm}^ރw;18>0kؖzg}Q_)id ][Cb: ޭ(HyDCJOcL4ډO<'=ݺX3&dn[3GK@? fCSI뱠:dYD'&U/{%{]UmF@e|~X*#y]y?G 2 5<(S Z^ШK,^_FD?sꗞ 8,73ktmx@ϘS6EKerq_ .>5H?_2X' adu.U-'XD_xoE잷۔䦋*k⮈UVETl4!}\DY G6q'P  rD="Qhq[ 7"ۻ,TLfLoju 1r'jվ չ2WSz?(Fׯ/iCv<2f6c}8F'Ois e.49KniuO_nL0-:Mwn:8?~Fk[Y_w *Sw2ujc!?Z>fd?w<]F5wYY" 3Ef#Jɾ0'tZZ(3`kG>b˕.+ LB4(n:NuK7;^eD ZW\lq]oa |y=]SqN}bT]= EBoݣpl?c?n}!AD !*^t/W7狿ws{&+'1Gv_s7[ϼtDE!\oM@eYkY߸L7`?Bc-6I@\\0L%MFjO딻XOilNM9M-]%Xxؾ_miw>_ȧV1YN> T{חLN^Ljܟ,ѧUA&q)VY*K_P5Se=#4]-J 5L܆cZsWjs.Rym ]\W? :gk=uۋ',2z 6j ( =kt7{D1P=uS,?AO,HP_כōorgc#&58i.sܕ$eSLĆ(rݸb1.sbvDaH1Ke-ăߚNEN'I DA+񝐹8YMI o,&rg#r4'N' [˲1s'}(|F~7,:(+Ic5"*Wܸ-O8?J@q;X/ rmiy,ҪTK+mQT= n %#l-ftJq;)>㏩$Υ{jʠ>W.bjo=uC‹_(߿y@ ů Zjt]V*xcbyܮ~3ZWiskavf+wwЪKSNZ}*{KT5gJb&%?s2A->=b׳N8sX̲8yp< X1+ fK$R*'/&WڽGNFdbC*ՊtڟG=bl v..c'\Mtwt^?ޅb,m@6Ec QuBRe^@U3Z8EռL<Õ1/@p[~Vw0׿K^XO}*ߵ\nv>7K7{73#*['⣶x(~p{%[*Z͓Oq8 'p?*b,v64sgyRu?7#=^択Mziĕi#rPY[UxK*5hH>OgF ='Ji;S04N|~N^:"ʶ\n8˽DWl `G17EtB,u#j*e|e9 < e3l 85K2DOz"r@zvA*,ʼn,BdV-R(gsT2%*KE:G]Y"#gJ~à GSBٵ;LDUɓCNEdt85!Jj> IDATES"E(I?RH6Q(\!;Lt~/$'[n uozz4,a!Y/zG)>htc/<fC:̝ ~\ؖ˽kk7sd[G ڏgZ>wGxXBwƚ%ѳ5Yn_o=CdzFq<˩/\ZU;şz6&\EߟܶJrX Rpj=k^{DaE8uο}`C[JS9fux/M*>R/*Q]؎=&mgI+0cWN8mD_̲_~] 2vuP\Yá6Q3K4ve)!?fAsV[;J+X>u~7[qyHp딧;TQzzdHno~ERARWηG }|"?:b#> |dOAz=efn"UNj^T^n*Csъ5߸S_&|I'χ 6ǕdueV; p1Rc|ߺ#S$#tfrS[^@Q%RC#+0J]eq/l}D3LXuf# K'r gI=3 @p0U3YzwvGg1; lji/\M7՛_ߕ!.3϶7#Obi?lPRy?xpŚido*+(m I$:C]itl|}f_+y<%_8ϥc{U[1Yq19Gu!%*ڿwrޚc\>Us#H+ve3܁ڌ`G|4eqEz]T.,6m&q@9a;\%9 ;.Ok',Omv$U&4D*oj3|RJLԫ'x'c|rz ,|}޽߻W}73zZgDN͹/퍵\vqfNh? MbTZ_|g U3LMgPR0JoOcW!( {]n$U8adsԪ\yEW%9K'%0s^[1'8fuwkNX{_^3yŻL;) ӿ{\Cą{kiꈭt-}LH]+1"U),rN./ʄ&|krY-H̩/<+)7=WwKTeXWyY \IN' % 8do/WڟzIsuiIQB ņäຯ)vpZe_ј׿Owo^[?z@ܖi3;YM#P;a$c$p2¹JDA q ?}k7r=SaɖEϦjŃo.Rvq}"\DR$lfw0J̅/}[3o].T@;f+̼ߩZ騛'aq8TYtABvRu]DxCkCDG.phK` "fWҥ^<3XtN[ŶTyH#HꥱzBe&OYЗ;G gSzpęk dqkݏ,Izz='_Ȳ? 0/?'Wi*1rpO\9Jnã_;Bk䳮8:!KtpS'{nj:fe曷YzbNVlU@obis0h7B"uJe߷t ٣ߚ^-u;VnFd!D(@fp@dxh31›6V\TÿAuf{R%,3L٭{7ܻ1R*/FێR}=`z77y"H ğ fK{NX&?w:bkl窍eКo]!rZsY%$Mm^xwZUXZ®ƫ8pc^O#ÙZ} (\W3UĖ1"a}T6RGvTD8عcn [l-T8޷NnAo+v3a4"T /b-̱{bWQ(9cS}6l.Vuk },ݝ0 H)LO<Y~~LGod,\>I}~DlX\\N]_"z*~=2Cu$Y@v;xMh Fx>z方ѓ=DOl>,ETӤjOqeoD=#&_]*.fK׋(x:3a-.-q]Aж_X;IcX2fM!<9% :[]6ޭTtcT b'"Of suǴᓽğ'Lon`,f9j:*qGd̒le0ldd}Y}LOh>h* ª&LK.z!KXdџLh8>ŇK,=[!8gޞ\F*vKͭ R>uo#i\ [Ү%~ե8P+kc']ܯ#kG3a^|:*2 6i>SĈ#H 4~ṚcPmXXil'K2fkmaY*`]tvԊo/Lxly* ifFUa2gtjôb6 Դ(H9,O0i,.OZ G!5sՖ^Fѓ]Sw(gʫ:cx +F DT6>UD}3zlIb AV^}H*H2uH[H!K3UJ9HB%~ -DTh0@ ÿ D;ٖQ j؅*ԉhy 'S F6Q(蛓+cp˯gA|VQ>Xss~wվVjwn S)'{BJ.qw6boz.W,Rn}tXP";.W9ދ?Dq/\wnh_F坼ϪڌB EjR2Dߋl:"V.T[>A|+B,h&s^t"^$yKWtc!|r"v'-BF>]ݕHW8D`1=Wk*+|TcKZww?ό(`w;w꒐+i6MNc /}:qdM%f7~)`Z|w`Hٴwo5B%|$j\Ū\gdY=TN8,+zzZ9jDE m1%;.n NDDkS~_9buL{5ܚژI(~>>ݩM ݧw@J w)B"7ڈ N8X,d$_5ƬiqQcu:QWjO䊩&$C/t9n/ӪĐ'XT|ï]K= >c&U0 ;֗4.Tm߈.._UȿԾU/b/?Djll1ZE8!U"J}ܜ.!Q1*]Ҳ|"Urk:# #͑TR=A@x"g8Dfj|-*oGnnoΟ`j[/ho/h 9%-.(+PO4僄DJO\%!=aCWbX5_{kUՋDuæO%iJpw:nK8 @ 9ѺGq>ZZHxR/^kx\ )D)۬HJ%;[(t7&zy?-ùe:5Y;SO+!H۲p]p*TPt.nnv&Y@cw"zh໪k [y>mIH鉫(u7AnY-S(?yiSg+ǸlFY+ PE( m !b8Deu}0A![(VIZvJHA W dFC< %N@iؤ T2@R"_0,q?..^{^L^*Q5IfbV-̪Eu-wh,ҶǞ㧾sg~iܽ; gք*FEcy|n03kUTLEMMrqm"Nc*'D)*3IQY(>\8չ3yf*۲#/nmUE ԡv :@|`ek3egUj8Kf~Ȋ 0:!PCmB~y ]( Ēk" Zk>tĕXzQ'y~;۴Y|LV3/Bu4f y~ i|sCoT QTEXܾEr$B(?yqw}Z9,#/B^t/àr#pH8wᕫ&\$IG}Euis yARaL4Wo5J6wHYrə.e<ǃp bͱF@Y_T$BڲF-S#P'\놕st4t+ǺV^5I EP"U].OFTbI(L6u$Dߓk Pf֊:t$_8iJkvwWLx,$ۋg1jV %|SRk]D/9W.n.i^r9ayV9k d.Ss%jEl] %lF }ZET؆I UeI@vN;B?k 12hRA bh+Eۮ+zA`꽟ZiDH*B$̣қۃS/ neMt,`W ''ğlmY?M$r@F DT IDAT7nGc!ǵ\ué(A%(bn7yD ڼ"1'ffoRGtOQ+WC֑K>y)4@yCx/ek,en& @Yiq*uΉ'#%iBNPoGd 3p WqeUk\+ Oep\/$8u]j˛{vtjai{Ux+gDc~P@b(-r^T)<$w0kO$ڦfBDB İݪy״Yx6%H,M.2pv0)^]ְkfɠ6_ UEDUbsf{WEIDV$C ýئP81pg˅r\T'a $l+AQC bp A[X-$]'i Z1G0!#7wmϲ`UauXT DmY .ĶQaJ=|A/{5"—;=E]0}+Cf >у(װH Mw>Gd(;Ϳ 6pnL_Us-(0x!H(ElK6E:?%c 3260]*o\.k*VgK Itd9KH/=#]mcN]Π)r;pU,U\2+4e9ݷh_V5>q}j4%yRn]Z1/؟WZ/C/_valc naV,!al; @dd=JU-_1\@ D &uQdTj,ݙMܺ6GR|~r6P]6EPVa '*jGbE8M g$V6}'=w~Y,nbJ)AXS LpV KD*H0K"bSS,aWۧ{]E+~G߇#0}HDէL\,\8{q(0Ң>6+4sF=$Pg什, EJ8Z T̿P5-Z@]+Sڧ39?$o\/b.H~I8RR 5Z 0 HhET* ea~`d߻L" J"5e6MS(I^?:N[*bwӀcl(Bu,\Rv % UJ 8ިjzb,L@93ޏ;3~Qr ѪIB6C};n(TM|vݫn~4t(] \U=2UI LA<poztˡ=2V`iܕk9e~,*Gcf*ZE!ͦZZ@  llAkqWDe\\A$ FFHtrkxX1ޙoU<, Me*Œ'"*(9CP|cC1k" \ҘSdLKYB  %"?b$ 5I F G)IiY2m2;Ae8B4*5 qתP>IhnRR %<}WIDY,T EEY9# e#ut(:HP %(66T6e9h![Ӎ3,fbc |sAZMwhYs6$> rushNq!F1P)> Z6$c-SxWkZ%BliRFw_#Z J(/j+iť|ho.9$vR@]+Ex2"-ywDS7i2сDZqbင+nǡ@㺸vq|A-{pgv5+0uJ)Bh'Li_x0@GO"BmASw,02csT^Pݿpg{׏8ĸ.~eףW~Ar%Y ֧OjbN3EMJٵBP(SY5Hq3 (]E8=}"|Aba?eYX̽u{BVgx(>W>~li9Ù0jeϋ$|N&Hb{e rNcґx:CI; yT:Diog_Y>J@O_\V)D(C yhI*֣T⧢M~ՠUc9Ts%,}  BQ/ bd?9η}O| ]1"ò1,jL'E{C :yX,X$~Ĺd[!$v\WtZYP@4aK8ui'10M_wXxj{/y̾D(M }KLn"#h@2 ^6mb XC/kEAR!dUݓ 25ݢ\ֹykWg+;sOcj&Br]/첎 hnq2іkgT GGEYYc0Dr(}8b'y(Ԁj]cQH@blӡRИ\&O)d*jj yyycn fIO|ȎI9ZW[˻MmUfk7]GƎ$c9U,Rȑ)(" s0z?zfzz3M?U]t|<}hw?HK IzQwJ $NՆwU0L ųuPW+HjD-|HCCI&P+]Fo! {H/5Ԫ2 UNئCvwЎP/S,$_IZ.7PWc=Љ~|A/S.ܻ_:Mamzdm B6DZι^~-NX]%=[gD_Cmko%]8ݦѭn-ސ)N֪Bp}w ~WAj2j]ȢU뢢{0E))`/PXiL$\&oQ5?PJ]4v[ebzrZ+]-2h Y13gZKmnpwn%iC> m5܃ag N)wy2zB/xB Mڦ+nd ? rZUgabǩ=g,%A%# w8x=of1-^*<7ƒUdii]^ URbrL' )\ z:\^,ˢGzCD{ȲD&~@x=K-"_K1W&t`>^{V ٵ*]L).ܾC߱P3&j~|-Ѫd0S8J$Bz{Xzgsj˦qm³ӂ@ lc5J*fެGdts=-ӷ5+ܺ]dߏg>Nc޾Q$xZr*O(>O2v6r}QnEyt4kcreׯk;E]Dz(U l o;} ql6`Y7M4}лB]ރ1%[??ypMj&ǽQM )CS^r8罊Z"M"GD/Tq<~t,bfiM xk$bvS,ŗH`Kn";^۱A[  Lq;Duab75, l֍%7]2dءΐiLͫ\/]f5TU_qYXpl y%"p!<>#!{$7CTD}gdY²/A\A(8dr2JU5,r0MBIE+CMfvmVEAZO.\\MYj$I?|Yx豓Rs~iu{|j(^5,q]Q[IZ}LdbHZ-=$0%0`dC6P=.}.P3q2D%jտOj`Az斗 %;khW1u C7IEY-o=,q,cn!ڵA[ >SDy,d>9Z"QZ q->"7&*{x~w.pq6-wM6p#l!s$Z?`ȹ~2*x=FJ@%|lzKqkbD璂@k"GV찴0N@] P^1ˊ(e,2 |> ckvXȢWTffcw7x>%v%[mm+ u@}+fb{冊pF6f-ft.(!ŵfofw"[((~v1[|>"ttI/@w^ƃZj6c.!u>DP x$j2˴I>[qԮ\L曙ɽ>d8%d]$c"V/B~LUU|Lr8}O*vC҄*Fid0H+aYoт&ք\nf,SÓK "`POW.*bap\ oЃo ˢ2'f "!}ieh3 K}q{xw(jKbJ,>s۳4 YaE?4}ZL癜]"'syfng.^&۞>"K̪QiWSxS ɐ_j0 A87B(A+J֡.F< H2D$"u(Nplrd&I6\+cPtdWÇFJkZ#J""ק19iG#gIP5/9ֻkoԡL`s*/unm،et>M0QU[)v5ܣHB k??Wlay*Gu$}۰\,eT=# ‰zGjQcդoe [1g@x]D$v,(6y`reTCFJY{Nv1yA]H5 P\ @-Wwy3ER#1I Pv zx_>ǺY0_X̾"8+,3m?|2 '>B+&{>mzzZ@>8{gv!R`ʆ^KբP2_ҙY(/Lo;. e"x=X653[`Wp\k"ʰȌeYl4ke}M@Ug^ )Τ8!I?ٯPl]mt؋?T)^`B&qG Ȝ˂uwTY+}uDi}j+a,$)]NK9|>_A$IAR,e-qm,[WyNj2 nyIP$n98KOC 񆛷]-p2AY%i㸨 ]%_!u] @hj"+R!_z޵K( edހc8 8u{u,v=r::m:x },zB #ɰܼvˤB 㙵FvJIp soS;bt݄mx]xP<#< JYƒ0lφj/ʠj.WQQ6?8 S`[5~lce|Y9] 'q=RYGdD {HQZM 7 .fkk q+Y-:W'?/>d`e~dMJU*"˙] QoMK&/,Cx羆c#){0,>B8%I&FVĕ_EvXoCRŤT1QyL% o2m/Vj lr`OJ%۴ Ulfr2Tm 蚎VЪ5ᴾ4cW星ɭ]zcx} a3fi %rP,@n0թ*fPl18НaVMxQQ.,n[鱗؆Q6Q2]G*qWu\DI\KYY*[,OPK%,&KDoL\+.m ٵȒXD d "BTANqMj zύյt^q1K3}d.U晪$\,8eVpFd|6SjگX?9M zGѓGK6j:& zB-gu4U0pX%9Pgj8?pd,ĉ^M tB 86Iۤ/F̵ `MzmWn99q.e3vyFph$Ix%"M(.TXͥo^CۤIh(@+~\!=hOON~bB1}0}qCjޤ}n(3\My{!@NvO-Y٢ [1Fz{j֛nU(Ͽ:F ' 1XSʼn,YY;ڍ!.ĕa[78wCZ 7f dk ?}ty]&  xp,0T~DYB뾖#!OGH O>. Ѣ-ȩ# 'cx̎_,C^6]rVb8_1l&iR6MIBJE=jM5[&,^ á;Y6Xx$Ef~|qDCoL vq⾁q#uPa_{GztSax{ԲT@XaqL>KkQjDR| 㯏sǷ[{IC==t}y~o҈j+DxG=/ȉ.o+ݽ}7R|F9%y_-`_` “}񃧺7֓ bWMfO%cLV0*L}} bÏ&0K,\P~!.۟(n\zǙ|cl,O^FS#wYJ&fY= EX,UP~ę]w֧9jyȕXν(gF$} qr4BlߐZ db-"UfTLJ_<! x %#(~ZI jYp-jH (-ԪCSDX%q$I Ķl ܾ2G!SnBqT/C֮5PѨ]at ~wUl&vTO]͟=]_Vx_ ?z=4n_8D?CA0NIʨ}6FFB d?mhÐ.7 uqW|Hm~8P-sF=;0:ԅ⺨ 9ԥBmU6?]Z\K#l8]uw5n#4$9QGDAաF?jUp) b `Q}%wE\ sgG+첉R<gvz%lsA|~lbk MW <%[ wm\W{(񮦙rW~6@8p\v>#Ye/qX&6`j6q0&ϴN2Yg>#7Y@<*!Ic\Xtʪ=p8@Tj([~GdؔWX6"zYCD of"^nyFZl8”xez'Y§?D%\2LQH֧a3,0DP֍17w,?'}:Ljm*}סC;,AOq+^yضZK='YUz9 +ǯL}˿~8/ 4mpGOK,=wyE};O,bjsgX\b O::O.uPC4Ѿ`S*<ǎp,qoi+iE Mkv۵'>}<  !X>.\*9N,pt$̉c-Fm:T^~+"rTtO[̧-C !h',VkyyIl飃+P(^&v[ecAʹ2T$;0y1EY$2#qlsqpXZU1sggVDTk MtͨXzXQ|`VykoK (LM⃽t%;Ƽ?-,a{6VK^tg3괡 0/?NYq]΁F<<ќֳ]Ew15t814KzHy?<қTJ\$?>H]5(Ofxl Wpqq#}C~t,~+UL +C>|?ܦT-pE:欙i6iu>oZ6|G - 8ԣ0[?eMOY̛ qδnQ]eRX|Q ވ@Pod?T^RM˓UJZ|8ƑLJx`6.H¼Zh*&'8,}Sxd%>Vx|2_mɭ3J殄kʼ|ՁϪVKwnO_zGNHM/d N4&{ᰃ]_cmύl 3ڻTK5~eȮ 荒Y(7觰,0s9-Gk;O>?ViD'3RIhЦU.MUƫYͩkTqɻa}kU5ߺ?/74yadV}wP(/;$a]+\ǥ' {㒙yrD^ҩ,eWBbH7d=Z5?eB .g8C$=%u4ҍz;+kpijς+=Cdg&S 8Zc-Ԙb1" `IЌMtx">=q %E y 7?IsL!C`y>._ʔ^_7h w]pN`Utn?jQCCR$WvQXz}u>~!@ng~yvR=5rv᭶eI uoZƞˢ/x{=f>o߉nܼW~іGr\&D9_͓_Z&k\Z6i_ 'B+)B?_uuQҹ{)oyϔ/eI.7'u;m+c/CS{dun3KUfkf;iGoγyzkVe4Ժ $2bd ۲Y[&XD$I+FjAZiv<"UX.4]u>;Yx׶b5m4Ϙy]?/4'C(CάGHӿ4J~׋:<͇ɮbZ었:6')oSqntYe7󒼹j]+>ܭ yƦeSΖv\ A$y-t= F@ 0YP-o|?fLp'>3B`sW𿺰PWq8_s 0[o~#26BbaL0 6QY2lreJc-#QrKPU-! ;4*Zafަ'gʛc|K }l"{2d_R٩{d󔗫֎azN'ϔzuu"*f ~aK$0D-2oTٸϪRެnV|칉~yY~$'>tITͭt`}x b,, ״r^\*eU 0GF8l]3l%޺]\0Γ| >+ < `L!ٺEWTR:U[,f'{"QPޢ1c;̍9F5NǶ?dTNW4UgN @HT"J%ćB[pP P!SfȔ)tIY߿+9C~yISl0LlWXi˱̥ZAd_s^.)ŬMgvX8T 6z<[훾Gv|YMq IP/{!ek8p|zzCekR&lN?^Pu}F?\ͰY\2 -|;qg%Q~鈂 a3;fx}wny{SU)窈r 'x/ĶpN>"W^G`Qy (j1iv ρQM[תTkM57;(K{[@<- 3D "Aa ]Z]f7@/dgrm? IDATK'HkcDZV KY CE>R< /e.]L-9< =KWio>|hb1Xf|6H#]>Ks\/;EcwB %`;ղF!sM(Z7/7>``c^ ͞E 7')a7vwӆȓ+G#WξRq*S28{5-N ^6l^cZ;?CDvS) -[3k57239"8UeLEYYO EضR;n՚n"j.JeqCv)j^]PV ͳEi^`96(HM^ۍgGE={o. < 52}QjEGS?$09E%#&]32-O;e5w78KiIC-mn; zSzC:dd(Н K9rPBޯzC q|SEooPמ $`Z'ж8d+UMpl!ViC 'z.[r#u_\d{Q]uC_|m9m`󕭶) Y׮awxpq. 벪799L@Ї?Lc7X#y Ӣ|Ƈ<Ea^ʻ6 qTEa7؆˷b `6xb4yR](sO.p7"Xٜzoύ5Lpϝݗ\V4vxPQ6>G,o/mɸ%'ٔ69g^C |}P3_ӽ~2zq,C 7ި/.%}7m%?NN}޺x~#p]ʅ̔_Cѵv1d'# D_d봞R噽9[<^Qxdk49cndp;z#"þfURUu& )HB7.3>A (> oy"³ϛ%yVAe q+}b-f{  hNu͗ջOu=4B Ж-kS\-U;YڔUY 5_{O0đۂ}a?@2Fv\u[߸Բ*ݼ-͝` }mFGy_|IaX Q+|􃧞7n}o;?/>w=犍͸V\^ʛ>e/q]. W^l\O!S 4z-z%Z8PW^~mGv1UMeFa^0_DژP_*mh'f|#z(SOX0TʨKe.+ >qر䚐z?5ꍇ]y1ޚ;/7<=}߱vj=+I/Ep8~#Hm;ͤV{ ٶV5tWvZH@EzC I|VS8[ަ5qMo/>u_֋B'}-in|ml7*4؅ ɜ>% "X,}bϟ#W2괞η͙lJ,͢uTlHS]) K IF^"q{(rWj(C~NK]ϴC{\wDvOZ)|\Z6=Qs+w{;˻_%]Q6gAsX 2\^^*o+tdⶏ3BD]K*ʱv($t5ܵ؅j\Jj$﫷-4_[zCn##9Ro~}5&x}H0r,/RО7|1 AKf:]@R?4Fi) ; u$R^#LbFe_)ö.RJcUͽ[Un 4oݤ4ٺ3x $d'=%9nmCqE@u=S߹I2G4>`cO49E 0qzJx(P$5|_#r嚀r,w5&J'KUVGP ~ºon(m9\o`˴LwKhEn.T4 KM?8܇->}8$ͣ:lNg:n/tLAQ #E~رMvh$?^t،j7\ZFE`Cdw 3UR#( !nð@H{Џ?({AwƐﲛ*?63Ͻ[_?u_n3Wc["}]BS R-j)J+xzg,e= %YeW ?'8TdU лx^F߂Aqf9 ukbׂSw]8czpIK һ;g"i P\"W1/?r_ׯAWN x4ׅp*_7 _zsc#=AwG& Ƃ$(^ū )lp"@PJ^ű]bAWH>QBkSJNrAtWԲ~X'c6ȔkzY#y%N,X'̵4,Q6:ݢI;JUmhG%,n9?{oW~wZP$Vݔ"YԲ9Dzsd̉Od4LYl95c9Vǒԭ^\A$vԾ׭̇ P*AS[n]T?}5d,)-GKa]*Tj z̵}^?8@+2-'W>pbatE$zI%X_x{$uͫ2vzEGvn>T[4N2yi5ɖ6*S\PX(4*{SpOMvj߶bGe; 3,'m ].12nLΎe-4%4[i;jAl3ގGY9}{2|p'Gŭ$".UA7ժʚd_RCLv`C0gXm~GFà)cQP5Q0 JFnLfHaBnJ[I`gڧ`_8m- 4F֟'$ägZl03O'fTئ#oLZ#5!lw:KuՉ)@԰qmeziB|s%LEٮ WH/p:ۥSK?AjԎӐWd<⸖ipc0;~ ٦! 7ejJwSDkq2C9q%BCI<: Ź;츱JJk3xB.Bz2oլV.ޟϏ2b=29 .Si p-ld\ YN(MʂCAF0tFSȚ3|gk?!8V(2Tp= q7>Y۴o߿~Pwq'x&T9䷖ii2% H5%k]Z~ޤ^kl {G|T3UJec^$IQ"|A\^7R{~Tf$ L}|葩 <kV/\}XO%1Ň'~Da[&XIree0hv2-ew0e_%t&7m4 ܶM]tQmҢ 2<й_<1 Wt۷x:ŶI)8V(/W wy8@!KUr;|gK]<6&+^\RiQRXt>G܁N-etqyTAbf- v7{tmJ5Dި4`]^N?<'OOQJaZϧCWl{ oJump=_.%ˢͤh0v\HqL~xX0* ~q+v~3A4>@n1sޕ㈂NlPLLl{jIqӇ72WghzQ DV%VfdkV$G$X2)Y,,d0-$ hnOCՔi]S_YDETI%m*l:d'{cz )}(k4\ lO9~T/\7-?#5p};ƓШg ۲iT4*Ma*a&o5>5( T ?v @%Ix(/w ]wtOe2l <6kҫK)̺ATgzfqvΝzS/u3. L۟po:WG_Ei&'n }A+ &,ld&U&]nr˄BN">!v ݠVnE*>@ "fo ^RJu !-RygE$ nP0t,mqF$ܸ*ߋ'&s%BȠʼn,hOIE-vBa|Nh__CcTgt02.'oN0ִ8[7,6M)l:Z'z9I{wp-S#0 (imO|_M1UR{Ax]ykY۲.H:u.vT]$:7Mxl=,uc MW xIX/hA>Xt;!uq8&mTm+_g۷N߱,{|<>/ްc$pNʯzЯyT"SA>c>/g؉ܞȥ[JZ-&4/>m"Pv@ԞvӬ6ih'pl̦ISUq\Ȋuq[-MFӵ]/4XF+>y&viiK_z+4J#wc v=F`cw{f<&t2M+t>-IDvUY`V[x;&89U:Ig E&AC7rc[p5s~DV՛9⒉&;Ńc/~xMLDnutY/ 1wו< I^V4I" U`&{Q=.0c"FN-S-#HVMEè5Tv]+7X00ED?tqVQkH3m ǟ8WQI/o`(#.:Sߜܑ(c TOʲ@߱Zбosz r\[ rwP(tLy"Y.vbqa2ƶg(k_©_{*/DoO\Q6Zud_.Pzx|:9ـ>M^l۞aSA =l +zrw#O&ϝ uz DIbl7]˯kx3iNp$ƵUgrW ?RWj (`Y6z{T*5eళ2;nEꎹ YTHm7cP,Wtf\h*6pTo_g;UH$NR*n'Ex$wq1/Cb|#-0 řIS^XB| u1Mh1g1>ħ3m"#G@,C)"~qq(mNpG+<7rmR3u!E!MQ4m[A-k׏tC?y _ hXl`=1g6?L1W"1o֍e&Mh$[v/M6:r+mWD&H(_XH(}SUS P7ʹ N3f Z&wn$jj"۶HS: U _3=7sy++D"ŽS~g ކ@ʼn%wP5j[{DyuA eyC15fr,mmxCT^q| ޢl͛;?0]ȡ4|8׾z垝N1`%M 6D,)dABF ybGZax&襝/8,TGA< O5Q>PGΥ'o{ WF\n~Mo qUYQ=OmDgҼul{ac'ZfNRw["?@jw{n38}Zb1Mø]-Q5(/< IDAT<~ġhqVf3TK=&.bD4N4HqK\(vsXĮV+uˤd18S#n1t̉ՉNrmm#[&y,Dt׶]7e( ׻;<;FeRy8z p>M6H}ơ /ᙿx۶f` ̿i!y߼17]rHj9`{/ sbnx𐟢Y}\ ?%(xw h2Nwݯ8l4E ˛HmEJ~*ܜjilQFןg5 h*n5ZS+ԗW%OA%]^WύmjVئQw" UC`iŷ<ϞW4Wypk.eMסmNzMgjGUbkmp?*o~|j;Q ƽ9wǻ:q9gz{bD⣽uLH~|QXPwh&GI~le#Ntti>GG#I&h6|jM]Dʻ,%Mhp>kCVh0yR-;~>ׅmAY  Yya[kB&6oM꛾;wʼn_mh\;8;9Fz~q ._?pK{a?)'lDE9!@?FŠAER U6djԗ+ ^-qYVRNg<A2#m&PNJ 8 #֏'y}+lNA K-!kh'D[Eznodxr qu`辪(\^~7/R< }aB _>3WNS|yd`C|,'ؽt1ureaca)Wgzgn3L#)ycU4T[0f8jz~;ISa )ioFidяGWA'GQ\^2UB'$ i挣LI53$dHTľ=U%n ﮖivgZtK79~ײ,wBq"T/~9|AQ6c@u973吴^$*r#$ެZm#mJ7^%E&m R%f'NI'tw# z 3yFN&(ۊ(ڿ4Qd2*\AuҀςx Iz.. wR=ke#{[Q-۲aqt,FܤX33|ѱ8*OH$\1R]!J"<ԋιn/( u:-S*1E&ю#4RFh^1f8G|J.D^L! "ҽO~X"[j7p2/JuC8۰9ڞD֢,οm[ ^h-z4.ϑ2odloݼϏYߨܡcEkb"X̶fL~m#XCrI}rcOQ)R]~8? T]SqPntx DX¸]ê P+C/YJu CU1\\i 3iި.M$p/uJ.Ų&s◎s?^7W$U7sBA|ޮ? nŻ{6ZB@''YF$94 nMlBZ!*nFHb/8/hV&(Y7-O?A.jHHBKq4di?ߡ0 R0y!N^%?M^T\g(6y*'BV +VsO$OfNq*+e2S_i'I3RQ(Gm 1N(MЉbK.ɢeP[ J7:$Y$1g4< >wu^hBDy;x =U._|njѧp$N>gnl{ FGn|ۛ2Q&ݥ,@RE17a17#̬4T#}eZS 굽?G@ȯph0kN l Wc%Ž*}{0Q#{HJ$!8^1iriJ,\v)A(3%.\qD᠛ `՞(.&4t>4'b2Ul#O"#OfcYw 3sER\Hq_:Q?/vD6cAV/{Ҩ;ӪK"tȏ& :+v CPtm4֛w4+ⴎ^q%g落'EߋuN'Wv2.vk/Ʉ*sLK2"=%$h}Z\O‡$|H.W@C Xmte64j~\ݲx NLs1џrH([&O[) ~ߝiԛW5hAcNКsU5gE,%28 rP؃iZH۫By*k )hZ+7( {Ofra+FDZ 4$ P=.M+Aŭvފܙ7f^O<6lsP[.~J)"ӯ]mi+_\roE}O:٦E_eNufRw$'IvKYRwm4҄)'L(N5vDw~Z^m3ۉ|M+36#mEE\L<(4hgL4G~~ęVU/ SY} %>$|BYl6&$ {[)L)N'3'7eĶskG@}z6GU Y^SOtWW(> et'.Ma7M[Tݲ([wFD1cMҀ;mR:.cs`~өE8 - %*T]VEtf0ڶWL0JKNP\Xta?/?0ѽ\ۅ);zğgãN%{F:bFNi>O`Ch̓m&}!K"_r-m%@HӦ[!%Q5QEq~<81* ;Et'5lteɡ\!ts;|F>{_~MFA%U>n>~|%Robv 0}&?*n6 *G>6A2YSEÄwhm @v(ܘG:o^ؘ=;)Р{OSNPJ*hb&i$UFj:vR]#5Wfz\-ZiZ yЍf [Mo~,ra*Ņex';NX3:>>=JGvϗ){aC~C~E(.in)㷚>u%\3FhB?_ꥻxqe_}z 5}0IubRIzOA͏n0X{Wxl߭)og;kqr,TiK4%G^}@뚲HY7 eۓqpƐ0FئMr۰&[zUEP>"'ex47ulP D.G ~deU [ZC5[d>I묾{aPQe l@<9|1tsl$T+M$U֥E]3m +%U@`wGEHdW[j׍?W O^;"Qim(p&3ӴZ.YP;T* Q,b&z}PG@+`-?!|4Ks3Loa7 >1Mi3[e{H9ds%;"u1Ax zM"6S4W=uo,15OC̕ FsO՛Tmm_!2L|ˉk@>=4WjkdίNzqVOeZm'۴)Y}>HF╧4"',`zO^lE"H h5ubZ[G>sT55(*l 0ʹIvx"AkwA|GDGBKa.:3y3ۊ7cL7:Sϝ&7c.cf"(&H[xEv{8cw,}HQqʕ?Tp$B;Νw GFoXH+;l4-Wl)ɼm{ ߦHQYܛ1 Mi=JQ&&DٱmeM&=f5 $QC*Xa$wϻ0!m* 8:}WW<wUFüڍMoU!}b';1BO mF>S`zrmy0ޘgG6 .LӢTkc %l½%&)H^ԙQi0;#NgJ5G9wӪ%oפqC~U]>Sl݃)[Mq LF{{eϯRȒx~mS{2mIy?I3߹P[T$0y 4wX.Sd1W>p<2J@x 8yƇ֜ռmP] y-9‰[9ԍ7cmQ-ո;<3.ڠ`4@@W_HیRLYR^k8cxޘŭмU&JvG(dNHgn?W3,~F/?<׶M@9!, _}@`OmңaQF SVSנ#'xעs7/;l醻<΢z. b޴du%%BY7Yzm戜 IDATnxDjD!MZZIf x]K~\Q|/;}0aV>Xe(aLY!P6zM5@l1ӟ<ɷ02sNzQ7BQ/gae6ͳ[Q4ܘqou#0DžDk=rtrgnJ̦-y*؃;^uzЄ{T./2ߣ9J!>xkTA{;=7Ow ?$sSy*.QZu#U9%מ', ( 'u|FR%ځ+iޫBek.| Whkdϯ<!|?2 * PIVuMf౾{JM|qeF\Qę_׈01&2Ko/YʣF"PNiO^):5D8AE ޸ "BZ'GQɉ^zDyZ8ϣ&=*x >˩ .nD]T;p(D"[)W*  JA$K]mhcw5"d\Q[F,8/>}5OZsn'ڶc*qcȮG 8#|ڶ#nuHI~@f2IVmZ  Qۿ.; ^שm /0(>Abo׽:hRnou߉x5RjEa'nTXpy5'b:b I?7=)ue\WR A`Hh `qW&/aS#!ߊG@e~/<`W(H~aZ%OvyH((/~0ToƟ^Du:Б(`k',.jHu).{(4L "Ne[.'(M44M#JQ,UlDV-S0M}ի<Ż)&+DŞm'Pɶ|HK1۽Ō^_z1GXk|AuL5"kfµ>= lIjI7$&El5є(Y;}ʼ*&^ୀڏKMV/YՐ6]]g?FH(ٮ~ @hj>ޝⅧZi HGvyr!$DqLo fY/kǽ$.b+U&'w`+yK7n Pz6\ ҟLl6L{u}b]EaxzL^v&X%D"C#\}iaV37?^a>eyBډys-CA\>YP}* Xg6ܬZz7i5 r# ՋX4RK Nzk+p`F/sOڇCZEi ˢ>v߾a͍rxZ<7 vޟa`5.a P$5 xf)9MQ|42{sڶ5,?RnxK7kv$XS=;Vh]8zd4 ό_7ɭVȭ3LqNqh7wC^i1Cu%OZ HȚJ"gfeZFIPk#^/&{@ӕ<v3 W;:&CL3J@b(~EqUa5xqb'%lD:E,\rȉ \=nղchiCS5\drՍ;Q83>֊:^Q[,]+PY|0>I$>b5id+TVkh,I25=VH_^CTdm546[TlO%ydi*O> w۴ P{t%p5%Y7Lt3mwˋW\u[,>[@zY7\&]4Nد0k:s?Ѽv+$ՅbuL-?zK& H4! c](9DIEܪ[U%bFDr7_ޏ:vSZA J{l,<puQzvB22v+K37E[fJ͔xK]HynOR '~[*H"ӣVHQi35rE { N W0͵hXga=ZjΜh&$%3mT3^,Qr%#aԸ>LT ov_)Dܨ>m~@}oHU~՘YDEY3(. ǞLҨ5Y]w XQ:ZJoOr\d_ewмC&ubZ~d`k=-s.OJ8C2>Kߺ@{~>uFefag^m( hs܂"Q5lnky5Mҥ6=6uG;] $w? <_+e5y8$mFQ-ESOv=n@ ٕ*[S?q4JMĵOiO%b=BM+ Bblp1/0i*G[5Է.}*h"W] |̀ .AF ckݓԽ"O?Qnxd 8(~ |{~0ZL^Ok8bp!Rj`ZHJ;˲:H+"'\5DkL{+m*SU7 4的#ZDi]8~7nD۰[)/wRK!-bJR9L-m"KOc=f߱oXlm MJ>ZmdzUo$BHj+oNcAg%9g.ߛÇVFDNw,fWW7HV!^@/~:]Ҟ!#M6_|[_:A_>{~}7hqoǜ#H#_Yqe]{+ͮIml6^o%+fSV}f?]FaY1#y{'0(0(2?Y%ӁAʝ"]h{ڟ7c]W%&Z7TX,h}2-teT C{DA.OP,6z7ȏ%IC\<҇owdGT{"b;* ժj1xE=ȚAnhc??ڶҲU8ODl{_Vd]pЖ3ղA1[!xr鍛G<gOC; I=@6M6v'c:_~#ܚ`#|Lp6m\a:\)*c8!^.Δ)SL0·Q1' UU4R \'A^j{9pX10ױkT#zWZmӦ2Wt_TŴ#E&&7)gu$U jQ`,~6 pHx˓*IT՞Ge`l&׸(ޝ7!Xe7nKwHl0BfQ($?\$?ONDt9!My4CO׍GCyd"PAG,*)a߻x{bl..%~Յy>̑^ B5A S\hVTgPdPFac_8tRy&7G>$IСxS`:Y˗D# 0G$n]N_1I$*Ȃ{" ogP{t=oǞ,-[ʎ0F!d c2l2%ɇ7% vx}`+כ+*[Mnf;@lI\ARqYMUDs>DfDV%>9ąEjqk'f?{eA}U79sV4W?շgC#jflxl/t}h3sy>[ܚrie2r+?T,@8)TSzi73XUoςYO6Y$.uiz.ٙ5Wm MAC n6>"@Ѕ湁E F= y(ZH8_|wP7 Nxx`< 8-7ABЯS%ę# Afyh0U3^ j>wcZT޾LbDODl"yd{1_in.%t"{*CA Ш=N_j̝?x\nz>?±x9;SŚ_̚_M5#G#YKc&+إc$w g'V|O R Ʊ<deك]WQO`uI9Chk IzrǦr#{ٯ$?(lAySˊ0qȮ:T@](:\oGrVH:(b Axu2Al0nb6M$)ϷN2i4F6" 2`sM0m2hn4'K2@.Zj] y'ȕ N5"{hD~G'p 0KUo7=Я6BNO6t-#i*hzǓu%xFGR@y #:eϊpZƿwe+Zͭ,NvVkIzGE{ ;C Tt$jCA޾6Cx2p(puN 枧g<` Gt7RuDԒ+Oa`7Φk?LX6 unŲ&̤G}F.GiD۫7"R,4/W{ÖgO[^+),,M;jPC AzC>3WbMOe߫g5n&#e#ObV ߜ1 @$z# /1uϨJ(1?*!=xF| P*`]+Nb>pt;#r<'*<́aG(wpqXA:hXj+r`OF%]鸭Fω=@5Yː"TKS d%7 uT|I >B@ԄE6l|{pN?r+ j|/Cl`u%u"B2tw2$ UjKE}T2m,ZG iYe@PnK>R<54[4RL$(&wlݍJƝO917ƙzc]8Ήuש+1+[;N^16j^8Fo H!rDCT%]H'#WrR>6PjS#Md|=D;iEQ(J /wv5.t #!{ ?݇'!7o;FOBP7 `B)6% lK0hysFv=)9Vc|^qGTx9v="7Φح|q oDTAȫ4 )I RV U+U#WN@/l9ƮLrHeZQ)Ћ+k*l"OD5q{hV 5&.$W1ڧT-SΪ{poO0%`2r4@035g*V&x=X7}(ԁ>)'!k7@ ?yEb#ugDAY:OTUfo&!$G1?ئCq~mğu#߲W86MR)Slm2g%W,,BGjVnPX+3/'KˮjYjVqm6ϵ3gF* #/ M:i⠭ ]xr(~ ۴s!INtQ^ғxƋu*{>GP7$?ԡYHz"TIٻpG$,ЊSLUrܢ+"tTtu,$YlOmNnlw.SL#i2Zd IDAT^9H˘߻Ј'pT'ZD?/MP5y4/쉱e~>׊NNAV=_E -\<6xZ<7G'Vn ./*` 05);>XAc4_m5@}hÔTVo 0w^Sk|稭= `yns7?D0m92G$CS[GSTE&FS hT#*+B 0-LW-PbYk/FN6LbE7$!BG['˷ő_?Ipo?%4Ax|Z.P޹w$BgCv60{nޗD\uN17L#'6CPjkF%ywwEp90?'@A?tw(@SXlXMDE$|b*0yyU8iX%0'dEfR.mm?jñ8mRk2>;C%xmS.: :XR>_AS i`_I/8ķ5W9V *C*w#Ufit#_=^²hWCҷEIɿ̊4[]q SQc7Q†KA^~Տ@aT2czNUe>-S!΅\|b ƺG;I5lP%f{ͰЫ&zv|~GM),_av$"(DFO 6VHY:ڷn Q-#`N~PVc#+"љ *' "*C!+Cg*Ȏ#@}G"sBEӅ J>\? V{Le$tVU#"PqV2'}?Qb= }z$mǴMd9QP?l@O D PvHϤh/l_;G]&\7zx}DiJC./hi?!;h2t)#OtRC_~+*{'F:lMgK&ϞE*rzCyi3S4}Յ{hr©U TK+,72E];*e.w_poŎW&J-dk¼GqyoI EA*]aHWDԃ@4|#g 7 Z[>GpWw)W8+'ti2 {+a w0aSG*nv+vP:9}`2צx{}|ZnӨWSo)/ .f}c;7;l^W&'IQuaWء(ŜAy'KMie}maPyCT/teFpom~=,hUuF8#ͩi3m;aCb@pMsʾ:V"[\b>|$G £]'63q?Vx`ۯ~~7evyAj0啿 7._o֪'?O 33zQGEuqק Vt\fXWo_WRJu$A=ua%*_]yx*2m<^*2,Dݰj q E =YZo3G?=zDȨT| 9 T%W$,weLaM@Y"a"U%d,WDvZ80 K^[M 8E;TG9>_Q̿;mڛ@H7o)DXU"Tlة;c~.UƃޗG]mC#|>ʉ1WwF9󳟤{O7*7Fi+2}JhHC;+`k5YȊ72e|?%~4Tps3B.]~FV$}ʶ cc9wݵl%>; TW׈)7Sy3hpo: {,)pֿG@[¶zހi-gS+|ܵ9DhT`OdױtO;pKUL֜'e8Q~(aή[ ̗~Oy"chI< ԇ̍5z|~xT+MyB"}k6ReHrLUSV/*Wg7/qkݦw!.Sڊ'a%"ym y؍@=@~{pU򯈧ß8Mc eļۄo:|Y{xD GRyޠ7ӃE|LbR ˊDWo`fYQ+꘺N'Hp:O@ץ5x\su2W⭢(pwjQ$m-R._@kr8^pSz*lߺjTE1Y,֔&q ܮPwGeJSi.o` O}zoC޲ĜᰧEf@8ydH qd^dq7 HM&so,ϋmWkPOzitw^1<ϼOQBbbQ1d'xjul(W+늦Մ*ш ܟ/;sxW|PTv%E7Pt-Ȝo߬7uo_&{Le 9pĒZ8?P]}9=oaCb3yܝ? yq$v@o-@^‡wk[(nʮ_m7ɂ@*0UY ~'UUaW@= ~X=- QdASn&;wg(+ υ|퍮)QW`]'o0u#zy#bv=ʒjLKk|Bf5oɫsd^SxO6xTPZdN U&k![d;*[TE[TN* šmZddtI`+P((-ĎLIwo?]6&j`GiGPLV:a"_֥qi;ekP<W<^yOWTS)MR4aO|kys퇷L&QZ5EI9n!~1>aqiq?q3gһzZ,1'E@"Ysgm 0-ڌ JzN^Py#ԊCe5D,q`UKA!1&e0X.8)T( <[hخE3BAp,Ίt[!йon.Y͍KkXC/|+}}k_?w7ϛ9zb/SHyv퉕4VjYatc֕ W|{/lgn֘]ZmR}Ä"U]|f|{mM=hL"f]dD&] sN]p1VDT+dS9 }~^iQFc 3d–e)%YPmRZPg$L1F=^=ᰊgI Q [j3E?H\3!"yu^1ʲ8_>[ l&R먊^2SWc+jU!-SpJ&U!ޥpϋ8 1;S,8P5p̥$"z;f1I #]If8Ǟ벫OGN_{H.dDizIC"Z+2LR|orq?a\Y 4F-{g*8%mtoOCȞz0}1-U"~M]h0[!Vg+LM޵}U8~zWI襷Gzw]x _i^:ڝ+?ڔ[Kz1M); |-JTpıadž|Ȣ@qz"- Kʍ*‘%E&q#}OXͭg8HI)Xi8?`A^5={;8H \\7?Bj /`7yJ&ɇLN)JCd'QHϗrT)W%3߾Zsp i&E/lj.\#y+\ml_GďtSG"dBOq' +Bܾdj"ݑOJV$e&ԜI-k"i"a/|MdFG =dK{;Z[u45iQ(\Ey*T2͇eOb-J >Kϑ0pe$ajSR-z/<^'>SŇoMSwZYbԖEޔ^O.uzFBzֆV sLʑȷjL[w:Dnͱ+eϜᥗoxRo27=/M뛺5YN:riɧP<2N: bؔXjcA%ߕ8&w@FGwlղIlb6|RF!cmҳ""{hWԸxu>(2UOX,*<,h;du:(b M񭠯fتc #Lyd2͏}|pogӰqaBg g,I斸\t7&Ԁ@AHɉ$ 祻_YBqξ,F6#r,'}g>u* orx5G!]'?;Gq1%*8Znm\,hxd^yQV^ˊ|WVd$dۇCņYxJZS+r eAjL![Ŷ>љGqx.l\9"W'"7.̓|ԖoK\m$; + $:klvz<{ZMx F =٢ɜ9-jLϩ#][mTbiw˴I̕H/>|( Яʄ%ԜmK*U1dumVZ <ٍ5߽aJ\cI?fI;Im06Gʭ;/S`#2&-972XG ,Y3 `!YKW"+!I O1݄{YͪXLb^0dq'%kXk5b&Y"*8Wv{Cm]c{/ K#Z4U⋟G=lu\bblZwDDJpj biB\DuiHpX#xFlWw ʑ\wBnM6ύ+y+?GWM,UF= JZEd~"H UMz75l2n)q  O ,ijߵkEa}Y]NivʾNایw-8Z|" =Fx:dd7}5 l ?8KۖQJY(`L x=˦&fx1Oz^QLVHWu**#}!f%F/ +hF wŶ(|HA ,\ҴRG?!٘9x|C|ɽ޴ Ulæ+lf'=c~&G\IJd97pG/+"eGm#Q$0p X̍<[Q̗JCR HM6U!ƞnYxșmNT2aϓ% ;ϫl8z׵L,O X'pǓ-#QK#`?L`s|ԑEvK pz;CUJ(wP*\ _fONmVw@/PmJwj eW9n)SnT<ŇӪȕb~@PcEx_T̝;9>vx{`IPųj$J|H[r8"K^ג;?qKg(ݥEj7H3x@f1db_i'rݐ`o# -DC_"]-"o7^mʦu}sctx/o@.jgTL*U!*s} ,ccΖΖU(=ݲjxK<òl& ױ&8+6μtSmz>": $9{B,^?0*S-sx/K05f|y$V+JdrDQ1X@϶0;CvV뉨\r$+ awtx}"lgM)6 =_8Mvsd@T, wSѵg;튞i o% \NTPɷGDs7Y@uʜ*p[k1n?Ds0k6+ҹ\ 6˝͗r47l|e9 Uu>/qi?gW@m1=Ah=7+#TDj5D$y(XH<i)nJ11ff6*~9d"u=mf +Թf}!h!PYv, "Ѹ(Go3&w\k J@)D|̍(/q:6ciO;m cف@SkSm.W__\,G+VM{S;" "mV:VD-(6M8g0R WS)zpF=mivgm]8d}&H#|Γbj2Q{rcZU4,M1R%{-K@O<(tR4LjkҕP+֐=(T)Wk7 @rguJ{<옻n1}{;o_<9ͼqkEP 6AYۺhѦpSDE 9n\{k4q[׾TYOX+8kƦF N{U^} CpH(}>|%}U=5u[q'9+$7 Y<+ lU^/Èdwq+eӺ>Qm̩fhVZqH+[ۭ}䥖,3 rm˟KwagW@m!] |x|x>'x3DT o4Jp)icLL0ޫi%wt%ټ&  iTَbBO_c\Qr;^L$9%+jYoH%טX2m&."J >I$<AUݻJ`zugaNKȚJ}xc֪hcQ?;Q诹ѐ>9 UEW8@Z <%v8UWz$Lg5Sw.1cVl%4f[9ȎCg]}(A L7Z5\u8;Hm='R\Kln8d 6_\+]O- <=z3n34ccmMkSTRIҰm拍u1MHH+obb Xf-DŅyx'л?T5;ñ3SeS)b{״lg>ZmL}}D\TѥT 5BT$ Wwݤ&UtC&2J j҅J!{l5Vf$o%}]*Y F rpqk_6lK.x(#NX j1ͯ_nR@%kLn(#+ĔfGk4WOۺf]ܚ{3j5eMeY&U$(#"UaS*6-`nRܲܔI= "}>RSE&k+"{Ҽ{0)2F{xq&Kx8ѣq $0y~v +=5E^'e~rcTǜuEX;V솞tCU6`աpdz\¼/k#yn1,b;#/ I7~6-v <8卬dT s+5Z*hOU`a&ǭEU~- N™`UlN]ZL/ңn- kK~ElMec;TusaH;xx ea!A~BנqizcU&e*i|ļOԊJCHef(:ػb*Oc?zbr3[1Ov[ZV' :3#}aRbYOg2̽uۏGcU˯S7Ps{3]!pE@EpӘOhYgb̄U36ێLSTylúMg9`Fj"VZu#lD9e1H%)tV8\@>^訹?:/x9o6s^ 5-WMd+"bevb@@JAg|e~b[OIrHސ"+q|˴QUӲ?_x'݂jD.3O-#ySq&ķ.ej<6Qïd8"`¯0JXG})ٴ+pXВ}"`W:+X. =!Th.:dDhRZH%Pƶ̪EfDGCYO ,:v=E㄂NGq}c%$Ef۾Iɼ\>5M^GTL!<9c5_lkkQw8,ɽmn\+5s&%5Ҋt5qpԔa6˲K._mYG/})r6W0Metzu _xo@KE /A]IءyP&!1 3TjhjI xn6W߻O E(c/ yT0տQeS+8 ň ?25Xgϰ 0zUm$ ,7VDٶE)oWGtéڋCZu)Q5 VFq.Y.aK6$7Rp{XZ;Eal[>3%)$K%E$55fmRmwBo֛m+Zx(0B(-}teE[a~aÏSx( ;чwW*Zskʙ*>8BZNMa TDQO jD|CFjyUV̒U:V4WYM[_2mr+9bAu@ͣ {IC 9rs2%&f؟ArHuem[xnP v e`R4PIV}*NϪ]VSؒzB(|}ٶt>ERS?:KG=>\ifie{KXYP E7e;r%W9<-k(fˌ?5x YADVKMǾ8L4x` |,׭"=sG[ۜbL.sibZoFx&SHf%BM(ɝDfqDJՠ‚יNU/ v|["kÄx͏{jϪ =cRofI$5 .*OTt Zxx |eBrappc`zyp~Rx<}~|xb bE l:߾s%>?T*$Ƃܿٹ tgxl]j$fE,-+*O0pfH6+ʪAózmkx~beӭs,5)9_X%u<5EmS/t4c%g:iy͸#ԌxY=Ap> q0l5B = G-ۦW4z|C|ZK5 JY)rgsLJ9y|:})Wm 8&4ˬs%GU| ͣ`ɓF5c֌R_S?;ZY@եoCJ:)9R{>=_c5HYnz*Gp#ڔy\;57v8!IVqs;yEHj'j+nP}P&-yyvz䋇'l[9s=kdZ+0ހ}%dQ eJK^B=I<sOc}/^!pi,.(jl3}Q^N t*FUoSTͣqӬ&k- ը4L%D>*b*l]::sM\p/>OzJQ t*JQ~[XiSWT: 7L夣_ }Mlwx;3ňwfK 5 \g?gb/hjH|+5?4/ (7?w (8+ KIlsŚ8PK+ekbc 3K׆m1?KsX8-I1[nM_'>YgW@k;;:VdY/mbCꬽr"Ub1'ԲwA"8Pv?@@Ē{ۯ0ΨNOaKo;$ݬf3_Vہqjv:7蓎-g59Ι7JY83eg 0db $3,vmz}o<?(;_O|W\hlUe k*'B-mrI#4E`?}SK[n_ | Y7v$N}:p;#Ns6jW8c)T0?yg'<*CcQOp(cc,-=v&i)͜YUI$ e[UᶯxQ) |"7p$+^i1ݴ4)IٲO oKϰ̪6q[4 5xI|ӫ@C~+? :AªQ*g EL[i< #2*Hu f .~$# {90D"T%ROf[}ţHt2Smi>j <#8R4eQ#?s.(.ͣbvJe,ϰS&F:=zlJ%ɳv۠ DHyq+*\ +<^lVR!:Ws:WeuXK9~–fn$o*Pɐ5i!Ç'y^lLgp>ʁDzգ I0m ^G-s % E$I+:ߤ9!se kL-xU seS n=TU!hvzO?O=}V71oĐF3tZ|VR^gtmW1t%S lXG;*ɶC.#hk,a .?mMJ̵s+$p4݉vzs T-Y N hL믥z' ~zjjӖ|Wb! IDATh}*7`Xe`z}`rRJmo8 HyX]SfkiO[aWWE}L ;G-g@EJ*|~RqSD"9;Ӵu>+> &0PnF#&4)9V\nb]OQ)XcHǤN [C%#ڵd̥7j\M죆d>F+H\I* Yke AHNϿ4|66w_K{m'xo|q0Ɠƽ^0|s5A:>gjj4^.2} ) gFr+)V !^˯h.ly:U7-<^^ߟ!l,pJ" Q3{ :jދ5Qc FHH_Iٜs0ַ54U( Inժ)N誨MIߺ*ӺG Ie8եyuU%;y%MǍE/9s L!YiӮmc%;FE<= x6l%.ߪѼAPH.>gP~ =[-i;-,v=٩'hx˭Ӈc(1w)P*mTlm<]Uu~/gOouNbh䁉l>mMJ[]R`(N$4CTK7Fˠln6gU0<]?3ML1`/>edLl&J%զAfڬ-PcJJ1?.!}g0/ o>;PyARgd^w[W 'BO*~U-'BɥG TyN1@ xeJ<)HS-S,ѱ!I./kχ" M|?˭;W#~!&8ysͅ;}/ԜG(- I {<1 X DPBHpZ޷n)5S,ת "DʙSTPٻ^Z6|rC8x'On4w/L`+PӜF1F1TK8,U<봗RB2'l]4FuKx63跨|c"'Qn5 mlxJTٹ.j KETsp [vY&a R!,O*zj7LO@B^Gʊ۳+|rmAx}\g(R%q*oZx{ 817`۵=+m' >!=yfn+ֺOQvD%TRa(S-{\|?Yr ##,Ӧ7- QͰ8}˲)Z?B@DBL>=-$nZ`5Z$YI膆 (æJH ™}5^JTQq)E1o$ `ڿ{$! ֢ E%6I ml-y%S EªCF㦊R= )aSnC6Fxg37 >h ?Q}eniģ~Fjt=u}GD\Gmaq'@,ᶏ_F"ޙ ѵΞ8C_0uyxێi&%,k`1K0`)"Hmmꑨh/5 ;6I3Ϯ*ԥP>a0k. BZڴu2%t?M! eٶ7XcuW69hIaܫP+7XUSd >OdSISDxQ"A:Sd@QP+DgfڲxN䙧V@!S\j/Vfrj^0_S#95Jp^ڲWc$0-Ro~#v uw.)&5"1.J :1Y$3Ʈ{_IU/B!|yeޕp]}K@^8C"O0S0#ܶ߄eXIWNҷ)DC Tۀ ~sjBB?kG֔wQ0-+\c?7{uDK7ģ~NKwW gn20/0`]zBH+L˳y9 &}8􋇙Yg}7 GhpXjіdf^ BOgC ~,WMP:#0) K8-+^2p!>>4 fJVۈa̷_gӺBf|Ny'$t(m-*>((Ě 3o9JSfU{isrPkb}q\'wL]H1seӰQTA {LlDQ7I' l4 Q F1g VE\*\jsBǣAVqGZ[loTMcRmYAEiY9uͤ<[&OMLRѺ"rĮ"Ny= ޜo|<M‰#(J>n_0jC>F7,ٚ3-l:5 ֎lCLO@7~!Ҁjj񗏶}R^U< pFhxhp?a\_E $Al<~e{&Z]ȖW35OmI/kVשrrIABQ?Ccqc}~.0e 34CUA[{(Skq5i"vp[$nA@:*LR;S ,F۴uQUAA{qm+R8Sk:'ss妅=`p> g 6n4capl_i\|SjrR]Q.AQ=Azj7P#v@ tzOЩ t41؁MARƶ$PJLE7L \+9 [2QnM[P׿ʭ< E)->_(\mI1U2D<$n,rKդG& sxGNV3%Fײ{VHkWYےKu Z@ɌWl  ɑ7-)[_C?D.S9\ 4 &V٢ofEk^rٛd{È%63aKrspؐ$7},) `GW6ޠl̬WA6cl8 fX!qyp&\ VbQxQ|+onjp_k2Yvogfa/%Q"xӹO^zv~8xjG(⭻h!,;D,QNNSJb;@z| ~Wc1 wTٲft V{JxKcDi/2mr" i2yC<~|͍)kbs5'5|Dd Í6ԌZ(;-L]{D*UxɧB;$ 3 &JtcU,x3xZL{=[_t4j׋v_GPT\(p,x7.|l!j#( YsiL$ h#ǫC'9̲EA8-;o. B~rO@mA~o, xˣ?$WPͯ9#rď`CjD!㜅 'Ü>k:U'J'Hr'~8 Zgֿ˗)L"|mO-m򜎴eC/ad2YȭqzhHYrp:AʯU<@ߚXX8 `a`Ek%[8l_:U8KV5Rڦ6gQdU_*InjMD^3TCֳtpͧa dRNu6TU!V B&[ZqPp1z-D*'Z/}+V@x>Ȱ4c ÁSxZjP(&cTS)cr︇,,(L%Ke\fq6CP F~' F}L]Zmda*)a;)`Nm9$qуI#HkPCSiKNT;eY\r^/dqWS9RK5Vꋹ7>'SC>!w ?Cv7A9~ =k[,/ `/m3&>6O9h/`FǨ'!-?w~GE.ݾ޵ʭ:/fJTU"TTMo8 F6wo)"Ĵ/v[D)E\ y8tOb4ߖ$LKIuTvҼiѪЦDzzJ洯Xy1 ݘ^DM%[آ OsG|v1ƞ:Y2IM/^fiqtT1Wk_3[ D Dp.璝N5 3^$Tw7Է6f~ i3dh!Ƴ i۴ٚiVMR}ߩ+:ٙw'X|bmcڤf#>F&L,H/b6E^;fC[^w 4MpЀsEԓ]U/T=|Qt_&ET,<}N.:ee '91ȉbjkl|ӣNO@0Y=ETʺM>c\]4u!ǽ+y4!  :fd`l.\l:m7Sۀ/7V ;+eLw'q 臟[:gFwwwYNT&yp6<7b!qRI,ٲriNstI'#*nIյ*|ި}CXĥhH"Ϻ$lxPIzTQ<.jЄ{nr)C(tQ,%>or(cZtbj㻤)U(]Ht! ׍)KO!zj'\2c2$4~W6<ǵ?O`S.*pB̢ghb4[w_7DPQؖdōU|g>Ho[n@cg5j<b~k'8ը >ȉ!:#3siR!k:dPAO@mǝ1||(#'Z5+U#q(䤀K "i$3&G5e \;}^bh`Corؼ?o gA'drF ے>eji^e@.pû{ZyłXw\:$-kKc.ii:eNTb0(3Eexd:֤Z[fLSi>'](qbx]? xY-8夨UܪMnmsFjBE{fll)7|L&Z,AkYSo<Ώ4} )b$&GĪI qxY΀L[ūl=XZ*m4 s!V5tlVIBҲu/~h190 zP)3S6}Ai־h^FGV&/fV=HI>>J>~u%䛶hm%dpICms8Mɴl68#PxWPS7–^[!9Jb,Xzݡ|B1{E]U,Xi5%4-n߉ᜐu8|_˰Xjc"=$Ä5ܦyU|eU,&u7S['v;w'"!z&SF(Mդx4\B‘UE4\VP[e׀P|DqaQ2պ^yglLfVݭ.nTk!%T/fzYP ȋ~K?jzZvʻHflV$.^|Cv+Wwin'}0dA"#g3ܽˀ!/L^֣S+*%l%: IDAT߰ZM:fn-]iu?)9]l/NI\<ԏqF*|_⩂Y9>ocߨ?̯?</|[XBmk5R[zmQŬ"9!HM|OJizQWl|Kx=2y3Ώ84.hX,0\Ei]aׁ{) "J단B|VˀfVn׽σU< j<>,.f\H"{_pootsVOS@x I6w`"fN$Eeg Ɍ2XuIwy(-O.qWOC7DSnfYqǎ ]q{xG~lcmt$e^q{gS/vl$]zu#_}u=)FP SK(࢏-DTy{cKϻ]H췾=jO~NJC/ i)7Lv꿵] w2W(KSf?!uEVfls49.kN,~K;kճe×mOx-Rp/\ y*' `a| v~]OO@2տfDrGׄ(NT(O,[of?B.[^ܹbue5ms#e&^dyYJ( )^]aUY]%#i3uy,Cʹ9/Ӏ6tDT|<?6džyp8*+o{:B7 QVʲ.yP<B +ͫL$POA8rOVk3pQᙜ39M L!ʻbSd\"}g`_y,bx Gӣ[3jCZDTpKE@%/d GxzM 3|*֡}H.G|C/ nJT<RtEA{NX%Q~Ns;ۣ߱hA GEʷQ'/<&Rݠ=>8JQ[OTUyTE0n/.K + [N:m*9Roٮm>Ϊ]ЗamY]aL8 O":oJv![FՄ^`g"[PRws>d|EڭQCv71tֽ%>%4Mu߽ޞY2,Ҫ`+dnlߢ֡u nφ&L^YN2 c?s94 KYbLn|Sz~~]kY|=/="g DaԵv,S :oT[Bbnhky5_ٮMo8 0x&JpGhw{<8)b^VWՂ)DY<5Zu $\phVzӻφGDvNDx G /;rbfp|n MUSxbA&~??HDmg<ځ,}3l5o7ɬř$ŲD8ȋc/NxtrnTEL*~"~~&ZHJH.)Vhj^UmP|6+v5ܒ( 'yaUtjPS%dotE-CnըZP'zP0 ;cz 2-,2zd/ 6kR} #g;=ϥu_r .}fV2.4UnW&ߍ'v|+r> 8?ZiKgeaaRlMh8vQ$i[O/#]}}q|W?DkYpIP$NDJg8~wYTA՜ePK,Zww'3 {? Tuԃ7$:gdV磻^JcZ63+R">* ;,mYPS Ă "J8JIJ/U3N _Ni@h(Ĺ3v[,ɕ +߉MDwp*۫Vڈxneq|\oj4punW B1JNIZfh>~iL/^Ք9`Sbzyw Rt-q M]ﮰ_*i?Jdȩގ5U<agKjmx䅻$/mU=匃 韈Co5 >^K߾=a, T*mԜ48~Ř]1A1FYCF zEjO{Fǘ|6?>'ZZ:$^ϿWWXmBn&w(A|Yզ#)m[ԷP͞YS鉘?uF5c8 @yzUXۊ8>v/.~@ `6WfV1]ۈ^7|TGpxE +lY}_Ɂ*TUE@=VC+%¯tQLdR Jb{i,Υo_2/ؿZx(mJ=jJOQ.֭rkAcj|rx'U=N!^{zf jSJVՠڊ;lqن;'Zk|X,@<73# [ׯ1r}6OR~k⩅זrz- Zhf㚨;(ၝ(ʹyaէA^9_Vu׷c]aah:էTHmfmQ%ҷropz_.q]6C{=!lgǝּ3@͆>ow*j"VYr[}[l癆$:Zm>v84AfUQD,W ,nuozX],P:@E(.znPMhdIȎc˲lQdHq(%f f!EJC H"g^~开:x8BG1nj9S< b G K!.n`5vVGnx;xgQ;8U:1-vJQ!O,nUI3&zu.EK't5 @I+=n믘vPV}?6 hXւ&u7 '^88Ӊ殴]^D:TBX0",V#&/ <ݨD=0؅8=i3hڝbrP-h6^ZT(HqnbjyMARoT9(ݙw0xS1wn?Gh`>o-&+N2G@AfW|/XY-5g# D";^iNn-gZ\ if>2LWlW*&Ոl%"|oM$UmG<1~ kƉ/u_b BfOvx]+Qj"EYpdvPXjU,8fb0FzvGǨ%Dgy=pK"q|x7ȦQ#*^TYω/ESG[4ۺ` x8t'pˆJEtVQ eN/&7aqUR97pe<mJ!|Lo$'D7~Ã͘\Bl=-ۜxi^9ZMB:Uɾ6EI/C3NwB)DbًQ[$t 0{} WGI9tg˟:6t&vn@ߓLM^^ڏg@%GƃP q{jiSK)BpqѼ] !)'k^UWHl9 bpXi(+ YS"SXš؛-N"}loI/%]GWmC%o7V=% Tsqq 6)4qysul$a.O 642ABkʢ.YܐaX-WW)+|9Ly-PH)Eͽ+2 Q&uE WPP*aJh''7$b2fsH-Y";z )4δ<@7 ߭T??7p3,ִ&V-iߍv:xGLQ%iTraJVJF*TduRzӽ 4JTP^1L@1 EVـ {+o6w;YV"\uA;> 亂Iװyce74KmONb*Zsu{gu"CkۧIz^I6;o_FB շN ώi1A~-KU|* C.fJ+ 瞯 0U ܌Ox"YTlቲbdc \<[ji1Ry\N]dcc|$׊k=MuW ^). ,vND-*>Ltoo3Gsէ]fsN03ќʡAJv|'^BL2^3܊X(;BʪO@Vb&uGx9Fͼ@:ܯp^M?iVW0nѺFdPJ"SsCe45^孀yOہ|(% Qޓ͈K),mZyﴺ7L$ۓH7b0@}^4֫A>X!"UNl2#o`?v%"Pz*+hp)B ("o-j_0Ũ;671A~\go;/4?I.ޏ`n4 \ܺ­+!cq5+]yͻ5{tPq+otbI841Q'|V^[VaN~&%8'-sTկFRv*c 2ЎXD"LDX tw*hte"bUh$XҾ(o sx8ςm*;8 JX֝e `Ѡ:$=^\s@Q%YE(lD"XM9<#hfJIM5aY"խ4ZhbPUW3ίJvV QPЋn{`w NCZnѹۛU ' xM^ż Q$ckb)VEKH+/`nvwU XR;rZl RPUf.NA|Qo(={30 +!Jx, (=UKFPNt3R_,G0nYVKfmpHb ܍*qhv D`ϴIXpp <<U!U! `0&{L#h G24ml6$9"RbQ<HE3I`׎;k(_YyuQScvϤ3҉jIFQC$ u^c*T|Cػ޿E`U`<ŦFLE6ʅQW8v4j} o"5̀ V!]!}aD.yS:Aל.\sfb'[3u7&A|?;BVA7.`)3JSƃy7b('L?!”Bd# !7ejT)\ zwI)̍/ n8w!"B'l&\AeR>l<" MMg0U{v% 8x{v#_? .U< nmuWHTO֐JQB_Lyg7_<E3oo󕨎tU*0MmfPm"J@;;n݁g*= *T0=6y SEax<(-ނK1`0 P=hV$bNꪂ 47J3U 5}eSdl$˛w^dqTjfD-tu#;'-X" :OyvⅪ;T!rJhfW8f&0~i-| c{պK_B0B霧kitZ{t\3Ð2Cjag'to~z`܅4+*ؼa~`fy3eAJ(@PzIV.Nګ2O %D mEV70~iW/`v.)hd/8_x6Cm+Sk"q@k!ݾt!Pg#}0&{nOSXJĒX_zF?MNt'2u3{7P071'q) '2Jl"X_0E4 ,׿v&n?!@jn,(DWZSJ-ҐD3^{GǛqg +ܭaC}w%_ITcߕP‡ҕQBH~VT1Ǖ]=ben(\n]!n61gk"q?5OB Xt T,ec]2xp yxD,X8s@ ?_j]Zw=2ޘ/ EM\)QTˆPW/aV~€bamJK2jn Pqp (ƞq@ʦrWgmWO|:NTumUmzx[LGF4R P:U:VUBacsw@ ei̿;H;0jP=lO6΄u /t?mGW .U`uC2jntOWmR:jW2M+hVwg ӕiqUZ@Q Ȳԃd0203(=Y6f.JJ 2x D8 ZZw ѡVNpZ;vbp (^Ftp\Tp⴮\&zVF`|әۼõLc}%' e (9I{uJxfKFN %[f&hJE2DG;϶A̼m(J˵>V (ƞBP*@F@iatw3X auF^Z}JXKV"Gs"y〻Bv&A5E'YeO=tس]O} N(n̼/@Nω,u c0L|[dظS\q/T[$ G{X6\n'λGZ,nOZ4)zhz\ڏP5R Df<~E:F[nae*}ޠ"d XFa(ƞؿEA X-Mp7Ӹ|N<є:S #RVEU -T{%]mK@Jc2pr'sixzA(_G:c7`(F]qz2\acD,{\$r|eX}*r =[<5b5#(@Q2V8ﴺW ڇR:2& i\n')!>P:,Z`UolM &yz)M רm*-{~d؁ ZR&ϲu]m)6AeEaRm )/^R# ̧͛G!KLX_[5V T*f%4;ݾcO.Xz7nQ[6B*>~@ӯߊH S|??׽㗑Yjd!?Gi; ?0-Gw#ջ5*U% ^= pw<㔑Y)B&o ;cEX=u߸E&#MG>㗑Y*d!Da}fE1ab)'T,G_-g`؋1o'Gفtru}(.2Ph:p 2dd z #Pڞ& 5•u=}S אeRG?k^ 3&Fm41uiGv#6&c,-I!;&|ݰ@Z9 CcJ\طh|y_b#'{|"tIrg>:w=iz^^Ijv:vGX,J(UȎpj6V+CoO{x՞EKdY dע̪Cg9\.<«/e\0+] 9Y#t} S"y˙|HاV+ȃ>rYFɬZ&:AИ߇gOyZS0kUe?\_*vn>2|!-s,ʈG_/7iݜ ^A\BZWdO$fFafYdV ɬJ.odRGC~}x;)3bV- Yjv[Bg7o#W:[e$lx׍PP\y;)j h`Ӳɬd!Yu~o X^?vR!h^QF5AHp*UxOڮK |Hɏ=YÅW\j_r2pPdVɬ:?dU?߆m,VkPݠ{ i̬^0LUu5'Ө$16}U`؋Kד,6zA2UGQivj(n-`_PPS:琗Ip*쑹}|ώUʴBr]P[-Ji}>{22K,d2 ?yg]ƸԸ6= g P&yU*(E-<=)ub9׀G?wWBۈGgG`Ie}{0p{?IedYdV Oo˦Ù؛ BܲOڍGy%NE\ePLUqD*𧢡nm2 b]JMʟ\Jf%" ̪*+L&mS3{x$.7{!{~l߼juKRɗ!9G?W✬2A }l5|])guYXFfLfU&̱;oے1KܥhikHrbaiop۲Rw~.{-sʀH5 m;VcfӁV.jd ̊/aҴ}q1s?cQBA',)7v)N'o{ 5ig:1{讽Xe`ðRB#1crZJA2j#:o}^= uY||H¶͙]Qh:UE掇~}?s:eP`ْ/cFР`ŴsddYdV,_?PYJjjX Kan~/z"ʝD,.CBs|?Ivn􈍇}uxu4˿Ȭd!Y sLR3YcF1 fmX_UҔ혗oß!-a}l>\ՙk0'KMS xZNYnd!Y<ŚB݂t}8qYIL\XZ$r|ܚ˜kr/v^}b<ӓ?xr" ̊#5)8\.Qlآ1>keUP7sBb@z!IG?0?^CҜR^ ے߽#ZѨ`Ŧ9_@FfB&`]ק«Gag]JIJ[%Ȋ2 b>nMr1ƻzďi>9YdVa# ]`4@'Y0:[R˳r JGx>+} \ƈǯ//-I%&w4YdV ѸѠ kSGN}%6*+!#+i$w= H={7ky; 'U_kZFf)LfEėn"$2W+S "ǤU\,J[,lEieʺߜ@d rJR# ̊@D$IQQ50ca<ZV񱕜UiBols?dǨjRZ{".FI?7r)22 ,d2+" BJoi ճhl N!n1I RI$QSq2>$wsʢ 8[HJJ]Pd>B&@IQ b ܜy nG$k1e|,{?VȨ=a;>F^$ݼ;jVG?c9CfqLfiaH1Z 68} IPLGsl Pü/׻BtFG22Lf y dĥ~o^= nqJR$iU əMȀݻ2+~,4, \c $gnߖv{NXk,,܊"^b(j߿$[d@tLV^}u,eV6, i!ukKӖ'ޟwG*tl3%_|M"+o/ݽ$T ̢_Ts)R"e,eҼ Z|miP[o0J\fI@RПfݻ}V ̢؁ʊݖa \_4b֩kZ| &[Dn۳qz[Gwߒcۙk땁4V|Lf4Z r.8<{(4:jhI 9E684gGW<2{ #33!]#۷eo"A(3/d!YP}QBAVv_pyfF@p=;3~WŬ(rQ2O4 D`yUӉZeVt·:kCYi~# K#d#~x1Wguhi;*}ˆ)L갆eV4IޭibbQXU/U6q3>N/5101pA_f<XQd|p _>e#7JT,4LZ?B`VVVLB&3+?P  `) 7qq1ݐZ a Wft1~= `_q7UFcؘ?r,>VU.1c UR.ds+rs#%5>Od͡OX r{R\s'[4((f<߿05 sbnDjw@P[1o?^̖Ս\·bke*bF+PB N樸t|ݺ2+Yd/UnG("qxwG*+7x gd^No٩ԉ__kJ_cu)JQԱ:ypաGoݝH%?YfYy*m0B&I]rZ@@=ÔY,lTUσ{s #iC~^o[7d `Dk{}C" x( aᰀ.f 9kCVU8.~-7ooy.pOoikwJK ~x_k8ʳG_Kt9sC}]Dt_QPJ %E8$"}(Pk*jRSVĺJgl(D LFtw&Z4CB#sז[o㣖j ֥NH$PB А$ %%sytqJAL8C*-5<~ేs+!|xF13 >q _ikvmյƱ nR@~XZRpýBًx㽏 - ~] MP4` b)bQ1O#0nź P}jN@8,ܰZ=h/BfU# LZ|e7(ubaY%݆v֧{E m: ; @Ӊn%? MpXPTp w Bit\Pk.uppñZ`Ss/P@o΁&G\- N_|3,*4"808|u׶v1ۏo}#9!؞QGOy9": >kJS-4^䚒J ڜX(YBXOi*jNkͭޤ2zd!Iɗ-&۰}kmʾ]}}xK m PkJFW͡0?b1t1 I0 i4D ?9#נCU>6GpMpMD\V(7G  zsTj%\vb疍`uJys5vN `s|M[-ΎfׇnZ4BTJ{lͩpQg<ʭ,BAWp9ɟB06$!&^)gaA34Mr"PIIL&]L$Z.ߒteV>K̪mԚ\7ߴh?82?|Brl^1Ke{U f->:?V_[:vB<:SoEeI!z==PЙX츹BXB#\BXa߉yFǜ8{*%IpfIB3EIKi]b BHEQ F2o՚by6Kp\Һcөa떙_F*w˲ZSBf)'ۖqCس~8uz2TSD7Fe7L 6IuXmwܶwݖgNh_[oBEUeO1vA"=.^u7VQ ppFk,Jo gD|6ేJps~^>(x0RQ3u94,%LfŬbΡ|gàà?G@]{o%\e]? א{}0e&#<Վ_L*LfY>|M(.2cۖؾ6Eyj(F)YcBZ=V]pbBDK Ʀ|$X`Q ܻn9ŀ/K1U*<]زa_l:^Ä`CQV 1 & NXWr#geȝmƜSmyK.(>,A#q\6fUkP{fs~F1??&8.$ Y>u̯cX|T4~Q?q6h]4hV:O h&jmjs,1[Sͪ;7oDC]#8*Z:fD,@g. aHs"e ν|]1wDޱ^-/d-fx9?YUͧJ~C'-|,p& jFXVV*,(*4Yx1iI(J5|ЊDZ}rA{8$ BMQxhLkgk '8oR{e 6^{0@#9CV.x#”x!qk( L9SjV>FVGwߌG(`Ccaz]> BנpD ,HUN Pg(}5'x+@};wjmEe7맠(_3h9}aVb#=uqwj,*Z ! |Y{ib n&'<&̌R@9@`6둣hAH*Qd+h.wN=cß V ! $dI"-b 1SIf!&~X,`TIJ0illŰ@ctAz1DoJ$!L8c7R1€Wi /_"` (Uo-n'>9#ht-;q V)ZVZ݃ƵʇYԸzp*uZ ^ ] &&I<B-4V* {$9͟Q+/"TC-8-6>AfEc5KW["֬eJ;buzTYdY^O+dAI/*l` V oԻ{<-IO%Xz|7u$M"Zj~_Nݡm?Jឥjrr6:(.h-+Wp`V& ( *n ~*U %'lIiuFI&ӗ'Gpi X^Ϣ2q E`4Ua+4 AWK 2ZA@+3=2pP5g0[ 0Xo,\99-T7d/sx㰲>,4a^Cg$l,)AE\eppzqt;g$I=Qq#,;g*$IFb)IEiA=G"D|UoXlҺ5J$\Ifׇl1V @.֥\-.6y.p\vQ,ztt+C]M#,(Nu6%b0`f!p " pL7V(/Aj1aF/@8**e r-A5q8(``sZn^WXPoVAkH}WMI2a^HD̓gûbL^val0ƛbZDQ bIIJJp[a{pt:8.ȸ|$pB&CmsGPujSI$$?EfG?S HRD -R:۷Ę+d8~P&5M$D` BNF`wwJ{g|mdLKA 4 ã#SY R&~Ԝ/dyQFGgr 5bϽܜ_yMIK hi5r^$P4(!´A% L0Uà7A_i,R{bi BEBv3(QIHq'8&=DalNUQ%%&;^8O>* \!D+Oq=X9I]%|uhA-̢փ%aH0 5L(́:E PT`~s2a2;Nmcph]׆5k$dj*}$̊i|>i$@#@ @i^ ۊr-~o_ȓH$i# A5^[Q&bB()5 ht*P-t! nGxo~/szu(C #u E)~WgG0:D8LW?9]S۹j %`4^|НpQED.ZLXaw8Ս@1Ag^R&JI.z!KTJPxWO\2VRa(@gfS [A\=dh7֤^xqܙZ4y(D !.w)@ s9li۵=Еg'h;9ԮRѰ$&l[+U!0244݃HEe()6dʁ)76ݢWf~Op=KRYɖڊKO=)A:2<~;p"kV!7/b1ъ-~O>$a?YF6VUϏ /&~ja.RC$𜐶>OK\يP@]h| .: $ xQW}ő@ cMPJXzBn EV(U 5p!^^^tv`wdp5KRs 7"{鏃+J[v!s"([f2;)^} 4M`2i`4YX?BⲇFe4v6@y`hE04ykB?z[e@${1El̐Cnmc}-2{b8Qs*D MĬtb6pab8Ë֤BE#PT%O'ᩞ)1[o/M"6Xin@X.^M))9`0/[?pvтUꠠQ`Z2:401)lvtveKBKC# EL4__|햧Ap9 mm}޹}ɹB4MEmmsa2i@3ɴذj JW٠>WQRSe_.ܟ\BpvQhtnz-4 {fիa6i#! Q$ y8!(KV'Կ9̾ LF`砵DXr=>A_zwP%|l YFӞt^f:M7GvvC ,m06Vv2eI} '3Ճps ?on8}6{"rم=Oȅ( PIAVlZ-+wFTWYfDab!QuV=ni6" ̲Zd#$=tiU{uL46Eu e#^)|Eb061yI'`~h*toO)QxT⁝X^aA/ ym9:EkrQ^kFw(F#"D+( r2 0|B8p2 J J Phh0N>F׻xԔ,EESq*,Βyɀ;B~*)dBTw?.(Ӡ6{yfSa=?MzRp㍁{)\,jUZVlh83l"N"c5R?Gg^7Vhxjy_'yz* |$W?;MФc̓EaG[zT$1^&A3p cVЄT G6B\_}?BXDf LpgTZrSxpA\U#Pgg rz(eTޙwh`m = b\&'; In1r0^x `jȅ.v3{ҿc~ tzw{nj|KZAAcqNOf+_Dxb3DG3Mـr ښ"7B_E !ƒFo\ٲ D`Ul=ntYP(67j0_+,FIrk6IEIa/ fKJ+ `0e5W.>9'-`& ̮YI|Ÿ3#쭡6v!qtcVSVb*`eQ7:=L i|nZ}ⵇ{/S2L8}׈ BE H~o4t%"cö8'"nY*ZTIQY} gML~c18QU^ I{MV_vBX21[6!+;%4Q,Ce3[ %N!J<D$XQ`lB BSYzqOo)Tܹ{+L4fI"`)5s̖c݇A](8_F4Դ0cj{&ƹT}6eqfh =bBXBy'n5A2F% ,oR\&e2]*5`@@σuщ\?ۇ KE ptX ZBA^''>$ CgPa/u f5 Ks=2Yͩ"Vy~"2a)I=-g|̏mȃNtuB7fC7Zi"X= 76id`+ad+U&83.wcpx 6;496.gqt.HalBpXBۺE)2n_`jm.Ҋg0@=&Kut%it*KLsTd\x `׃`0P^ŇcΔ$QǃQ#>pxD7sd);$FV; NP,0/Je"6g炻gB!PxK%+efBReƒB(́hn h(:4Eg/T"P5j"4Čaضu ;q qc5N_rLR5ZQfJ"+=OCRLrؑ['ϵ.t `d((,QjUSªDsCpNlp0ԕ|h>s2ൈu70`)h,njDZ7>Lvqt6휹 ÉS+rrZ]Ǽ(O]֕gm}03rv[>X3L{s@N6 IDATfgPu sksR"ESܓ:ړھP#>{O ڋL/  V+V@τ g<&tNڧѨ'_Ƿ@f?XTl ? ^|1jvKtp1]R-k(Q(02$j[bs;#!w剚F- RQBߕ٘"1<:ż+>z#g^fY锗\H"( E"w7`QYn<4ݗTC Ъ7c$ xw$&Z8q۵X&Ph֢֢o$U/e*|Um̾>$)Shd>P 90PVG<1>X"bTd58[&ƳJk yD*I. 2 ; 0x- ξC۩:vz}ÚbDa^HJ9eSOq}k{>x쯾vY ƿ`a&3e0߄뫰{fT[#F0(1!+<%jJYQ.H;E~,A%jqpI$!EGK,q͋2n%}CcI7CMnb]ZdLq#v?4A1ppj M'Yg.N ^ȫ˅΢R`rB5vX9`сQ" !0+(g{0:@21+QPAqj44%k>8F8a JTUr"gܲ>wˬ5x!k#gZ r~_/\IX5L3Ate.<\z.szŏh;Ƈpq?Ǎ)ϵ4_!RFtۻh:!CC(8(PMŅ$.liCg@>mJT2PD.AX71v{E%>mq]'d'1 ?%Yk !(b*$a|xrՎ]#⎽w2/zI:I˚8#uGR\ع\"DB߱9S;8҆-m;y$ 3VZM48?7n}?<<J5Yْ8SIK4NvuMk_j禷Ii^k7MfĎIJ-G5P13pyI\w-%p4Xii4L ˒R@zٌRL⽵熜ѻuno1srq ?+C≜pE+75ٌ X$ R+\7ҹҊ5=ւn KK<6Z{̥h2E\740 -٥:Ub4Xzk,7U8P[TOk׾RGQpaֶb#jhT*K06pgR ږ}v2K67jMeӊ8pK7gύ y׀vǟ>dA b?nb$%a@稬d$I]Xi|9uh7Sl 0.8y#pmT'OƳ T4/dٴM^\"X0[L8V&s RVfrM,|qC,V 0TuC;V+gW.eH}An3)ӋEv @FXK~֌JpYJ{sV_o߷;/ҍ|o&wf(G@%Zm-nZkY[-z-C:&-zQ>&/1͠1h9t MXztz Ƣ/1>.x"}oJTqbl5ҏ(QWo'b˧/;k[lqYL38b~6m^n3D" ,lnwr¾?obDvid?ovp bFDi[t&8Zhbѯ_Mz}d%$&_N :^%d雞q۩z~0(AxdU;넷dDv'1`h |W\\kF]vR]O8gx&Fvqtcd<\:EdX"ǀǾ{@ȏ_xDuGvlkS]թCf^ϼDlQ$عOd羍րԓeh[U42He-6L4yUYȢD4& b6iٺOs>,&zq~:DAdGw+Tzo<$X0ł~Є;9r\!bt02K&鸣ݒaCM4"׷ 7bS2DXY*eOCc&f$n w[t3.(""aIwG ߺEMߛ]428^^5MDgת3s6,1Np<d4]HЁ\>ZnӺki!YVkpchy37Ti-^tz-wnqȤ;1DhPug4HJGp~uYmdI0[?~K#"1@ˍXԹ: 3n@߉anc3fJxlLwmC|C'œDu$I(2SYa&Vx _DP^,l"/ znlJf RZa=ejL0il3Zf2tW6J tJy|Y 0-C2Vl>aTPQY_?x`)R _ԥ3ypk{5eoe2 eN{μJ=tzt$F:;6e wF7}aE*ZPl`LEFYv4ܯu$ I2&O`*/L0|lL{Cu=`pJ0.7sTک871dpu_H0ΏWpۭYrpTmAuC?w}F' f0B[$yp%#CMBdy vbzߛώH,ܠk^9ZR\E2%X1: f>]?' ȬL~uFBU}9 `0/}*=^0>fep(@8$ɽeT>EA8* Jߗ›6 z]"[/~'2YD"u$HvW/2i8Jm4:,!SIz[Jbฌu֯Y1 @W_"/<37v0oȥnZVd 9clvXkcq&BdD4h^5>tl-fԺX&%X8u+'GF]CRd4њۈĂ FO>9Bw9* EZF~@_7/pb:ݲ^X!3}8۶MS+ɕh TMA!JRܱuCTM-w5?}9a$ Zd.XJ67+ Gb\38'*X'>t藾I*w |K/|G1 w5 mG'y" =e>|Pn[)ȔN%^ -6V$b^ZUbu0c>ZnL9cDf%i[#Xq?:./s%)3 ө7mDC{K-0r>&A*-i]swT^4!"tMs| MT,,!+')F=͈X8hZ4etz, ?~}P.^NQ݇nݻ|d8ꐟ ҄>QE?xvƻDV% ?j8yw^n?n#bjԒP*.1y1Df;;cmRyƀ\}4d4At e ӳBj2i0sJd=х ?uC~jT[`"<;7bˮCϾzuZ$cXR4bN k=X~';~ܴsYc#09=&41>KSUZ9ˇG>xbMsG+* \=+#K#+Jeh~Z2sHE%z zנ7P"2I݇: ?,Ey8 ׋wJzdYq=!=_~;nHh&_?>_7VzRq X]r ޵lPO|Լ^H$h]p yܥyw B,$V kc?K`)tnG)RE{j/Fc!eE=ބ|EZXy CfVڶSaݷ47]{gBhI4ܰ=)EPS&M'L80ڷH&~W?Uu-lO_!aw8Fd)\ٍ8"mtrQF/Ĺmg8,KZ-yFCVW*YΥ ELe>W0ڼ5&Gɟjh@EoNb5Ի+j,dD2Y̫ ] cEY(MUR7h3ʑxc?\8/Tu-nĥ'T{tg$}y6r-۬̇2rk](URVfj@%Zw)o$iE?yl#?|eMm>~+]" p:8 gxS%*BhD [\hK2 kA|8/06W3ehinU"w;6V͋F=utmAW4vL[Ajg][Vt@mwKDjt/F{zceHiMdd-*<ʱ"j/l,NŲk@N;:'kS7-CSAffcF  jd%e%Ks j[ {-4afqf?ۂ,565{#8ծ=X/C}ȱ+D pczjFX^^l _dj|/\uVV4q( 33#o VV]oG9s:4ֻĊwBR"xR33nu9SZu츿&UY2e~>jM[>^@b :C }J\鰙L,b?ܳo[k@0%X,elj(܍Eihz;-D' =rriOK,Z[&jzƪA*&\gJfM a:!]Cfui6W62((DM^H1K衪tD׾q-nsc&9#.+95lC4.1L'1ZJ7 4ݹiMar"X(!2EC-n&oi%qPɣp?U,!?*.th/Fi6{q5=6칔'/!gFbRV!2"KM '2+F«@60Frs,bDfi݊BpNΥ09wOܯY*Dd4MȔsp]jzj3t-)_yf=W2,߹Z\x;&4}H3腳|5:z\/+uF#rZul( [ F !JeX\-ùJܹi1x]eP@dϻoJvZ5.둉xGHz~aV4"hgKɒBėP^N"jE-FysTLbRʵFEBqr*ę3SiNwBu z$&d$͢05̢X@Qk-j(%6H<Ô76Epz`Oޕ8OFbc A4Z-r޹L.ux=N| !2y2"ˤ/E7wZ\[X_© B1NNy=K#%}bD b:Ԭ_\fh bum:w c>} ͱBdw}JAxtj6HD ȶFDSiSƒ{g3E+P4#zo?)Re'޸mRVY-؉K5{y]>D7@cCJ_T21 }ޣA$X D`pBdQbl2^''?ղ4JX03gۘ^r22,=:0*:"]3?[yhƂahIY-F<)vm˵ ==xedH k|z 0}UPPi@@έttЗF+?y1Wh$P9!?"5*);ޥC%U M.<Ⲡ$ \Xx0n[72foY2ZCVLbs&b5ح̍,.&Pdp0H4Úa& l`%AאͳK>~'ϙ̄g~9SHD"^zJvƩK}7^oEY:.Mhp ׃溚" a+6X,N%.hc4Rd$PQFPkYHGCbr :Y;+ 33~Β|AF6%3}e!Vf%Ηnuw& /`` )3B4_{?|yfúgFH%34w˒^eۼ^wF׶G$IAI#]omc 4#xD002lx !],"LC] Մ!d5 mLJ}lz6H(lF L(xkX{ U?a>P"|d' #s;-wǎe2Cx/wLEn4ٔ\ ,_Y^.h׭L|{/O%}3a¾Eefk9&n˒ߟF Ų$LRFHR1ϱWg~&mc4OFYazDDqs?Jd'+ 3"eFԐgH+ߑn,!Y?sx=Os>uLXjX<ɓ/?R;X٣݌=.L (Ш-hzj54ՐL޸`A|J)]qo[喑c.o<bwɊ]hw( 5#_p6D#{Ɗ PۆëJ4WoKHY&qF+ǃF 4׾,O<{s{u2DNWFe&#+MŘc-[H&?a_>#LtzPVKȗ[ؗU$2{c9w _p{a4xuKWG VF@>'I"eb"bڛ Gٵ s"k洐U{D?1|u4lEFnBA$J ; #7@4XW}U3/=Epy\SM;a$о2zQ(uIȂYB\G| ~uq9%Ey_g׻`4|^Zl-w<)kS,JY8FeMiB0繗NZ,2PMVʿ=Δn/A`fDžU}FWYqHJb8qDfQKwH0 ,dvZ[p"`fϿN{itYTL&[~fC17sOI :ҲʍU)P- sy[VDh|?vꩊ"2kפGOW?=9N1ҮC&lxj.1LU@X7Ͻ|^>UBˇipPXzMM\7i19v# 2^c۪F jdvf!V6n.[z8+ DBjqܭom3J ̏&|œ]bp+L;gjɋa&04bF4UEc|)׍cf&BCM͎lL;p10PפkpQ":-ܯ٦G3ԔBHT通JDR PX}mPޱBO됢>ۍF=.6urZp9-lȥi]J5 ~;ڪ"h <(vUO0-ۺzc=)e2;z|X<_>|ѷ{̨7RM (K#VEb0kuJ&LVˤd TkacA&3i?OB)5I޸7.qFcԴ^>+$&Dzq՗]*"I0;2b Wrkt'Z N)!3Izru|řJ^BWS4v NH0}cvW}_^dhV%9w}:-+D9JX`Y:n;KBBVA0C HV&3 KY!PR B,. UɲF SM{Drigk۷5V9'Դ,_SUgFpyƯfv\N &{9wGȼjWYeZ<g3(h:6Fv) Ec5Nk4 DyrG\εk;:*G}FRIx;ӿS £F{fXbxtOdfssX5f"EVp_<ۊ훛̟S;mbބԘk!(oL>XqVg^qnEmfPalF"I "e% eg!t rK׫QҷVes9-|ذf att޿v6L7_)gnM6{nW,'ڪ' ʣKn*2Sd݃;^m40؎~r"+$f,kHnmek+X6#   6 n_:r'cSI<^2BEdi[F+gA*zm@f/>{U[ of:;sD"U>f{ \nFu$ٵa"[]TDdZagb~cbidZ"F\^{|ˋގ3#LW`M↣bx~Wp佷}< E?fsְ{thuv8q1f "-^C&!S Z,n"˲D8I&ΊqjidskN)5n;6R3}Skgvn۽4vhudygcބoFCGր-ʹ`xoOt|)j[:l`=WScuD+o/)-MBA4'Yګ;.wf0dp"jx3XS<2{[xC"hyo 8kt6aOu7\L0X^Y1P$!Al0z vEdjLiM+(-VY^K8Z "(+5,,mZTjT$pX".Cu/L E 8.Fu\^ 8UtP,.\ihi4sJl44#9dzJX>^6u@k<F"dIBe7^a.ScG_E¼L Ģl\FKh5֤7ȗ]gǷ>^&gEvkUsQg%V7mUV(# *svLE\ZyG+f;DDso+DLB|2^DBFh b=[dD>,ѵSC={`kwƔCvUOz0yu?wo}~9g γDDd[bq2FkEKmbd~zc"Q;Dk$?]Į84ҝGq%haShUV S`]^" 5mk&2JGƟ?/B :|H,ֻT P00ή3ի}bFz:MkX#Oa2*i2],EE5H2)N66dH]?kB@䤳#?]s傽c Dx{ e&Zu_!B\AlgWLqM,8i->rw?Ϸ>οL,Q[leصarF6m,t ba`X NM~ D:(mvRW+Xp Щt l QB-TZ쿳7rN_el Ub2{Yn)+_3Yf)ȕI/N眲-)4˄O&*(4іR"S߾DL+v;)/Q)OcU6)Yشwc)}<3.L+˵$VÉo2#ŰU[hQLPY(CgӢ5sb$R䋟_T[y#:؂ɲkghHdnw2ϋ?Q;n/AD29)+rJ~F3|xWт_ㄯp:=4c|1lh!?=oœ{TUC -Rp{\T6ItbhU'= FL'ӄLoO^ܺ;hqTtǰUg 7`oޕ *,:7Vih+zCh7v}DxѲĎX46/+h@YD|YY\HKGsϿ ̫%Q,%x6m`z?G⑙b$fr3FQR4*FIj.+E$yՙT ~kݪڠn{ #g6[3%%lfݿ- KW,Ͽt֦Tb0h<|Gy?̥lFfPȵR}Hdܳ)[e勓34\Ȋ<W&jN%%Yy` \]J墲xBF]$X~}VoxCdVßў/17f; +`_fhxVn͗Ja=]tl]y]=@8l/?`K=#o2ڛM/,bWb0#С+9˔*Vgǧ.>svɯIɹhlBVSq-Dķ|M8Gj84_{Tu0Ob:=@/"|ADbmxe&((0j ]zմLw^w?Tv_ 1kT糵h Jdf PnX9 2OO]7Ak~ < $T9e+*DvfbQoaw0ǜJQ֤E(IȌDꍕT-u0xΤh.UmF&y f%Z$)|gP :m{ۮ5`n#pGbxCBX(1j7gjRuW ^!L#J"NI9\n6xD^`9)'RX*G=QfڽvoFcKqo &u"MF(#KZ;qh(8xYd2M"B&82,8([$vq"yCRIn@9#@ Ad뵄)D 6ܵmTl61s9@ԓ> NͺzĂ+mqW| œ{@j$6H$=BeDSGcZ'#¡(w^o˽6VE{WugxRӶ!_zF&1iP*9uBZ&ǟG8!Z8FMCΰ+_߇~-?XHgUAn,}1tˎ}鍷h **pn0/–BkT3;GewR"K_D m+7j3v!4ԛ"Ҫذ'7PT):j kԶ J"WH%S z" @u F4:*{ht Z@L pehYGttFAa2kho&*|B10& Q%NO]W%$94L[< 1h9aϊ1Oe z!#1~ڻ|IfY1ޓ0ڕ,_."876IY}0o^O{E?yg1; 2g{|g~d|*ڷvryɤXLM,&7PPF# 7ΤE04"+|)4pkzrR_pUϫO=XYj(ׂ`$YO<tbvZjV[ƨEJ;U2f+$SL{ˠaG{;ڹ}Nn߾2[vQwFϐm=,:::칇֨! 2tnLVŗ)&x7 d# J383̸'kV*4ZlF 3>LJ3vd9K7.E"=ASѫII|ZHp6B;cE=~u| ذ~1ao~ ~umz6PG[D,M<}ãSTWXn䰙̪<(fH,iGz+-r*#a?b"ڦGqkeLOx&H&!%PjUJ/gj,–]=.(6{ct0c^괨ԅ@ueP4̎1>txv> |BR`2.x}LVP {Mhm).7{a SGn|<.'--Me6 wly)ѢP(̉D ANEsJdR)'4Rx_#oZ|#7S㨦VFE&Zl47Y78W(D2x鞊rTf$Iqȅ1&H"?y[YɁZJF#FC 38=$I%JR/ LV+/Άͥ#338oʇOk.RZ {]lE76`Q"ûxݫ>G!̺}o>s/#1WFa*jVo`+QDž$4 q-Uv!LL3:'hTcǂ"2rj|~eYcc j&;Ljx͒Ie@k"Ǔy>wiԢK^w{>%` ״D'C)z x 'LO9{> &DeF  Y^8mʯBrDkh͐UϧRpZڹxn1 "hT{v$'2'{=ð ܾu-uV|)b_82FŢDYKs%OabhGVeS}y`C ﯹcYe>}7ۻ^cY†mը J%2/ԬQo I̠'J`-io‹حԵӺe#$sy bDJ/F"D[6񡇊 Ra$麍1Y Lڕ#;I2$:lTݸ$09-SݸUh*CS]ͤ3$ɂQY$% vGfC&g_:y\l|̓Z'5I]IrUHoЪ\l) { &aBbIbyF@SaRs."1g9f((w.7zC~ 9#8Eڥ$6='I.:%$I48+T9}hLni{eOZ\>zռJ|G>p0ps{ *-[H'E:Mk6n*z쫿oA#pj޽o:wN~Ԣu2_>c+FDY2$t+YgG=Z+}A - WCk;ϓW g?}7߷h Ywyh,NfZ 0 ġQ+qVبAkc2g<zjk0-vފJK%]+v-P f%`_-lFkndILKK9O`tNgIPJXʲьƨ#1cK]o2G`h BD&bL\bgX(NS?-|wOIME}5y<>|~s#wFaehtyЩ^ٰDch-l-PD*ٱ6.**VK6mX^ Osg`бQ&'eqϏb'6Ly9$Idh2!g36ҙ g5jJK#N#IR~2nO'KfFyf03 V|Swߖe0O!k%Eb: FByjv(ixx?OJfP+/Zp' ޺aIuʭ?}mΜd2ݒy~ Gﳚ$Bd|۲&E'!.p mg LRbfvlơ \>:qw.,&;6(!Z,S$R)ƽ7LWϳM^݌B+B̕$:)gR`٨!F9)?5gָbQE Z=NkNk9U n۾[6wg cn<9tZ^N,S-|C]Wr0[^ ։Էٸ݌R(WMi/Л&$ Z69ّ1y xX୒DQf*:ԍc+ƾ[s)ŌDh Hdo:g[>BjXj[ P~Q7P!zKgqb76sي7oW} Vy ۪)[$L8 "Td BFz=V*479_һvr27&T/$2rm^ϘC,QNi%/>qhH&SJ;%ICr [/Wܐ!zǯ qX*V@6Qik8˸6N̑@,`bxQ᱇vv]7}xcDqf;X5`3 U-+WÌʖAo5j6a4$NI$~&Qٮa򵭫AMMtmtuH rr )wKmQZGdP vo,z.Rbƅ4# @umk3Ǻ{}C{*76lk2~Q| AjU쿯}ll]yV<lF._0Fy~|c>e)|C?.v5ݥQ)0~_tdk|م:ju_\ƅkJl64|9beCU}gY܀*gO%DO\:>r;KQ/=<pC=I+ JM){hw,w(ũEȦ6 JbkC[O1(ȫG.3YK}9r36;;]Ǭ~]ͥu 浑Vff$g2N*նtbFm3oDz ;rVQgil(#ro"2 - qߝ{p֭ 8D$>DnFsyN8r,gk['V=?}m|>L&3 t Bw6Xwe2£d2ΧQf3llXQ1WN˜´I1(9Fd2!I~@t]6Ķ77_ᾑh"{Ϯ%;d2rVl0JnW&re2_NNy$J ӈ٦3K &cq^4kBT5xfPFȪ>gvV9,/,/10לbی_ǽI~| zH|oٱobT*UՍJ Nʡ:f:mL(E7L4I؟̑bT6hr?cw?LscL0_dk ki.^!kG ea\ɑFcm%D/cѨy[뾽81Iν}2gGF97VZx̖bυC'>#yD2=m120Tw`-y*nݽqR9~:vOh&MBN{-29G:~goh嵾mS{Gߺ{cL4`bӽӗ& '$GHM S9u/QJ(Kz F沕S-='GebG/Ii,zV=E/RX[w:jqoj}jC2!+H@cd^)҈,gM*]AYkhIȏղ}ٍ¬7$@]~̔ :*vT c"rmҋy|叿PIK}q/>oQ7*i\ϏP٨g˦f\%M7q-+m_s]8=02R6_u<"{جfZV yȦ޶mRg\c`h*g4!a5>;׆*6TX?%:v/%Ff$$FoΏ,R)j$$#_=qbQY@ABB%:_nTSΐ$ Xj4ᤄ>{Uj=dp B" %S.0jD $m 7'?xɘZB"R4:%?ՔJsDdr b TE$`V]xT7du%z'Fa5jj騜TP_xdR4ߘ^gλP ,*44w93%k Q"ͽi` kJD\ c~H&|]vF8VOs5j[7/sH+,B4#!'PW41;@t$`Ʊׂ9~"ϐXQh1=|ԪJyo 8008fbrLug'Z*7z=1:2cvQk1i!@GR $QxX*3O^}XTK}UH(RY8UjSKCZ# dZd9B* Ǔ^*OFqɉSydATF='Z$L'~9sd]ScLnM(vqAϼKF'gjVҚGԕd~>ZS⤕$zz&q^t1^ FCpmխmeU1r0ϾtÅެӈžycP -WQk,MQ5(ne o].\oSoӾuقT(ljDo/цn,f-][E0aJZ.D1Ѻv=\~8PRJN ]qTqTk-sַU"WYX,ο?w?ЮqyUk׃ə?@4ød|K<^V0[&)yo \ #ݓSvV6U * R5F EEEF#  %|BERLvQTD#9 ?`$i0ҩ7r$$c~qϨ?o*X^J69&q{ZL LpesܥiU|ѽ+:x̻K@sg)řSPE@Wb Mzʬ*fWw_+\AWnJl qNæ]ftu7ĢVYNN3G=2]kp(33nv IH͆fb6j2G:6W׫I&R]s|w,GY}%4㨴֬o!"d*|SdiFf}+6K?1'85y&ŋ1UDqҩtIJ_a?={gP'i0b\hbF%3FgVw(zWqļ.sCsKn"u ??0ꂽeLXLbF NbnA E tkb"3`hcdC#@ 4}(xl$SǑſ,t_(H{S˺qC9ll~{vsK/vw0Kr%h֔sKڣ(RK57H\N_%TuY {<h4n,YFO8wV܆YΝH0Qc}-GL{Zh(Rn63rQQf O0>GSPFIOՊĘr!)‘\/rpK$bP딘Jd"쌇 ZN[zf#ue<4lУYO:ZStV{(zؘ}2ݢ whm&Ed{WugruT*fi\7 I@"g/Rd曈 d6QG^h*M_(a@S!)DE5UH%Ă˻'ff8s[w(?8 *p<ّ||EgŮUz M&3)8z=8#\<ًo %nѴɀɪbānn}Qqd;Zuۧ'{wViؗJ{Gk*I+?}SSkj~{رRqdbs@V Zf,)O$O$&︾bWNҫT"DŽg11<-e\Ozm&pINC몑#K%x -w((6kZ:r2tqo/ ,0Km1Q))&C<$I {ӮiRe7 R DB%&JBTu-:Z* /&وlrbnl]}d2<Xs7|Ol{AhI&iiߥVZtڄ`H)lUHqK]$"86ay:z~k/zmaRx֏~BϵD*fG[k5}b$^d,NucJg3~eXn-ŀ?Hm+:h IDAT} n9^JK`2.|1OlB RDEp2jEc6q{HDD:a5\uU2Id6@)L$M7ys"DD,Nb~`AWRqÈkpmp  ̪ub]Wqgl&&QnQ34glVf%ۊDо]O3swd9\ڎ0(2 qi<}C^R|#w(3rw 7OdaL-7nZ00="5+488}$lùb|Qb`tO"ɦo50Vhpf{\^Z O58#ڷ89ߗklmiF={xt{՞A{ lZ8; ,Y^HN$8zZ!Hqr C\8å<=BҢ3L65S~],H0gr$ KZvC 2*4LUȡ0QL&REm4ץiiL`߼5mlDL,|gmHESS(5 V2.78{$S8* XVwK/Zi[ " څ7=-2=-JeoTJ`tT"2w϶o׳uF5 ebmRpq*Dzi%t~^JcɩEVkiU*R{ MT7il_*{B1p⟈yc&n\T$#)|#F[-F:,Ja ./n9| {\ӭקR#[ĺDO/H;tҌ˔۷qmd@HI^ФȠVI<,2F<}("Jgzh1nRDQA;IQcwUZ[r ID:Z2\4ň "N+,<" V$'#xS&D)@2+`a^eZ;EqmXJoOMꕞﻻ']v.r"9pv*?̿ L0d?; y5t2Cjd(ZI76VBبd .CS~f%&-Pe9ے1ᙢ m>C$71w{~.fu -.'xɐ!N0:r @2΀40XėHGc5ʢf@$VFmTWbN[3 1+7Ox??ιw/֭R\u'RqQ7VSyY&Q@D=`j8I4@k_<+XhL")9zUJ"9)\!{ʭn_LbfmOxX{zQWc3]Yp1zRblP.\20gL.)J!*$D"Q}W9WuUuN3=1A F$)[]KػZ/9+Zʆd VH0sꜻr~y=3ÕU~߽{"\l?`_a?w|oo?XEI`z4OPRPQU>t.]rsծEBl:9IJ M3aJk-w< DXƛq\aۖ NX9wsٯ (mr'P"iRᏗ罙)S(!|/^xpk/NSsuaW[`#v *g>QW ͠\_dz70Vyu7GN;ZwR%fƚ[\.~M>_!EdE Ŭmѽ.^WX+3Yl],?I?d#6_BU ݕ_0 tVFUה!;_|!igPLOѳIɊx[(7ERY],g~x~4[w el}Op[ dFz!V t Y%@opczT_ˇ./wwY oc-Ql;<~ƹwJCߘEW pBN׸q1C(b'Lh([Ph+Dymݜ(%Uٳ"쾭Z2b?’bi( ) 1Εr?wYAٱi(ܮrSnXKzd 6+˪ľ>/,tau5dL_ZispW),D xk)Ϥ✖[̑ ;GqFgԂj'/^uo[rhߤ %!G#䗤F.n-fs̏9EzC}9¦ Pet3=׈͗H,xVkj1h$V'w`Q KB'A3p^|f `rEWLffxhJE؍띢(=o8wq&1U?9ok Oˊv` txˬf.0$kH.lV6+6bEWڬX7)7d51˞]u_Oc;bN;:xDjT&=T=r fot۠:y.x=vXF , dA3Oww]3QJzݚ( x֚.CFaa8,%SMnT*DZD+l^e,"RCjؼu;ʟ=_ zӴE*U;HI\A0?w%u?9ܒ+ߐo.\47ުl0qĩ\9!Oq[|2G!p9|~sgFuQUv:ݺ$…P@h$.Mftl98;~^#@g4YG[Xp,osy%2+KL^XLYf_(JHzZGyLhz$l0Js.%)ݙc﹀=s}BT~$E^gE,U6@×_/fjbqKFK?ro#-EX싺ΰ׃ElcʟMv㠿LbC'# xy4/~lLˤZT>Άu4Qw87{O$+aR}=ʓzzz {ŖjwZYQ~22"v}7_ð,d^Oz||jCDf#tHaJ0D"G U&r7~3|=/  MG\EKUV/ td 0^EM'&wΆb"X<ۻq6CvQWwhcpO[yQeR-ሶb HyC P?*U.]NwV/F@~1^jVy8VYE4m.tB)ӶkS2#?#'+Q]r;۬++&۳9WuR/*sm].3siru]]LL8w~1<>"}rN'nK*`ľ1SQ@ 9- P  tUB&3:fbg3,7zzx;C<\J(2 =JuQ:'b~WEB=}_?cR .$7&nwbV~𞎱lFōFeVH>'9RL6MEc9ىm6+(?a"iq=(/vGm,Uqa7:[?'(P-ԗ5NTYssшȯQP4gG]*8+cg&WB1L Ih:E wԊm_9x@1V^x>gz;9 T=DBXD\ܴdqw1e u֝wz ٪lǎvQ?ᰗÇ$s'tibQYyH`ySgg dS*}O`$./DQ1)Z,;&\d\y%Cnv}&ңfމwl)٬ yh1bCR fCtqӴf﮶2Mŋ-$2O]9XoOx`+2"i'6 pl9'sD|DBRZ%Iӄ') QB:⒵5Df`TY-H%7-}t IرǏRJ\lV~k@璸b2%\m!BfN>۽8BViw7u W꛻WvLm+_$hEzmu"Ru4$9*ͩ0"~ȏ x@7D7"7+ qO}(sꬿ`.ձLEܽp؇$N?68"-/mV*(VaR:vi!dXv슀h.61;}%G7v{XY8rsxs k[ŅdZJ\jme=b_B>![p!U^֯fJSoc2 IDATU̽Q}Qob<g+&Z3 ; {O?ZdW^=û]ʕqtW.ۺ\HKq*(oÂP7DOuUE.YB^˸/pz|՛عFD 9뷔,`bVkD4ob,t$\{кr%n|'X):y'szo>EHN.A&Z0 &QY{jכ K?ӕ=?.e$_ÿ=g6D[k{hS'ʅrtkYogwCWu턝 <<,k\Vd [ 6⢆T8msQĐ P$gVlTǯj8l9*{U}yKzxڞ'Mx\c:a½yum>̼jPSaMdD =ڱynw}t>V03' pq8t SjDd|=(ڊn5Z+.jU$TRByCyMghJ'7(1Θ:'K|²Df\0[P[**!2Cv[Եb $oNnފgDU>m XhfqA?V!'ǨFZӶ k&s ytu͙ w5y>>3|jpѨR^%RwW6m"KdTQg5k|IIY|jVUφeѰ u*AAŘR5]{qF!{ZX'-$V(`s-'1 et_8=֏_>,NViG= H 9k>ݵ"/cw[6V:$n8*e<5rBPJ!P*LHEp8$*ϽvuRt"6qrmx+F)V{z53";jVV㭷/R,)l1n2|lt;Μoõ^IN)Dwqԍ^>f┌/bsJ?R:)jX>Eո{51 ӎeh"4𺵱\-o$I`pWh0+l(Xnqع-Œjc@3:Um%ZK/eECBM.Ld ~MX%[T5ɇ-QKVYdq]Pq:O?gU-4pc;_Žʨ{98r&G?dB+ 8 kI,#+;TrN1;ݧ:_aXm<PyS&6Û>MٷD4>:qL^TI\,2A+Ѳar!ß̍1)fm IV 6gcT"fD p=WxgE唢8tm69[YlE@#32-֐zH*'bY tc[1 F, 2\=?tJmhvp>^~,hu=5Kd.υD9 K6|nWO;ʿϊľ"rAcbj%0ʳ.]&T~#뫽b<5tu%K6>>mgrڂb vk?X:/߹>z}},kly~P%`qU! 8%4ib@ۀg0>9pP+xy˨]S4|~bvϭ;ѷs`q^d$i-?[(D-3Ac+&lJ5_%4ݭ':Ն KB+\^rf+H:VGϥXQtޭ3heX2f!c R2lEyFzsJ +q۲e2JCV6fciO.P,D# dv&tbtJt[g FeSEtZ"vQdϸZy#nK}_B7&#eJ"_l]ߑ𪛋;ޞ&]vЇ#X{dEXI1~' 615/w CS4vqۉOX, V|VFNN-&) E["<`#V=1OE[]B{;+*VdGAb,Gr*OvHz$ }S-)_\E$rkجwJ4&Iw[PNIfTz&OJQhN~EM3ߠodYO.+һ'@)ѓSi;Q$J-HSV0pj%sJMJ./Y6(l|S5? U-F{R5t9po/dL~}zۍ' S{VM$ds%.K[kN;6Hdž'a x}rR3LZCnZX)G`KEn_ WІ_^Zi%۰,F6XSwwBm,^![4Cy% :eF< '湞)6 _mqdIЖt/$u@};I^\t- |>clV >6f|+Q ͧ*P2ks>SEoY CDN&9dݠmG%J:-ya|zE(ܲl Ȟ~^y"""BKT:B^\n, .DҴu$`[pRWȘn25*:`y; U3Z|טӠ/-6Kd8]}X4;,z!Na{8Qu]{vFcpk{?wFl&*ًE|E/f5]+*U6Xbč!m-=֕.>7.W 5m;++ZDhB{vu7V(xYLoӴ.]7X]Kc<fo@U?6"m_nhfdJ\ tWzm 2l]ZW,_kșci5/c؞19=yHP'Ҝg:m b%UT&00))ώ_䮁 _zps65YcL͆x%{|b?S&2>cc|zIgGIۍp&ଣ 8*`+ez6f[cv[f;LSxNx̹1>ޚsϕbN(C6%c%Y@VwSvIgݮq]ޥ%3gǺ+v!OσNO@x%"st.G+n,>7s/l.og=|wO޽ůrmRgAzSmjN>̡+7h_oCdW( 0B{]t?Ix;=K^ _"GLdi` ^݂* cX<$_ϝ}A^;WGr[O]+R_i3 ٭u{Įg=_X\ʎ/wD@YYgrzb9jl#"1c">}t]";YȆ/>Y2٧DlˊuOyvT6UbfX2+ksBt=cQoЎoq=hdp~Qmm zע!S~q3s"OzB!ؼjItF&pE-{AʑX9OgJh NǺ&LblQ/~9U&)UK.;.7#j9Xs> Wg]/2H9fOa\.$duejD>k ,A<ŗ}}iWnzcW蘢hLwz*`\@iIvV_D.\b].s.-Kp}vaK5Gkݵo`]3VjGoN&EBhdFW-)9:߹}!V;v|JF]D_RAG8D>12Ѯ"V,_?E&>^zgLV|$6Ed |Os\ZQp؃osWr+#VC {Q6pWN"2; |gdl8 )KFfaTFJ7꺀jua=Bt׆te#YDzwɦJȥM/5 ftWZEStwx)HqE8cl^ BuIaI8̿^:7ܜHT!ޒ!"b&1knld8֟T, YpEko:Ty$C{_o}Szf}fٸyϽL{`uc@_NZXZ&8.2֧!,N35}lXIduvJk.{Cņ_^zwjQD` s<52PvU@ X$* $2Qx&͹ROkgb$tbz-I;GVҗkfp4Իˣqlv-Qs3qؘ hƧ*碭Bǐpθc;}oakoI)J]2Zl \6m`o~[w=b`$]FeWl_KY~ 0q͜ņ@D 4XCnWd!?q,"`goU=w*h%9ZŮZmrhoE0m(ڐKi뻜:loj뾮ܸH[gC {ۼP,rd{9se0YꃲCeΎ<&9}}a)爟@5 B^Fz׺Wn(Ik\4'Ҙs\x=C+滍г\<1Kl.G6U"*1?҉ٖHl+& ގl"n:{wtzi0?#~5܍ _fV b׎Ny`}OiNC->&v⤺a[F'a]dŴNEwEZ|hC{#5.![F6#GB~ OdjRTINjd%gm Y'>0V kasq3y-KQ8bZmĻu_|>JJ_f/o{q;m'#V>=Q*2[$c9QdV UչvalV|H徍͖ e44IRO͖:諒{dTLJ_ ԣj jܸ1#lYj=œJ6ӽefJafIT2.m>8pݷeq9Vo_aBr |pZ]rSd  $ixu_@,fpȋ},KJz暦Ւrݨ;ٽÁ/33w+r71P:Qܘ#,}hl閪.~P[tmtv3 ov.%@W2UDrhF31/>Д~+T@&Uݷ.Ԑewrhx8{|b.TجA?xeMcs2E<>ˊD?V뾶T9^pJlD.10a`OkW[ckq|YhgrgqGՋ&Dx}>DPr8D8}ѩF&*N'm*xU:Wq,M;t`$r~.~&)"qŌA4OsK^D8FO'^oPsEBљ?yAfAgKQY)<}+ώY%G#ؼ`bvg_|KQ$7H^ܷd9Yb\Ftح4px1~9G[cD>3~\{ncIj"i74rJj,H&^G{jQi><~k||WX6a~2%_I{WlTUgz,"H(ݽ(}kᾪƋ},S,N%_PXozr4f=❙V;4 2{~>\^>O=Jp%ߝ6?_|Kk荏9uEֹq1ogρO^Ͼ*s +V-[Mb|^ݵQh>h>OL}s!_yp6w&Gtɻ盒YӪH!<䞐TMz#"'ɯ/ ֒XhAVm;IUR|Y+ Nmul %#wa|frEI pQ,hKS;_}?}%(~WqR%rԣc)mOO6%2`\.{ 2.bbkǴFodv O[q'g8{*S yU~j|Wa>*_Md?}MW4¯=[p4˩x1o;yzobvwOy&Wjjs陋Eq eH0 W?"pT7E`+s\;wŹXȬ^Tt:l@A[woyym>ki̥#\{dgjV$5VV:<S\08n#6M+N,D v!q$q21Gۧ"X\r}ý/jKEo]@5323Ka<ǹU uiKfdr͋R!W,}HFQԃSF;&ńΙ5F[ ׅU9ؕ ;rMavvhE^?QsQB[8xiO vuzd: qC#֘(V'X%+X=xnz}tR8qZMl-fn({{/\*prznLOh۱q%5Mos)AV{hN*lpoUv`5-ęa~1NjR[n6M;wl5h"k'lU{Y3,QTlNh(*g.#.KZ\;,EVf*v_W**8[j˵Wۚͭ!2C17Dbx$ jKS^WfYR=n;~_8llT.QQ~/Y&*"'42v>υjᮻty~~M/Ou ɕؽl.\*PH6}dqמh-;x"M[ 'c\ "m>}{֧~m#ڜe[*0ڶ"DWO"YkعsDY%ڂN9 ]"euq[DwֿE+!GinG9wv̺JFW{"e|+lQf$_Bq}%“]_{|kVQzJwXN3+jm37.vk$r^7=Npulv^_(tz@$+N3#󌼝益A߽O|x'ŧo_].^@'w9 E7ܻau:VEdwt} p"pnBī~"2,h0Ut # m5«A#Qj|7Js=N:/MP2Y+24 2MW*)|ZÜW}\^7oUOcrhy"qjACmgٽA[Foo 9v~Ϻb"=-#g+ §"ݴN'rN K~QeguyBRUcqxft}y3 =nb/GQ4QjZҹJYJ;[y^`iT86Xpc]2mmhʋlΥdNIPm޸fu,ɛr":L]֌x7ĚjW"`Z ZL&3chr\(+a~o;q 8~čGuo;(dΝ^5XmK;~ዝB[oW?+bQXrm$t:Qs/ąBt*6]HΕo6tO0 bV=joX2o]n*TI=#+2;c>ٜjR`lZ݄|D^*ڻȿ./UԖ nZoYj[ ؖcLǀ6w?P m[IŌon$rTCu#(,W`lF $8ƴ| u]]TBf MYDxރyTuG 0ɴLMk㙖aÕ5aƦ߬Vo#- 6"[UZZ{$y>'9A 4I%˖}:u-[?NC|%[q:Aה}JD @"X"- l;9OwOcv'M)`g{z{yw_65bD 4ҊE+7lC70: %SFaK%:kaA,VM V3Pi(x{bZKZ OAjHqlhJ$RD W,5NekG)iYHWB`؊%!;*a\=kDOO{ jSb/PȮ_ͫBV+~GoۿM/=FbEuąod_E"CACM m" %oFy)W^%l|3 .ν6(f.׷(I CxmmJ%2hsV$F:UK"> E__J"0p67Z}~a1XdQh- ܍o:"28̒/fd@ϱ3'n㭋E]ǡ}诐w۸'#25>-McA7(z.^z sQK3'avONWM;l4+4?dh G`,AӍ' ~ >ho9R拥IjKYuH+FM&rpE BZwFaUYOc=?80bQi7?̭@ᶴt( G֚a鈂(O&2<mܘِks.ܓDFIr4r&wK-MLF{[_;Z`XVtqr4*ǂ s@/z$ǰ401n@!4dz6"J Bӥ2l 4bĒ,ߟ ]_e]y,cYa:)X /Cqv1oxHeA5l/o(*?D_"Fp!d\(Vܾ q$)pI(}EXg?闇:q{>z ҫt{yupuIr.߿"p܃2Fx&4h1#O3gqhnCߓM(I48jcNKh3? y [p& eX0vyu\0t9R \]R!qhҘ{|51NȪE8;/J)>X 8*h8LJ32!(| CtD%q9Ǐ&1I0h~T6fXJ2% K`G_}8l4Ci" ߚY0pV{Uz+kQ8^/M,u{&ϝBWGsm) 8#O!Ξ'1#chzGDxlV-SEQqR F\6mrqύ=4t1!2-HG~X8{x6L "3t 0Uq*8ߏΝÕk~wl|s`51}v;d2Of"pR5X;XϜ×~_ģUٲ>bi N+x{ 4A * )""+lCh.5lBIsDF,^H߲TjJ-;bqx؀Į[-ԜiA4bI8ES,p5:`wY!$RMLD[!rlӃ1\懷⟻mCP$ Q\dM$7oȖzg՟:h9$  υ+; Q(Xf@U;FIWe\?d}ĆP Y ZA?9%aa[2{\TC#DN47,:sV/U2-4zFF$>B*WӖ}f%,Ȯ~ފɔX\[WvjdEe +*dU,)foMc{p>4lۺ]'#Nc{tx/ .*#HNA\vqh͸TG%,V å뷑$洠f[qb)-[@+g>\yp~ AUu'17`ߞFdqJm_*),CpY]M_SVU 7pmp ǎij?=-?1%=?*\V2_ >HRZyK¹tEDeB}͂xt#sEӫ =*Ec[ql2 J2^v"_σ^ɒXoO+v*X[klg1Ҋ0Z9Ft6:3^zz]x; n :Szq{|iQak9g#[_֏&Y{ ӊGյi)f < jB:Z\b[@1 !?&yB6x jS{rBJZ同HLO,`lbVF{gc1ϣP?. cM$I~+&·Yil9PdªR:$NAJrRwk[7._JxKxKhlpԑ#'Mi96h8fUƘv3̺.J/VB$@$tnHTj9CgUz{q|/bd~G[>J₈l[X {3atlꈷ>ZFc!d7V/[QjPozϷZ+[J%nBcfl֖_oWwcwcQ1,~hJ !OjI4ex4 IsւHdpx8VqBchqAKu|w~|H=AdϟrؖE_Y:{m<; OK3RT%OBj=X# o2kIb`w &!2`yɟfoN]a IDAT3:& OoC䗌`mt`>s!uvg_ïW=?#Ѻ)Y4SR( [cޘrl 4.,+(t 1$Ϩ5Ħ&f̏e[tCn74v*$8 ? wo"=ms,3[C޶ӉK "եv#`heIw[X҄k\h,!^$.kx׽ =s-V9hXaZ`u:r6^(EY~h(E$ y;J'Ȣo"J.Z^M"nOp$}PT ǦqnEJV,?9HK2ₔ{#hEێiJĪ0N-Ixqlx+6<ۏ7aIV01ao$"&?MIl+@"XUͨ"X3O7emS1)*v=ayf$MdC&4w8ơё8.] "ZkHҏxͱ#s_.p#O9l:A| >j_%(f{Fl.b7@57U:YP45/G:!"&Vx/9Zm$::o6ľh4BoDW+ wY+Ft[`3?sy8̿n&~#PfJ0(cd$b^A0Xm$3  g'{O>^M˟9=oer%v-AOwsb3"ac{)]f]f"g#>\ĉuGfS[Yz>o^(g~n۽^D49+J"Hk@7Pp7[1M̎ZU~%B 6mK$@]w 'o ?mt@"5$zx׫NE1 ,l 4fHTܐ0}CPӾI޿ؗ n"\ɳvśeNUgrYA؝/ v-cb@2$4YH{ے/q6X ':lNS]bk¡sK#BH ^ k氌8zvgK{v^_x  _yl7hAށu1Ȃ 6> qڷhXF,HefoG@1$7vFegex`v([/09Ycmm TgaF0ϑϳط H'Rm\P dE,[fH8J ]] GƠk )Atl;Tz`[9:.Z| nB4 F{' CJHdFE<0sdJO߁,軯Ζl!izMP5B@D:&}wnM0bj\KjAlN2IziR6gL @,^m jDTw`KE'WA, " !&,ςbhC"1vhCS2|ӥѯ\JJFŭAtlڊMgBɪQnEPb8.sm@ ѥ.ũER00L2,Ovʻy몊kFՎvoulqHM4 Sm6uIMl:Pu:_Ybt.{>tb?eO -kCl2%`q$ QJ7-.tvYh@Fa`7W)gouudpj=9~+YEq'~UVA4 &o1s;!L an,XP(yfTH4UG2&"ɘg F2*\᥷_ rx|3B HB H4F@OD@R$6TF$s1p{c4KT9Pe Wp:.9!;fM5bXV s $ ;67Z 4P'p &t5k &Xu02m=/DdϟrE,k d`vZ.mg~]DJ+V>ͦ>{xv[QV vedH   AI4KpYaYLg®ٙO?>/|Ƕs#: 1 C ~_K ~!߸䌆Dps0.HODW}Hbl2`+ S띛q!nžS!WJb444nx?V="#1ħe_4{̖!+@,:6/j!J3CK?w I-r/^Qn?rer$f L6Xy-F. QµD#Ő0/ckdn2Җ@l\AP`,]ø"cC #lV9D"L,V}mG]j!>&brB ;q+"4TFV$Dj9 G?G?i[b\$7k&hEaqSfj1ѠLඊYN-l4W^JCd 'Kù#TK`6I' C:%kΞ "RA[OZ!i_WVF(Vf\Gf#j&AՎmN\6+z40 bg#xdIz):ƆsGl#wsGk&ꯟR\uT,T, "s @w3͂8 3\)-#E7Zb4⟗6S1 W`muGa+d4%e84,Fp RvWFTN0ZH?~ ~ncǚj˄vMej`!-AT5L$EL+M*Ai)i)$4 jO)\MG<ۏq:3N Qtﲀ"2<`ţ+j^a^(SOyQql6[#P~qiD1p gqMhZ^bwz'.ѵC: R,A㰕a_q~$ i>9;!-EIXJǐN;| Lqq\x֗px9 _sq葲al|(Ou~ϧ'*q" } ENZL`ij% +:U2CA+R4nRV.saŬ(p0pqnXUZQh!M0v+ᐅå1vDf`d̢GDZYmG2"C^ހloӲˊ mJL2޼M2n7&"Ξo@R{P-,h0eӌ$Q$~=Lmm«3!\ . ]`jemՓ)L,;)"e4 hP o.+>FhRjƖS4C'J2EVc;tᰓpfp:bqdS4[ ĥi{Xu% ̌s!ܾ>B}KQWNqW|UCcg_)FÌwbIеw<?2/Wz}0nN')wh W_>ݠx ck܊¦d*Tw9\% ,55$fn Jpz{%b~"ZTWvy"Ń郶w[urF6W!G8vp{-َB]Q|eD u5Vʁ!I߶ > nyr3Xxx 4*}&g8{#&I1uSo:{EM%ߺ%4O+W$U&phۛR\3$U&>r\Cb*l#ofj$-F;MH(*\v nO>nt‡?U 8&XqcW(kN:L lJqJN# b0|IFFp @:)#I;xx= ,%e3A <=uxy3TTbcO7nL#w;xG,FcG  T!3I6рTzkM N,=$IB-SP,]CuhlH520۳_iZhU4o\,,\p3NTjq6ԍIfro5cs;&q~7L+ |ހ>UGq["Sd74̍ .ZDv{!@3DQT6(">/SEf FRHq}[M*՜K.Z.;"0(=/&ڌP#ˈ4݌GR0ی0U9D4kx^9=HĠfdr63Y1$WIeCTdgg;\ͦ6tFXDmNDd  bB,i  Le83[YL[[yY{/A^GwExGMdQ&Tr>z &[V[~thP*}diaU@:2LG֒{c,J/&bHzf)'?p ~ɽ˰,DL^KYy /^.3 zaHؓs٩ϵ$*G!j\Ծxzl&W𛽍5#rMjka.~  iФ1g *]>Zf @HIza b:V[6t[ lRE6 &s|W 8w[7v.ߜ%Q1;A pӗhY ojpU-N§5=ܻUB%qJ/Gdk"gdʳ{Htl_]2crƇ?o!*ltY WqMx¡>TnEI9ZbO;̽xS/<{ O.$"Dqc`=1%ЮEpv7zܹ j`:W`Vw=j(Jr;ˡ"oCg=Mq7|z;[Ibnނ!_R<9 IXVF뒚%-dH2!x$[zXP@p `욿fZawӲL+oJ3# ̌+|"ݶ]'jaUK/稲b>JFG`jiI "f㎺V_kbOoql !`ZZ<%'SbIs9,L0ca:{3-YIĮ}e h I< +O=GEπUD}&Ѻ͌@ +gx~q 4=NY柜QݟKH'`6@gq8c)K'슯Rn _&$y]cfMRٝpg|H/u>Q%Գ>V P8P}-&t5/Nhl#2J*DcmLĖ#%aj)ɦU,9AFSZ9!`B7~gY-8MGwFw3(pk,Yٹ1Eut8`墲R|1Mә͖(afs ̖}OK Nꓝ_ZwdjڋsUrkgVgM~VxP|L-jcnhbHF:oH D"b|b]B4 ´#Eӳر ;W# / /;r,] |K$ɰ6nuC@bſ}RA"2)t`y s(lYQ&l YZa[e4r8~cDVHbO<~lJ #%3-%ّBL$@(*D wbCosHWN[n~w@x>?E!!dP if^9}_Wq_ѯw?_Y=g.]D$o>3oG03Y_ԋ8EA. jB\rrX8fmf8RDb4 p s$\bBZ,>ކ#-bKExkno-I3 n q/RtnY}$14NV. hR,ikk,v YWMb0i|Nc.z%Y ?I@Stx珕n?V(|EWBP.Ő8F 29lŞeD MWGdsHid-o'v_ qepe޼L:ߙ)92,)R\^[N) Ou8x V'1`vZS~:RIUb(^\Úi4ѱAn:ƪjpߺk/ =eQaTL8ilit0ceyA/ ZC:DI8r}meiR#DӰj.kP"L\$\tоYvl0RprN 6Xк#0DdA(Y4$aEřPH1^J$ O`d@d.hDy?} S>N@eKq C;" 8lK%EE22,AUHh%.\;bhaaq)ģ8נfe[-X>1'\tU)FAbig*k$YEߖoW$W2*&8Î7C, 2nqyD%ȺbSى~+zOѹuK/d?f~IhWdG?CSى?{p> IDAT@P/:Ӧڴ,3 sȼ& {Jqc҃[QЙɀ^j ed`1[+a)tsWMJSI+KJFԵRR‹~1{LV4EPJI@DS["I 92 ~.~U}f>6˴Of-:¸}<*? 0fIn!ɖ_{탁ǷR, >#&">Y%9]o^ r}):pوK%DӉ,z,!GR (*7@PםN\P}LfҌ ~ˇQ[ ʲي*rEM3 K.(Bo4I}}"PQ\w kA_*sI@"/ ] !2J|Tٕ.Tgxk32- i {B~㪣1!›BǍ4>el1`4M#BE^iU7'gڸFw|R00\id ,iϦ1w3D~)lR2O$@0H]F"dEk*M,GF얈[48DZTJ7}^*C$v?Q-ʺ@ $t5Suوo'ʶT;#\R~v:lnC]8' U ,*2S)^PT\ ?G '1 iN["td\r-e ,)\?APOh#6%IHd/=Q6QE}c |aiH/U=8Pt3 NS΢n%ELBę~0@ҵ7qf '24abPrg:̠)8o;b]`RBwƧpzp6eLҔIYǦ00OFܱ ! iZL&p>n {,f챚`, Ҫ8^KTNPealm{5EkbT/n"* 9PqUʀ<<7S,A? f4. ,<+qB) S51 [Yn! >QPQ jv80`Fˋ-HUq|U(xi2&)S1G=O6+`qt頂pFߌ3)5f-zV۰gwo]oi2,!6PhRŅ8ڄ$B> oWq.kd#\̺84 bbkYrRAr, vsI!@  ⤷'CPUK֣҈@a0;+:7ԋ&>n UNVz]E|?ܠ.#k_,%RH៫7H#IJQQe/XM1u)'֬lwy}GA(z:L:"i:4r 3+VX \=tYx8_{t>"H$\Ku%iE˥ [Iֶc v & #{FMgE4$LM/O tg"玷=dBC1uM@xNF&2h{ s+dZ,ž_u#<&?$ 2.%/ +ogBC-PQ 6 .} [:1,v"HB.Wzq40J ޛo4cb1k߲ IDeh3KO*faVl:~?5öq!]ؽllX /~ %&x:;ǰDV?!D)&pm*2( (V=eѽ/G6~9DHķ9'YЊVkAVn_Q_7>*`M mALɨ#DIX[-ӌڊBf͈cSع }tթV/AWHdE s32қ@q -MX hv;BK ֥#\~#!ZZ&BѲ 6Ō 9SBpM'jZ8{88{8(V7skapw_ Nt# P.gj4N2 ?U,Ă5e' ;%3œDa1;LQ%'gfD4ijF(!2B2Ha<@Jq冓- $l3g͛|tvcXý8$I~w~||SJdC+\S).smGޔ] ,G5^Xҽύ0OOmYQR'n﷐Ā|4V0bd.1_ Nv7R4He1}{2u|ZmG$3Bw $FUD*&'2So6oo8E>}%Dw)G`m^kX}Fkg+Лy,Y6eXʗ`z: 3K"AQT+A„03<F2ؾ-{\'̹Y--r5Vqg@Dsn N.2LvzKrf9΀كvN paDmIX>_yNc~DI4wӘW@ q[]tG3$e#7טK/fg}aUۂX j+"1uv*Gb+1`|鰀tXk15s5f 핣W.\nQYT8R5}Fܾ V--Ò9+>}% eiLZ#b;ym&*EcVT+:Dtw@3 Rx3j3¸7_:!!D[+3lꁜTY*o E0ƓiaM!,J+ǐHuaV DY*D>2Bp•Ӊ !K~y+ڄsÈLU x(}듮2"Q&BV7}J?g3ń6@s弿,CJeoB[&@UeH c!̄Ep&.;:8aT>+3x Y{Z[ 4b-X=4z1q @C ޺q7V8r5`6sxSR.(*nDxw!H+Cd: uA p)";ayE4b>z [?_'] ~ludO;hTzE*Eh`շz""k`Xb#2+IϺi@k)X) Wų(!.hW9 W Nl f n@x62\I$2H@*Q!gT }$<.Eᅺc#xK@pRPav}b2t| %X4̎;,0[ =8w]bß/ia N>]ۼhraϡ@ P ҽ 1v͇>DR $(ၦ(MҐ$IWߥpO\f| 8$,/ #d9 "=-{w?)CLdžЬݽ+&a-0J@^WMB΃;=W7jIjRq8mQszzᲫmVM3*Q o|8:Rfgus~̭y,uj$‡OFq@=;pur1{-sw&@L~h{}Wh9\[&ml+"am3ֶjBW1vRQΨ` 4Kݥ(e "`G鄄ũfGˆ+bhsǍTSSY1Q:y0Cf^ue/vVW.f-i̇LĊ~p&O`MϬKp}ޛGyV龿ARi%[5؎رcljM2AHB!f M'=Kt49sC!! $ Nc'vٲe˖,YT>$w \Y S(+QפkZ)0i1=3I1AT TS"@o ̅eā'2q̕c8n IGr8/EjSW1[9L*>Ԩl/@z]u4TbhA#%ipxb|rެ$#2տ)3^^v cg`lR\w[R9F*I@,ƒԵR JLDYcW),Bܛ=@KgR53Sn̽8e*zjkg$vȥ|iUqލ JV/z%џD)AYB]35%oRy}Y2QoUyY,EඬhO( fǟvu8t]QL!?޻T,U*pZ{(]Q`:1qkfL)Bj4ЕEeI$2HW6aNѶ [RIt26l(G].NvjZ91kvDP)LDYfFAl׭ e+."3_q3oR{4E6vwylXJ w޶5mYيF?J֫ ^=x.'Wq1ݟyQ \wzq9/r-@s# 1_3X(g.>gadV+euʌM]sRCi7x9q {X|:srqGFjЧf|^BsTT5ٰdžmR,KDP5QoVUJmefy\/#55PȨ:]ߒlVn3j%VrwKk !urYZP4_z}Jm@x'}W[(#f7"8`}D>Saa55H.A>WSaC˂h0Y1)q5Ҏ b ڝ7vٚoͦUjfzD8E#6U`0V$by FO=DZZ:+躩sYS 1A"Ro,fZ3!JxČ?Tˁm^2sxynh˿+EXOĒ8.OU1g` >ND;V/UQk ftz8LrB\<蠮+qNqNE:"4ח|Q+.t(w+FF(RG :=o|`2khȪLxUjSH JmƋiMuWH$hh4ZJi0$M5J=1̈u6\BYl6E$AD*%1yy{q±{epz 5Zݕ[p̋'8J33.Tu2o4hYco=Xn{5:4;Ŷ`~4Bl]1#/lUJ>yOvA&h*>}'(4d.ΰ22V׮D$5rdM.DJAVI͂~@GQ(l~dT&_-X.}"v:&re7>5j*"(/KhfuiikƺDŰPu?,*ynݶ%2w/T&XC_dƦ9w+9WXۘ:Vf@*OMth~] l6*ڵ(ꪉCOMO!j/aD"R?@H ir3=<1sg' yu]Ӝ Y\/4yRpkDMx\^μ% 's>?9X,e,aJ"CIhwRD&Cc|c5A)H3fq-ܲzkVk4thP{[h^_+k8Cm{3[>'UVhg]u5a|z}lЃm&m&>}(Jeb8z9kϜ# z3mzob{Eoޒʄ\(8Fc(}"} ǿܿ?<$k"i h4"ux:O>m^X"&cp೦ yӗ}T^›4?q%2j?(0 G8l ؓ9Ik٢: JU Fti"V3ԆFf2ݗMWֳmKgѯ&tw$d҄?/Pw G (2Lg(uj9*5eO=ʩϵRr m[9Bfִjvk0!VV, , IDATRV3]qEg lxW1ίq AS0Drw? 2ʰmhzS RmbYvBxbcc!7!e^ؚrYH%QIYV.:,VkU.G4(!IjT2q\: uUe\/x;o˞)#ybi`)AR Oc-rƎ57sݢ>_sB˲`$ęECZ82>v#ĘcNP9_=@c]#.wp),4b*$9Y{A=ZwB|ȧRsXI-*94}J*h\ƥS^Ia܎s}c-kRkV/$LjںPȔdV/6wX\ 2Fsm9H JdJիj8a ~%++hf]@+vpt.ߴӀsA*%#MHqy_'(ClVJ /5c 2 wٹ,)$z^+8dBњљ/ĚڶK.DABTB!| 8pDL" 1Q{|#=nQ|̧{a$@HQi->J*I8֞yS>i!Evj 5 ?~h+3BiS5pqD/H @UB]_8K䔬+d] ֲno-+6eҪd/am 2;8~嶺G&"EHxD Ͻ:o֡° #13VIAUp4%`IDʹbɘfԗ)qRv|Sg}g,#Qu+*6Q\Pu_*Pb2ʖO^k쑄QYp?N|QdJdR jz@ TwAeJ'6 u`ϮME;{ٴE#A~}3H/#&&)Xl-n_..pJ621f\0o,3zq^PZ}|zc}#ݽ/٠HYܛ[*xe/qgKRd-=kJ.HAF"1;~т20اՕr'8I(!NKgu05sUKE9=;{_)K):?z@`X؍Gɼkx^ R$/U-U(rB0TD*f %5kS *:0qɉsr;bou3C߹ULd2 צJ ٝkKk^ٰ5T$KXD,A@lj"UZږ/#OR.Wx7Q~#3M+lň2}iQ{n(#.?iB=\![Znk1mQUnTg Ui`CAJ*obi(z `8vvgmN1-Ά mق }\L1+a1v[ >G(JTtA'a|Vƙz˔RT&f/qBJKQI439r{|:e;^܄]+t܊TfT )ɏ1MWsU/bc+VTA7##DBfnG3D*!}qC'* CyiNFeM[#<6V l[WPأ]'<vMdXwriAH0eϗ|{ck~LLמO*_g aj4'tƛbE"D"q 6E{p_vKd]zPKa%BٖxXA~-rA˛r̝!ZA/Z B)&N[IJa23عWUԀZd6 9}^D(aL4C"SѠJ46wr4 $R}=plo;ge%9Ms'zIsY=?CiMzAnuKyh?ZW*fׇkp9D$UiH5NҟFN8U/K}I8!w;׷NoO8}U?{*T)-'Rn /@v/+K ht;磢,}>vnҒugilHrJMoƑ-`z$}Q gqWdzl&W%KvED`@m5b٭Სj6Vo6o_}ln$ Ik_đz<@U9\ψaٞڦԺREe t^`AR95m%V6'ݣ}{py 9[<Y]z?C6w; YM_̅KH$B\\ye:[h˾I(/5ޛy<~ת2̢21g6Y3YOD"j _磷d<-M32Gl;6u;W|wl0;`WC>]ۺxosUlx%zrBU1tJVG }O]\)*:c<! n٘_95 s0TNL|'|㯾T052I8hڛ}T7iT52~ڇD,E\&*RxBH4LX#~ ZG_wژuzoTP~8ca+j*mwV ^-T"D)x>3!3at NrIYq;NY3'Q0OF-6;޿YAq"F5 sjg[W?29at(P6Kʚ٦]QI-̄-Ƣģa(ż%䇪UdFY-J -eK(Xny?zC.lݽt3nw6Q+پzGBQ3!J*y* jU7ɰb/  't] |Ĕ7Fq[j>kyȢ#W"`r3:9CUyu;x] 97.*TRߚ inO Buez:edO]uFn#hvl *G%NxĂ^ҙKirDd"ޫW6[$7:l&6ܺ2 > 34T2]RSeMuXfxyxfT g^>֓db}%ef(zG\HsI7OtokJ;oⅷ 46_)!G4Q/$Rb^'?ERI(hOkd`.P+۹-ow`Dǵz9 )/wUt/hokW8^Q6g߱vG ZCJVɹ9-C| LNǮ^SK~+Lf#}CLg 3#f}+5urܞ0c^L*jS#+v$R1Zhݾ}oMI@<ɹb5Ln@aa$b9%挏[ȨD8_kf%'dchh~OsAc"̲?s}6kW,&} %tjxaVmiVJfbNߑ~lZ4w/ 9ݣ z[E6v$2m^,SҦI0V˱OyfڃJ,M-cVAlb 9 8pZ$M. :cݱd1Ǒp8vVIYuu|YwTLD  ?hT ۻ؈6[ mkٵm-:Ņ%T)yd>5J-Q(]~ yG_+(N ^'vDdfof8LŒHw) \Q]F&Z ui4adyi/\)kra {aa5&4U5|KF0.xKUGA,pmGR!Evi]T&}: =?eC46^15W뛚ڨ6 [Faf&H33>0uu&̄$Kek=#4F1>F9EK~RM*)o1`Y<2b U#Ze~v:)(ψ& J}ad4D< #{Ha ,}LM c!8Qf1{w8q&b"K15+iWbJՙ_7"ϥ?gjaGNrǯrnp}2Z:2 9Y* vZ Rež18|LʖZ}3e%zN%,̒T0VQUG[Ve+UH (~vm-9657?Tk(ogxF*$‘(?CCm% l3V^+ip,׆E2׾o/'gS6{x\@,cZUR9qNEh 1!~W[wq!vCL F l(ǗJ%lf.㖮OXNθHj wI8\.{ƕ d'0}Qw߱[6Z=Mqo1ccB7ݷl_90?n]b~G.G$2sdv۲Fɿ~(-2 FWa})L^rɨ__\%%]:x<YQYFhh׋{d8䂦LT\tn6Yz6ur AeNHb6=dk5rQh+|CJx|l@ QZQYd2IH˫*S󸃀7/ߞ{6 tsx]sk,gRg٣s~Q*(ӿ  TvԘ"GB$Ki]٢%& RTCŏeԍet|*_7o.τԔRe.{$H5w_!07Hf6qHŌDdYn 䧿PLDM+&`(5U<ɻάZ=D8,$ÿ991g}ƨ(ޔYZ IG$20ĺu-45eOh4J7~z<[d$LZGF8?2BJ3Д)k)~Fe߷qlAZ۲GCK!Lp;\bNx5/wsaribhT#ͱ.+o W{W7u=+'H{c'6G "} %/c3kJqWNF(9KtF"kj,)"K %Doݾ" ƹ i*jgIƯ&ߞۓy4Ʊc4a8,DOe`i['ǍM5M6ɖ&2=׷VcHŔWp]uPnҳ{W'wߵM'L63¡& MԘq6m$m$olYOBE2B{'2Gl]S1O ġװ{7q8VPYDR^{ds=$Wo/2GQ!sR)::P"}ӿRݜ85@47r#2A_*X.P^#[] qRhXĨg=![o_Ķh Ok'4)?z68rƒ.F$ZRɹ~BXSz,8#)$61ViԄTI_@:FhdD.YX**8.^jwn^F&-1nfm3u2(&y"̌Pѣ5_&d#0JTjUu:s!1xq3}!mEW@ ˸_|W_?=wm,Z*1K9}i$0v9T|;#FV$zR}W^ U{oĂd=MH[0.rRwh`tvfVK7 M1fʺpvv4485$ZV$O4 "MtIQ1{Lλ]K;mdߞiiy )G|>Zw{Х|垌љ72tu'kѲ)U:r~T%r&c^}شGyLҬly?u*^ZQIuP :^vn<*"rX2-M uȕԔP*LՉ]%3TZ*4T'qex~{s=iU4*hXs}"#g(drO>  MH|o4 $,䋤_)lyM*^o}1츹.! !xDW&f<-BOc[o8K:[ XC8_|0S~l_Rn 1ذS:r֩(ꝏ>{m%{_@ AqkSY o0/S9<\8®]]iRy"haR3x,ĢՉbќF}{m?F'Ϊb\/NmJDfR)uUaEcM@_:zu.ɱkɥ wN\)#!Wʨ_QAiX$бQ3F$~ESSEd,aՔX0[.c0ɐ)?!Q[yqU%HdƿRТL*u0 R ;+hYDb8v(fM3&1=P@_>V{gK|?뽶Z`€{UW]n[H$Zpxh,&11!FfOZM7D>c\ϟ[E۟hD*uAi0뛋:֬?DEy}X?LOmJ7_;>qOA r7}m&l=;xժN.21igdԂ] "Ջ$ IHg$bZ1w}r 쏡+WtX < JƪK{k=Xn<ղ엮_9cC[,Ùpd/ʻW IDATx-'%!I06HSb6`6$~ODT!=} <Ȉ(Bk`ǖvz #SD18ا""SA>[>y']{9/o?9DAj4th4DbI~YO u-Z^29 G<.DiʦlX7@ox}BߚɹX/'_u]zQ|@&O#Ɣ׮Ms%%Z**I=If ̂Q'eUH +{^Sl*WDG|hS籓1.eq氟x J|[R0?3?9Ư_9Gtvpط)% DXU'ضmM#'i F8L,A*S" zwQdJUZT.I(2FM%5oID1bu<2obt{[n^{kGN FE /Εb׷̄Bs_YӈTɋȬ#.&؈c9Z2 ͏7r!vwr}ΔL&nYL&etB8mM(m `ւϝo"J"fy؝^Tjd4R/s˝5Է/N+@e&#:]k`rϝ7笍!{01iC_|k毯Y"zC篺N5(ȃD0S622*|bqj**A~pֵ&'EWNOd{ "bk{;,DFD+*-y:֬O!?^S# 0,DSx#%q7$>2޻5'sGYJ#@8A2/ϽWՄat&kb'^AC{F.^3~GxYk  űlq\dK Xt)-y mǖvl`t[GrgM~hDi09$?F~<ԃZbHeR넕si&F c"Bҕ*З)ѕ*їn{y1.R(0=|{caX=lo kS# vm |kI wϲZ b#Ĉx2sD&V _z RHBS*ܞ9-1>a "c^;1rQoM"䉫f~{G>{mj(-)QTvzx.+KIz~|A_,6: D%2]+ܵw]b\ؽ۶ӱ*sbXn~7 6 2xb]Ҵyxi^FXT0FH  Wٲ0n[:5_6՗c慃y傎/Z:$R^'R]ě7d7΅2b ВHFif 70flb>ReK{Fw_ʠeu&s$Lp…=P CS:Yur.iڑ9!!z$" L> #`0Ffl&_jeX,Cn/لP!.nGϨ2#jIo|%3j9o,/1pS^}tDD)Hx0k-x(̿[7: /Rt4a4+&ۮ%Chj+ط+88z?=ƠffH ;`bUF: jT.{N3#*i.=@&b@>KXp {X|AĦ*K\D#Ifp s)U޼w O~󟺣dJ? ?Qn߻#XRK h]{rc~G7?;R'/~ښ'rIɳt9)Eԭ.r?/>$^"&~sېcuND&:Yqz̧Zi: "L,N!c^J QA VEm%iz-=1H Z֘|(xXAmMbl/RZ[y Ǹ| S"jGl|A4ϚrO{a4!!Nh4JQȆi~)2c5+S*IDN%&_lV%O;+2֗hQ9`v3J-ƯO`5n)?WThf)!&`9oD%6aO[+qaLu;qR%υ`Άr b{=^xkEGkP[YD59?J%1=Ż_x3HMC1!<'ß>_U>qr)Ӄp*.]/^K[ӭ镅$?;НL=fa3wSEэLc'O'm)mő֗X)|@ lK- <|?o1ow(Eeqyz]i$A$BhvXiLM]%biTes$,c6Vءrԝ`}&;l? &-Q;q01?r m|/qW^GX~ȉQ! EPs7(EP~I_[hҎŵ;A@+!^dd(ײbconF;2dqn|}`S!X)*,)IخPR6; J8gB#CWhYL)AgkYO2zga ŒY,_E0) y[?w_M,K@;h MڭNO|W{o%m­4i{lB(i+ 55~Jvֳդ#12o I,[]X[bŦ*Vl7h4gVgsMA8?}0o$?vka^Hz6+&$ ab11~j%e79?Q 4Jlސybv fKᆧa$>} wa.]FD%-A@;C &l,f> !~7^ddҚ ȕṄIΩih8cyx[y987Q%R'vuim'.3g2i;6Nν4qڙMi;xZز%ٲ%K%JD}  Ab[]r%TA "F2"mn.dYYɘ˯Act<6w=4o{v%nqBML{ Uw _ ;{\Y>,+5HEZSR9V, Dv4EjSs r%QMKV _I*4\c< ӣ!WGN#./[h`OG .O1tbs/0q_4^T4_ed$hcedVt|:5H~ Ί+DA_ _Hf=[y[RFOʈ'Zڙ5RAΠg~sh :WB ~P_u!`SimlEfNIT"=©&XM* _ZN˥kVB^BYϳ^C8Vю>v^ɡaF&ZzwB9ؗj- :#y2h>zr}1lL.)r_=#蔟?5JNjEgQS;5xl"T%qhs/жG]G!n^;~a~CՉeɥ}cVV &Qc{+4UC)}NĒgjq&gܲk@SDQ,Q.?&/;7P5HΪ7f#rYsx̨䱥Unpnm6O3XFͳZ+W#|7Ct9w{t£CWg\o)s15=70|yl6T"hEX4p^Юi.tMsZ^gz=[z .FdP g#q.Rbrcm 'K hak4#Yɪ'J"ߎ<&RY,"@B,3q}^hn~k.@6 IDAT1b4Ϫ*hCJn׊5RjP$=t6OC^樽C|wſz l{ /9~ RJftk7\OgyzmL2+4VM< fo(EI&>7E^.DS5zVPrryq"+%EXFҲōd,ӯ8`zr}[aձÅ*twH:&jYS)yCDʩ%B}GV:jdh\"ڷO|y[[*o0M|?N_↛LEB3꫏4hB$oyν7>wr:FU3CVhm 76Z t.k?N:|#JHk%"1c:ln Ht*QftY$ ;3*_ Yoۍ<0|^7w~}ۻS@@ALӿzT5jX\/sJZtnᮾ`G6z97wr~bHjilک‘MڻZf~:F2^Q4u7euAlx*E@ͱh -=O(Wno~mqY-fx"]r;r5̩Vnnzi H36h+I"Zz{+Q]NU^'J.|NQyLNSz" %#PΗoIJ]Շ_[,DF$9zu>R9:GN%6̭\ \P'ѓo6O^;35w۾6T5h,7nE_vr ]36潷V>zݏ|8/=oe|=(-ƋgY~: DOvKߜNqoC[8ztl)4 o WHad5M&$W0lH&scAԅyNѱo Oׂf,@D^'n[N?[tC>rltՙ@*\zI$0Z"S燙 )4f39b Άd3Jb=xz~BQx6g\Q0`,+Ƴ i&D>^Nۺ;xxyh-hZɫZřWжpVVp|cMӐ5kBdpXl4:T"46=>碅كdԳcg; zdЗ &:v,DQBJD#6d(Vql%<9`lA۸ۅeb{c͂Z'OeM3WOO|۾CuX =젵:wS!TV{ xHgޏ=o V3Q"=}C>饴i)[BVKHs)M Y辡z780V ]m5CZ_ ͣ{]8; г3$g d0-w~aDKtaJŝ"$"=)g2id vR,$lDH+~&mᅢ蚏5Y$rJn HBz5 '>?K&)cJtlh t6ŘT%s:-CC3v.9nB#l"Z c#L&T MòaD\N-ozm7ZQT,B*U R f3s{̝ J9>z s.dTs՜#c5L[@曶ʱ "W~7o;STR2.GKsihZ~A] Þ:sM V&3?Ygd-\3,oOIv"6N±Mb]D~B'*a!թX@\䤲$V ƅp˽8{tpS55AyE@nd|$O/;flWɤdkup1$Zl[=:B}kmu:OF1:YNT>(xB^Gvq4@c^Dɩ$io@opKV+h4K/վo߾{̟ 1&kR~ I#-#\V:ռJC8fz<\5q%t!5/j!ʯ{`Ѝ pmtb|{DQ?z*2#GxYf vh$HF2D|H ?x2bj*b60;`)X Z^PgeY_*>#bԊ|gK}tCO=x:UlfrSM*$=.tx8M~JCLيA0U9;n1wnp~JHc`px%f<>ayh U>EŒ3X8ͅL"\lGBuHIij\JٹJ$J-\lĮm^Ƨ$2XH$A,ՇQdd8Bc-N #_L&=s۷{io_"yɦ'xs*ci&nc,MOSo;zzrCVDbI=z1Xz9ZW=Ɩ/^?Wswl3;7TJ$^ڦw~G ほN/^O]h `n/05oFԥq t ]{W}46nl!̭g3#)/}bQ( S *}uQcҗ.F3ʋ~$߳kEd&xx$x(g ήY`2NNV6H&b(JH(X&nZkNev1G T{8tN@!"BDeٍefB>FҺ݂^,]Npd6.B"FY+jBŶɐXz~2]l6*ί~ȓk>od_=3-M¦W;op}͟Gdo<cRR4&t8mؚ@o|drI2$\d8[TD9y%@koMm.f' zHFC^1]Zvs-k?\ZNwDhA&" pD U ԯd4jǝ[~>bZXK흂oaM3iڷ_]wds"}oM |[TO}[K;n@۞ a?NSj8+> NR%CQa4Xc7yz-l-.6^Hmi@:09$65= ^ദ5:+/ԦK =IɌ_ӽSctjbdkܢecʽNcY6%̉%T$DCF9R&\$K$ ss&TC469hlX.1ǹe)pYa]S~x 呗,A xnG3ٳuZ"T584NOcL!ֱ^2yjAO]OyYEX=rLz&^c^lUj9BHdx`W@Ǟf5W#a-=`9)fkQ r"٢E"nQ/9i9z Ҹ&j\Cvtg:(=ݮb1OK\6hᲸEc|^#Љ:z3z5XEaݵ|%(jJZe ;]z[5G@A+8? nRa#hIfDVWN?E7%Z[*-ce&gUI us8pKb<Hk*~r(b)Fjaa*0|F+W$bH&s{uV=btjiY7Hn_!: A,#8+c "|Vc'Ȓ{{D$vb1utP0A4)MbeH^5BW*G&ؽki׊]! M5gB_nTUcd8ξPP QˣdUv}nu O 9bsi V++Pur"bx4ݍ|lyp#ƾGޕ׋2/~`>g?.vCC )rMˣ2$Z9*y&kfDi L!JIj`L`"JZSpfY,VRl8s6EŢAغۆ/}B-')>y=}ȲL2Y ]m?XyEa2%34`h$@ Xzd1o&+םȬfM>F~Ѩl6NBU5Bd޲ДY4֭'"F *겵(.,JLA׎ժ5bꑖ^վoszIabSdȤUrrp$/Vp,8wuY]7VhnsZq8LtɔL:`ZJה< 0l4KqV>N>dIN(lMTI=[u6^Yopqi`8>3ޝx?n牏o57y;7_>{\CUsŦϵQH*r*9k1!ÃǤ|x&,3w>J|:V1%:Q ΢"r {z֋?PdF$L%T"f"sX̕X-fuw055o5H- c60 R8՗ Я62:[[,6DCv Q\E k 3Vb,p4A ®5ihi@ IDAT ᖛzpcr-h`1974^7pJƢZ;\$cA84`d"?T9]B~t b:N+/GiP])Kv*FhtwxAϮϾ=[[̝;#fգ*]Id_x?yw|յhXZ+[7mlrd aNHTX,K\.݉*il 1 G$0ctfkZ ' %9C9/ܲWⵤlm)j8s~ Ø•Ȥ3L2:4]FYN$9ug9q<.K14&H.zLz\UFI AOOW'e?ؽ!^9-]Ed_͝&=ZO|kΪުPV/ˉN2ݾ3:"H*ʬTHƻņ`70hZ> -?;ikZ`vO16(2p1,>%XX!hɳ Na"1"F+B-ibOsJD4I:!HL2F'xkhtCnl:fBu(ʜ?AT3ɭ̾N2-H]i^M+ϏAYeRadja%Y|6zU3X)9%HA'eCaz=}ӊF^Q,K/6{3Ue0v2s8,ؿK{u:7:\ZG]I+Od׻q?[>Mnڎɸ~ǂy |;$-)$& ;㔪T':T42Sh?^}z]B4^3Lgi[t,"&)|&ܰ;*֯>L&Z|zsawOr8o223WW < \#vQ"D!" i8ش1?p!XHS Jf[7t  $u XۆF3kNczߖ ݀^c1Hz kP9$|c-_L?^ctr`X dUE<>=Dy x\Ul%b9_c-HkOŪ<KOw}& p?p|m8,Gv?~D僪 XF|] xPjRݼk9)|u&Dkm"p~>gN$TDJbWɫy OQx!qmiƅbmkf[xHmseMp[in ~I[`˶F[=N8uԳ$8J/]᥿<3c){  QQo,u`7O>w),ccb&R"_M)(p (f N^ 3+A܍YZGnxy^9:@8\8\ßPY1UՎ<[v?e/ Я.ȑ X$q-.Z[}kc¥I.N -Z7g}5ۍĆ31ZOLJx$Z EHT`ԓ]XwzB}X1b5lX9Iq4r`L-opp6Jhws_e2&>>˗wT X3"8/ޢ906 u`7O>(4Ig3 F:V6 7{ē&|@Wیr$!N f[4{j7 8xGNсB?( ,Fjh\%yo?"5M{M[q+^V%$.Mr$&/tYt|Rn#]QFn.dldtqHaqح{k4vqx ]icTJe_3H5k9~ZIl5rJ7xW"iSUbDbэ$ RE8X]+Pj1Ies>x#y(*u33_9dHgh[}:ۛ&T!֜jxeNRL9. : O}zaȝYNC^W" )g2G4|~BX|9pqlf{txlZܠ%w}?ѩnbyRjԗsxgC &ʕpFw54>W  $ S'Љڽw`(?Z=j1D2*JVŮta] (M6 +Sc(AjφZyGҌ M4o1to13?.>3~_#8N8S}-Vl[ Բ7˂VNLpx/77P_bR,eSWJ7FV CW~gE7NgyNtB?<M;+4|?>Hb(FKTtQpKǡ_I$Nם32I Ӛ:ii zQigч1~ieֻ_OP' _ԷihX4xG ҺG_I+qؽv޷d:Q(j׹ƽ8Coӵ=KC9Ǒ'Noai$'發q.޵oC!J:8ÅcX]z^Vbn$QD֛]x[ DI8\bԶM_~D025Z%ݿer)rv':#HIst(oGm}TDI$PTp89υj^;7qEf?U^ՋOpq4na]A\y-ei(v]_H׷953$H,!b6ٻًo#OgPJahl}S1BW63ل ik,z %~*v7B^Lb.Eg^7eW}aQZy>/Nn>y2p2ؼLp2S$^6U{00]]y|/UZh&Mb0r߂F"a9]?rX^;L:YnnP%VvF*Q􆢰 J2˫ gE1xmYD:D"b?^9;qۚ~,њm~{ L ˊ0\"ků<0YsF'yĿ` ,ܴⅮj 9-eX͆ۻ|m$UydltAp9^|<(૿MzIGm.DIi)ŘMȌ.ﵔ. zUVIW!2&\dξ:zՓSb-qHd"2A[YANfCu|2eR"YزȒ`"9W:[D:.d(G_Ξkb씟}z=7ފp~OL\iwX Ք4WpT$Z!_nrꊥ0̄L dmknbl-j{{: IڃN c<ܥ8}-ڶTniir4*kzHe&!(b49CY014t6:5!/354O&%q3ж߉^12SWAj8qp[(HDDS-4nq2;MϾ?j\uHOG]D#N2cn$EÖASZY.̙Y-UaJE$RE϶j^c\"D f='s"?:ioe7^y>U"%voB,nmDбYYu&Pf2y7FF.E05Op&,0Iv̒ :,k,ϭG)ۺxΚt.?ɟ|[w4X(rq<|S5l>l 񯭄EՂdc6JERy\dDoT dR2Ҏl2^?<Ʊ3زՎրkH63vaR4nsyx[=Gff'Y!,M PBK[ .3NgML;C@NK/%J@ĉxMv-K.ˎrŲIG|羟}rtX?1*D%e_DfBR 0fFjш/r8X Mq\H/x>?99* jOe2p:9[r((TC*AnF=7ڑDp:\8[ׂ kλCǧ.C"ByONv; uRNzFvjl5U(˱# V#@VHD'LfTYDBA*TPhhP)\maw鄉 {'FK% Ԡ*Է _hzj#KINêepiBrSPJ) Ӄ[bb(3= 2Vcl 8 +=5=0W{z%4쏹XnҗD]( :#DkfVtr]_vO6 ts+S1OjK(sM14?M]#u8Xk4&{ز%crj8D"utѲB!mۃYM+U8a0Ůr2B)zMpFk2ijyi DZ 2J 8RA#IE{SF,  0n(:do5yLU #cQ ۑ'D:sh4%EYH`BO)B*O Q! (ʛr$ptu1>fA"@ =SIŸҤoEi~9j60=/$L}vΑB$ ѥFQUgkpGZ޷$qliwa BHt0L̤ +B_$ uatLQl-)%82´L:͑BOEfw!U+\Phː,] >`3EVH潎,yO{Ǜ~lm-Rjꇰ; kP% -ҠL 8pēsClAs^ij41}j VTy}><XY&KhDrozm !0١c{.YSS$UQ9'lsOc5bus`IyIEƺHJ{]^Z2,;Ԩ exNF2/oCtH& hHU8Y!Gu!E Ma*N[艱ǫ䯪(Cc0\8~S'Ò**|^='9 @TC8J].',z'4iE|<ԍkoV]%bp/-4 +{qqD+f)Z5~{ه^:L~;8 %M<rd&&!kJR:x%~"L"@JR VGbEe&'O/ç^2c; 7a,Hb 1b/,0;0b 49NH"X 9N4~6vdvzlZ5}rgW_P.  ]¡sB@/@bJ@PiH wF #HU#<^ ka&V,\'pd~3I GX:bظ~%w%rs;T#BP+I&h##MBڏF~41R%PEΓA$Dzn97ariʮ>fJ08YjfG׀N=6̤V-)ӏ|'-b"%Iq0n$O.}V? r&L#DٶԨNН:<܊4|D/ '1RXrsX mg᰺[X7b;RTx(;7G xs,0kD8 ]v+:߅H)@ V̭8lhGtSIܛТILEjt]! m 4TwIIJ`3'{"}{~2#L  ..&m:l\2vؼaYUFţ MsM'VA mñ.Jc7`Rādz.2SH'bXB(d.$'5Rʠ-љı{"d6G"& BPOgT5IT, 2n7,V|f2IM>9ҰvaG} zjwT~'ˁa0Zݐ<ɍ[<"7#H {4[4 |7[ނg&'Q؞r4مKFlxE)AdR`3jԁsdwHX;X93 <1{V]L)`3+Ґ$P* W)B[r.1"Lg>M0̔0 FwN,+GYi6+}8/z:e o5KNM>`O108>\i1ZK$)A2B9zIB) mԙ?$QBny?c@@ai&b gqR3B)Xg๑1ظL#@DC JC+djXF<()6heHӨP 94P"] 1#u_1<hhi w&Ԥ ?YZ _ :p50tVS_luQBޭ)P_0;1ڢ35:;oIH)TܚvM( @HtuvP!KWKҼiX9~u{Gyk~=2e@Yi>KVL+68eABqwٟe6CMx΄IX."Hb+ѣd4ӎNN G*V!OU@(ic9a9q~n6~?b%CAQd7!lS7cRf^:&;?4>&xWx^) _Β4iG&-sIi2lFD ύd,H4i H)juકL)Lzk[7ShZ>,t}}$roB[B톡À!eIY{7և'}9eEӍ A 䦣07i)Z鴣`Vt9ruB3bR9gM b8V9ɤ -_ hm#Gj oH52;s(,&a0&uF?B.qvعEF&Sfnm ۄ5h M +zUDR~3n߼!ů_݃'U7Dڳ';Uh3 \"9E2o46d ]vPpg&nފ[ź{a2:2sBLQ =GɉѱߟaԆ9V|RdEc3;1a`,"Y8 #3Yc{eJ_I֍3:;[a2[t( X'ɣ蘾IOI#~m*-S"abe,/ǺUrse\̴B MZ5͢iW^pE3-ņf8BD'Gx#[֮© ܁5"V(~_ޗ&EqYt.l&aWVc$^Gυ2Mڈٍn*ى%zR%1TPiAk(X"_:G rrkqlnRl#~ Z rʄ؝*ux19D rlA5hj7pn{\%’4v-Mݙʐ]'R-g݌ ;-n:,q/]@~ Na1A$cwiHU@(m2of/"v{09rķ,YtVt3UGG`RYпEccz+:;}tS̙ٚvz@.z/_ej1ZԦ1mǛͺ[~ ZrIIH<3'jHd'_I"yItmuf"E $F %s8\8zFtr k 6+EqQ*vlmhh+ )h樄 @hYe _.sTT/64Zj ݤz 1݉@>)!f/ )6n(y94bر(`kU`1u(7?VrW.UUHQB!B)AVdS c0c0~ (s^\!KDф?_/rZDl+f _`]:?ݏqWhhhs/CwOersr"GĦ `zsfQ4QYj52VG'#p;B W0ACPBPCQP"lG\bK>PBy';b"J0uEQ~7 Z,] 2kS['^z\B==(B{t)D1;Bb9Κ*Q&@y|&) Pqw_y tC' ~y0_,V=niܜ5V.HG晟WXs+{}WUdJPrgl?l ѽnA_߾>gMZqDMR5ڿ|r־BvOvC YW׾pY8.'吾T :!n2cFoE^뱘BXiݐוo ٛC}OC4gS r4sb`J*D]۝֙fD) .\4}f1Gdz>܄:(ԃpyef /d7Od=͛bG; juRK6c`7 i|?3=ltLĀfͅ6ߌ*b~lS0Ť2!QC&/`/Xr[)H q68jՒ%*w[/KKAg&`),g8t6hӧmŽ{n8x::| ! yɟP AUZUTY)ԹH+K\]pX'`7xoB!nU'a/3 ȸsk|Ml-4^gC~ԝ^-UVvKRb$k#woZc=F{Gݑn3"L&×ձ_Do7fdq1,=.w܄];ȡF;!w}1 S?qOJz߶ۗU+f۸܉eCǂuR0:)rW'Abàt75 B?6N Z[ἐ He5c璈Q<{!fJrsD&!S֫~{ed$ 'Y7Ô&BdUB=GǑT G^(͂Τ+R *+˰kӉ'j[qT 苣!Ob ?UAAIjR%Yٕ /V !'Bs&!kf,p'rrsh08hiB赝s 7HKKYZ;^H.@ve|펂b9Xoq3e61&d?x6i=Y{mx(r ӌ*avwŷ\ pSZ̽ ԑӍI?7yvM&YBo^t`ݺҪݏ>{}E$aBAzĄaO {>85HdNo)mrhLWܗL*qؿy,8AB̡-#\|ӉXG~?y#1!G:yYo?fss޹ N00 yPYXQl6Gİ/"+;b_QGО_p&E`Pb3L[0qEÙuc1V׿vy5/ba2[a׳*Xm[LJ{ְks^ x#WZ +JUнu%L g(yK ZLV94= ++R>#bjRN| UF\v;?ww1R~oN,xՓj~Q;`uA/ ]ܶлӣZO5=;leP#;8".{BgQYD<Pǔ~wԏ{U^_3<_B5˺{"Y^Nڹ{n+ʮ'cyN~X7=MQTVn΅\iMj\d?yil +~W8Ʀ{7uD2?{A= 2D#fw܄dxYNP^cE"ca_}.\5Pm|z#2P8'O] v볡^-=ECb6vk(/Xَ꣡f[W-[E)Go^x/R h1[!eR?ǩ#C`_$Š$ܶ>+zmyD)'(/(F4x||wG=@p/@ÇD<ϊDB"&(/~%''E=KlZ7w/d<yuƯk7<zB-+Q^ٯq>~;0$I!5Y V䤙0;|O4E;%#)ҵщS,gwRW2wxE߹x//dΰ׃a]jըI1267ƻ 29YAzYJ3%IC<.^q*1GO R P^ͫ35aeN7ܭD*!| T]"!5/ӼmxnLx! fY7k zUe߶{:i'Cya6L)+ Y^rLݴkg tz8#]:=+~e5a~ O'.yewdĈA|s^#LtbܐJD{edE'fy6+8bD6 !uz?]#EEa5^~M7/Ɠ0x!㉛_K=ASÇ7a CJuWi8?,$e0",wE{rqJ-C˴s"o0qjbm[1w[N|QgNpf칎eR{ \Sq}lHII&{lJiZEc|b3;"M-.n'`o *~y Z^'B3'~zAa_G(BuXRCkP@IJvxrϿz\lXl1ca:_; 5PSr媰tz+>ss~`<_8x!3)Pܽsr=:c6*ŌM_I.p dGc/ ff"0`wM{Whp{_o̓px!IG 1FX\:6шJNSZ1l&`E |]'HH͟izq /d< a:7rMV}'J_rlV)VAz| 4gE=b]ޫx=< O訾: ۷ŪR˒ʢ2x1RYhӨ7T2c&\*k ;$Ok ;)Ǝf1zBгؚG"Yma&9qv^$tBRa! K՞gᅌ'w;Ys2_ 'lv,f3o1OhűPΟ5z"׌1S{xx''.wwcdЅLȵsar4pw-EcRbQp.h ϵv&\5RYx!ǎ4 ~C>)Du.|L^h=28ә]"<u8{N[˧y ^x'9"˸zp)Tس`1s \, &nEh@IQfuk[Kss+#vxHA2yP74Õ0ҷ\ ZD*B&Mk:L;Xgusyfggx3/)F QٍJVf2dAH'fzH$#=Fc ط2ye]8v!T;l1Օ-VT cչasPT)Usv |4ƳB3ݵs>d̗@(r=wWDjPTuEE譻 ,s,*TF8lZǜh:q5\U5>:@y=b2kȐ~;7*Mcv2/-tz'*(X4@$T0BӇTLa+vBf5q5OEVo{RgWyx+<</d<5CCӧîʮ^f2$jX\=oT&KETưbEdt#FǐqhҴ r_S!F8~ҊCu<g>ᅌsuF`[t\wJ{!K:D84mKCmMB|ͺue!\鈌^͢QB~hx' ް2Aj~<^x9"uZa6B(ö[oE0LcJT.^rtTF2R1*+ C.P߀ Qح[Lu7I=䦇a~>xx^x9;{ǜ^ݷ#gD oYBƳ(x:#(.u1;g:PtQw*z1"*HȾrukšy%EW$Kbs],j^ycPbE 2 Z<(tp.a#= F(+\921@¥SBMMNk(^y]LAc-{cubwތꞐf_[n*b+KSkHO:5&G/$ }mWby >>rMp8_qLtIq.֮Y܈Ϸ|Yg ߋ};sVQ*|cFW*֪~'k (÷;dcsG<,Bx!.X#M׏O5xpӆ=MVx"Ta"PU"Ng?K<]kOzq; b1^x;}eB ^{S.J]4D?Ȉ9nt[9L:t9D'?o8Լ1>s]S.?5,#Gꫲ2qRDnbO,R85cp0H֨c0S\w Nˋs>`E\<:O>5#zy ^Ê=4\.'3%1?zʋύ/d<={ 2g8}eAe*U)ICCz7{ d&<7gETꛚz19i8@G^-va y#Gz⸭is  OTO>79i6y z!D2+!~$m,~qhcE~~0& /d<7ԙ)bXWM"z I~陾}y]]c1?. V Z!9vxk[oήYKX ]B"֟8y~z#aWӷ,*,u?aG|D/'@:T;^!0Pjh> $tODZUe?cb5r|!v;WQ{~bܴxBe-G"TOڲGli@qQZ ==5Ve?BᅌgQ]8p/j{Hj(BC/yxfIENDB`qml-box2d/examples/demolition/0000755000000000000000000000000012310072714013527 5ustar qml-box2d/examples/demolition/WoodenBox.qml0000664000000000000000000000073212310072714016152 0ustar import QtQuick 2.0 import Box2D 1.1 Body { id: body width: 100; height: 100; sleepingAllowed: true bodyType: Body.Dynamic fixtures: Box { anchors.fill: parent density: 1; friction: 0.4; restitution: 0.5; } Image { anchors.fill: parent source: "images/woodenbox.png" anchors.margins: -1 } MouseArea { anchors.fill: parent onClicked: body.applyTorque(400) } } qml-box2d/examples/demolition/Wall.qml0000664000000000000000000000061412310072714015144 0ustar import QtQuick 2.0 import Box2D 1.1 Body { property alias image: image.source bodyType: Body.Static fixtures: Box { anchors.fill: parent friction: 1.0 } Rectangle { anchors.fill: parent color: "brown" } Image { id: image anchors.fill: parent source: "images/brickwall.png" fillMode: Image.Tile } } qml-box2d/examples/demolition/demolition.qml0000664000000000000000000001206112310072714016407 0ustar import QtQuick 2.0 import Box2D 1.1 Image { id: screen; width: 640; height: 360 source: "images/background.png" Image { id: skyline anchors { bottom: parent.bottom left: parent.left right: parent.right } source: "images/skyline.png" } // A wheel that will be created dynamically Component { id: wheelComponent Body { id: wheelBody sleepingAllowed: true bodyType: Body.Dynamic width:80 height:80 fixtures: Circle { id: circle radius: 40 density: 6 friction: 1.0 restitution: 0.6 } Image { id: circleRect anchors.centerIn: parent smooth: true source: "images/wheel.png" MouseArea { anchors.fill: parent onReleased: timer.running = false onPressed: { if(wheelBody.x < (world.width / 2)) { timer.clockwise = true } else { timer.clockwise = false } timer.running = true } Timer { id: timer property bool clockwise interval: 100 repeat: true onTriggered: { if(clockwise) { wheelBody.applyTorque(-3000) } else { wheelBody.applyTorque(3000) } } } } } } } Text { anchors { top: parent.top; topMargin: 20 left: parent.left; leftMargin: 25 } text: "Press and hold to create a wheel.\nPress and hold on top of the wheel to apply torque." color: "white" font.pixelSize: 12 } Flickable { anchors.fill: parent // Try to double the contentWidth.. contentWidth: world.width // * 2 contentHeight: world.height World { id: world width: screen.width height: screen.height MouseArea { anchors.fill: parent onPressAndHold: { var wheel = wheelComponent.createObject(world) wheel.x = mouse.x wheel.y = mouse.y } } Building { id: victim anchors { bottom: ground.top } x: 100 floors: 6 stairways: 3 } Building { anchors { bottom: ground.top } x: 400 floors: 6 stairways: 3 } Wall { id: ceiling height: 20 anchors { top: parent.top left: parent.left right: parent.right } } Wall { id: leftWall width: 20 anchors { top: parent.top bottom: parent.bottom left: parent.left } } Wall { id: rightWall width: 20 anchors { top: parent.top bottom: parent.bottom right: parent.right } } Wall { id: ground height: 20 anchors { left: parent.left right: parent.right bottom: parent.bottom } } Wall { id: exitWall width: 85 height: 20 anchors { top: ceiling.bottom right: rightWall.left } } } } Image { anchors { top: parent.top; topMargin: 10 right: parent.right; rightMargin: 20 } fillMode: Image.PreserveAspectFit source: "images/plate.png" smooth: true MouseArea { anchors.fill: parent scale: 1.4 Behavior on scale { PropertyAnimation { duration: 100 } } onClicked: Qt.quit() onPressed: parent.scale = 0.9 onReleased: parent.scale = 1.0 } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 0.75 visible: false } } qml-box2d/examples/demolition/Building.qml0000644000000000000000000000073312241175670016012 0ustar import QtQuick 2.0 Repeater { id: building property int floors: 3 property int stairways: 3 property int blockWidth: 20 property int blockHeight: 20 width: stairways * blockWidth height: floors * blockHeight model: floors * stairways delegate: WoodenBox { x: building.x + index % stairways * width y: building.y + Math.floor(index / stairways) * height; width: blockWidth height: blockHeight } } qml-box2d/examples/demolition/images/0000755000000000000000000000000012241175670015004 5ustar qml-box2d/examples/demolition/images/background.png0000644000000000000000000021533112241175670017636 0ustar PNG  IHDRhHPtEXtSoftwareAdobe ImageReadyqe<fiTXtXML:com.adobe.xmp ,v IDATxɎ%[.dfJ :!GUFlw|^(Y8Bi,~-J=;<<~Y<(r 5QE׻+&D³,7X/G ^5Gs &:i޳LC50.kTl{/_ }3 &3b$_{Kt}7VXp^TB8 4 T]#b>Ǹ"932ƁZ1@#1[fBKAIŚ#ݡyS){Wk)"T,E+rݥ]qQT0!rĽQQQ Re7ԈzQ(|-fG\W=D0=ZlFS 'Li8ԋaf٧,5gLY6tGfncTTXRӿ32^װ>XK-A)IQ7 K}d'5Z~)ja`QEBiv.;IƔRQ2xnl"4QVkA-N4j '?z" eN{jDXxZ3[=,NY صNGq[sFB8m-X X k6ͅ_no3 2='VجwеR*б>dO /.k"̷qt^ss''{wUKzKj_z_}_~EQ˯y"^V=f[r Ks kAʼKTwf2 G;xi v7~nr,PV[4Gs@,BA 2 (A\YE,LBM(bLJG2PNfiv玾Yn|)D,hY3L -ET8r'o,aU,3*j]1) .qp`+5m4ц sXsfgfkQ*ljpƉm7MM%.P4]{lIA)JсC5 2ٰ6Lme7`G&0,~Y񓾢 tI8 ,Hɶ-ER?|UƩ)üϱ WLEl0U qjRl|l Ƕ|mnɲ=x@c0 0z.88)D;Se!j&~ט/ ^V3D&śU?L fLi w2ŀfp-7rմ.Z6;N858]`Ҋdװ!O"rq'hxu دnZQkyP_ ;{qmƩ˭[nS#@_As/u+ _> P)#w_L~G|˿o@ &Y}pz_}}?n2ΗuKt7X{Os,/ʝUo_x*4VaÍ<kHb1;yRCXDϓxbܤ% xM1䉿M`MnW/)k|I^őa}xR۪w94!Z*A΀O' ƙĩdY:5֒_IZjbI?qWa]TZ EN0d)LJkljq20-[pJs7IB.{94RgRFMJpS&H\}wi+}QSƢ ta?zA;"}P@L@tliU%-CtI1Sލv,*`+Ve1^Zjރi([Ex~I-k+! fxxU.骛$UQlXB+9ERFAO) YndW`ӾFZВL%ؚ@ I핛—Ρ=}U?];,HjӲVP;7XĄpO{J6/S%u=/]V&hݰ(*Ά^^k :oY=O̹8ˏcQMRrl\RuYU}!عG[e,_gVl[gTڎ]'Wjbԃԟ{ڶP0y"K񐅯sOŎzҺp ?WTCJNaBOPi8MkF=2ٶe |;hYѳ-Y3TE82eY8?B!L^|0&L^ؘȸq\ +B6ωrBbɔ[F{ [Bܫ*T\T![.VQj;|dk̠1>а͖q(O=Ӧ=rC{z$/$ЕYӛg:.(RgFOsvNfѱZ,z%ܩ"@Y+KWꗔl^/S3?;^m6rX\}"q/?SwStcSgX~mKz-;z:rS"=p?>N O7L^KpcnD8CeА?>i65 #FWmbU(%㤝&)bjV},lJw/QE)3cDީ>%QXeA{˔S<ըBh<۪*.FfE678?yI]фкuG@KB8(SU%1H+X;e(cPA{FAo|Yi]'/_mb`K|tU@dD~=qm\E(tlFl̺gҞZ'"mfoKA2yoF0'?J;g>xipo{C;*qm} [aV?Ns ʐL] A|DWNX~=ob_Ǿuww[m˸ųVzp xaR S/;H Z]0 7??վ_ Knz!Q#&|Ak_:OB{kN26 ~2 +xD}6z2r sҕ~bfN| :+0l.ێ͟LR-Zb1c2 +DL]:|A r09da E]fUQqFn2|zU#F~!٭">,~yO}/7Y#,8agAvwg &%sAT W/LMr56Rq@}# <[b EvDZP͞ j+meRKOYPQ c%0j)hD`Mqfkg`WP <99X ST\60h`}1#+Ĭx*v &3y1b8I-4@J)G"Ϥ/*"4T9Oj 坘aͬy'JOSDs:S ɤ UA}V>xӰdd[cbikYH*:t '~]Y:t3ܠB-B0 '/JK>iE s/ߢC %5/JK5R_8,Oi(Fd"9kC%q8'c˨zEoz|B E*-.3sm>A\;=wA@/~%ZReP h$N*MLRFE; hF͠}au9i?WWN>dź$aNw)Mg츓c9iSU`h0y5n/}@q >yr#>8?o?sM{IF6P@j޼<_. 4@x-Jh8o&p.U&YVЏN:\<:ƣR8CiljaI,b T4$fM]U t[㿰 dآя%O AQrgMs|@&a]t &⦙Y+i=%(&K^\h}P]taJL\Tt'^lg#TF!@绷bOR{_av>]|1 S0'O}:h!+xlQ܂;s7UiGTN*ud|s D" @OWH?}tIC4)q^?%܉Cv*r7ps4^GCPNx-S(\ʵ#!L@# Iũu>>KJPMȗ3fW.PdZɭ'X{=FMSR>~OV)F=P$ O91vn( y 6hICĩ&q.b$VN[a[Fv2m?:{z9Հ-&%;JY*""_ m¦W͚nAgu6Q6eoNu֐6TR7D6=+^QuyLLXcb RP}bnҒg`Qfԃ-ii'ivcWI).7Hq%i f|ijtC3`=IhzP&MlCUNfJh*Vݴ^5*-qMfL8c;|Nss`XPxƀ=L2/aTiFAaFOŻR|!쐃黩zJ۱V(v 1n0~HhTv@ׁ̋LO4A\L̢Ba5 kّL}g ԎM)!,yZr(`Nt0^ōd售< (n(^EHuJNKFz3v"8XvR*2[==#Wl~.f4#֠>"7PKt,vIۦ,&>:]C=Bf_,zi)~$2ul7(4-دXD@k"EVdS"&1ɒu:$ s$I@,=wJZ8l,f"d, 2UOb?w=H^lk0AQZ78 U;ɊO1e)א(P Y LǤHBd38,8KEBOH:9 %dkA'>e:e\. W7 iRtUJйa(B -x $o[Zg&YUIIdh,pUp=ֆr'Tۘ.Q;Ń3s-j2yԲ\s1\Dݧ)neQu{` T /5$A?E ڇErMNP;b +4`w>#1Fg=D^"Q~/J'LN=l$:EՃe,MOlvK.S`2@(ࡧ3uwg=)94:Mx!B-􋈴 ɚ# ZocD;#cl%\?\@~6 NuZ$XuA*MS0cU]`+X\]\HȏYJI´@ڼ#<cI4fPQhNz$,9EZfvՁ6Uic#u<>",ΥC:Z`YQ'}jXҍxDC*e8K& }B4m=3 ]`:X~P:8 30d"QCڿ:,ƮccZMc _D%цKA%TɠBm|+ꐤ: DgF(8t(v-ؾ@N x՟#XV*Ѥ#,৥>0 љZ?B\mCj_!$~!Iʘ<%ojL >nw:Cej$J7:  sLdR[B{IvK7HF7mk&!ҨAC\E9?tأ5j׎& Y'$d9 d ݔRTЌDYKCC nJ d.ld7Vu&yDb4cviOP9M?q4ơ9v^ryM3hy?+q\,N ,ȐX;k!Lٸf`d^ZiUu5BniI#-׍ 2Ku\Ѩr=Ùդ;{RS`;pB;[HlFh A:0kcB8skB"))y.8%$sKᕬuJYByYhUia[wSu5eQ$d&T#UJMe?&{<1R2H.;K6Q4?a(\Fv9 cqLRB {+eŲ> nkYP\$ıkx5HJj1X"`^"* )R!KGg~#J5Q61XTҤjrddU ES[}NZIqRK&m/v7LMjIj+H{|ȰQvYQeg$o)$++ &ۼKӆEZIʱKӾEalRDf j#2{57+8ƑF{:.JӍq_é\)M TY,MrtGU,Q ? Q2jn)PԞ. \R(#Ҿ-ʽ֍M S ܁LuFOmbFE63J>ъM%, "xӟNFɉpR.|đ«BTF.a}+WusRYHm<@u=ó jTljqjmaYJPZ} (p4~R 4jzikvz[Εp\WEpjڐ%]G ` sZۤ4߈}Mu 9r tSC,3T+~yf+ soR];02Mկ>V)LMD`9VKњC2K ]_vƂ1ͥ"7u]Z{J+>׏HF)V4@%`ht)j*\Ԡ(TMq| Lx=Ƭo}Ө3tUI}l`Jj lvӈ0 9?j')R<ס'!骶t0}@p#3pFkp>z§j !]#B tA Eǭqt $pf-E5Mgwli[M$DL#C%٦yh+r[HTq$)\rc4:%vw*^"D_"ya酩uUR| -ސٷ"M']O+i9*|4Ryq"*|v("2{H@!ˬe%(9)`k ?}zwEG6#A.;{DV/%OwA=O'_ 7"?T=*[>TZUڞk.ܸW04,ot,gwʮ=H,:H47ޅ챫@ʼn΃2\{mqaQ$6]:^QXfp}zCwL"xqx4Å8eI@'LŶ8?8A۪KRjw+r6)sS ֧:nIg{rȖ;EZE?i.HPPE’JiªOYz_} z_-z_}`LوO+rn%<1Ywȫz@;L}{/!fx5V%umaYq-Ҭejv: U`eʲkLD* |gL; :MPH&UStEkIYpC aA>,,fvK#t9L*XPw!i_熯Jo҆6 ,f47dh~W ]S74`F6nnՍx YR& xKTɚKD~Ӵs]Z8w)h1c'Ed>wc6ڴ(Ojz2r; YaiUfvs%f6n0i@R{x=ԆJuff6'&奔m.QLTbẉ#'=K:ӓ@c=3e*d5Lijg.TBlp8=LYo[Ss/A>XػMA. xjڢƉ,xLH7l|"[ӻ- ;S9/_W;ao=jAg7#onO$*4y=+wg^_{,B`uM/G n֟ 0|"w83g-I/B"~щ9ܹϾO֚ĉ)l1vA璑Ps+MeIN9 ǸMt %_"mFSG Gd˘c!Ga&Vv @kIBW. pHZa*s X)F5in:Ԙvz4\)m:FpN2ljIz~8 XE_&ޓfyp Ԥw9'{yE퐍jN\dE' @4%S`=ۢFQ~7jfsRsGo*|S>'g^?ǧC~@S!?Dzq#Th 1 5.wɋdRЀ}N5{j E 4R\/nOE~E'R}n%Į_Z%Y] >qjÉJTEfzDx3*d=k߯N^Mw#nD7Pd~F0 %o 1ȟ@0ZU4k_lxͥЪAqPuC? at!/4-R9 Gq KLZ`9/ |֒kk O22($7}N;&&uQ ?ŧucFr?FO/K*bVs^5A'u:E/S`,8 b2}rAo!9>?ܾ:r+o}Qx/G7wk-'04AWKT=$ uۻcx?Qw҉UmƁѼ;jS޵br׼@GF&znDžJmNuNh@n nl541] z^'~I>^2(Th` d4FJ3D^9# !rif3`YfjH%`2ʕopBâ[Y1N,/} ԡ6]yڽUT!3!!pHbvwSf 0WA.IK5b(zB䗁p .U6sRmm6R:Ř !RΒkE|f*2BpijO5@q:.bGq:͢w'_RNyqΫׄ06zI9bB@SCkI͜G6pNaBPas1 dba'3P\=D4_|I$&Dp]@ɖ+Oi|숕4iK;u9@9/F(MH_ȦV5` EO0G< H1e{aaOaoFFkHBC^h"g K/C z''609 4фw*/3gӧKdĄ흒&nU87lF=ӤLLglz,PAp2MSɇ;cSPiCi +٫_.z__}o'jFw\˵y߲/<~ˍn}/.~=a َ, ȗy7H$=\D*98D%ɘӤa`iW"m.~*͹)UԠM'UZJ1 R'RaEc.FW#s,M`|[ꂖELKdb)l4_CzU^:>Sk{և%MF{Ï7ge[6(BPݿIoЮ'6d{pY2%K`XWܼ~deT VJa*No;T%l5vjHNo%JƲ7zF/ܴEDŽr$WNz#rk6S]%gG:}ÁqGc㰰+`BxzmN:53XTMQ+?vEV2>qԇbX X3c독!qu<]v(6?/zXti?rj~Ar-dcA8;pj[żהe1oђSEA_é2uYz`ꛓVW`*]LvbմHF'.,NܸM%{R8g47TsQم -7Mю-ZiC>%'.퐰JzdOr}ᅶM</Цٯ~ܗ*Uow+{ot_JhU7+W­<^۸_ӬGߊ5޶qVޒ}dl+U޻)qs29+O&粡I'ڈp [z2 aݩG>#w]nvML~mFҹϖKQo)ױ|>x Vtڬz2@ڵI gMcMExёh!ũZrb:}dBh*H{Ɓ#rQyh|܇yH`KFaRaӪ?wBK,65),;mhl&@#df+n|Bmf}nN#IpӬ~~ /$ʉra;1Z%`'|1sG Cv|evwO}I>OA?@EL*Dظ>#>y),Gܤ3=)á.4HJ@woI|HZKb׾@"'d@ ' Mzds~Ed6IӁGgRqvtМ @4,+2n~Zk,e`3!oy^895^2;ܓiTM(?v `E.JO)P{ܜ,~/ſ=}62aia3OL 0J%xMd5P|: TymRK)В-` uRܦHB VTǤ6'Nڧb>HtVy`>;8mICJյk 釃"+Q\Ҕi4E:NRͦ=7ub0 \d48DKSZú:Ed%\|DŢ}*No.D]SLˡk/ %2ɊjJhBOG\_RO ._K8eXS'lΣ ޝV*A 508*ƀ UC,EPE2>xYeH?=^G8T=!r~8L8o\Dq==im=p %'-apTח"aiY?ՐkqleЂZ^Fi^zz:̈:z-ҐU'IʖW5f~‹@:4m@`}-ZXOBE.OdӎQȩBZ JbN%}'V<@'mZ=NQ8M_{SQZ(-ZD@˗-`׺2ɜ|.^"@*D XoVe)%gUA}wk1-bp8yO `еV`xAeQ?*E\vJI %cPF  @KQd:I2ny2ep,ƶhwYWȔ>ɤS__Hv\E[?-PWi; eUYHO ϫndlkY.< 7L5;˔ &,ϩҟ7# kX{Sޤ=S|,X&OL-kf6ƲEOQ쪶fM]cY]EvUmY!WXdrY?][hE3މ ni!҆-IB4p~2jN3VÖ4O)e'7YvcA6vLHx` ; J? 둩?R@MFdhfk_ƺ,_5e-Ɩl H(I!V=k[R2[kߣįD "꿱 zڼ"}-Jjk}!.Ӧ5fa_{G [^{h?gWI/= d!rBk-Rmr d`n-zFz7>jP/g޿[_]ԌfZ308dm{h̎L,i;1¿3]T5=,25tU̜` .MihXE46}}^7)rJq@2Ma>wt y[4֔a (Õ"^ErB[RGzھM3}~׍6{ ?c)hKE2GM2Lbz% 7 k ꇌWy_}/7z_}~_}X%OupoA-p?|D|yMk)J1ELP1s/@+ WIKl,UaO/qÛ@,^%:t$mX4\A=g̵FUtGFv,--:"2sh0Z31㼩QIG,7p,J)ѣ3zd=tXZ`7Rqj|MQ!YHH;ys^QdM4Ñ;mһ[OYY-#h^BÕ RF 4ujRxh)3dط Z`\R/1V^kҳdIM}\do;dgi G-"5 +HoLdLk"&s7X˃[6Z^Z15}-JFQ6rRJ'^=|SӫSB.FTo R{w(43H""yaw[f>"'ν\L -!^'[d*7:>4xwM4p>w{/M4$4n7OGޠc#_t5&mXqؾ*Px6xs y>d MPCsd =5N/v߆ 7w*t ?YP8 {wGdᬫ\`B.Sk1N9m[-ŀƉIGgˉ4SGوBpě*WcIS[[BY)NZ.۝(q{Is 9]dK}1 d;1uoUC0HݬVA50 ˤ*akݫb gd࿒aznTѬs)Eytˋ62T̠nyCgY'$HU.C߬?_h6z"6SQ=h,^ )(6-"#'X#0~}̰DN3i':p !@5~l ׂ?T )\W=}Σ( hA~M~Tۼ` 1lS394:9(B'B:D`2Z*@Cv.!&>^0a:kη1G~ˡ߃SөnzюrV3z4(jm p`HXajyN҄uRnZ]B  La,z2 W04SPvv) ٰ}f'H['3 bU@ .[K9eoqZuƇx4>M7ǗDӏv!QlaV44jy1PiL|xTwhZRUGyG 75Op?@c2k|MZ/ey;V3gs(K6 ĺ%`8c} ) Vѻ &ٝ^{*?,6#L>h9Rٵ 0@hc X8"OAdh- %28 iLpgyh5཈ dNNs\9 0s*ʈbJVTa UGk}`[̒ΗoŽ5EJk:wB|FE4Qz PՀ; 醌E] օ|\^J:>M& X]2|ލ釠1P멩]s`Su97u~w=L-9kVr6g o}T^x,N_M|Ɵ+v~ BݬE~mD[l#F-~]|VTxWSisu/ܚD}˓h _'k]zAuo}lA9q1\}qGc-2`䋐"-~r)A/[#"M)^@b!Umt;Wc@{ 2 8>A:HY׆Xf@>y# o.1b_+VA ]m,{R$ѺwtcAFf2ފ^||8v+27d &6%/o;GKJD~o4)dQU烁vu: =KjΛ|n#Īӣ2rM2tMjޤ2 fXdJB:kA>e~*e .8 S(I2WՀQI>&峤D/MD.႑.4DՓaR]|1mzaN="'r 7.x%30._iIW%W2K-$bS,$_Wr煐wzG BŔ쉹bWF_d ]6]xY.s}_f2$ L=lYe~L}Ȑ{KU7W}4k5lNۯ,m=jAgT#ފo; d5N>TdPV%f8Y\RO:',MUQc=8*cbmj8z. ZqKNb,:;bpmpR굥¥X?L7DZC{)u@愯Ăʢ' &9 Fo"ciLʹm@|墨zx+:h|Xb>Ue I0k+:[H\Ir;)BwQK *E恄t1Vj![4mFcL,ߏpZG&f#"$)Ru&7%a.C9Ttm\Ћz\r!p8 O+ڀfL*8  F`R|5fő?Mԓax[I1Bm3*A()VE~6Ɓ+5McSFO ˕1kZsIbE$Ϟ3iA؆Jaw"wM *ŗiMtj cof23xI1{O3M#@cuCfRl-(62.`1:s%seY:B-PJj@!DnO,$hjrDH39}H]#oL (!kE"Ο)5e>'u"?i#%f\N$}pʏdlTyC5p O"OZ {5:"%\˖*f :PXQc8Gf5ʒ/l;֒> ]OF@[ $[)a e`bϺnʰboЖ-K)U%*9mvL&2ېPk?= NJ=Q%G=ylaK%vYMilTq珜h6?mv~:‹eR3VP_?mNC6PwPF߄*9U\qwo8V)_#vXlm^sˌtD:XjV;/~Iv\#P_mF2#N+k'NGY+5ͬA#?a=krY{Fl+}r;!|qзO\FYHx[( Dg ڐ*?ݺN7"zؐ{t3ZtUԽQ 6 oo 6Ib28-l"ikγKZIblS*ml0CTы3)HCi"?i^\~)2*8i X(5z`HyJ _z_J<5]'|< xK_h:2{j4cgdk7+/^@$g&H`*J 5PLB8T# =ONT--$XdonǦ[/J}:hV~wg.!yp@Xw?!A= `sjv$EG͚e\2iN W=RE-F<mL2R,ٚn905w?*+,av9&b cPйc&i/Ǜes|Jtٝ]mo`˰PHZ$K#lrb8EҨJdױ5T$YTvw>Cw1&KaՀ\j}uBĽ YciΛ(![u )D}hrJ$]j`,tM.OhRxJ./ɲeR9xt),},jm"[ )r`h]JT͠\H7{>[ Xu4Ə.bkX|nٔT[٬XX OYK =bR$Źn#J$(ł8/٭J\Hݸ4 vG՟L,(%e;zx cDQ*E71IVfG(ɮ=TsdW-m$ Wdp?  He 4%Uxq6XՈt JW# eA`n&CA45>G-h W*LXXO`s6u,R4uaLd/D9V8v,oL:i&h3aMO=:/ qM6]f*r1Qv„Q5Pb6#?Ѓěޒto ɥ˻7e1| *B& Ld.CahMX"!mq/;vâ cZfnl"Ślk7eW=fĎx{R2{09-Vsl6M15`xẌ́>KYͤff7)j LNXwWڽKތ?-ۭ㓧@GgY9M{ 7ċ<'hvOK{wxi:|?c5,z_GlBkO_by`nLSkzUSĜR7jxym!_eWo FH{L%D|֪2λ];rYpnad_o㯸TcB}'<'&6Knl<~]?$ƴ-^M/jr@1,lD=A螶{Ķ5+nR+IҎ\r4aΗlJ ĤIYQR:W$ É7+SCKXc 6@¨sdb}4D ngGd(I, R Y46oU(,fMolc邥~Oj)3ϭQG6<fv ꯱U5chTe(Rw5uNx= LelQ~Q$R 2raҞif"ml g{PG!dmζ`8Ohh;{uEo|cћ^>jھ♵EbTCYxdSEcp4h;xo|0 tAq&~FJ8LrxFG>Q;)Q~,<ȭi X`Ņ#Z ۘ ﭤLz6+Z=w7xC1)`Ds| O,9zrsl>{ܛxkmG_xj/"2"?qp->zd 6Ud_[+X}dS erpLu3kHQ\6ܥ u40&,I(%FHD#zR*OC ,؈F ²Dw X21O~qIhy-uDo.QUdO;h &5 U3;b#u>V30tDag!87pGG™%QŅoRsUͰH'CPY+HhA1(T#oګf)8g>iYMGXB4h 6IQƴ:fئGy:ءRcC$aV;ȱE9fSq}.7E6>~?T, THq2;3z}P3AH _IXcv<#}\l\yp6u`G1(j%o~/ёkkzS,B_T+pEY,iQ㸑*#: lc<閏 M0 !dX12xb [PXP cj8ILԼSqF/7!$_8r8bx!j+2w uOZJ䃸H>Wq A=29@h3"Nj2lB@Z_:J>ޖHT|X8hNV(в_U\%P+IX ]3DgF^$HM`X 5sPi~b^S>-\2NieBdfRP| oԮN;  科4? { }|xGǴaLBu8ZvQ0[J6"SV}yfy/OEAqwِ̰7u ` +i^O)RPLU+]ެf"TAw3} nOwn8Z JB:jS]-܊,]D}F0eiJr:~ՔX)ScUZ/u2u;S`CFSw,' b %T@[l i1EY /ulωM=ay.c ;u!teV`Hʽ҄/U*zLhц<,SԖa #jW$|&y6Ⱦ-E؜$~d /6,b'U<蘚 s"kMkL`qAg1) %RmΩWx*qG\vaGpmCijR't& / C]sZΜ@8/(l> Ĥ r x_奕{.|qInD\s%Q8=.>8?ª>Ϗkm?t%eYs;1h}"3.MB~RUHQ d ZJ}@O[ʪ-Xzw5&pXFrˣ SSؠF(4YbZJI>J H_mc)t!}e)w)o1n14g7Cn^+S1NX]6 cUs ?Y2`@ւc(]CX S|a"ۚFH,Qé\)}T?!ڂL}i!զVv4Zf!]1 8{:<ӈ%JB7-jDdӍP`Q/X_ ЧkNu\H2fy:/霅 Xl.䚍R~ C$'4J8*3iYВ(k_u)bbn/G1I|)6,i"u#$d#-, ^ԙ/䝐b8ܟfo…Ë " ;E$#TY NԔgg)z -Gf ֏LtҮAX92wM,%d@hc.Y-C4wUaVRV9!5TBvviӆgނ2:!BƑ]mhX1lm1kaΊ  I0õ v@b&BV$qhE4,q)ͲFϏlME\=m_F(E;r9hX$F#@֛wM5E~8'*L ƒۮ'%3Y܃'XY\P 4OP3o %i M IʵG,iy#)E2Qk6</놙'*غ?  `6L,f6~.K$]Z\R7eLA0^n"}a0U9XHPEϽXD37d|՘#9>ɫ=%mfIȖoU<t 5##06 G"6QOyaEh ^$6cN,mf#ٱ(K1 t(P#[/8)!]ꙵj;Gٷ6_mx_Me\1¤,S-v;N fISveble\ۦ4H@ijd瘏瞖R;wb,El*a;AVAWf{p]" qa6ݹA "NzBiwn} KO(yԢr]['URӹhv(HspA[KɰQhc1V uK5C6-`Iu?Is:VMv6U,zLSFZk+.V2m+2 gtmF6ެHgNl^a3}OIM]kW:aG+BEJ_1[mva:j v]d8&gxэnmLkx㖋ۿщYf.(.q0+h{ﺷ9EOH%2- ns .\g@|~>?{o#oWZґ// {SG).9x6YY=oKv~lۀE.vS;`aaP Thiwq*۔XK$¶:q"ۄ.NJN" Ud9CIɀ.$KɑU=-,PZ2rh7afwKyZz "a,$mJ\"YYjj"Ԝ4B5owyRphֿx~gA ]`Yhk׍(Ze]~d [YW^`bnz6qKGSqL~Ug #FMĦA=9V\D< \K¸D,fBDNGm ʲ&e)XԳ8W cW#̓J2Wh+~ X2KήoٔH*gOCq d`p)be6h[ FɆ3M#<Θ]b=f* ݘ5%\Y ZHeONyxj)MeǦV$uU\]5Ѥ&J$+~/p)QNVb/[l}.qdhn$ 9}V1W\UO:aa;_/ }#{|H?䨿12i8?SY"z3Y*%4w8ߠe|USwqO҈& kpqۧ΋0%-) ҞbՊ bLJC7+l]G?!suӅN2|P>Cr&7" /]~ێs.1$LSu23jؓ{٫f'5nt3Sa{v uvQö qwZA6Ig? ٛ`=;Vovwvҧ98](Yt3` =R}yr์صNL8B. )%<3z\맵_O8 Ҧ=YẑQ\ ^'hMk ݉yW{\1-ohf$4-e3"7$LEU0A ZpSG >s#`bGD0M"f `砿LSFL;88Ls,X-6ԼhCϕ)Ah@;i h'oav{zd r*_IF'~D|zp:xzتgښcm j_ɤ]U ȯ"02Vڡ. ǘ%=mzQݐ@d,cʾR=[,C-ftƁg'-QsG)EdѼh8[,ɓɰm3w1YSL^3S\FZp?$/L<3xX!a߈z즨d!d`>Mt2؎Q<$m?s3ZQZT+e{,E7^G~Pc]0cCh9ځnrb': .T>$sРFgaWiۙnDcU~vmn(gOphf9ưT eydnU0+ %Û{+pڗKTk g#1I rKdbRk" fp/a]bQfuni?1ָO\s*q֤D긍i '%3%ul'khs~%.hveC#e?_Yj;˖G&ėdƆx9Q 3 0Hcҩ\%L3i +[ )'0h1‰bRz#_K9ND5Pֵ\yPD Q&SD{M5'LS*\dItucR_ b9tZ`|Krr#g<~cgtDd6a%=ɟ!46.],ƻƄN4j('ܩ>svjʔr8 ^1^Nrt .Ntj% vxd2U,Cz4tA14rH "XVup~\,7 fVz}YU5zNЄ"/PZQ&y A/z&%IiȂ>ENY ʋSb(8|*&~2$IMq)q0eHM(6$W8fEr%2jr?*'m'Iz$ 6Y+ fR0w;\1iI|8 Ϭo>ˍʺQ$+hNFmI/w8}>q^oyAnl K{q ddwId?kSCV>6P G!FYE3O}lӆВH)bd]c̑=1Ms|\?591Qetg_:m;y5P 4zdG Y8bn8$\#ވA6b9Pk9Һ%[>2d[jjMdԑdҼ4WQi:h4i_s(:D{˱!XeϞ!"WO#>72hD QIT|ʭuDFhƢ&OufDym7Z seċXRUGBB58P"L+-lKoJA%c^fXLfͨ'\B FTHYܩM<$Dc&XsJ'`\ (AYq׫nZ5D_lӌu `` {~?aeE_֥$e*ϭpـN#wŮ[/ڮ{(rj5꼢&GuHgA\^O->O>{yVjr0SV0 "|_KeKRF}seEFv6eQbYy:4t1F qF4hytwĔGH˒! D\uTlG-æ+j7|4ĵ1=Fh/ ©UCT-,B(BFP%(whũKH]Hjx!dq%˟O=Sʤ-b5>o;ֺ6JSوyχij#>ɼ0Hz_*CYE}^p)^IDir%g >ky+H}%8.<6J86/T[:PztY4U}Ǫ"1,J&` 3yZ+YXVwߟ3r\q+AXG߭ pqr?Xlu#!W*d*^Ma5hRJY4,,P8aМEH}oZIKHҏrzs-FN2iqE"ނid#D\U_oauɤh2G`Qd(k%$!agCPsI8X&sfrFf_BfLƭeL`!`,n Yuxw>^"/ӟ|>>o`}0y}4=j~_)V_s%N þzI|Cs1gCN IivvSu_+y^P01' ^ . 4.Cqgp |:)襪RW&OZ'hDkGE#am/N;V.e[E!+i=*p\CS:*fBK:>^d{GtCs 6KIÚu ߜRgX7ohhۇ۹Q̶k\y0n$\޸S&@b!䛋!olS ;su'Ԃ+N0x.u8 b "Fö|>E%9wm;/*Nߋ"l=ssqXonAsb[s{1Op4Ţ8 S<(uN)F=s_U9d/ 3s(y1]Ge]z B|n[ > ~u%>x>1Ro| _W^y{țʩf-M*;H ,{g2Éu^-Z6Nn==nl}fao[6i=FM[@I.5UfѬV]X4 >T!i MrZ.=\2fU7tʚuRHAzdҪ:z3o٩~כzw\< [xU[d~!'c{qsQ$y6G]r>IQY&c tw=j.x 2vm΀7CHֶƗVQxe'dxIL`8.R "rjcҒfL+bZӽDR 0ժ]U h9dCPc'됍ioGh MwUXlZҀBƱcP.s}W``;k1@n:K TdB`xJd"o ߿vdDk_2d a Te%_CB`W]3ZW+bH,-9bl=v fs 9 s r/\,xsa"U8[n֍pKA Fk8U+z%?|g] ]M! ô&\';Wv Ʒ=C f(n[F[CEnwR5rJ{hp{郵{Qv0o|B b6@xarUaur-3xap%[b࿱TA%ujL芃[-Cݳe +@J]0e hGb[Aā qȺH!Sg$w0xSˎvX@"%Xgy [Q]Cx%H+xdƟjj vٚF ?(x;Ez`NװƨMv[RWkoIֆ1vjEf2{*vdڷV=keZŗݹUbfeuk=20e:E]C\Q,g&e3s9) _1} kfkJ!+Y\5Nn/i-r),jN6JXN)A$ZItYhIGrj; ^ںj,jzW:C꦳C'wQoLL{'#7xZz }Z^" X%VDaa6%'3ݨT9PYCPtwļ~7-vՍʟt׼]$W}ioon5lr-$x펙Tw8?g=TqC޿y7d2PdA|~>?/|FF.+?hAY %3Vԛ*}#:YɍT-, ?=xmYoRXevpI%.OY^6nڔsב?METf;`@Bۥ Mn 8x뷝ʥq5cqq/uB_>ݜ6[S઱ 6xj3ffC?um97/S4 !-U[mJA\RSvRp $Ld]JvAx5lS_hs9ZG`0,8뀈AVl + B:TQVk*^% X7:6W`OZ"e^[-΂-Zui_ðn+jZìHdP)_E=-l*n4*-eRVZHFTv\ ۲߭ݴA̱5zb5Q3eб-ASi[[Oʬv"djacjCL`j!a76, *эfbazb*ۮK&{5_jE=4Ey&sgkn-oka[;Zuq2MydNَEqeec=T;ܳ1@5^ⰼd; Uz;CqѠvnmySaJչcsT\]UKz;^WƨIxi]qrќe]0?;y/yxx,,Cbk0&C| wpfA@u)}ugeZp#GOlDrl>dR-,rP^a~gF\q!9V+^T62nmp'7 )al}.8n鑧fr)]<!1CdNcҕk8Xĺ(L~c7SV^-lA Ї&=W`AR5 /X+j}XDᆞ8wR5iƍ \ވq&Jjn5 a1r@3&3D.hhMgړd]4/F<%%)A*R%ͶQt洉TaM剼)7`e㏈!4| 尋L@cvEz%c;d'\駟o0w@T`Hsu0΁EoL&1Bnm]C6!N9ҿxlM&ߎI~]Ci%,(ͦdZĝndpcƠqOJUX[)y2[s 8ɚ#=f;TY0ON:xl >ǻ-WC9sk"z'"x*܍g%逜wV%}<{=9owq>|P;bf Ih`18G|˅F44 D(80q9"#KΉ[20ТT-p'*-E{oh`^?+4 p %PD ˚hXᥖѸ6l*vF|p03:côG V4γ80y(?4*@WRiG`1OOq#gT,#NH_P(wa((k=Zzǟ_]J8E,wiOA/rrTp#Tp06eF]E͏pV`FFilabƟ[H/z<ȣw~tjIz/ѡӁ h 1B 8atzGl.-X9#VEui:8>F~::18EJOꚕac KOcNj`jPP%PxoOcd%B0~kojOց"?,ErU6JD+5iN"?b7)0XWPk8c5 W{jшdNo8wq5Cݦ"-d=Hdq0Zh/i Vxs qIg6ZD !jO;XE8Ih^q,[~ Tqkb86\YH`ApchVOk*2:Hy`LIv2 q'˞^[i#$Ƈm+@k@fݖvcƫQC!jT2|>Ij3ܢK0A%z ~Cu,?a ,I ^h[e>~eǬ:w#f^"}/h^Ƿ{#A8ְ^rf~)Qˆt^}~K_G>ʱ k%'ՓV/{|| 9ˇ ^/~=Ĝ'xqHRAK8x˪yqDC__PKH쯠LhU`bw`Yq_*EP:/NWex^K/lRACf@ݑ3Kv<_j_vK<~ꭡ2hNwu >،c^ ]A}#:-8a *a;x>Ͽ8)>+Z~~d?>,h @跬L<pnm -yd/z/.7]]v-p-m4\BuG`,bѺo1Ϡڇ2M4@V nR0A%8:īЉ C(5czi9k#Z?ae@s\tc@ %qi|4y%k.u I3T<릌 BzqնףkTyܹђY F dzcrl8t\\BKh79H,yy$Ω| +Tc EoK(O 6]/~-fS ȺE) G`/]f5̣eœYƮ;+ et< dmWI[r,8 i_-5IKXG$-d8m3-x+361vѹmn"M+' 0W278) ߸'n=dHL$9Q4a4Ί~dvkuiɚHAURVL9 #׽QqnPM1V]m hvTD٠մMb ,܍zBr΢yV&EdVd-Uhy$KRT=L܌AeNS\geDZIfF״LšYnjMBrS`0v+bE &NjN/M>BZFB芰}^!!]bwK65@;97bkV0 Ym,"o4ˠY䄲BƢ*}*FɓuӸ1c͘pVZ)o>3h&1y^B7B]]|x7.>oWim=XxqsĈQJ1+&BJ fE㦊 5pVs-kM+lDVӋG5華G)`c_+\赸Xdc۴J@rVkfѦWtXtvqX kdX۰~Bv=kllLFA e˧Κú,H?&`R/)]! j^Q!<[jj-K}(9 '[[ -6^Qd1q16Rw$x*z4BNN?@zU]2|L%,*f'Ֆ1Ejaڙ80@=V:;|#mVG xFRTv#۸+ª@gD]TVٔbliTZlbl;iz>*PTVzi^d 7xQdfr&;OR">KJFMMܧ456zӰKv^%Ԍ"!;M[9 Ny Sʗ|# @VLLyt25&qeondv.iLr Q/ݺ n s5};%峄9w 94fNJGzx 7c1|~>sI ??|~>?6Q2'W.oR`6x>QCf=H Wˬª֫[؟&)OyƉHS(êеVA{{[^1,ѹZqVK+-Co[V:0}گcȀ]t_U6ХP)?b@Hbd±*&"chvR04aA3H:7gjO.ZUjL'6M%7ť+AMMv)pc&dH)p.w5ۃkúFcX׏2tJSwɧ͇Hm^9HZLܽ+ӪnHZ=5bl`ܹ["5=6':/.} 2Jv.H=BΘt'ϛ<`p]m{?qEmo0\1#Vg=o?0L3\٢1.%4IqSn Qu97kN x}Vkdve\s'w8T>zo³sD=V>=!e]="g{w7qܲ}ꤦUQX1Q* ?6ϣ8DҴj "pSo앪#QwNM7(Cst(͒3>Ya3Wn4]P٪Ta)q5"3T2gjo哃%~Rx4 $"XSqJQd|w` Փ{v4v옃i{Q"R~7+Ϡ7gG_~db-q9f@!p63;5;7cY7=JM*o]554す 72O‹4c鬷+rx rߞ 359Wc3“R'lU퐼B;22OMG#o/6 + 2BCK,M;6pbBԒ5x>uR<0߃>4׈״sAieASy(xaQ?OVO~ 8CN+YAv#>h̊?ujk| j(¬{OCN&b9#?6b$ i/r[#ی+! Q+B{I _{(r DဓK, Uk=V@/,pz%rYc~?hςORP <:͡=yγJ$ zNRkk$T^゙Y)d6 -SY.}&]kSB+rܒ/̯jm#{-:`SG#&WTZA+6 UB[a&u:@Zf$w1r^ لinnI.h~"[ʠi_w7]DHaz}J  fMSonUUxO B vZ)1geRWZګ1sɄBd^/WU\0夤x&aqFA"IFF?tˬĥ LzV6bNf_a11$in#OU ?ϗHmH 玳Akҭ'Gq\`/fdT> L*"M88w =eRp 2C[mwl7:%0=һ>->vjZvJ/q'sX2D$\;h!6I ǷGƔ^bZ:;:̹7҉Mƌ2`.?dי+G*.7)lY# !Yǁ FңEZyR̆V$tآ:T5d8WJ]Dv0 fmvcvOMw7 1`Ph(cnG<ڃx"+k!.B} A;r|@ۄ 0ȫʱڔ kaѠ7U >vطV" +V;: Kꍐ ?^Pve;x>XG2?=KqewI;`H8fոhݾB#tt]4%_*P6Vt0"e/_]ۡtv]][Lv4͈ FaL|42idȰBbjࡊgjJ#9/ĉgчyKPÓtݳ:t ]G< IćA7ݭ ft/)YD'堨BdM*rk2lmxXl`{wv0}vy `FhP +ṵshv=6ean,@Uw|huк'a20zLXGL ]O;Mq1|yut[5UxWnxܛ O/s`O G#k.6P;2,cٕ/ l m5=r5sI6U2Fi;]B("lk̦Zr4O KRnTOX.{aV D'.͂JJK,e-cOɴ^mXM+#%0ɑx=yj$m;<9-Ha*v$L/8Y8K|>a'sQ(EVǏ9+ ])^ Y[W4MЎ3J_>.ikڃa<'T0ʗ,CHᇞu(ȡQ[o2)u2eXXG +28j^|Y~T=1i'Yg 4:"ڗ_D^D1-@aHPiaxGr1i9dvɓ=c/Aqzk)vtnp^4Hv8t*7R/+WpQQ^̩01~,N{ DK3iRM ]H5-kGc% ;K-E$XKQk!AE hљ-DBcx%8)'Tgn=#r6U%AB3R` )» [w]˲`I$6fBz\3^9Ug#*D_B6%Ҟ78)Zw.)PMt$'HWU@ec=I<#F9JCvU*-NG]G‰p>nbND`ɻb~$*z.uSuoQErR]PspSU+^ )ڕky;P}kXtER9hxTv(K]B :#ֆU'-`'M^]E ̢XBO8]eV+UZ ؗXewd{i#̾ki$4C̥$G aW8*E@jɚS#)@ŀ=M¢AwUDb`xrV_~iTɐMԏGnbESRUD|ynZ{)Gzc [7aӸUA0(,!c*QF#YWgqqvv1X5YrG0Pّv'۰1沠HIcc(-E0WBEZHdwѽ }Io~dWzbXT I;-˥8]z2['/F Uzd>۔3N'CfȦΔU`Vhq 3&*r.:㦍Lij~xq1CA`C䎐 y>n%CQT^ٰ3d%M:6 AqqzaSlU>Ш?$z3IrC"Sp.} "_V=;H5`jm5W±0%p/'2O ].l#}b%$:j!Q) ]i+HV|z x]|BZ}J7UCc5%Ɉ촊F!(Y1!9N71. Y|uȴuOEfjDP1Lj8֬/MZ FQS=/vU8ӄKiAގᦑ:(Y:*SC{t1Hkග0Nif8FYFjZ-NlgW~iOI$-g:x233i $`PD_Ҝ-}1FYk7 J|MQ.D?v^6,Lzi" ʒ'Y8yG3ʅrS('%Mh2'I؅y`FXKg-?JCG=4+$kr}煹b\/K;Kb-ce@#"˟26]yë1䠃>Ki]!ϻ&&ChvTTS@y-t`}׸=X'vbAH47)a"CT~ԗԙgr1ް)HHd`I1qU6O8Eq)YuH:-#Dz0cPd޾*mU"FꄶĻ I~y_xEkAFKl[e箝bV:G Řon.W$oǦ_3'܄&J#J sT,mD}[1J՜Rˌu'Nc6G~ƴuݡ<\pGoH=Y\-zf!wrq xj>XF,=x:ƶ[`mڊ4探5vzhо>[]z|&h]hfTf V.#[BԻsuOƂhd6ƂfECьQ6vCS@*q8^y$v[4"=!FTq-ú^_JPMm&E9\մJm?l=loW4i3Mctnarql7LK٨4?Ue5 Q_zlK6ʎ[MȹB¸I \- 0++w Te&3KQZ2ĖK&$哩E<\$:i.jeH 8e|R%P8P浤Rk [7L3l;NWbiv,;u$wiP68#0|SpW(m`m 9֘eQ-]|3qUbYInƞV^8c*[ ~uP9VkT ){e٫:U2ꇣKx~9tY;}b4Ԓ殾]mLeufH*Wș7X&A|aq4>KBGbF<3h*^ 'qMz C,|ʶ:iS&eѮUbY3l%ɛ &)}91Ӹ*.+PL4)+#VIV.1k;="jĆ"`pALwKbaIÚ51g/{u1tru(:f,.6-\3|~HݪYoz).H:=OIiYB`a҉Yd[B]/ I_2 c3k2<,Eed3a*啎2v=0wB`zP,0 6g6sF\"(ZQ7JxS(_{f1i3lGsfYԌYfB'C(t }8K?ͨuӇ6ϭC>oMa=+nxRNضep{ˠe̪*юqą(cA DbWv<1Or|([Hg?o9G"BwOX@IњR4q$dƾGk*FŨn0s:ڤKHĂO*y9m00P%1ɣQDDOqZjA~"r'L.I+{*|]6n\U> gh~ ` B\~d8ԅ=+p;ú譨;֮PDhBی6Fۋ(KyvAijbw:U]I>(2+4(>5,1ҳ "7CŒ? Fsofܑ;8Ҋ7g3e-CZ# vհ Ҧ,f=uzjp!jA 0A;8S.ۻu1*vH a _qh4MY3?%psZHJYs9&_qaIW8`DZ74TV.u/ay,v8"" ; OoiS5(P ]h y4!Tn@,#7VN|{ܠv58a1AAEqIs]qH{$~|'CF恧rHp5f&ދ(۔gxc`_n _*A+H*&s$D!)yC MY{5n#P&P;۬ld-*>1ډv9TĐp!qmg׶:6FQfನ*DX|" NMd/$DvS\/i5+Z^a1Ip8dQ'w)!F֥pGH%Rx{;u^6 LF{[^Q\3!6Y3*4R3Yg˔']ZF1-1knP6Ft YO%LIƐ$O؞6 Qvs.U9)iAW<eGR)q,ئH]Uj4;zZuMhhquI)uj^#dSլ À{N[nm%$s Z!Rqx%242u^O?WQ}3RQE*b^ 3k$'mII7vUnE\1B=leUk D^I$tu}Ӫ7m7lfi-+[K̮Вˠols0*dl6%+*]|'6mrS|8r-Ўػ-!ժ$ߡjdCU!=ta~N/n\OfƵ˹zS:\*n_5 #4\ZVQ5A?ã9}aPi=s{ܱ=*bDO&| -k;/eGVǟ0pV~cf#󟭝ZLȫVm!R *ċଝì5Pml nLsAޔdyB#Rw{UoƁIN i[a64EG7aQ:5 P jHfdpA],d8 xN o{N\܉@uz2G5q =_ߖ}L͹HzY50Yf!r腻}CQ|rnoPu=:*W`|ckxc(bf˜nl*C'IhmϿRFispCwo[;YVݵ}( Mw x9gsI=_%OLonF$I9 Sfc[-4:_.\'y9p"^$۵q8q_~ 0x)b:\rC ҈t;MMWC!P'l ;K3_mҏWsS]C+GMwFT6s Va'\ҹ^HA@;x'#sRs#8!ej.=~t@6aϯQ T-Gɮgqd2Hky|-(1ז؃)/~aVEOUjAf cs0+vzb̋AM5#~9&A |~|MvSIǪxWy|{1ipF,L f-$It;G0pHayjH2Vr K`#aC\ 3Q4aNJsZ#:NM0HyM ̙{wyZ:8~ecRmf*\dMBI gm|l.7v}8*5NQT"E8Ҁ%DY|lGXvnA?{0 V3A}l˙"f^Ď"%'ڴ 1&K}9X"-2@eG5J-" dn=_4(eIu cV02^d\*pNmMݒ4T}/6i,'q -[J΂8FU?i0ErsV si0o[X&agtCV&`'c4Rk@L-REސE 9ٝA6E$'ZJX! L <&Z6coeYp=׉m 7gY]w= 2Orcf/CąϡO~{0ъ[JOgz (/LqZÉ 8&b-*nmPho~hFl8+Ҫ%VY^+K2KeP. CI~#^ȹ4 /!ɑ{r-13*KBBS!;Sf5֕m\ cGbb_ `!gaНP(\_<\ydWFwT ]"88Z7nRu^1.n-wZhS2D1wblhF^{.I[v^T=,V W 'D(om؅׹Q:rο{Җ+ԸaU WĉW]VY& VN/9t m4 Pow)(ގ1uE{f$'$9O^ѼLL)vN&%#Z|2XF`?NMsfb04%84oѠF#ViF!-hÄu]ޘ9bUqh6x|Ec3ExP2aD/}9.uk }l<]\8 ['rIFuIZVdj%Ġh](XZƅb}#. @f9[\ 6 dILx]At-oX;tC.^Imiޜx,#Q;QDBú3"9rOH9mN]pplv *:㐣CL`ɳ8κ.vE B⾎N412^ aSpe"-I+a_/F$Y 7=V2TfU.W7dm$+r b[;ĤB,|9]l»_<=&xQ.EMdۈi)C!lZ^Iܦ5V^\5D aZgS@NZ5e-vaq/Z+$dN{֬vyqYg:GnOM:ɪX1ˋY;hnSe" "K̑gs.TG[b$t-[6+`΢`̈́רA~ՊuXA_\YuEcS̽ɂMnX7nfs)5*]7Ӆq7'HR5d"Poꤝ%Y+Bi H-@z޷Udֿb1HP*$HQM~^L=rm&u/ɤ9m`dեXQMo^ܕ i[\Hs9$ \n~Wl%;| /w5~1W(O.XѶJ]Wcl'xV!WyrU\kW<ơ;Qtz~‚3~D< y,vp;21vRY[t:'qghpVOBLnr1zi%_o3OzUJE(5jv. }Q9&-D>/ȟ`ayHPaאk+B̕! ؕ=otc̥~Y-oxN,E1 cW Kf0 '*F.ɸRl:ȎS_2:Ji+VX_j-~] @8PdKn}Ǖ aGGˋu7Lw邫7J-fiWƋc}{fW{n#^tJF|@zFJb+#xW˂W2zLN@-WMͲݒ둱G͈*xxz{& /lb׫l2̣8tG G~͹4ceKJE[ϾZ34Wu- q!$gryc;r+d^j?WQ9r"] &7%uźuR  ]ֻ=wY1w!|~>?k|~>?[^s#qWG X={Ix?H/+?^pi!>?>s0~P迱ryAйV{("vGi ú)mpj0zmJT ;d4j v\ŀ  h'V3@!lUϖT !* ;🿺=uhSZB^f9Nv6bIM#AD Kn }*ON%O_$3@@'EWz#˒7a`y= :k$Z XhP $pN[ (Q,s [`593m\ =W@ceGШNGe{ [*iUҰ!<9hȒȐy҉<$00|`y%{rF*ċza"b,A+rQY&ڡ W*H peFyhT_Ns<' ?S@"ADPMhe bq y MlEzG GAe^J}ס#Xiбg2p*O,sVDMG+ 8U,;0 І5Fud1!ZJ@Q_wGj>JѷI].s) s`BNF B %?J>͢Œ}0{W'KyD@k&Y'G-ߖd>Ei؊IIĐ~R*aM5 s8YNy& ߪyۭl1;>w:X_jVĒ)Qc%_ Vv0g3a6U#̋ա~έUGjT9_څ̍$$MDz*#=aUalZ<]<$(dڼ-RGH0iL8g5_(.*L$Ϫ31}.cdI2/~ ;U h0N̏ͥ-0Z?R'Մ˩qfǕzDy]~:{1|cm4-R}66^SQl.'lY"-|.Η>#TClHS/~klH"vZ _7g3؍3sk'i)E'/nY[OZ QtviKYIJ^6! g1P,b! s+-8D;,:Sj N î&YG]ir-47F,+٬؏L{v 5$kTJ닰Ɵ0 )p6'D| ɧX8is0^FyyxӮsScǴƐ c˻14l Y휐O 142i~d)ΊO`04o1DH*$/Ú.j^syb8yć(Csmt"4e9$bvw4O 6' 9dz\OG\2Ù< [{xHVϷ֞b`f8e34U ܇k?cv۱Ƶ;x-l ֹEJ1Nbs=XL4l?qB}d4k;*.tE)w-g'H [JŖ~M/|˞DcSbg< ̄-hq)8s"v)S̪QZD"9e-C}ϹؤtպJ-ס]s~!dR88҅zI[{zɫ߅_c.ѯ0]Qo.&-\ 6~V 5hʕdz4pzph*0{ `Xzt?aQaR5} PJ|*˶a3S~ ^k{J1hxŘ\M0bj{-ڝxsuc<++/m^7'ӏ8 Y_x{[R|Q5|>ywT^\u}|޿c\92׎>_T/~?^FrIO^XYJZ^h 4P da*E.jq-^UIu%ۯtJ4T99?̕fHR?K̮g-xMqC:|ї7z[.PuzӾPU֫Z^.kSR]m5?+^q>WYWxgS% p 讦<k, C>rvgڎLLeyuʿޏvg?_P=* CmR/Q gJ>E^w\I.>@UNl"PUݯyUr@WW{Azf}tmp/6Ldb dll_enop }/>5_Y7qrVz9煖Kuc-$PY*-W/D5X#9;ޮШ QW{WZˤ?#NƩc; {g~OIo^QGʒϟ8~{8u?} lO7~g'3O*+> ֲz<dǗ<OI?S$OA^d֟%Xص pJ‡>WONKd68+ۋK6bOsh oO]aaa]gcHn ,[S'O$CXxsBӭa:,!OoO=#fmaPcwM°R6han.Sbsm*bPWX8 + yOɊ9=="7uꇁ$T2E=a P" UR M {Шu`XwL0k:m\ k$O廼 &QQ]:qHQ_z(B%>fyk wEGʜohtPS#o;hþ[Ի0@@ʽmcXVT8(OU] @^ydV7;S0d.[.$7z$f' ѵ>; hUBFN/% Sୣ :2M=XwECV{~|_'FLa'@yK!L :;TM q][}X-r'{&HxȂޏ-d_(2WRaud;\TzIDu]"(t77%Cj8x(hMIBn&1VbCo-&-1/q+k$2L=" soѐ"Ǧ5pa7D8†rɿ4'oN48V dW%I!J$9eLuL8#oŊ\e-nHW'Y ft+%? , ҳhk" /*sbpQtB'ׂBڅdAoCs46fÇ(AB"L klpL@/Q+*r Fa׉I fU􂡹m5X:e\?lPx(lSpcgk`JNh!T]Ol=Qɽ 4ҹJnC?#14t^DD,JHql=ʖb[j+N15 m5k^-8k8Mk{ C^2f8IweR*Od*38&gmƸơhȬGR(z8Ef*b *)u(SVPqWņt-4N$ٍo/f6Pk :f~0ǛޛcbX~&yj^MI l:*CІ@> o(=UpAZE9Ŷ" 5QF^!֧rTĐOjѩѰ;F&oO&%$loT"hߙul,^Eb9$4Su`$'4mkn DÈ;m8,kXR>}j}`; 26ϱ7P$; 6;!=Q\#^3L6Ჾ,&3য়z%@m_X@aG }▉4!%VgaJLⒿ(p%j~ҍQ5532{DYY]_d5K*mxfs&w2j߳W Sm4\Rb&s A!])~HJ %f'`Ϯ2GSSZO;?׉FSMf;Z(;2J;<0 m`(PME:}Gux*縔O("ߠi{ \jdʓd8\ OD;P_Y<#Z 5%VE'+u䀙RYU`f:PĄ` gj9ΰV0c (L̥֦G86CEik֨rpEFXYBȩj4Jpchv[ӈn@ޭi6S.]gm7 A{ignfPT^3r_^3r=g8F|_hBDuh aninC )7RәF4*p WwX`R#GpH{ɋhuLӶ}.K26^vvɫu[q_Mف"RRm/-J$H _K Cn?MAvs3c'yo!::@ fpS²s=X׹P&BdPҀYwЦ긒遺Ϧx c5`+ .3yAߊ*5X6) @_GӌB2jls0Q7B|vtz/{[3`ju+xuyU)E- <5H졟j[Ce=7t  jխCߖAz$W^+[>`5H(¡/jᣤ=9r K&κA,<@ 2FcgXUmA~~4nO44W)ٝ׵p+=t#Wj-!-&`T.y,ij/|]*` +e+]6w,3JM0A\vJϜ"LĮj1A!bd׷ywVl2 c桳jٓ-d{w- !cNn;HW-dX0EepMJFM4DΩW٠6K]‚?G]TJWƪC1I ecTc~6vUu첢*]xbm^k/_x&3cdtkBf`iZM˭I`&NqQ' .;%,N4~OF .\9.2lv|*] ͉pK&D^坥OF plwaq8MRHk-^SM!@]Kt5 ,RkU}5,Y{QXNNF%GSZӉ†4Yt5jGXbkG/;vc0.GnK⡆5 S\oфԄ}ȅޫЇ2#ôZ@3G1k~#S|aT"k0r0)G=K U=KBJځVFB4qT||ew  C*.2tLKEe?"oaZqiLTZX.eCttըY)DZ- D(ǁڠewXVCB F1U;fvrH@`fג1~D*d@HvYb / ~ [!BJ(*7͘VXl(A@T 'h7Zm٣ &pmY7)ԸIV{X)lJLJ.B*](߽FSf/4-VLdɸ؊Ց@NH`就e!X#122 Tk ,G4Т>lv`aPTR@A|읤g]BT;7j*I P#e[(@5~]a/GWg^`kZ1Jt|[$F&Ӧf&VGFh۬#'DGmGH후>q{|-pNHt!*DL*W,'Ru#j tb3) tξSZP蛝B2>v& ^ y0qoTjQ|U"Q(/@X f̙z/6i'̕v{y09VRӲz_iJ-( bTtA#-#ۯ@M}v z7Siޒ^Grr ] c` Q)ڡh\I1jGX;`uthA#mTNyP}tLeDx Nm0 :vbj2j4I?8*\)|{/${=Y3R4 su%ݳE]L y30IC|[[Uf34@2 jDHAg;! y?eGPGlXsGމոE%媠5Udv.E8*\: 7fJu4e R|R=hxڢ( } fZ)P Rm&sPH\ٙ ⟄(0Lʠ6$a-6T8lGm]؉s>:HlF8y'7ɹjک_;4\DW[B{j7ZP?X 2@@55}Es3Z"óyP׋7vX([8R47AN D-b0 .qjDZA.(JnεpQ>(n5E>\9gmAA6!{G166iO wlB@`H+331;noqc;V2P>VSBb&ffGtd TBuYQYʞ'D: *Jjx)f)F dGO,SNGgFlUP t{hZECq'd[7Bvk*Dy܊\LPvhK"RA%VĮ_gHOl Q' XeQ7̛P3LX+.SD!I j߶N!CC,B %{x1"lt ۏYi@[apl߅Y % :42ZAk kT:}lodu7f -9MyΎw OX80\Ss. *AtYN.^\Aj5q4e K&]r;!om'r[i&:)2!6gsJe+'nzK\66Ʌ#ĮcE7^<>m̓䇾pRn'm$3~LҲC˘}jgāZZ%..Sd x|7;rH;[Z"YBՓ>02:C]gJjۤ: p-wֱy$^ :|je^VyS[ Jz^seu#YTHaםBoKV? @OEqϝ҉!n{k2S$2ҷ-(GK_æ3Z?]Cc}zMWj-'Q ?cY!YqM>3iyH XIDATx %uoMo=t1$DHDKd[xDɲ',++)%[vhL"Eq  4nܿ[ou uVOps}8BnU,>޸ [mヹ&2.^GNo\{0U(bsf|,60 c77 s>wn\vY<8P/b#;WDqLKLB,ɑa l۸%k^?_/Cܛs**):3ΠU="|PT`YYLO E|oaDieS33eG~8ijrW'=p.7?b:䱇Wxׅ;.>ɏ?ĽW{ l_-_|W~o_xʻ7*鼬T"\. ##ijAׄ̊ (AGIlGq_յ5imZHG4an&O9+^c6{SO\\Y{ `4݌p؞:{`kmå/p)~s[\*[[νW4QM`Mҭμr#G[d\Fa7`S7%h/$/|.2stƲ>/ =F=NαHzk I1ڦ%dΡv -Q"v@(4cuPZJmIR*d_s7ZTYn2.l =p\|sO2m&0:ahV@1.Lg]Ј{ +&:K#K5kAϾ> 09([dvY0wۣ>#ACaPbϤ )t,QXgL $ ?AyE"QГ!h )/1Mf:-4(i=c@BK#gxh6s^|4||oc,?5v`U^>^;K}2 ~CWKapBN]Үߐl'";I3Mcۮ 0Jo^8f:k׎e|͞c˂mx;gP[}&xObz.ZlM ۄdy% Rtp]iRUp_xR=yꃌָvT0zQ%ՃAӆc&-\%G!F!&}apIex5r'l$DC}vJQ㚓IǠ [wZϢWޛb,bCs?se6oc;y Fۖ)\-bЄlf]@wHko:IpbHyg8Bd?&~M;)ӈDHQ½&1֍TX oBֲߓZ7?0.,aQdE<ȺpʍvN v ݜkW}2c1} LK =[L98>ED $JTT?}ԟ'Esh^C2DJQO9,?*ȼfogX\B 1a23"v'#bn\ڮyN|k?Sg/{Xn!8j5N|J0l 3(J'dSO4TϠ }'CNC"4߷G&THQE:pĭAO FEOH N ,T̀Ϳ׀y5d".߄m SC\AWe'k 7򫯜}*fq腗媺*`5402\6a+!$>NWk[%T} 4`&+vNbsԍ3W?3cK)E<>,F'oDk tR=HNtzփ_Lk*़Amp)=;IOeB. E>3E&cxc6@:j~8}-apoRup\90c|'sFcymrsx:f( u.-N: ,)TvNRqOe`v0w :q9Y{ u\uӸA!>~ZH5jw4sU'8=>3G߻"m=h]N!CeH|~PW=Mc~-ڏQYk/&uơA@0h4K 6hQ .|Vp ḋnʦ[.lba Pܦi68j5i86X>BBGl>  r>mo9'܂]k2jD9]ƀnƠ9"8&(|=4Y܂ Lh4>etzJIL,ڼzp. S0M3E=R4\QJ{-}t4?v[2htx졧dËkR2*!z)VMR T.\9LYجy_aw3j" ^ikR͂Gl#KNJ^aw>c iȮL:~OJoR"4'B${7A!)z+̈ 8D ű.bO$ia]|3Hp쓏Ozp{E'r< Rͭ6Wna1Ӭ5Tx!Dmo՗&h ׾=kLP |ԊQkIshdBNpod{Q@!hPrR A՟r{{JxM"-()$L iHZ~>"HȖ"6{'6D4`+8MM=RrZG*)0T4>0D!@sYGݫ}osz}KOQ~Ѭ.wPϬ -6c~DX~Asu:2DQ(\" e0̶VOh| VL8&^;i C ~O88Y34'1(*k_a>B;!ET^! h.(U9 'wǼ'A˰-ubg0dHpR?I jc|p߹c>̴#<>gq~?e24N^G,E%r̐ %FFKe.6w20M tO.u=&\f Dj)GH:w}&&RX3B/`rסQP\TBxDHHASDacxǟI[+ٿA'[QUh8sqiza"sQơ)98AaX4;!dzD:t~گ OL+8%2 lP˖(NzPj\`uQx[Z'2QP;r'0A |ԇQ'i-W}ۋҗ^AFYbn 43h,/?^sS~Ϙc Bvn^qxa`ZE5"ѻd `@(t ǟqí!WI*,k07PTOWb'`312T4=5 Q vÐf UqvH|f_֗`Z$QE1⺫TL_[*73qfUO٪.~=4 NW5ǟrԊ3-Pk hDIN,9==L1&miJmi`xׁ Cr/JLҀz›Z h_*y[=MaVb4"ݦ5<)}4ػJ9nTT'bRjj|'TZ9a;r{j=&٬A{kpDZ%Ѵͳgl&C(ך%\;|([50eɼ($6_hNlhv`ThA۔#Pˣq9H#*i9%}47VCDZ(mma95'{K; "'FMOQ/.X"ENq 9vRz;PzB)=OglAk4 2%J S{Q̖ U-#0֘M,,܇{l~@K.7sbǘos򃡐04!{Rړd?jw/YY\X{]&9 ZXS<}SJ}ZBlL496)F͂L xgB %@]ƣA([\:55m7B:ڛ }1бV2>&嘭>o7ޙUɸB2O?< /MCq4rpKWPuu KӰ}K IIV%@-=M*Ț&M="xI򓃪ikR7l( FB!O]Vix8,Sd FTr,`?y ei泳F[J}33}˿?4}-^qݦV^mY2C0d­!ƨz3h4$D"R+lAF!x]xOqM%tRyƃ}~31 ஖"&O7Rz%QX8^i|p~(jBIЄxGTP S- Us!ϥiXAĊ@b6TJu(%3Fÿ-4,PWv0EeuUǎ=Ou0 ssW2z6m42 ܳO[/|R2,@L~ g^=tؒM5- NLn_M:$B9"děԚI]&M-QBh[a3hH=^6N`!'P:7a~DB1!e4 `H<>\ ̔VjCWN;}=ؑ#=x_ouHKD  y7¶MKW.\. R!dqpq~y)7y63X8/ts#F7$ E:hic̩E Kj{ac߻(FA C׷g<;`X6*0x)<W lH˲P {$UGf[,kz%m@JWQt`g3ckRUxei Pt~]Qo8^4~/8)C1"L=SJ[2ĉ'/aOV9ӈg&۲-f,|qch A Hr];Źi2T-΃cc='*$5kAz6t'?R P6&7#lhH$TyVMrcttSˑN.*^_o?/ # sF+b3:50B`AZ) 'Jh.[ū5P: Oŕ:?_hp{o0q?q77d1c'EvYCo~zƊCH ?$a|P|)DTb 㗁3AJu+2a>а`t0,•1I퍁chċ"깅+e`W0Bp4&\'Ib(Owdxs29z~&0qkKF) $XL' GJp?~_DW,UO`Hڡܙ<"ҿ;?g,E C(w>$TB.O=n$i/w\q3d"e?7k[3 /3I&HfˍeZ=~⮟d!/]T՜<0mL%cLW2A*t=pN,`֢@Ia042i2: գPyqFښ"mnN!uW<t T`dV`E|~K%d]?e6<׵x7MG۷+mnvVQr (EAQ,m2a4:j0&M(2)UMTw{ReO=hqj s/A 3aq:0jͲd-*32A+$y.U~v+K6$UFMs:XHD&(@jE5`BxZ:/@Hq=aN 8ԝ{N C/Le,ahC^ϐ>wPu2vɜ@d芇+X.{'+ijkfk{=1O|ZJW^ĩ6p*oPV+mm5rI>{#~hV٠PdGR+: d"N褆) Xqi^4 E%3>u@E gwB^xt)osWO~ɝDb ,*0{ee/ͽ_zP$6# Ÿ)x7o,Am̅*]ukc)AG;EAɷR@yHbHT8~>tՎ1;,QsEҗXȑT AWGZ7<)DշE5+#{Jg*7P!# K%5QS $.ŰDr DJR8*qZ Ӿ[t|OfUrr҇ <Q') ػB AMxN- tRy7e&׷,2f |0-) 0i(+ >MS~Vy`u9uz"-ʒ@8{v 䙆BA r20j*7p=x Esm!@9qL]~+ח_FѶQ]8S98frIv_ɂnZA*}ec;6o2Q@_+I1#E UA%*UHBNSD.]40 V9J5x:5A/=7k{I{RoWe|Զ 4<hdf=$Q qǿJeeALLeը9ZAo)%Z:ڷ"ۘ" Wp';{4a][ҋyG 45daQ!X1 *JX5E@6]Cp>t 8<q]>2"3 n{8p57n1\4;b;sNA,֪ʡV7?`̸2W#O$.7B.@ס(;=݊<QX&%/ZmNCzw"goO*ްno7& \Ɨg%q}z~mTxшFuˏr;"IRH)HG2iuSe:;Q LHGu'h&RjYjD&vZuj5 ٰ@w%,Pm4݊ո\{iӬI罹-AN;de{-8AY8kR.&|{OFo xcdP1ג+$LG8Y NTtZJ7\Dkw>PKu=k$4>Es7+J5n\x{#Sa,ۂ-8a^GZԓթs0s "XoXOzMEm&)!Q` wrJ@ՁD ) KD$Ҥ^RcCC $Jj![%}_<$U4aY=s|M0(_{ָl6Mmd,;[gѨ f8RI8ƚh6*[8eA ]u(aM V,Z HkGL9&UiǵCUƘTGz&3Q Qj)`RY<_#vj>m[&l5 dpqđ` ˗/㭫WwNH X@blDx0)b\4hNTtyH$%}(PLDr{.r=FjGIMae`Hk1ݪ;Y(9A8t}\|zp-L*M=G\z:^z]0:vj-{suP&{g5ɤRy%ew_I -<"8ѮO3oZލB:VnH*wxFί}f`F[}`IwF+m)N|뚂a!aΐ!aCP+qk Nc׍WXa_""N O0cIQm.'m}/aҶA7#:C+"2D 1f/Qi $xK9TBJ<װsgPp~a|ʛxtLma!?Jj*3`#CX_0܌1+(%M| J}W8]>Ƒ(sĢDD /t<@hU$W5-Uֱv-~^ke @hikDXB-!Ԍ# VͭiMUP+>\OazvAAWAXDuO )-5 jҴFH U2)ZQ}(Z)#R>$U"F 4%~Jl6 #AmNZ)kIf?]j۴u%q%ȓ̞e}yˁ=T&8پ/sq`N?>|_ GKy6?g&d Xf;ev2C>TD XrlJñ*k5 &:tytb}z&v=6ńգ>,L/i3(y E2@P!RX}X C ~So6q2m^e|RvG^÷y6ec8ښ|5q~M)]򃯲Swe2'V=?o>Vj:Dh;$kIF~jh!R=]ncꝎe;!hҵn-P٨#涇49E-i~r%;ssN22sGQW RM|?Dӫ#'+`a=y%4Cxzfr(M|BS@ o&G"md2HEN&f6OwwQ!ayJs;t{޻+P5x G6Gi\v&F-a@f[!V" R.qՊ=b*7GAOkWːuD?˰UEv]AOji`5=ż!/Hty-)o"|JVp U݇=A>fH/{Ad`H_,nwLӴ, .ò3c`ubPܱv%K-LN|oJـ(g05C^3v5ϕkVܮ4Bc9?MM֪\-Z8r> c٨ֶhM8N]\~R7kRg@ >REGG{={0ɴe<-~m+fs+pNv)0UTAh_@RlkM`h 7bm0l&>^(ZKDaZVݪf204"fz=R03T'j 9avs@رGz2l)wHxdhK4dmR L `Hc뺟Pt%$Yhu^ 0؍QAv))YubaJ <NFQ (F* MfGFuR20]njDB:& a\=8oпa] 9T* `D2kp/ZJ=hExV*⍋ jD‚a1?ݠB[9[݂LOerhkFĐ?π_SX fz!T1蔻#m|ph׹9)MC lb{{[,pg-s*cbq3 fnN7 9Z}Mި=9p,fǟxP؆x~F8c&u > 7P4$o5&1gm^mԟC|"K3Q9h ƅ4w'1rabD;<)9 -`A;um)2Voŵ20 R&ح͇:;a(/941ω߾01 3|~Cd^F Թ9]A Dyc @(,M#U'i?l F 1Z2g\Fuv.zDj3m_-iE(N}:F8:]p"O+# ec jYe@hπ ʲYgл2LL$ \af3K(΋PșH̢\skAw^v^WIiZ^c+%beaqqK͛7[ge;)MS+WQJx2YXhshdU9th/_.\* %2=Bɶ<84w*۸ }g7yqgCLW^Qj>UvH;SpJZ>aD&ok @ߓ *9*>v6DѯL ,8=4Mfk+ՠCYk'PkWV᜝B} ɾrDBBlm>z(Ndm0qMžcm[gOܒ 싗(ݮom*ܡ1з6L'te`bXƝDc'hdAHl|Lғ63h]x|ҏ>au&ܺ۷o c!\<ǜ#m {x.2m͈2xݽzx|LFbRdk27¨pt^Weu-.Λ%pC EhRs, 4p`]$xo Bhqä1D~zȐ 4DS٪BзJ9RioG ۧa2Վ) >b@ӎT6J #CC%;b[GX??;j(Yi%#XRiL#+k(L66'w_~Z b,%pW)5u8yY.P ͳJatnW߽k ERnRHt-FțFg)hi讓],Mt7<: RWɘ0p|IYF ouV;ɶ{dEe,\fmiwFH2? t:-i٥W[4kԾV`sζ*5V>iξ|O?m0=pv} ,M+R@+ \EyA H4vpqߖ@S)AP+|%f&?bdS3fQ+ɕJ_T&Ğ1NLT) RI;%M#G+~v+{Veվjp7WT:`:20^d4XMlg1$9Ѿzڿ!hPZu[be=_:V-=|/|ETY\\Hq܋SӦEa4@|fEʴ8LZ ,8/ʷ1w]mCuu0KQ2EGjHeY- 4ñ12c9GVe}@%dVdSdmIz!. JƷ ]!uh6dzspȼqo"%p޺|0Pz!^?<T~K?V_u:^[CeςaZk&~%j,\x.F+W`lhgNl G tX D1G{%5'1mFX`ި+Oyש82P7N6n1`q#9,%D+Τj'hQP 8(-81hbKڄ6(P(oZ6a`Ʀskq; @W5`#e^]A"}*6eZ_ioj2$U$0<84쒋/U_3ه10eq#2Bee3~xwc2?δQxbz\Y'"-Ǹ+p\TK6Z|aj33YmEZ@ʼZԈ2R,Zz~N6T+0,r\߼߰Vp[(VUY{|ɻ^Wm]}j~kXkx eq͉spVU⸵&ـ2ˮV1 ˌ\YUc 4 \7H:~51]Q(b3,TK;GYzF$ A7Lt%[AR 1$ ]N|ī$^6ޝɥW@"a|z2\13GT83Pw.4 t嫒Y_S|~̣p? -aoH#<7?q%+ Nl!V7阳Da٪ 8+gZ`] ~;Wݣ# g(//}xű+~JV 8V OHj-OUD)5KO4 j20": wϛC*6Qm4dunShwZ[zP,GB2ρGY%[mlm MʷXސ*U2X 'k#0CCaNJPf<<ʍJ2?P@lN<|hFx71-ܬ@xDV W*ZuT|wia\*^C8?/R+z<NK0Ǒ& bj7?R\6'PV8&ZϜrc}vĢ:Q6:tIĩߕ )Tt%a)frrґK󄀧8ɳkKgfw s|KhԚ*HXY]fh;ADeǜx$^sA{`8q7Ngg ^?tt4޾-y\)Aʿn_9m0yVEئ rp-T,HY?{#ZoʁHi`L4lֿO4&ŠS]qr;%u3b0OIO* - )pa6o:;?Ҹhioe@1r5?玨OԐnrz+s\i}Q8B-ӜW۷SiYqmx%X;ۃX^b~HA"x# egV-FHScũ:q靸j{t/(Q/FLVW9)ϠeXWwv6腀,uC(Ô}@ #.̓/m2EΓl"luln(sX̴5lloJz2jjG'\>7]Uϋ`\~.Vws[?'U=X pp<[+$MD}eb1*- Z՞l;wK tr[}3)kaڲdlq/ʉmI-sra8~cz62<4uu*,4; 2&+aaj ߾S?9M&@'^.\Ԅh6+0e I'79hܕ]\\B\F^C&k?u,,'$GbᇯVewQ˔56 PL!/.魕2\(kgZY7o\B.3͚7f 6BA<3G3<֯Wmr$q"S>Z ՅsxQ5x(f}g4uTjo}{X \Rp73q@R(Ȋ 8[g$EVLtsE.DO|$M6{vj\/C1 ’uZ[ۦ{e x7嗷҇m,\WV~W˭ba}l<Q5P?) t:I8oQgl )6ͮ_1%O~K: 'b5}U[@ꍁwqfw6.ո@"Cik@.vrG7EsSr{ Ж'>Vo:,73d-мHXb3bYۡm\ږUQ׳; ~PJYy{΋Md4ͲXj N|Q !Fi~|ZԻFq*G x[ۘv3 JܚXܕJ,0AwTrx2P^(]!ۨ@beK8y-0)#waXf}=p߻ʍeSw& !_i;%('vZP۷M8v&H={K֜#`pE1,yԊ3=Q<V7B_s: ;96ru.5Wo4bP@C۞iP-ŧ4Z/M20QwJ:ف/!XAcFqb_glVig5?E?Lk {6Pb־"Vۋp[ 1y۬.Y-@q%pNd%,wIa|b ۱z}5+:x酗155ρe=,X4 a|Vlqқx om+S?Z\͕kϠG?ųW/Ԝ37R/xs:uf-Ӹ.oAyA`Ms(60?Knn\o'$/=߅:>jx[x;/e*N*/)qܜ`߈S͋? 4 t)Y , z"n!mOLQ8[MӴ>Mbw[OZ ! ]ԙt"}.*Vvtz9~I[2$` gȉg,ltVy6妏_ޞ;ͭ .Ra 2fٷ.,TJ+%)3P+xϾg_•^]] ZשS\z)@jvAP D-n+fb2e5 KxGw okOf$iRD9T9ufPpi%shۈɹR\XDc*J:Uz\"Ƕr$: 7nh݇ yn{fL.c>@ϲBvﳩĝ %%3OxDC὇"SѶ5 *С-O 8Y:z<_% /5ɤ\<ܗ{E0̰Q?k>zߌp/_~o|>s n" >d@!uMJggmix,BJ6k $0_sڨBͶJ!?U+ \ fynf}~A1]$f?!@q%2~S^sGjB}Z)ya<5DQIq200k!IcCI61jSynd,+ϖ y0uۺE[3`ePRBI̾~^V6gE(ZgV7amb9hSkg7/KvWfSvl\Εf|[#}G`fFe2>ȣ39dsMk[>N-{8xbk<o̗ Yr}w|`k\v .4nm?!#zwe͸l߼+ .٬o ],%H HH, -a%Y)Z ۤELъ`&C=g1s}wUuݯ;UWUW4vfg1_f~%OPQܳI e+Up.s&p tL|+T9VlVQ?@[G'Nu8{~v WBm8A#Dxޯ\+8dZ>|t2Ш@Xc!S`䏡9b:8>g6ßBfS56lCVȣ 'E'/ $|46̪,x QHmӟjC~U]cQ?gk; _9u$$'uLOo9x>OlnB25VLS46@`[mѾ: 5 Bc*nޗcAx KL6Z{EH_38Y>'y?3(*IO=KIqmȒ紀OEYS~ fb*?{,yrŖ|ӮkHR-xvPcĤυ@ޙh [w/Ž|Hz %GA"ŃA;́nlZ:'lK30Bh؉'w7^wi-MS 쿞OW%#[m S.4Z ""eDl_8TUECB(8wN>{^Wx!S4۷/IP"=`uIƠ[[7HTh` A $g1Ƴ^k9A@>+~y1Fю㚗]Uf ¢Y^"^Z$= gFR+KSY)]h Q<y9R(N8թ&%{.A1gR!7 dI(LxvOs\3g4麒;Vk/t9:C=30ZM4{f >&P])SLǕjREwDS=o#^>f8*F]$o?^~M{1j#e{'Ns7߸@Zdد\n,1Ċ(PwkBhș(W4Tpz;$ۄfS/#H<-b) XEzi"r=|뉲vo ?oⅷ|,uo.HTf ͤ^B"APa P&e3:l["{1v}t#Bz`F1J|r~kGh*U2vն׈7Gdž8_qIΝ ycccUb'x1Z1Hn{?QkE^͙C? ,sla8A{YR?t?[dBM{]8Ea1«!hlo g-ըO x?7Q9x>hGG:ڗ! EA@(C4!p_XU9(|L! Փ{?l< y>W8(j4pY@ ~Fv,JQd?'x.nn[B׈㨂z)Eb˾<eJrEbX\aHIr%Y~ip{J}kJQ[^5-;/g@A7&,fD!Rh6밵E|X*PG$59ĉzԀq|y :$os0-h6s=SȌܢJ<Ӯ\鯓YeCr/(8h%2sJ.P5!I>t%s  HJta#j08<6f,ળ_PU$>ߋ CQśԢz:o1/ xuѵ7/]O͗x:v WI`j␐OC@`hb,GE01Ld1-fܤ+Rq=S-h D"UH'F  Rfn]."I=G0mf*nw6٠@@Jw]:+;?Erw'no'IAXl}^zy,cK-%TThl*L;`Y`C&a&T #j I߇e(A૞wx2q [ġy.ËXh+o8b4}4 38TfXhC]Mz.)IxC#NWDlM;ԬH 3R&ÒnK$<{4!4hÀÀ#d˜)M] ^1ۀ./?!տ蛥nq*uϑ vpTJ_HQ 2jqAhzPߺo;znr4 zx61HYcGAY? b*c2' ?1AN }  `. %DZBcqЙ?[E2F$l"9pUk#QWq@kwBmۅN;B?`i!eǓj? _RY 5)(smwivjjs:˹|xɯAkFy $d?bߐU8tĀ7: vR7ګ04F7n tV4I=N=KD#I` ~p Pi0aF퀇)VŰ8zRHP:A{y%㳪V”5i %WͯE= ^"t {P؊ 1d^YR@$n8wLh@hN8܊2}?2EM)+_oj@hzF*IJFIgiV2ݳs9v$쓽47v pakK l0< neb<2<952vD>TsJ et4dvq\u\\/I# 40nr..dzqC Qjry)Ո`$ MeGՅs+ 0=7 2CG%'d*Ѐ7Qbt4EmC2r;Ł%N_DT*S#pȌfEbQA~IdK/C&WkuCCc`AdVM/}z=`o,Y'uғAl I[h|)H9s8ԇN/mg-Mi]`рQg0k7d5UcVLY2Me/== S+KK0Mn<1@P4M`DEFgOv_{-mh%xq{PTܩN%m*:Lu9"ٖмDkehդ XPB7i7 Ej{&4U6яpxXE"d" 8iuUo5&˗#u!*(QO'geT!9|?m wNfT@BlU{EO=s?WsBh}Ž8M<@_{yv#nIydx9 b!j2Ϗ@Lg!{CF,#Ӵ۷v@yzTS {{\Fw$1)K:ȅuioJ0U#w0{ԕ)rS*~EPD'0CzI5޺yFdZҩKfJaĎ Xk.߲gtbWM3`UeÂACYCG˜UpP;^D|.O<ǶppKBi5 N z.ئAjncn3@lReN( Kc]C(ڭ7@tg2fDfņ 2J굂}-˃UG ) 8әNA6$B y$tMW]ƝP#-> |w+U(,-LnAd9od5?i&kmI։VJ*j^)It.(.t,]4s*f?*Klf߅QuH҄L)d2]eϺG<Ȃڞe(bA2w3Y^:C?ES7bD422.~fn]~Hcj|zn(`p;~NAܢ(є1,qcqOei3 #ц+O<,1p$ɮ茫e)<(qfVPF&Y(/6,ڝkm7`vgʥ8^xP2!N^,k4v^Fl(~ma d,Ҩl%U H3 =g+:weE K+B^$$)nN!O{ۃ$Q 'x٦%*.DxJlekbLG1ܿG6@m1Z͇D֯)]ȧBHB-*O:8[@y !"xڽl+{e"+$?9! Ij3SlW";1Yi ֧QJZ d˶y(2S=W?^PdaAQ1EefW~Z x`۳Kpx8Lq$!gOB#]9gxAzۗv DPf&z(QEԂ'y@<>2je}RW[KM;4ù??KbeDDUc /6KG "pTvD}%(rŸ!x=х$8-(ɒBX)4Җ$ڿ;qTf `8!'$'-)Eڠ}&-8'aD*|T%4FM#AEsDEqSo5Mt{'p !B;ƂÅ 5/-@Q~(8e-6qܤAno 8J>`:zuxA_MtXT$нclLi/߫<> d:l0>9h_gzx5V[|VV K *33c'rpsm}}U3*Ci/# \o< $+~GMV .I w*!ms3{= MB|n^sLSҨPQ|qoL b®̓(SKQj޺,b r\Rlܣa khP$+A, A)s+N&ckj"a8Q)| -p H(1lkoWv Q}we33M0X_'d^gfPj}IQ6i<)"uǿK v^E? AC &"㠏fɭ7LP??;yw_*cO`}Q Dt&{X59He1#aHٕmk0  q)5g)xBNmisB#)R,ẋ`]heAkJcBQeJ^O6 =cA{,mS$+IC]W;Nwׅ< 8>F" Ѹ9 4Ea/,Xa($Șk`#C#o1gp 5 ̼wn%{A9fwyCX.­7R= &| z@a 6K)KCÌMx7zyc)(kd¹fzP;ǚ6F:І 6+y:gtؐ,.9<Wac= O?h"t{'N/h߾L;z>f| =&Ј6^V}^7F|#pz~Fcvww$R c<D" #[d%ya lr~@}q"zK3mдܕЖ;~jCol@3 [m]."c]`BYDz'2: ۴&><5" LgvA d,L4e L*'&Ic>?\)h K:u];)ת8~V {w.مŹ.p VXr-)x $L(Y> y*̆ a,^ "O>]j6.]IVaaaZ:T[`~tG翱 j.>=)IL:jWoW<;'XR]ag-q}44 IJcRۊpOzo*JxCQ|.T9`~T f E"{GnGe|tAKtosnmp^yxnfi6a3-ON|l#w'p8.Dx3q='EL2d=mjID ,F^8bp4C#,uáۺjT/ǡy X*ڢM:o onG#``h{IF@0$iR4z̪OodpIt}Stq%A@xDl7E#rALX(.?D]7 B:D,`#I:FP̭4M ^\4kux@d4ʒ"9N(oM!Ԕ$B8--A^(çAU)t,_7Ј+ \_+:^X7IL5d]٠ߙ/0=SFG0k[fSc'`m!d  7fC iPow=(t8w4k~D Wfj{&^@t@~:+Pi ю G>4pF@s9 !ab~pL6R4I:usVWs|Tk&0_yet1,_b$/Nbj;asCAPj tf=OWN,,;)5OlBP1,'g+`qiM7~? M˿ w{V1#)7z#wm/n7A}Pt12ՎSU,&^eIzIuhhlvxA%bVnX[yhqGw '1vkUo_&7@ F dN,yt)Raڞ#m@y.'Դ0ekoB28GQ"jD2U]$4k'5\U\0s@8kW Kڐ6ApO(J#e~#rk.q|M 9=1!;4U{43#n`yBnE|gbc45I[nłbцN7s,qQq!&TX~l/k|H$]_ aڞOH22s9CO%yv*;P.m :uB T0;jt}C{xKO1tJs {u+v Wk#1~?݃?R_5Tvi] ]*iG%J[#pO>TҬDq⥋Ь6aaaA4LMM=ȣpI~غZPπ(p3vppo9 =Y3)^`+t[~};fB9X,ŗVlE5+gH/P\u~ZflR"H@ RI***E !Fݥ1u9MϠzozrlBLQT«ooYR+0<$Π86x!i2Kgi̥鞢M$BЛ#MSG2w<6u'Ih!Sr&ϒ4wHRR]V9@C18>I}dJFzS M 1|LD/Wmzй!` ]6|"p\BhLп\ȏs++КߺuKPyiVEgCŵEΨLDYƅa<X/P ]Vo~}n -W!P. }VQXL:7pU*s;_^=sonĺ1ni\u\RɆBޖC0\БSIuBR21 AR$"8:D }=<* -FAb "vk̺]hk1 a`ppnx2K)1M@?E@k (] Ŭ> >n)೏_1:{mXjWҵkL`##A cve;UՔiu|9ZNOh=ƜO*^1g>l 9#p46ՍSG Я 1 p4|&J9/ 6QnϞ$CvkH$"tNa+ѯ.O੾C;x9O~o빟bGʳ㱬< 1`肊pi<]4KW.CВ@JS|N#)wX: $7ׅT/'f5ˀ/|jXgr!r!-8xlpKLƇg/&[Dѹ(M Y`88$!4-wv n̉c_.UlV2y4}%5ovly+8I fJj[[Hu҄ޞNDq!^&|db #lq"Y'2.O²LlC'FМ܈D:dU@uϢPDYGh0@cnȚ؈b@#JwovBK=hwG\"h ]F Z/*p:<#";GJif&1I$&3vdVʙc&kOMB oF#8dJx*/-AiLk ~PK3cllD?DtRjI 뎟:hZgt5`E[_իd]RlT"2uu|e߇~2܌2Ww߽Z {PAk/!,kF,cu|xK9,̢1ѱ1YS 00Z~;7}wR2k$k`ʿ3?׮][79:t :ݶ(/-L#E>v}82033e>$d}ii<x\,, O)Rmaa"a[\D)ͲPJYPV>q.: OIȞ01@kgdĹ[k Ќy ڽ~ _rb$L@O+r0d^W'Cp3s);N gy}iRxښDm :{'ۍW_5V"E }ϰ-sxWXEӍy`l0 YC&62sv9!Wv H~dWj rKͿnDF=M!2*9 _ `("'sds3anvZ"4O/TeA7Rm ,cR&#.ЅcDžkoBԄHn ~4j5JmyQ>k$k "Ɔ2A'xeǢCbZ,#X.Ry]t ϶.ZQƆT~ٽت0N'Q'?aC7 `/5Ĥ=hGuտ%1iUc,,r9OfĐt@Ep81`CdVfP̌X,%?]@߬c@F~4c)?,k]וeO R ;?h pCAvB'LΊD}G_Пm,0cT'FJ]=hL= o=-~Yk/6Zϛ#N '?سT;kZ$!FT _Od$9Lw%64fV%zIΨgna!0\ yy1`=seu" dK+Q5kfSr:Ǫ Qx%h#\Fht "iZ]h}W.xFd}dv{"cN;Nx65W#&Sh (lf[{/J6RfM6 ;eu_+` I, T-N|n .P _/Q 9?.?{)X# EsINtisQNO^T"vU/@c.dU tTt$>V,NJ7$3'->rf딕ȮRz3dTR{;B+qY PU}J2"H~iR8 xb3B "rX4\2#)P$ S-hN{,LOUxne2RCPi6NYp$Qw'mgAw?\{ %'O< 8ރ}!2Bw=.k3gA u,o5Kg`\F$i`h1n@ނ>=[7^I6)[uD;v|^pPP H.9%}4@dyA"@? vu x%ǰKRC s)x]hCi0Q C߉Õ)4VSMA9M< T&k"b)vx:{fzΔ37%GADtj:q{PZUBG ŵQ*)siNYKjb-S>F|y"{) I֌0M4{4dIi'iϣAr;"z:@5;5Mخao]B>"ys3ܹ╄ԛ(?1" cTpm9 kv')SK/F3݁ܤp$B aMt@Z*)sوJ u:Ǩn3ae.k)y@MIwb}n : èugGYc :N4ܦYfrpl@"JŬ.NIt%:G@gBZII H4h%Lnf6N3oNڬ ҍPgh#XNQebJH@rB")Ͱ;p߽t!R%rO>Qm( r"Ǣ{\Gxo)M Ga^܋(ԃv%|N(_F5'%'N0]ձOVw;k̰SeHb*J|xTSGcOfI:b3HPNC:Sy zmڪemB$r}\.쒈`PCpbfpBɐ!b{xV𬷛v^:7ǀzK&mSAD |o 6+1qRI?˔13TL!^ZDʪfey~ҙC&58$ܽZ"bmg+FX(p84 .eNuYr1tt谐 QiVGg~tq{mU5%ĵbx͚<ϳs_&"4hf8 "`wdz#űԨ1TeF[[boE^t $$muJh_GaA8 G"<BO𰉟o9?; v_:t晠ƕLa*5cUƟuzs$}|o+>t/MM}5Tڸ |$d^sl(Ն{5ّF F3։jiJo&UVkL4!%Yb[MMU&#aڀBچA}Y/ģ@S#?A(`ooWiP6ԏ& |' 7 ~W{ש5)=xq7c>Ʒ;ptw'Tq-)H&I@$Y[L9.  hFnK+V è)yIz^R:q6ޡY Jf3 sRQ^GZ$qb 3tw(D(KE4z~e cyXnB2dt53#JVVOHA8)8k^`c}G/ hZS4 XqB1@M謢40XFٔ9w׶;@cJҍ8+Jz, G;m,#x-_F^>ޫF(0±GsM@Bh%X^0qy*WK?*vG۩ .' :cit:!ZuR4&DybIi ft,npi?:"/ l0(Xrf@Zoz_M8f1p:5y-LIP.ak*Ei)0[݈KdѴ$Fm~rz 3'K  &HA/ (!? oB-!C6/ A%1$%oxlvz.8H&!òmh4[{bc 3[7^z}F3?DNKUpGVǤ )k~ q*EA(W(T\@}6g ߛei))͂8GN[t޷ڮh$ah׏@tyzA$&9Vv "aDt0wGHJ [EpiӋĂ4zxR/lR~1ï^Qxٛ[egaksU]RF@6+ Mvxb46alvG IHnuwuUVfw{Fo}ν/IT+û9o}sf!c4 {/pb/ ?;qQ_q0n~rKW!^?,{ ' Nچ9*wiFB@`{N&K Q\<|dlʾ!%FlKxkʂA|f^vdH8eLmZ^U5_xyN(!`^hyLrdDߠh^ӲCSA2:Jb<J卿c &3&S 5F" W~7~j kFpR'3X,~َ_gUf+ꇉ yuZl a6M/uv==}}58⽣N'roPP?GX|Q4$&5Zy@%z&e#Yɤ0coܬ3mdTڕw<}ҧI__'gfugB!ٖIFePoخzƉRK|/]_nb h/?GQ.s9C?ΉauFt F4 ֨Ua UgL%I=3ZքiM޺seG_$ǧx2XɥacK+4>e?9;Bm:bR ˜fl3zK:᛼yt~={87$Ư*G} ȿB)Ot@П1>ώ6wZ`iDb}T,3@$ŖjLP'h.&mLǁ6b-˔ R>$d1|VZ1OehxSkXW2ѷ2ɦ)Ô(D>vnQ v}zo\aBm;haƍ ]J`wTheC80:F=R-`ovDIrqJd<~9 7_hZ.;eT)Ol9;ƿ9Rk/\!X|XڬoEnysc}Bj`!0P}&ϒ}Wc/_4?sEL< ٴ] 9ёR+d-{tp:Fo6мm WHJWoYv/F|Fl?Ze{}~wkk\M{ǁ2ј6+Ejw&H0hЯ s+m5I g:*d E=# MI4$-Y ]>&1UG~p@6o7#Ѻ]dPX+3Qn)҃ahm28XztZo/٠J1GQtﭖ}7(duo2ʻ]xx9yٮ=q]L4YV#в}HtVh$kKS"p(#|Qz6ZNZjv\ObSA>~7^zύ>5E R/`ғkeAelVGEh(nq< |V9ת.鷻r-(O>PZǷ_?JB;';%߹Qh+ 1AI \LV晥2 ŐNG"S(|ͣ+ 8+jH>t6F%6.gPU6ǯV+4:WdT(.y }8C{۵+@/N֕ -# |};Ө5ئܠTiEǙ-PnU[#_" g 3BQ]#, FkI_Hʹ~k2wB둭_0m'rEW?-*=cY29@ӎ(Dha̷zq#} s3,WIlzՊ6y8NLJoU@lZ/׷Lpwkt nz\#EJ `Y.&nXj=!׫EܦrȢys?-h4":-رOLc/I@y EH9cϗd>@"-&"3|]XWTpDMeIj%rӷRRi+s۲l0!ufyPIuѤ+5q=9|9/BNmN?m5*cb\@67%8 ۻĔC-EAxW jqFb9񵄁ȃ~o@&g>|lĿOl[Wc6R b,Jax'hBfQBR/g>.DkuGvV)I=}x@ KTns\!^C95A5Je)fv$қwͱK=_}#Ck /R|of{s_xhk{֍ӓ A gmHZv:9?voi{~B-Nr^_N[JeZ uP("fqpvJbƑg'8YtQp/Dž2'*ПT.lԨgث Z[sҪZoBj'S;||H)~)'Cz@ږF F3HTb*|]+𜼓 r3rV$/|o}Ы} ~6KLJyx{9&><~8$`QP0 *"(a <8ceVHi_apJJk¾;QaΟ=;d8yz(s?>|Щ+_gî*5𹹜f&.kcVKPX:Xuf $ƒ@~}i cm yޟ[,>䐤ϗT.iooNٟFAo*~gю 'b Ƅ2ݼq=99GI&}f}T^NgM<7DR3ƉMCV57/F X3.C}sQ= p 3Vɭ+}K,zⵊ1eR}u!6ŏ,v譥Wף Lʧ&ѕ>=V$O ,i1N1v>ӠJ`U^O33-u#8:ߥ3:iPrq &ʅ_HV,BxƪIZ.zXh53>+>T}RjҰV`qw{ ᶨa~`էHak57ݛNMo_x]c7?Ɵ= |O!GY|D{>cʩy/{/z5ކ^. JS~PW䜄c a#_ޤ HM9;: 7 LgYB[{ŕ3^&u= )/zI0>ۂ&o6avgL(+]T/L)0;d\82H𧺤6ز#lS}T$V)s&(4އh6U:? (Vμ K>=|} &KJ}RP$2^?R61vZ$vQ).ddEZO @ &͍o/ߪTT(WK?go2u4gk޾{DX NBKp!%w"Pm`?Z n;l:;ΦV(Ѷlclt?[)+P!pA^dj͖d>AwG!8xN.Os|'y#?'ȷ)"l9>&I^Dj \Y/bWSЎE(_)қx0 WTn&U7xB=]pYYĔ fB4TM)]e?#=P3+zH<8UTt|N0\5EVr8kZw n|͜nr.͘'tعHy8mٌv6vi0,bDK9yB.'PT4 adŁ5K"vLFI6ڧ$J3$f:xue~&v_;p8/n7cNԽwͳp:DIӂ< Ԥlp;!'-bK:X2Ill|!־Ѩrlno]ߒY9@sqԝ"`-AlnYW0zVpvadolGv91k9Z_ &dmOCnWT@5 񹣪]iw.VzcL蜛a ٫L)62qJlRpG-SSKc/ * V+kP5 4o;ĴrBWaN 3BQ}%КŃ,6T.Z+e/ %|0"]ÓO2 ai3qFڇ HĠ*PkWTg&莵RA3y胈dI^e6u \QMVl*W7qf֍ mS Ej 4kL?ڝ?()|#/rZ@},UsPU`<_/ ֨*gGE$MMflx|(!.|8QiG{j2stmgKdm6ؑ)Y*AK=\!"LҞm^L'Ƒhд-NE眑ת-ߓϨV2u 9^(mg(If ‵Q 94Dx$MS~ݝ>Y{f*&arLszBmzDP$:~!>i A+bϥT6[tuz+NzN)_a9CX$8v]숊N&,sd*شm5zGv9U5y.8 F7?EM~tu?_~Q9˯]\0%A,wԪ]eMLS/䐎ژkbȤDɖ-{jv9YpźrI'ؘ 5dx}8B" %_ϖ?E ۅL %=~Ll=FcsjsBZ%ޑ 76@7?O(.T412CQ&DkO-:ŗj*SDm9 ɫ-x'8z,ACZrWhR#qҜhӍtdMLFDU}U:mfƆlboi_RYXO֛Kكy'4Fe'R5ѵ*p1*j64t֖PW<}<* wpɜތNfM!:C 2+m-)Sd}q*Ytpņ5Nrأd*RNdϥH˕nDP|Agxc_tP6OrԽ2 Z*NN3۲ˉiL/'cTv_,G:A7TMh`ŘN}œ\slX&"3u.BrllCvh<h{g1ה^kk,P׫4 U(Wœel n}~?KB[7'˿8 Tg1|shM`AZZ(`bg^&Rn82Tr`7CӢe0sX̧޻ G X$YVZN$ҞAEc4Mͺ)m Z.7962 mTbT,;sppS&r?|},t2r^hvIJ|OASc.DPs!ZcMɮVum. |:|79iuXtH'GrMTolrfV#uI`<8cmѫ>P _&wEJUtC)vlWplBAr\7To622d#*D7.U3 yڑ{,_yTe*WJ6' ӝW1Z@M>s ڲ(eTNg/TҮɕi5ΖIr{\Ή42ջT)K:GܐL豷A|e *N'M%*&a d 8"gQVAZa U@ NfL\ %!'t:?yz1*pzog XX9/bh (Zs?JVG * n(x>{Y|Bya8;9wK75ېrv: w^ /B!ksex_:5JvFfoR*]9ז0(S9q%89aN0ʤ .*Y'7z=z9'M!޻w@;7_~9r}>ӆR(+{gޟ*d(y._7gCktvvJQzCޠÖFJZ7PN} #2 (9ےXa dv^;eNֵ #vS#0wo5؇z)ϥ-]CX3A{:}Q0Kpq/NS_x &=!TQ]Ck֨j YĹ/$T9C?~ AiR=yzDZ Cޛ i%ǜ gNFng,WxW]r4BuB5%ZOZ`vN=zϱN%C^V=_sJ?j~1o,p.&-^k=|.y\;Sf!eHIJ6F0$UђpoL)SRǨd;mM(sUգyf2"ҋeo`́YBri1e>4L$. FbbdtmoBa7峣Y-5Q 2EشgN~NH9QUii89װN*g(Q4peI 6Z^hzK/,%zX04Z *E]QdZ%u*ՌOSD6e`[c";Wu|]0e 3*53Z*~%R_*Vfuv< ypI6h]s8=C*%:7&ҜC]z lk-zg3;,@}|cGpw800EA9B3 "CPKlQSBd0: բx_8ZTJ!1)ZA%lkkG7#]jMXۥG51?IgZڶ@K!yhSf(㋇hݜ# 7Y{2[D-OqgfI'Fu9@ cME`x{|PX0Jf A D* 7wOdޠlHTR ]%G~~#ӦN~#BMf{iX3qf~GjKвؿyW8.'˯n(NssTe=,>曷2QJ%wǗ1?&a#olo[6yNrZ𵋳4 _Y8]K[T=VOq98t;j=/TGX5F 1Y:VJ>,5ŽI$UH gvЖ4N oWonoA>_kmM^)3z zn][?̧|9W㖟kAr 'lTtL ݓ0 C;XP26 (KXhytqmdj(j`ov?žSsV՟5R,p1`n4׊ Zl'5u$=M 39EJ;` WTL nlCVAbp@Ӳ[mRJnk sb9U2Ys HlC륥1JRbI@O[L勯~h 4Q?v!ako*$f\)&R;Qe*:NmD)'>^8sS1_d[Bl8imTєmEdJ Kt8CoB{=))NKrI}`yf'7bT>B{O eC'J&s3]Kȗ?#eYcTX:0bVE8Ȁ,լ4O"ok_?%҈djTt%aR#ި3^XXGm/эW^棡L5|[y5פ; c??#_tݍ  a :'\RGpm9.ZHGdt }KC7S6/8O9y$F^ڰX(+\Cт}?Qkfs@s9~`'䏺'ˡ<㼝g|1jd ; Ro- Vm`{ʂ4fq)+sKCã4k^(ʾ==> U-`tB>H Fŵu0qMhWLg䙬~;?z(pssqZ;;+15V.[uyyѡIyNg!ݹE8HN;mn4M.HɈSiӂwl Xam[2liN|Jr.v{V3QTQ(5S!QGUhch t۲^5H2 R]|#/TE;gO?6ll&P2Irb0h>WR {HX4=|RM 8\̻h˗ Ag{xTTb3-\ qd2H%B!/-kMugA~%LTmE%~sR5ǘZOæDy|i$z *gF'sLU^ȹP&MIck#K(r ֲXy@p&2^sA7_.۾|2mI u:B\s))`=Ę$Q- }zQڱB\LLtJ\ %v SW3a$P&Ŗ&f:{:L6:ӽDyrX\)PsN.>Nn}}r6{R.ID P.4prFgJvit#w""x30Ni`öVS2(h{06iQl ȱoF|x, Y-8hLc֘sF-#5 9{2չ'(`!U|Z.xlF h?O_?0XrsXek~q?\6Џ]fb6Yan&lol\(fK1;мlr Gxs(NDJCk+aJ)/R[ غoFqdΓQJ2g٩QĆk7iw<~Kt~n [{ě <|%f }T'eN[2Y@d*`1 ShT@qp*ƙEOT?Bg~QsWH>ՠ]nrUn}Y)i^TВKTmU8o &;5Ss"Ni-cs,ĖJp"8! _,N,b:05+:LR}FsQH[fd EͼNX 64MmPX:QU4Uɐ_ T,0<r_k2D}D{ۗQ$%)CWWrXdo{pfL 4Nމz~ㄞow42IXZTLBeE-ZI_α  f4 f4N(jbBĦ as*rU*"CG0A.Qkmf=iҭ l$vH-2r5ΘGB@hc$٪qw$AiBiy AYnkS$%kZBh6g|(Boek4vs`q.Ml)~g{1oԻ͉%P5 =P-6=:5x*NW -O٣2M` ֆ\ DKdmŋ+STh~U;0ry׽~؟!sbTA,kdq2lǗH ^#; ?wF@ JŐc̿ůٶOgtmE56 U`~bMxArG`y?Z?SpʀAg_׎o'7>WVhzޔ\L|ۣvd!?w{aBqIq;6l;L񺞜`vLnP!덗nь dRP. p3DvV)ģ(S6;l1-(G4iiΤ>6 dzɁc41BW*k|4&F`l P^%[ꚨ* $XK] KD*)>O_ɻb{JѠx:LEp0|*LAG\keTe4uqjh:+ZˀM ;&z T=fc# /Ys&nc1F(t_0^WI:Fz)GeY`c5_roloRT3vT)MEY'+! X\>7jAf|/^a ٌ5paP:'+zz6VLZ-$)Sxi ݘsT4.:2jOcB?+N#eBo3Ak) 4Y8[ >2-9ؽ9 `8q"Cțٚ U4"Co\!JIC~W$wedȯ=bðEUݭmm`8Qzءӗw)K$b pnhZ[=m+-%kcW|*U"@e M ~[tw琾6aZ{<4 _ .AODBAE|C `_BpI֎FAEE=7 #1\isg+lqtY(m>;NkX5c#(!J.fC8EQX?޼&VAeC; ^лGgPCիtM*ŵaH ųb(Bb4[%A fo3Ṝx_@"l?;3oSѓ%=jl:TinQ8ݍ}) 1Y;%8Sә%'vHbT])=yc(4L==o2g J+@L+Ŏ$1\$~qr?ND ߯zBTK%u,KG~bIk64SI<7}ZS $)ʼnI1]~u@y6K2[Qo򄞟<|GgrAdtcI&&W/; CZSSWKҌD8%&֕+E 4n1|QǶRZdԃ'i@%eIu6ԎnwҺVʼV U*0GbXۨjc-?kvȀ-'RgxLmv\KA+/Sm&ߐQA ֚5FVsٽA߼9k|4BeUo%ln6^WdՕ0Z3*ɠ"j4eJx0I52\Ј"R54+HǼI&?`s'npA1hDLF+4h x`Tm68Ƣe=rŪnY/wH/'UI'n|͗nZ񛨊VKTj 1ndĦSKV6}֘PE#EU+ 6_'6n :|p&2IUCk4xĦNa;VG=@gɐQ4mۥg }/8Z.ȴ@1:/VL}&@)_51eL΄݉a+H&:ʚʽZY,RLt/O4=!L~~^Re8̦8̛ZUYp2$St5i*h;F0f5vt f 8yQ:\?gC!Lªqu?㯐jq_Ll"W|` (, CJuݔ@ڦdMt@"Ͷ,iikzjZe '-uZdDS+~ݭ=];7_"ZA炦'I)ZAQlmpU^CsE}@}.Nv'vٸa bF'}lHnpxVc0tj,%Á8]@'J6 )nԩѸ3déB:fn2AXdM  j-ADo 0'(MfmiQlu?}T2i_vmҪG-W*ġMNTa.yި~0swbm{DF P/߾Fgҿ}tt2Cian҃jZK*U9jnn P~A@w<*r3c6t(ėCʩh]Os_ZI iQ8K9򲵫ucv^#G5>p?EƣbѥV+O/ .g^z.gM= : `1=]f| t6Mc]s&Yt2lncA~+jMŃR12XsMq ~m&_/`zY$9TϺj $Q WChh.+%T0a 5)zjrOQ}Sd:PjH{p{lhe E|nܶ($gՖ ӷwvH ڛBYz vUz=ۼoH T2@;~B/[)_%qJc25u7\ .hJ8L]fmTgs2XsV1bZQ$P '[,$24MQrV.9_4| k֎Wo rh'>ݜƺ8Z.-2R+n/,S5gv :bb$8_$+u5-2Ú2 WڨDy'`{h[pB2 `BpБ}ؠ~ 3zN}𘺗dgAYX"`_ueܔ|mRA>UƇ$y\浕)=X [atwgm\Έmi6 Cpa`9-8/_ tAԊ_Y%@sZU#35/h6 u,DbOIqv4B2OK! `4~t:)t{B%pfjUڿGaD9ӟ{pCHon5 %az3B @o0!Y̶)[,\BGG'.Jqj 2iw$܃;'x7Cwx~v&g 4İJx +eG:Z` (2C2#E_ZGǜ`:n\nhɼ_B%ڠ_mɹ'g؏SYlD\h1 M<ׅ?lq2o}^K?3qWj:;;GO{y_y`ZTzgoiz}g.v^ "a7BsL/dÍtttI{2 q:`ң84 aWQ8;%~M*+1㠮T)P٢@2(>B!581d^p*R/0|*5ޣ>(,ѐ#޻w;Nٝ<{X:`% >ſ{Ke&P48hZF*1~_- ,Rh : J GY8Za*ZH;T@]xTO #6$|@6R 4kK7Jۂ SܝB+J֩t@OL bH?g:QĴE]jQAQWpt3o"@'W`['}ȁ (S@s#Po[%ZF2N2ػTckN{Cl^13g=<3,H™Lڻv3P ђOlX6Ce% ^l_v U&[}K5TD90L٣T8inb=,[bX&*Ak6k h @W8ҿG{굯=#N|ZK^GөP jap$ԪaG -xJQhBu9*= hp9vIA;f&AF h-{k8h*/_= -U4 7 HvbG g9ݺ8㬤R@CWaRfSc%خW*\w<'9> 6&9gI'%{Bz /"h:E8 0G.kIT6u'E߷{cms#Be@36}G1k/c,+}U)=v:t/lIe<}B ΒL˩WFA & M.I'ڍC:ޗcUϱySEӠwB .}ڽu ~ٝơ#]I3kwwV{_ukmIo fI:l=#mk.$S΅fhd)J4Ȑ>|6UfLZ_arpmq:#XDkVT]ȟ^eZi Q ),3 ,+KۏKS]4gL| o!nn:וl $ݔgtM/Oz) -s亥tdCoB>5ʲ _mk-AMS癶zX)D`E61n%?d#$ptde"?r=_-?y!75PVr@ ̋5F& I EQ[y(y_!*h25h:)-BC 74ć#žZXciX:G#jnV÷%/ΨUHvB\|@l fc3KwKYҳNae9}{!ܭ5ׯ8oߧt-+FQlM/ֱT Vط9ch|K~LOOTL;f_?|XWv$ l䣬| @:M"-WUDQ>y'&ŚgOe ;ނFޡ  0uO?U.\A$Qq&=?g%Jd,7)R-ᤒ KeX0ݨ'Tu uז `YoRT0U;;2P\`O8"cLg)jn4D:АjP8d BM~DXS6&)ȝq8p$y-YG8H l>g XICOIKF0P)d",UR F"w|r1ژΔ=l)s,?dN0c|yz&ݼuڔW huTd/7<~OλoJ1a9; r噡ݱB,;)@^Ӧ"R+ԚeIn6&k{j[Tlus/Ϗ1y理"7^J-\(ɣI1؈a !پ^mUm4M]JjC~FZ!gWD$en߾,tL/:6:꺒iCSblLl-"xR͚hH^ߴ}i چ.o{Xd/d@K#AXjLy:h&wLn1G+,#M.q%\E28kxRtdxϿ)()Ms@Ε|JK8#JPdt5ӶTtKdFVyjD} %XIn' ϜZהHU)Ft]^ I9T*prҌVJi)Q-URvWga0qZF[~~--m_le;"Ec)tCkN'8Zߵ/hng)$b"3e9qPlo6w{)IB&yGG>{Nk4#YZ ~ ,"BμmlQXmxL3# }قϛ3qee,CU 8% P mv vcavuW `qnD'Q/q`i0=_Fk"޾̀/eܴcYYBп#-$&B1ymghlHE ,q~C]n *ن6xܕʯ8rqcv:@4O2uNFtejMW۠фT,A[&ٰﳱ!`c="z&o_vtq 5 LpP(sL&dyړ |hwb=1:ᠯ_\!pw ,~g@Nqʈkغ ~鱳 TFGݷ>kLQ,J *mГ~KZn -jz2qt|9#Sw5@K ;x_6N*l7L#6C5S.jU='FzU t{:s% }UC [Jiˑ?&0WZZhi(`ƹ z6*>۾@jPEI;~N^7_G~htk佫axT)6,]!+S,ئhET)B9x*8Os~ V)41kJ40R`x6¡:bHJCkHdd{La뮉 Ŧ6 BUV@̆,#ըU)3oa&ٙal_C _䐥ZTPju8U!߁I|rE%|l<$kΥ g6pV~/Ѽj^~}OCfb|!$O+k܆벬{3S6WekzӒdĂ1Mb_*jgPE:6IV!+ h0 ]€q|k9l1J"r_<Нs¤lj&_XQ,ުѠ76$,=N%TIY#]4辣!GfXLK &I8|\ZyώQJVJ7T-j|(+J 5|rYb(G31n@@t0fZAc2JLP QCrOץ`),=5h-ʲ*҈ ҼZkZiޡ.&TW9@ӀqJ,,S 6x>}f.*9>b2sPA e}P 'v¹~zBD ״iڤ80("|od.t̴p֛ZiBfhNsyofe@!$Ġ̩G` 11 $^7@ RQT!Tf{΍~{q77s[q=;^˗ט}+hm'[./jj%{ꖅ@Fҥ<+cl\aᏜ(nqH0)}vr=9۽+|,$w won/$ w-&/yR7ZLy72!ۈPX$d6e7f{]Sr/JK2b~dN$OК'+$XΞ{ 5'K{Գd]D>OSw.E?,ɆwoF^#/?pR٘i t=YI:4SFY[;֞9A<3#2gs I7;JtԬHQVcr>/s5Ɍ+ۇ^XŻ."&:ƴB:螭2sRgVkq֭2'DM ʼnxd}tE('5%U Qϲ4)~пw.5r5eg\p!޻Ѩ#E /rꆮMOיFi .{3>jҾx 6 ά߾}#BͮLDE"|v>3_ohMlj 4J+B` s*ݛZ yszv dA0{`__]޽wp(?+qG7r7NV~߸ϟ>IݰۨLنX@b$|eH2G&Jc|xՏ?};>ohϿWXa r,-ąCRTbQJ$8}60~˵Y!1  0\&ʕC ge7+H%H'8}KY]f,+f`xzAOQG_JB]Ĺg~s}F jD{?w[%9u6^홰>~.^[oV<,Ȥ8r/=?XDZRK`nHOMe~vk]y tdJ Ρ $М03 6U'33Xn|[wJx_]_dޛV[ ^TbyPbd,W7Dv8!zJfrK1@xI%~9r[ r϶,FĬ{wz~..1>+v49V^FK <fJ ;uR,E2:X?| Iw?+b5 ֥IZ,^>3qwN1yY4{uz{`Ʒ&JN(Olٱ^208RdI!^Km #ySɳe 1 $`!w Qup<|m"w{ϷY K3u5+6n.Uv=|uVKdT0+[1f4:s.|"4u͕;y/r;0fω7z>mvY_,׫˿9=q<mr?壽n/ʅ,wk/ɡ\3 q[eH=涯~b06CJKӳcnU]%l_v$88jű{l& vP]ϠQ$ADm}Rp5 Yi%^qlp8\3_$NX8-n_H* "9e|L:ΠfmLXucWWT@ϰs*%hv ):YÁ&e&EM 2=%:3wlx2{]?fػϟW="YQ5mn>kI֒<0HzvrNqغD(` YƝ]+3ET\ڜb̒FcD׊ǣz}vIMez2Pdɢ+$CqPn`?HwxjBVk`Ud]݂Hv\Gł3!ڶ `W;ğ~IGρ~{)n>]x.U޶ЙD۱@'n|ݛfLh03U=K7J?4 QHo쥶._{NzCljH!yo^w5Ix;ԑKEn(2n[kdtM,Pbk*++}UtsAEQo21?@}svAf+vH9tGco$D߸$+Kb+:C&YDAϛ& e!T|i_xJb5s _Xmc]DKɖ}J;6ZB6fj޻[IґhՀާ^%o:)Hf#uRnp%#,5;lIB&?cE MN1Z4KV->C09#/ܰ(t &i%/Lqhwf[Ÿ1Upm8TXlA~o gZβvv@ł@2DAem6J"nrQ6`qxFc-;bu21=t?N=vcpp}]ljݧ/%UQ rvnT`/ EϪ4}H*i\ !T v@C0Z7ZXD%a\NYϱ4;^#Aw9hkRYP VV)v]'u QV!@·-U5Vю& Sf߇ô26>C.N+̴$୬)!cLht@tTZc蝯e;`[1vIq|s#̙P<|3flBl\PYudݗ7uf8wer'*&vѹTD끌$0@la5&skv!n{ꍮ@vZ>i<1T ] U'zX(V C":^aϱ' #1vGb[]I5<ΞmzS$x AAz LgX=>ffx'Z`<1WhEcW^v=6L Aǟi5뀿X6=r8RCD΍.gl,,76:RqR'6 TE2dd=9[M9p_0HJJzYmvK,ؤxeH3X;>CPIiBqKĽlK0';~RE/]~qSw[IV%fᩐ#|;s,8O@?o-vuԉj- ai doSu4/;XGpBwgy?}Qi%c,Fј&`WNɆ%:o;e8SPsqɯT1;8``qSiKS1F ?uÊX}mHl6v[z ݃_V^8chR./NLϡE$mcY< ~WDgWW,# zfE `Gk5%BΖ6 .$m|Xv6l ـ%ȃaqW,k9d:EcߗX<Pl[DZVkw{-v_itzMxIbޝ$ݭ|KV*.Kci QdO['X踼Tz>K~oY+hLi\ZB O? 6[]B+2hc {AcՃA0Ʋ^Mnn5jR&4٣ #3s\X1מ L.s1K { XE]tAe`FPC` cwMő㜇7;:g4nxs& l=n$L(ޟ %k`TwV$s" O0[42Hx锲NΞz&Q7Ib{5r7[@dDoeEq0LߎJ~-c'0ljkNlǓ_BvmRcCMt}4MOF+3|x#ڹeXVR%b 4ϤX:w&q.J8ls[WXKl B`Ȭhvr>ڨMn ȣ脗/ZFQSؙB/ w4nBQVa@ɰS_{}YۍM~6:34e_Q.ˣYR8??a*d\)R9šM2ПzRYbnBIk'sfJÐz:NL]Cbzbz\l"{h1_PE3#d~J5m*(.qj</L%ZSRƻHxmvOcB"jjK4_<qgDΫVnԳnK#"}iwyΘL sU-%삁SGtJr 86vB!m,٩na4evr,q-Pbmx=۝ *)ћvBN-8":ilθGl|`- [hULp}7$IA6ᓚXJڷ-7: Pv_NXvfI`:5`jWYb92q4A(hr>rGuR`1)\<}̝?bhMӠoܗ/p[Ag]R:iН@ZAXhY*9JJ7nx LI=W&% 7ncVdKW5?>R w.n߿B8Յ{gI8Gr6mg%YW%jG;.MVʊt6*i7&A*J;Yb{,1PWVF,Je]ܘ33Mg MIxwnTןkb$LB:oV>;_}'x199qG?_$ό2i&ժCySwz9pO Sh5]q+#/UdY!Fuq}N` ͦ1q/rmtǣv52Irji/<֠Cgy&~LEG 4.caM^Vmr-C(ߟ෹m99`!k#uf[ hwdcl{VҞsק2Y$ÇDǜ4/ZixJ1pF}=:&^QОÔc* -9;?g:(Ѡ`F^}Xz0SC0c;Ce|՜&$GE)#Ÿ!$ދW2?ـ@0jA{JGP\Gv}EJ_ T>v\jXRՊuz\ZH]<"DNF8Ik-p$dp$>8;///ow[<=Ip(Q ݛnsD-΍L.'OYBhzFjS,z_[f)؍qt*PKs>fRBM|K_+rYuk %Gʄe߭f=3=Ozĉtp߲w^ɱQ* R  %f`#(f-h~xN{N+Ç.fC-hu>qVKi*ŧvda %}dūzzs ߦ>gХ÷&P ,zLT9F" 16TnmI ,l#D5 -Gv9.\3Ⴌ@Huj\{叼ȩ$'R/#8"i+ꌲ-i$[w_9Fk>$i0~F5qkK^WpP \^dL(sXwzqI |t';:h ZǪ2V6Xy\/S^\UX Z}EoFދ~FB/Nw$;$n8OwD]AЅ0Y5jq02;+wsT{BG߫28{{`N?n)r}~Ge]&&OZAGÌ6&Ip1ъb_!FUa$r7;rXo@_W;5uQIBU޺_bDPMlnzv* '[nHDI#gB]bNP_}و H@'1+WxHӰZl߿rd ٙO >v1%S5j7M%ˋ4ΐgi[玫;tMJU7YCdR ̀\5P8FmǘdFcYʭ0}P]p a#Hԫ3 vsvYkό9uGI>_Sdaz~jBz5XjC:vBLQwH `)A6P"k]3#V(q 42И F 4)]ߪoɳ n։5BVd$_!]}~ #KlcŢ5pݿ4F`U)IY .ǀ| |32Q$m;#? f.WJNý` hs"]0H,@~rOػO7w*cLG,N|=`=3Mkc`GX`}7#p)ym4`5TOj %!(\Hl 5bqpx#WroܹP_x~|Jgd#̪A6kDN*<0t+t.B1/N!h0v!q5Zx6*UYpWdlv0n2|Hٱ:(rqqxgg0NTכ=I9FWPCy.W}Py#e-^߾.Vx< G6ѱ yWd!¯ 0~>&٠:czLlO~f˗ aETf&jK&F*ӳ[d!ؙ_F=ky4\g =ϩ/h箥!$SxoS.Z -H&X遄Bx)"*ܙ2~mNtϭ~i8@H̍ ChBw)IلܶlVR9"u_ەݎ=484 ]ݻs>G)eD:ЏU6BPz"G :dbam};`gʔ/E $kQ %f%zxЯߺAޑ8gd&e5t;U08tt~¢FV] itd5;s}V5cUǓhx:)Fnvu!}%(gYk\KU;WRmL 9Fy^9%>GÁUmI;BIRE5VO._J&+[#IQ^S d,ci(+5aeAxAN\W*on5,wszb[0ȣ9Ĭ6UL!'VL2 ;j`8!F} kݓ@"QPҧfF0TכPzD/#mbOЍ~`bʚwa8MD;<=>2mހY;)UsNMh Gb[*us V4@)U/7U09јP26:1lM{~r; 8.$Y)d}99s']?~L%*+<c&3y 0㽑ALdmUݻG {`#@F?\]T:uQ GjQ$4 1W{%q{AnX*:vWקB"U=qgg<&$ԃ&Hxe<=0q {8vֺ@1&1C zfV!T7WZM`G1^1uAGbt ,OH81~gX4;=Mؖd]~WmxBXM/ ve//\ܳ 'g>A ^V>+fz <6w:n7=C kImoFa'ٛJ9y5ث^ *&I0^z߽aJ7{6NIgRLCnPIDPޑhU֙K7+qSg)P!]&4 EӠǒkQy@zu'JitT8f"C+UIêRJ!F0`,QEL\΁\2'=$Lӝ=5z=ΤTV)fav;/V 0Chy$,k4$F`ŹGǶ !IHqqyMIxuoE1n <Ց; P:\5pw\o^ߠveMn]Alqr/u!4!uh#؊&>gڕI!!yD$ժMdA EEk+&ᶜهx:h2H[H9ӮkL{uhH rv<{u:6S+N]Z rx67[2u6VӶׂ+0hpNArBrfuR_(|${kxQz~6n[=; .1BbANߟϥfͮəHmsKěYV:MSo2+Pk\PsoIn%Il9*͑]bHpҬ5LsGtr6k`<pZ2X[MCnӘ&`Tcq.OeM KSB6s#Dqڹ*[Akn)fq``VwJ0`-!Q u'c%!hjeRaLi:Z+{܏TPrtN'SzDKvQo,&FD ߨ2>990Jl{yyQӓAp O/jB Lxq ]oTm~BCDPk2BVBB OexPGdbgiJ^eh?P@>?9Tou '$.+ە-kZI|顐*Fۨ!~iB1|1t8 ?gǑhzrׯ^*=18+&wG:cŵ]8eibj>E^T`|geFwoh*iа/02.g'i]"v {Кh KW_;sܭЁ12~Dfs)z/t:fwÔP&r؂P7347IpU 1.>G sC(@ "BYy&hkH|- #;v$S)Se/21+g_{غ||*I\Uvd3}yv#Nː&E,w Q/^hU8ֆIg&NFSRYٺ7w٪#X8d7o $ ̇KH0%V\T\`R7ZRN˫3:&<<5H>'ñ@u2^M_]m'$^$O''C]ZI61 cG_%&9tht5G74+?%iC%bZ}]BQCA?w(C~- [ >WlS&;>Q*+j< 'MRm-<)hU2e_CL`+x6#, s;z }\ (u[3]Ww]@qI#]>X>7#^%i1T_>}fIo^4PCE0SCȼx˲SlhvՒN.~Y.B҃UFGQ^k^*PNn6Sx994ˑj65]+a'3pt'3P&3,lD˫\H8=g'G-Yv0YCsk :ag٢2j˿-do׶0f 0hH4tXrQR.a@S#j; d[NEluW; xc)$@hdzz!ң1;MjtV[v4ޚX$urH? 1wIW/ U3# z4u Ygj4\\LZo݅< ot/^Qޛ[hrNk4nK;;Q!k]4xR μba6f Z516?@$A+V*W%kŖA5JB._vb|g+0Q<%Yi:LLveM[}M1c{cz<1ȀkclܱMj<T]͵ύv(R:YK,WQHX RBHo%"01Krmk.[1%-AŌK6|kW`8suټ%Io4Q9=&P1c{7cKmXX|6EbLkPۆuNX"`Z} n|躽Q/̐H5f|3H t`9?`ZU*5j=~]MmAxd;\7*k'Fpm׾{ZSn,/sڂA/D1$^X5~^ӂ j5WIh5yME1bѡ@v~˸ѝ90G@`Xj7R;\>zQ䆱T.`-|9];#PLȠk0Lq49dܛ-ݞ p|,\,hd [ZY/&*F(R/0F/LЋђJ?,>Day{5t@#;6(IAUZ Ґ Ř1e1]!Z13sR|%ڋo8qYO rqԢ[L:-ql:FEό=YzHD]{tbvlW<*Eߟ\=^{O!p#dQ (9̺mgcאct o8 #.tziXu'7{JlȈZzD*Zy}#%}|FݶXrhQ'N]aVJ2J*Q.eYrvU'l dm~bgcKR@RsNrr,Ȳ_\/M7F9HSNݛo6VI "ֺVv~[Km5xYzP|"Vݰg!FL&H}|jXFtC0M]? ^eWeVVJv6C \GsJS[Z%bUe^MSg\xJA5!&lN䬢onCm1;KM8.[>p6Tڄ?x:^_IwO>8ժʈWCQ]!C>wKI8P*x"+ʥnp B˭a~L+-j]s_4@u`r2t&_u5qq}1I|~OT 6Ɉ<$b SݻKG4>7 8nz#ǃ?lB;=@AME<}ny}N"1Lr72>͛:t'l팼,s%~󣍀WfWS\M]Lۈ2Fc(P5H&aI(iJkO.U)gł.$BT?dh+޾JCxHNa]]L%!5'uWIHN1QGoП%V)9>a0wuvjQjij %N&})CQ]۶뎼+ߏ1 =[UקvBfU*3AO6&߈m>ڴdU. C/UA!XN0XBLff۴,rkvVwRS*5A_NZSzU@9Dqޏ06"v!J5Oٿ]N^b7>_{%n.ٻŌk>vU="ˉ7jq)/w̪G7g <+(YqKr1]|Ђ50yv)GUYK5/8-E,+:ILUj2hqCHb}V鈃䍺Я.R*lʯ6Rn0Ōd@&#X'WlrA t'J\Tc+۬'&|W't@+im^灄p{&UC̝2, U[>FFok_%oCF\, ۓى$#IV B`l6z}bj9Eg;\ zX.._Ĩ+yAZWFw˟'d˞4k_*b_l?䃎э3YoZVz˳Q6ŴN:?dm_~v c'H1xG'dj}np CT`\DŽDsvnEDCGHB.g]\ϗ:p Yʚ lXtxCB,0$}H̘pI hIˠx5aW{:0&t[l& G"v*S*O1Ra: 1Wz_?rpɧ B5u+Ӡ2g_ S Gs[g~[Θ7-`u!<.gJGvksZGWu<eZpE7<4"YGڊqNcۚ>!0.fwpBxݖ0hQ'c0!MZ_?ɏ閬EÌv}ΫvߒTU>Lq%AH8S1]elkvcSFPupExiݚԎ$ UpǠcFP:@CN`5$H}g{Yopm_ut#kln rJvoyCf}^3&l'&#Z4 8SI* vp;IV\K@y'?/AtFF-p{]# <qSO8aVoF *8~x8Os6@B-eٸe6*Ϟ8Xݹu'L^m 4V8u~r&r׸c''|(}0茄̉M]Oy{.yzh[s5)H+K2:#( `,nD#e09H||/EgbC3|{oj#g;Z>~"f"EhFX ;1 }%:z{*w 7ȱ< RW~I'c=kɘyGBw(Hak(%c yqonW%Вڍgicjl2I56X)M &cû^ޜOjB{bfc?pMX>6%vmꓮ  쯞΅"$?v=?pQ6>(eXf {dL#.]NчWgmg:X&Q  ٫c P}Zlrc`بÒHxnJ"n3_K2 [do~7dfvq5_,QV #x}nKaYel! 9mς*p&#V#)Nء?<˞fLđtvcmcCƚ11c=7V-%z)<Д|p#UDkK2PI/O&"x6+$WHIUv>WmD=4Ml⯜0`y ]1oF0uEOkR%İ{wW3ϻ'zsxzu~|!3 zj]@ynDb U\=ڇ(9MMRiX%9p|bV<*Y/?XcPU*`҈kziVhM]rNשTlGsB3HF-j0_BK9|@RY[t^x61rduzq"Y2D̼ j#+S7ơMΓ Wx-WrQ]N=كpu}¬@k:# cJo"89hB3tY<{97P\4]>Vewowsbr>lb=$ H&#H nY-`cYt0gANiQ?|E8fg- 9 Ğ=!ϛ!hڄڐ,PFKk\IPgĐt8^+xh*Ot{.5T1WA@6"$ 8\n: \WFA6_,1s]0kE_E z]Yb3}D{6*.S5'۾@}oc\(prjl H(4Mfc.y=T`gsQY ⶫP-zLRz]u>0=ꈋަn/$9dhRQ$f6c˅xM]"! 4+ 7 ߏ( (+ p4o*難Ѹ9eY_x4 ׳fx@4ZcVy9$|=^қ꺗qf׭ʜ_R}̐Lqű*t#VbCZg4\揷.=yQ "v$o?R5wb/\Eڮd沥K;PCݗ 1XNz5n}mew zK+k]mTEnE^f>mwnRRv'z%lgH ! Vui(Uw_cK* ښ2̐YG :GyynǞJ[;T^ |B'u\"8FrȜ;ys;,7OC2f%]tR#u=]ETpf]8VUzB5[k,pj%(@iݑVesp]2ŗԼIW6LJ'gظ`H, ºHt*ձOL !XIrmC,9|n'X[uf)GlNJ dA}[W%ëꕷMԥTɉcYYo[ة̈lZ +eyN ]kW I96)tgjͤ f%|Մ{{˷s kUJOoǀ3ЬT~ܿ@x`Q5;L &= g2i'bvRAK}9mDvÝܨESWSm@R#)CLYI4=whCV fSŪ+þ=9I`Zޠ[]Ou+gA,'&u Ƹz %alF̹W8Ikj{Hv"c5L1x#YHʘ$ĹUIW_@T|j E|fݣABlC!A1bNvůWatu rDGU::!dcL I%+=:\;$Xq+%U]ʟ\f:-RkIО&Ũ<*tЫN}=ts; CqWfБFKko0J{.w_oWYx@]ןo>v^6\ #Y՗MX׳)' 2BiR!8%ɽDLR!  !~|x'o; ҚU6HoĦ˙W\kPNBl{5 z.cD=DWy5d!Hkͨ[}$A! IrbHK c Q7љtFAA)3E b:U8OQQx׺&q/˖7 1]^@^h窕z3PiZE R:G,d!PLx6ܧ5 ,݆#Ү(ڞBUl.'&5R Z] 5}Q^DΖ2i62s.1@r`.\rG'@bd(#ERf0bz)Y ,lO^Po,?K V&K&?F'S"{oΓѩ̤F9~|ܡΉP˂ IHJ@h!$-D7ud[n!3`U?UN67$hS%o6SI/2kA*"yH[w,ƣ8Xm6FI@˾giGH|a!OeyX;6Jt]&o[S<%^##ł"EΜvZS{͛5ǂ]왝fr* *ĘfLu)ϕ#on/iZ,ZvsM,ٺH:~Zgx!A b^"x9[}CrrS\ ф9JOQt^VR@~O5:79X׏Gx~x|ʄ:>z@} hH^6m#=}܉7;,kCܹCɖ,9a'ΰр$H"<TNHOچ2%x6V Xme3:oېǼI,Ve'<*݇BHL?PhS(jsWQxeb ;qޜLMTm2i{ r&VT:cq^aa9:pߡ 1Kܩ!kyƄUNt)P{N-2~GQx=n#<-9Ɉ8tg#9:zfj:#>wzRdz dj=NONݵnk; 5Ps_}t Kq"!NI *JY7+vA{C2nVCUG*°Sn0:qVhv*FZ=,*=mU|a8nCb.uX輓)M=eucDf벋vb?' -J];FNI ;nߺBB?#ˋ+so%Q= -$$Q=5zw2O #Vn|>4zUuW5ȭj Do;exmeVT*mMHOR s[\[$߻_[K!X LkkFm+z­% 74iI8fG#LuU5J&M-+ϥWS°0cXr2l (s֖rtD| Q>2DՇBచeٸǖ U_Sh61-‘~=|Bm5PMwDl$K :HADzRKU>(vWV`B$t¼5O#>ʜV&oz>GɈ0lO'ԑk <Ѷ Q- y@X%[d*(_E>] a[ۙ^X@nT| LDY{:kiDյnM6W |su t/t&4+"Wr\raؽm|.Aq@} A :VWxF^r5kы7)hʹ?!- tBt5rtr&})(^y rC;kLJ~Lvrim:!&&  ϩ|RKՓ BYv!Fz˚ 7]WL;'HԏIp3# tgEmq' g(V`0L8X+EOe2nNɰuH]#x~e $Q.gmOo0CJB,|$GܬuwqnB ʊT-ZO2gTMAzӹ~&Y6y"2.Q_IYv.MirQ :82=R"F%.РQwdaO㚰nu}^6 a`}OL>1L݂A2}TsTfR- tT ֪q:  +ݞN? h3sEekUWQ I8$:`j+ ZheY6K>Ɏd ƘK s9DD}2&Fs+Bi4(%o4kh()ҊșIy1P"9 ;prɚY0 h ~ mB$A P[.Mpoj3n&(=I.sXI;8uj-ilX4]2pPnL#/'5BO=F-1I u[.ƩHV rKjdhCITMkE7'^`;kȏ iN-pwD*k3%L,ӉRhZ$sXDdf:MiHP$h'e)g0(Br'ZT'Ub#F ez\3hWi0!O eee긊_>^XۆZr;I p`Lbrou+ B-xƳjb-6+vM=H+_2aX8dT,!N#4P {O)r U7d_n;qtCl̋8p=6h\=U7DCG`ZLMn!$Yh3"mf'"@o/?{3y}cA)~nI8sv-?gy- J/Y fTMҼ%46˼vo' `s~ۃ[-p *b% sѓ# UZ1_-ƁL  hSE4dJ EgܛNn;)W\ZՂTcu@Wj{Bzqs2\=kF5{vfP˴A= /E;x*ؑWNYu~?MKQ@á0.(-^>>*o,7O@WkN0G?gy9;DC]Ģ;!Qy9b.V܋?īݣ9ѣ =MU;N{w|_$ @E5@ 7צm;eJ-ܳ}![fC6oJJ; z_hIlG{&;V{U=͎mOnӃ$mOiddMɋ#>禒́l;{;0΄q(A@INbFA޳/'y/ەwYI$poE'W=C#]lE:sw@C\{j*B"MtjTQ7kbPTW[>TcDւԇ\{bApUtxN-W -m 8vpTg"'$?:}-V!Ie!U\Tn"&ȷNf6V 4eZ ը(7JŊcOLy LR =}TL ,IkH(;NbPé"v1$әg4P4J1w!fcy {\g{D?gD3; 2ߺt)x=m$u=yd,O5y~Fj{FMT/9p#?~1ל@ =KC|q]]s-(0r ѽpk{81{/ExB9laW-y}no"RXWa;: @tNpإn+Tʪ| YpoǧU _n0u7Ñ%ʛIȁ3 e>|pHy lvB Dcr7rѐI* jt+cR䚼02jpû xډiȟQU%LczHZJqX"u&m9އtLҌ|w̬,L@b5qe6V(1-:Yv&]mD*[`@\4!U+Je"^:hhQz49Dwh &DbFa8znRbM\o6mϿJzƼVXSrNZ:4$> 2+;B IL;Uz-t)d~cŠ"eCQA:5)9X0iumjrW CRcUWJ /'^+UѼ\pa{?i}TlU$Q{L%9\MHp6*[n~ߑBG![ȳп$6$ $0|&ґY,r/;i+MODˊr?@@nz 'jj }&㧯YzS0_]^LOr.+ogw$ݸ*rx|A}gvSg7@` U7}`sD_<̥;96ntQ^( }˕ʾ!惷S5 ǧ')" arHJ{|"d4A W\m5X}xw6ݜ pRR;-$y}`44 'S e[,ën>&) @ pޠУܷuUע`ɇ-V~wpL( ,ڕh;!~T Oy_ȼA.zBDZ±Jcw߾z{r^;<-6#>#5Kڕ1+tKWfU,-"(ilZYhg!fA!E3${WI!Q$ڽ-7<{f]{X WnANQ0\4 ?wϟ -Dzg!N"3@Ga>/KMT\qI(wqcrf7F!wme~:d62RHZX1w@KY÷?$9lN#  R-l ލ 'dA'lpėvIeAt&l_N>Qq%@#5Xbw;YZs*`~jw^f<<~ l ;.h8$]Ts?X uVK/םy5W^sǮUʁ*:|60Y]Vˍ$KUIhZ`mz|ͦ'Ce 5.rp8 ':-'?Ӓ晌r/Z}!wԩ8[x-)6Z!F`izMϒ 65tIDy 7EK3d}who $ud `R*MLʖ8g-hHEK_rprG0넟6AYjr#69;'3EjJ٩ʠTl?|_Fw-)|):9GdVbI ލz̉~M4_;qѽҩٝ$,{#d |"k'y>3y'Ycƃ=qg?˾ꖜn2Y}꺓.=7s*'Dk>˺nZ3ZrQOS]S@EAs"{g8D fG7]KRdRٕ{q@&n qoϴ QXWowIû BY|O"%u IyZ&EIֻ&Y-Iq#a(=IH&H-1\hPT(W[<?[Y#79/}n%ټ)$"KEH[]nU{q JDNdžeJ&W!'}Q ՃD`9RJ'׸A+#'$^(2^ R` kb|7$$iٮkb7H!عmV| Йgl.q Je"ߗHҤwOU 7_p yvXR q g}C-~"/{g0 x+qP!nwLJHB R\4SY-ؠbgUhﰗJ1  8Hg_tiyvR, \)Y ̄*E`Of%8%`|\j&i{*oƝ͍2z#ײEksÕ 4#ųFXY& Bh O{G94 b1т@*-ڍ6C8˓[}c1%(}}C,w @R =ד^H/Gl\fgh1q]؍R=E@CJA|mVT9L]_'3R*{+~^|g<\Fg6PqId| R;mI?~ n"Ul{@dq`( ORxOR˓< kgZmΔPKS LLbz~ Kp/@os#HE8sT=N!D$ <6DfFTq@ޢ79DG5R#"cS%w}鯒$H =lիNpOHXWmÓ<_B/"wL6=H֟_^ȍ<GUx:!y}G9 &{ @HTz-"! M]@ٲV˛$T)ODq iUvt%: D;.>$ BFvVNsI+|l F#jײ\a]y.3&c) s8$2… U PU1D 4}M{E@PVJ=f+\*)Wk(FőXvIՅ.Ƒ=&opЁs˲T$ʂ AfFoo]^ł Dd=}~3$O_x#!g(Wᨴ ݁;$9W+е-%]1ʡۤy}& ź\*Opfdp>oȣE1s岃s$N^Y} Hh3&qHKPOt1Y猢q"x@|b` Ug%O|J$?1Y\MOIZEN/Զ)i \NÕ4_ 1t_KbXv~tg $Q>_W&7`a8T*6jee3!&Lo϶î$9[[K'ƀbl<G`nM*$U 5'$p<,w(#`)۾>`!%%g g+ T6vsAmZ=N}-:\a%&*>$l`Eg[h_}Z~&@ލ 1ypOITNX@Hb5G_38ҮdP-mg'Z9|-,N}|ޑ\wZ3F</8( r@<VElO$pz0vz_ jIQ !abl*4ZY A)k꘤U"ww3m}Iq46`.v˲<BAKܸ~%ƭ*tUz< 8gRN}EGÉu5Z?~A(eԖ &.TT{"WIF0WhY |A}yBv-- ˆm#"#}}؁.qX_=#gb)˗(2(|Vwz}yZRTï$"$<2(}g\ -j;&(1,]xx~a8а`8ÿ+Ӑ#yb*ߕí8L0p7I1Мdablw;ph'P|Z}p0S:hC厴]IL2<8xە*%;˹%V궥*NR%zVM9&˺("$&YRH*x)dp.q(5Q&,VIWʒg-] ǁR=)O2>%eBϗv@?t4 ,Z5o8r;/R BuΙN(;gգOٹGB,Met2C0&||5JC`Ln"_ZdP+ e}R{͓Y]2ڪ *vTÁ>/W\p/@bw0 s6 Q\K/ nlJ.99t_&AА+ጐC]]l<ܳ5emk\ZwF0O 4S91/u9v P`w/ ܨ*93~c( )!SW"r]joJ[{ ڢ3jl+G]Eyi7d=w٥.o\-MtJy)۽rέUpAk%I)9g̤Ak4j)$/CR6Փ%қ-F!e I~eӭ@}z7۔Fn,],JZ6>q .lEܝCa|+A1R-쨘<rБ$p$=T!&L8Dd'HT([P&-gޗASpUxvQh dKm㰋l{@}I!3n5Qa"$rۄc)#;Z̀Pe<.R-}{FP9u"m0fqK~EA5MVvIFU4\\6EjBxXܧvpndZ-ʢ$Jp5NrкFo"T*_MPu !C+mmRbI#_" ywS:,>CέK| i[H@Fw$%gư\4g$@CRT ͆@.m( \ X- &@8\%IE %6lY*D1"rI) r:l-"CYҴ1 &&G:X܈Mݪs&k&{uQ21=kڃdJ:aEYOy4.p-7gDi !Oh"rەJ pL "Q~LHpy bJ.dhy57|T>Nݔq@` yfւCt ଢ଼RGUcXL3; mDCFEJڽ/$23cEw |az(Tnu}DLRj1DWv6_dqY3H状_2hw]+%&.kuM]_XeALsULEh+Z&P"Z%,|9rb|qR5TF #Z?gtVOeDZtުAa!o4g֑]>;@ϪbrE$SN.g=T6&E%k"WI5B N8rA+4qNeʽsFGv@!\r@%es &sNa/"ɘ$.+|PI8*Es-G)O tLL[w,W,zBK\/|`G:KZi( @Pgpa%q^1؟{>؊.D+=MW\,=ӵC R$|j;*J6z$>l.~*_@+h73EL>/LV|fw6W %r P(TЯ2dyó83Lm3FDM*(j_;(M1UHS]Ð-SZ&ܦ:%~@ &ʌ-*5s& 5ulFn* aJV̏?JbNstQʪ8!XKTU$ Y$-b/ ?R89BCPP !g3H(1.^TxC)ug_`#}5.%/Ƭ7h&m-8HkN"e|cUxMW\'%M}qӽ5KbH*M'3k҇hJ8Odl6PgG2$H;U{u2LݽD2Qdip^ΚYk@VRj#S!W@&kRʄ8omLG$x6eSΙ$T̐?9oB>qΟmї@mܚ2rat N/&i)s V䀙?rt!"jk2-QC/I28k2Sg"CRg>ڸpn5Wv+;E$TX3a !gFu5J7)2E]GZFhXvf^H2IѥY&Vhwk]bG8,ӽ̲(M -F~_k޷k$U&*l?%"&>iRFK^:AgM:̲ Ȳ.j+&}ohX~L>ϐA:;3[uHb#}k+G=||[KN.7"75P~$(8k.6Z;6fh W$Qө`U̵UqQDMhē@o ebj]I(BP%72mkr,.RGPi:B09DU4Lz~D \5Uh΍aLT&3Q6FVY, E8r{UYDF.;@;&v1yz 7s@ޥ&-n m,Iޓ Dɛr"5cMyӤ٫m&z;FZGqB%ʭ[BeYG쇉*͑B N^B"I"6S`:Ei&vL}HyLro:$;*d[f=\#>}yQG\oD鋝z,x&f-Y<]h?5t+9Ub^,SG%v}(mu1ye-TUɧMG/ #1!mXfg^5-oXՉGf^r9hXb?^+x ''ʩ/kt*j#ݮ~w Ճn 峗'WI=-Zl ?5 6t1E|24DVcGq^S1HEgKV~骵9(նVM'{]B7ټh$<\]M1ÓH*Iu!>Z?Hn^~ނO )f"jN'Bs7YC34+#}!I): 0IXp z?G4%}K9Kgnvٺ 1nK9lT.U v7b8) ~/Wͱ#Rhm",.K+m|mPY|o\j >s E!8^{M@Iei|vUS֮6܍/+j!L=k>6C~bǭp0aqJMu۬FERzKSB Ϩ\erӷS |mƛY8hrG"k#P}JנNH& puIJCƪ7q6"?x4coC8j/8YǴ"D1Vplxi*%,6џ^p"HigT/%1%Qv0Vk X8pÙk.Tݤ7kP5I_(#dWoxђuegd 'IDATx}Uչ9 e H1 JP4 bb}k^ͻ>S^%^b VHgp(3a 3}Zk=@ stOeoM˶zeA/tc;Z}OOߏ|/ѶjסZsRGxݩ^^oh1hC2"\ug|@|mUTqkh}Xv!ՑHdZHEG['j M1=D@5l ZPٓԒ)]3 ڵ*=k./B R[nn+ NAmӮTUUɄe岷l5/s2p~԰q"%h/c@ Ew}cs,À$8nذa2Q}/eÆJYʅIDuf dŪ*onNk߾}e˖2vGϞȑʛo-_}8 wTH$?DT OGO1`-# )袋WeG+x)yHRByu*Ak #5+e֬rߓ{AYD<ǤmM@M6T! `,#׶qFY=A T*EV{.{F*ks8)m۶AΒ?\."~iٷo3s,0)K oB6xAmg8 )ziɕWMR65{nS%aX4mʄYt'$،LL$o޲ECٽG>dОDL^V&}ϝ[{R`ct|:=Z2hkRF[o˧| jFFtQ[@3v4 n#m{h^I:d3bya6e*E1J8T&a"sdGxfi 7Hv*<ٶ}̔tĞ=i]ƭ ϪAsߩ Io: \vEg&yǎ*y^h:8G:)0.s#ݸIcʪә́r#M4дiݺؽZu)?tOPǒ*8+jqC梋G7$>Ϭ&ȶxUwг8k͛5;SV\ -hB,Θ1󓾡4PT&M'LKG-[PWM9:J;zJvZٸi#(밂H%T o&;h\ saƓ;iC,;$:1lnXӦMʏW|f98DmB@C;g 2XAT '4I0xH\RhGv*NB>zJ샇#=z…A~xO!_Q/wdi\t&߱ ; {OV~"K_*a\CoyeU%i$'L,655ً Z&A0aEةdpm .uQT@驄F (޼i4+9mu*n j5w^ǃ fPF,˚|~˂! mTY(eذ2ԬNZ%p66Du -7nځД Y2ٸaC0aڶvȖ}P`(5QSGe$x4tѱT]U”SԴNǷpdH)Ku?uh4vqp<eli*B .@֔N!9 Me۷8i )y{U|#qm$) YjA"[ \~cSrGTN VZɏo`VX^jO?W;C^ \(v/D}XP4 R"T]d9<Ç:D 9"Ҩr.˗P+Ve4|⧏B)W'qW/WNlKJ͑;>p/J=m0LcHYz]?%97ͱhΝeea14WA5& Do+zR5j5k1`ALNV?g8AʺkOFra1ZҺMk:!S&עD оΰ91h~퓰mxbt±+͕6mHUqH|݆"i#] :{tDLDzxl_`X)knҭ[W P=6oXSs{Ђ ,FaʞpZZ?O$dת5:KE$&%26ܖ ok,7ɀư/c^*˖};4 /`ӴʹuG) y\ 8rq3΅*É(ү__7[ftb<.HGgGzSƍ/,~,yIVF؎- 2pb!݈ߦGbZ4/ht(p̰keB 9]X59]AZl)WVY ;/rɳ XY I$R!wClP r Qp <;w&hߝMjXwWb##|Z󤬌zGeРA ~4 ǡY1Cu`/QpY!3*KOa:Ȓ Rν٫#QO)13]J0Fmrt>DΣ.x?: èb٥sUYđ>+;KF%!#ÎpF!l8\އ&LК:;* ~޽!-VPhr09 &-[m3}pY"9 <`|*;(}URb?qGz zt@sDz|BTW [c)0Ec쥗AJ O qj b1g~a)L̒eC\ fk;0b^֧MHO(_):!v{n@!7/4YHAO8o^`ىߗ묿[*RI!&]k_GEBf;o4Ћ`/_~)e D^b 4fY霈}.$Ne+rhr-4ƁՋ q m /zP9gRp3+cAm<޴ȑ*POvD;m͋9޽{KKL8eKL4D٬ԥ %ĨH/dx}( !x3KǞ( mWԬH3^y¸i' ]Ж}Vnk dz_$tmKPfXȻ8>rfJh٪%@%o/ZDlTZm~z`xd]i~vТFJ,nvȑ#j3δM,>n]2z8Vm}gYG>E[h BϬUAyH&_9.@2YNh9ќ{Ơ.8]&ҭ{7Y:f h؍koټE1y`#>9&#GtxhL*7f> 17#(.=%λNjW 4mQ U x&X$jC|Q4 4u:yPDl"ŁjYQ+.* ~^I#ٷ Z,ȵbpMYYE m;˅C ,>ACudu( E'Ib(4mYA7lb+AnZߛFk+U3b=jշf& B%wtxd6֟ż+>P ⡼)#:7khP@{FZ"[S6~q4 (?0_;RU 9橑E1f}rTHu^t@ՂyA_UtI*K<ƹᬑe#WANLtr>N^(AjW. ~2Iʡq6gR@1m"Z;~ p^Ycl*L\ee|z8O,TE[qb54S-2Pm<ݭ Sk sOqrh}G ޲uQ,0UO;4[njrpn MmB.42֖WCi XRA~pU⹲2ެRY($ MMLZmsR+ea_ uD 6*' 'e^cSKo$ԈZ0g1Թу0+dj<2ph 1Y9pBuoxa9p1[P,9dŵW%14œ2*T6_A}d]1dI-ptp\F<-S=n=@C^'7by2cSuʹN eN/m@ɉ5 {'ꆮ(aUȳ~C 354ا5]G*8@WMFAh5A2#IKMoSSǝfVT*R@špnR6B;|- h5A2E7~hVm @O@_W^سg7He&g8Ꞃv!RWҚman Q^ծoKȕL:y2|sylMi8ѧ\r2VA3ࡃR[SDk3|PU~/-'K7jXCeٙjְМZΚhZG< aqb ,fJhjc|Wph.5ɖ7tU ,g9RQNeȮ _;h@^?%0LsJ|wQ{kVٺ|UMoV>X"ƠTŢO4!ur*rtT@wtAYܓDj9,qJ(TS&b.QgnNp>$pu΁ٹs'e3;3CpEő S ~bq ؙ |j]&ߥn*/y/4tu~oDG<&Yҁf0׭[_ ) rEDSf&.虐͛rA3CZOH8cc,u.B[wٳuHbR}џn=ijs5FNZbKB7(x%OF%pSz6eĬ2H/dhoR1gh P>`)=mF' v:G\6n%S3N){[n54!2mMJHć'Bf݈-ǽaZFԓd]]ӳ9o&|[<hee8oG&ךXjbfDd[˜n6nHM '+4)wAvp|hMD(|fOa8RkjY}e^ԧ@3iѢ [؈ɜ65D&[B4ٿjHmMM\<{s1k@&u2VFc Fs|?hh6Sۇ QIrAyWO޺uepIȲpRӔy'ĹHOW5 ⃘?P;yWr l镜Ðy1k{yq~kK,{+& }ϼ> (5 7i|ql ҁ-NneQpy+ф}{/7:ʬOidG2?Iv)Mf?P$(*2C%~,mǮ,Jq^bP=4IϜkU. SF U)ng,χ]Zɒ߇!Ss^<߹s*/+{G}l6Tڱ nC)t`^vXQc'SAXkKWW(G̒\v- VJ PX13sO557iPP,U'c_ijPJDZ8}Pꭚ1r[T` MŋbBgX40: ,kr8'ʛ`14uT1Z Nu{"f) hPR5#8އXĹ~ ݍu9`R(iHUP{}?.Cía ^0G{KSGg~hKugRn@g-钽AAZd xG;g}X`a85zrE^ кa^&M7DRh;$3);%$t%d:% .-pi:4a uAauE `_5+vɅ[i5RkI  Le'}jWWs,zOr=X2eyC'UA9U(j@rfc2ĂzJ-{ ǵFsK ޳:PWٔ5o<7  o咊XKm }2+ <.Rcqn+$5j$D&(jpSX~dYw6!_:'NZ2qFg3`xr1_^~VE|8zDՎ`,%hp1͋Yf,~q ܒ3\" Ȭ^Fwu!|UNWoB{KJbuV}2F19wm| ܊BMދ!'n4q [v,xq9|\?Warv"0z r7}7Hs>hRVKukNyS\R.wmەYӨnJ F<9r)e=;*pWV vQ;3V\\ >j܄,#}PQЪu+xy ( R]Ͱ9))?Бl"Wn{_ZK|N`Eײ?t,cAb&W<-ēojrQ1Q"vbƍkf5fMBMu'vdX'Phr[2Œk ƫz"kO׺d0 bL+hǍLӅ!U &ag˰8[1X U8*p32- zAN5^nROI"\;QNbSݹEB. Bg͖^{3ϔ=KUiClXP۟͝hU|,Zgӝ\TO;세/ki%dw}\PVYcEGNe, 2b#mQ-S.@z!Z ^ϗR}%R۵Ofe/D2пQ_u~Bz|:T6"[t٥b>Cr:%(Y'WM{ܵK 9XeXF:٠ÁxdP\ׁ3%;~mn];7{O6rʛOuZm)Ѡ)?^3@uιcPIN|4b`RgXLp-MZACEq(j}=ڙܝhyu7Y(k`3RqnH܇Gq2 k?0? >!(vus2z&~U8 ,TSޤN)`ѭ mq2lʭKv0&\KSmh1^PWC-4bm ld.>ZI62t,[LMҲ20`D51 k›"mڅVo2+YvB%aֺ,(鸗- Uv#t OUƌ1 C&?'Ƀރ/i1a<lݶMڿ<ݙL9 c$mEjbؘ /w46sx-P^f6A.S% /"*/HdeIhO|S!6?6JCR=͂iqtKQqj KP{n=9Fv;oV d9V[0 m'g0`U EHF. ct_Q!atuam"su?lպ_kjNu?/cA3IENDB`qml-box2d/examples/demolition/images/plate.png0000644000000000000000000001272312241175670016624 0ustar PNG  IHDRIc CiCCPICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/9%bKGD pHYs  tIME GSF0iTXtCommentFile written by Adobe Photoshop? 5.0ai IDATXý{UM#l >yIk $jH!i$\%!ш1aEY$zI LP- q`vQץqd{]9GU}-NcoR={8srk1x<Ԥ#hbAUBPLMUTQ5B"fFTKjf* LLT1 By)f S95gfb""x331o""fba"cRX9}Fӄq/y{W׿,@P5Cpxl]#/8kysN9wB&E7E "I)/E1E'q*a! q[Gj$IPsD$}Y&jH4$e&%%330gU!%ƥ,zdq1:qw7Gg9^ΐkfD"HY"叕ðĤ'#֛z3Q߹o ;htBd$qP8G{w 2v}ղɈ2_laFXڻ_CUyG3 Db`#kWy~ # Ηgǎ 0P(Ɩ-[rx`ر)\WW/^d̘1,_?3j(yΜ9î]p΍Ȅ$Ihii[TOO۶mL0K2}t 3UsN}.\K/2.& sۄ)k)6n1c}:Oǣ>J$tvvK+i/ .NXlƏ)7<QF1wrgΜ9L6Ǐ#"ê&㘍7eqFگFջT8q"===)f͚uDP`Df%'wn ̸_M3ϮOWI%j) *]ҳ> @cc#*ǎbȋ/ȶm~&yQUV\9>[ofٲe5zkr%DZG3CPcYUZIU&"޽{B*+V~kViJ;G"_5r;ҐÂ!k1?ZcTr!wue.kJLDUR*&ذVF=^}}}vi2e F*;~UJ3 99`$CC8A$B"D6xArڵ p=w:ÙzMrJ̵rD, &OifLTiH*?lνϔs✐$`` -w;@C B,IHBríT*ZG1uz}DTJH!)!!!QD"D(8!hUrb\6 Bc:a螙a/!q̈ȣ 0xD6'E|u NY 1Č3$"UB3G"_;ۓED"^0od$S.TIB $ !Ib*5AQ ql| ."bPTBbi4K!wisIENDB`qml-box2d/examples/demolition/images/brickwall.png0000644000000000000000000000207412241175670017467 0ustar PNG  IHDR@htEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp IDATx] a(Q4jƙ7ҩz&st>h*t%8BP> Ddpdg{V& i,pg /&nP>~0ۙX>Vj=+USn=*s6.B[m`Hjޭmy%7ۚĜ/;IENDB`qml-box2d/examples/demolition/images/woodenbox.png0000644000000000000000000000474012241175670017523 0ustar PNG  IHDR((/:tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp ev8TIDATxڼXv6@m⤉3.M紧=()R)zARCc٦ AqWdT(dqx6tgi$T}Q-YNR@1aI'mbI5:cL'E)=G8>RJ!2|˵x-D^ó0Xp55\b= 5x^'Ik{[j=:逖*LFnX9Q82ðM 9Áqw t X$4Yչ.:ͳE*rr@,Rd&C 4]EYOsE;-2$y{Bˡ΅o_}-Yd(CfOt 2DoP#TƄ:ځ.b?JK4>=IW@MPҠ4M8J= aT]5T'enEW5!{\jL,+ r{Cm=L˲Og@磢 Y.U+O~ QHAotIOf*3!D)3 c:~ CyO9u .,M,p3 =>Bw5jfQǪϾ.[t;S&y\To1Fk0%A gfmP" ~e?Sz!< άﺥRAK(;e}兞q/Z3Jd/xnEr^3#}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/examples/revolute/0000755000000000000000000000000012310072714013231 5ustar qml-box2d/examples/revolute/revolute.qml0000664000000000000000000000626112310072714015620 0ustar import QtQuick 2.0 import Box2D 1.1 Item { id: screen width: 800 height: 600 focus: true Keys.onPressed: onKeysPressed(event) function onKeysPressed(event) { if (event.key == Qt.Key_Left) { revolute.motorSpeed -= 10; } else if (event.key == Qt.Key_Right) { revolute.motorSpeed += 10 } } Text { anchors { right: parent.right top: parent.top left: parent.left } height: 40 horizontalAlignment: Text.AlignHCenter; text: "Left/Right buttons to control the speed, Mouse click to activate/deactivate motor" } // BOX2D WORLD World { id: world; anchors.fill: parent Wall { id: ground height: 20 anchors { left: parent.left; right: parent.right; top: parent.bottom } } Wall { id: ceiling height: 20 anchors { left: parent.left; right: parent.right; bottom: parent.top } } Wall { id: leftWall width: 20 anchors { right: parent.left; bottom: ground.top; top: ceiling.bottom } } Wall { id: rightWall width: 20 anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom } } Body { id: rod fixedRotation: false sleepingAllowed: false bodyType: Body.Dynamic x: 350 y: 300 - circleShape.radius width: 250 height: 40 fixtures: Box { anchors.fill: parent density: 1; friction: 1; restitution: 0.3; } Rectangle { color: "green" radius: 6 anchors.fill: parent } } Body { id: middle fixedRotation: true sleepingAllowed: false bodyType: Body.Static width: 40 height: width x: 400 y: 300 fixtures: Circle { id: circleShape radius: width / 2 anchors.fill: parent } Rectangle { id: itemShape radius: 180 width: parent.width height: parent.height color: "black" x: circleShape.x - circleShape.radius y: circleShape.y - circleShape.radius } } RevoluteJoint { id: revolute maxMotorTorque: 1000 motorSpeed: 0 enableMotor: false bodyA: middle bodyB: rod world: world localAnchorA: Qt.point(20,20) localAnchorB: Qt.point(40,20) } // Debug DebugDraw { id: debugDraw world: world anchors.fill: world opacity: 0.75 visible: false } } MouseArea { anchors.fill: parent onClicked: revolute.enableMotor = !revolute.enableMotor } } qml-box2d/examples/revolute/Wall.qml0000664000000000000000000000016312310072714014645 0ustar import QtQuick 2.0 import Box2D 1.1 Body { bodyType: Body.Static fixtures: Box { anchors.fill: parent } } qml-box2d/examples/rope/0000775000000000000000000000000012310117216012330 5ustar qml-box2d/examples/rope/main.qml0000664000000000000000000001052212310072714013772 0ustar import QtQuick 2.2 import Box2D 1.1 import QtQuick.Controls 1.1 Rectangle { width: 800 height: 600 Slider { id: lengthSlider x: 180 y: 50 width: 100 height: 50 maximumValue: 50 minimumValue: 20 value: 30 } Component { id: linkComponent Body { width: 20 height:20 sleepingAllowed: true bodyType: Body.Dynamic; property color color: "#EFEFEF" fixtures: Circle { radius: parent.width / 2 anchors.centerIn: parent density: 0.5 } Rectangle { radius: parent.width / 2 border.color: "blue" color: parent.color width: parent.width height: parent.height smooth: true } } } Component { id: jointComponent RopeJoint { localAnchorA: Qt.point(10,10) localAnchorB: Qt.point(10,10) maxLength: lengthSlider.value collideConnected: true } } World { id: world anchors.fill: parent onInitialized: { var prev = leftWall; for(var i = 60;i < 740;i += 20) { var newLink = linkComponent.createObject(world); newLink.color = "orange"; newLink.x = i; newLink.y = 100; var newJoint = jointComponent.createObject(world); if(i === 60) newJoint.localAnchorA = Qt.point(40,100); newJoint.world = world; newJoint.bodyA = prev; newJoint.bodyB = newLink; prev = newLink; } newJoint = jointComponent.createObject(world); newJoint.localAnchorB = Qt.point(0,100); newJoint.world = world; newJoint.bodyA = prev; newJoint.bodyB = rightWall; } Body { id: ground height: 40 bodyType: Body.Static anchors { left: parent.left right: parent.right bottom: parent.bottom } fixtures: Box { anchors.fill: parent friction: 1 density: 1 } Rectangle { anchors.fill: parent color: "#DEDEDE" } } Wall { id: topWall height: 40 anchors { left: parent.left right: parent.right top: parent.top } } Wall { id: leftWall width: 40 anchors { left: parent.left top: parent.top bottom: parent.bottom bottomMargin: 40 } } Wall { id: rightWall width: 40 anchors { right: parent.right top: parent.top bottom: parent.bottom bottomMargin: 40 } } Rectangle { id: debugButton x: 50 y: 50 width: 120 height: 30 Text { id: debugButtonText text: "Debug view: " + (debugDraw.visible ? "on" : "off") anchors.centerIn: parent } color: "#DEDEDE" border.color: "#999" radius: 5 MouseArea { anchors.fill: parent onClicked: { debugDraw.visible = !debugDraw.visible; debugButtonText.text = debugDraw.visible ? "Debug view: on" : "Debug view: off"; } } } DebugDraw { id: debugDraw anchors.fill: parent world: world opacity: 1 visible: false } Timer { id: ballsTimer interval: 500 running: true repeat: true onTriggered: { var newBox = linkComponent.createObject(world); newBox.x = 40 + (Math.random() * world.width - 80); newBox.y = 50; } } } } qml-box2d/examples/rope/Wall.qml0000664000000000000000000000060712310072714013750 0ustar import QtQuick 2.2 import Box2D 1.1 Body { bodyType: Body.Static signal beginContact (variant other) fixtures: Box { anchors.fill: parent friction: 1 density: 1 onBeginContact: { parent.beginContact(other) } } Image { source: "images/wall.jpg" fillMode: Image.Tile anchors.fill: parent } } qml-box2d/examples/rope/images/0000775000000000000000000000000012310072714013600 5ustar qml-box2d/examples/rope/images/wall.jpg0000664000000000000000000005271712310072714015255 0ustar JFIFHHExifMM*bj(1r2i ' 'Adobe Photoshop CS2 Windows2013:12:26 19:01:20((&(.pHHJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ FPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIM=((wall((nullboundsObjcRct1Top longLeftlongBtomlong(Rghtlong(slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong(Rghtlong(urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?8BIM8BIM8BIM ((xpJFIFHH Adobe_CMAdobed            (("?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?W֓}6nl;B}nq l';+i-p/2b.^56׏3jVoMumiī zuʹ}f;l~wݵG9:?%TtlN9fΎ\Ja~f9)'W7kg؎IS>}7 =ISfq V9. kVУ22m]{[c?FvJl~U`IoCu kF2}~vߗӈߚ w/*~omqW)1].`;4nWJ }c3P,5tڰ>W-l7xn%U`鱎?EkIiJZ]88*,6ZglI$WV__W..u8q4$FF+.;lx57*ldz~61Cz7!V\.-`p$ҟ@npw&R^~ޟ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM9http://ns.adobe.com/xap/1.0/ uuid:C4BF25CA036EE311B973BDD412D49CA6 uuid:C5BF25CA036EE311B973BDD412D49CA6 2013-12-26T18:59:29+11:00 2013-12-26T19:01:20+11:00 2013-12-26T19:01:20+11:00 Adobe Photoshop CS2 Windows image/jpeg 3 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;C35F3482A0B3BE42B9BC95F1E43C0D41 40 40 -1 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;B8B61DF93A5C6B158DC209D8D5872F88 Adobed@((     u!"1A2# QBa$3Rqb%C&4r 5'S6DTsEF7Gc(UVWdte)8fu*9:HIJXYZghijvwxyzm!1"AQ2aqB#Rb3 $Cr4%ScD&5T6Ed' sFtUeuV7)(GWf8vgwHXhx9IYiy*:JZjz ?,ӵeGrv=>Z6˟7Mqn 49 xSLB:xn&ѮeѦ^>#i߁JPcN[iU۬V;Ar!MUV:_H:}k槠~d}庩աYE-f&I) ck}+oūs*էҶ8ގOR_x?x5b 3;m̻68qծlъ*6aqgE|{ M|7o2B)Pui號k"Ck$ DgGd]5~-5魶G&dS t899 Sy-Z*5EX~%{ĕq>xI٧GrX?kbe{ '?*j7=t"e)TG3%0Z}fMOb۶/-VYMu+^WMŠM"hiN5/oq9r1RZx,omFvbp^Aܯ!>A 3עݲm/|B/Ȃ߂ : >%Izy-Yt DN$R*8SH>W٬yma  OG1i1_ йP@,?S& }e;o[ʯ13A1[+1=Vb\f:iEGOM-Y$٣7ζ]lq2sV=2IȔZǩt.v y TOO54<}M{j\m%TK[Y$thg UXRsZȑE{i(+@3FoK߄PI&4i+ؿ#[:W;c=e:f񬌈H[rvn;/'䠶CMlZ٥ph Y`9nmJWJ_8zܗOZw76c;rvNȡ,3XI+)~[/,= PW`KBJ-1,@~Gnn%P]F@j8L\{5P얣1iڅRt<0GEXezŸK{74;m\|4B%i_*gNn6,(/}:TA53)5hhxϝNU|?-4<\S`N{Ov^*wogCf2pNsRxP*"fg[K-7.ޯKCo$U K}+Ju {֒̑ 39Bgݽ~xx >1zo9Ჴ3FKrâvYUW$En/,o_}&)Q*P`'}(}|^V| I67caM?~O>dH>XI%NBZ@Qnku| q2"%, &j~έϽZ5ɷS25m.@Ezwgr6/{5>Geft2ch" JXdeW&n?T6r@)-y7*._' u@VFm='⎣wl׹کGV:8c: ^!7`H˘n7-i.h&& ~#GJ.Mc$P-֚k##ܛ_m^Tܛn>D,Ί:z yZ%g*jQOku6չEZccS_@ۛmyd3Sֆ$YWWuAdjy^0RV2VUVTT Ro-]D# 9ŧ^Yfvسj,MI'ԓR}z4جcT7KE. @8t.w]ٱ`: Q2ybAK%$-K2{`|{ҡ#;p®>]dwME6z+ipô"V9]UV\&o\a4ڼE&4ת!+ʏ8n;.m(-. @@4<\9cmYEoDJjV(/a*-E;h~:-=MF<ӥ\QHC2NI7knnnkymUUkJTT<~ސt;zmk^kc? ݮjTp>]} EUM0USA4uqbU,+U@R {"c hu - pAݶK7֭ސ>A:qml-box2d/box2dprismaticjoint.h0000664000000000000000000000706112310072714013723 0ustar /* * box2dprismaticjoint.h * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DPRISMATICJOINT_H #define BOX2DPRISMATICJOINT_H #include "box2djoint.h" #include class b2World; class b2PrismaticJoint; class b2PrismaticJointDef; class Box2DPrismaticJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float lowerTranslation READ lowerTranslation WRITE setLowerTranslation NOTIFY lowerTranslationChanged) Q_PROPERTY(float upperTranslation READ upperTranslation WRITE setUpperTranslation NOTIFY upperTranslationChanged) Q_PROPERTY(float maxMotorForce READ maxMotorForce WRITE setMaxMotorForce NOTIFY maxMotorForceChanged) Q_PROPERTY(float motorSpeed READ motorSpeed WRITE setMotorSpeed NOTIFY motorSpeedChanged) Q_PROPERTY(bool enableLimit READ enableLimit WRITE setEnableLimit NOTIFY enableLimitChanged) Q_PROPERTY(bool enableMotor READ enableMotor WRITE setEnableMotor NOTIFY enableMotorChanged) Q_PROPERTY(QPointF axis READ axis WRITE setAxis NOTIFY axisChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DPrismaticJoint(QObject *parent = 0); ~Box2DPrismaticJoint(); float lowerTranslation() const; void setLowerTranslation(float lowerTranslation); float upperTranslation() const; void setUpperTranslation(float upperTranslation); float maxMotorForce() const; void setMaxMotorForce(float maxMotorForce); float motorSpeed() const; void setMotorSpeed(float motorSpeed); bool enableLimit() const; void setEnableLimit(bool enableLimit); bool enableMotor() const; void setEnableMotor(bool enableMotor); QPointF axis() const; void setAxis(const QPointF &axis); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); Q_INVOKABLE float GetJointTranslation(); Q_INVOKABLE float GetJointSpeed(); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); signals: void lowerTranslationChanged(); void upperTranslationChanged(); void maxMotorForceChanged(); void motorSpeedChanged(); void enableLimitChanged(); void enableMotorChanged(); void axisChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2PrismaticJointDef mPrismaticJointDef; b2PrismaticJoint *mPrismaticJoint; bool anchorsAuto; }; #endif // BOX2DPRISMATICJOINT_H qml-box2d/box2d.pro0000664000000000000000000000250212310076017011307 0ustar TEMPLATE = lib CONFIG += plugin QT += quick TARGET = $$qtLibraryTarget(Box2D) TARGETPATH = Box2D MOC_DIR = .moc OBJECTS_DIR = .obj contains(QT_CONFIG, reduce_exports): CONFIG += hide_symbols API_VER = 1.1 INCLUDEPATH += . include(Box2D/box2d.pri) installPath = $$[QT_INSTALL_QML]/$$replace(TARGETPATH, \\., /).$$API_VER target.path = $$installPath qmldir.path = $$installPath qmldir.files += $$PWD/qmldir INSTALLS += target qmldir SOURCES += box2dplugin.cpp \ box2dworld.cpp \ box2dbody.cpp \ box2dfixture.cpp \ box2ddebugdraw.cpp \ box2djoint.cpp \ box2ddistancejoint.cpp \ box2dprismaticjoint.cpp \ box2drevolutejoint.cpp \ box2ddestructionlistener.cpp \ box2dmotorjoint.cpp \ box2dweldjoint.cpp \ box2dpulleyjoint.cpp \ box2dfrictionjoint.cpp \ box2dwheeljoint.cpp \ box2dmousejoint.cpp \ box2dgearjoint.cpp \ box2dropejoint.cpp HEADERS += \ box2dplugin.h \ box2dworld.h \ box2dbody.h \ box2dfixture.h \ box2ddebugdraw.h \ box2djoint.h \ box2ddistancejoint.h \ box2dprismaticjoint.h \ box2drevolutejoint.h \ box2ddestructionlistener.h \ box2dmotorjoint.h \ box2dweldjoint.h \ box2dpulleyjoint.h \ box2dfrictionjoint.h \ box2dwheeljoint.h \ box2dmousejoint.h \ box2dgearjoint.h \ box2dropejoint.h qml-box2d/box2ddebugdraw.h0000664000000000000000000000301412310072714012622 0ustar /* * box2ddebugdraw.h * Copyright (c) 2010 Thorbjørn Lindeijer * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DDEBUGDRAW_H #define BOX2DDEBUGDRAW_H #include #include class Box2DWorld; class Box2DDebugDraw : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(Box2DWorld *world READ world WRITE setWorld) public: explicit Box2DDebugDraw(QQuickItem *parent = 0); Box2DWorld *world() const { return mWorld; } void setWorld(Box2DWorld *world); void paint(QPainter *); private slots: void onWorldStepped(); private: Box2DWorld *mWorld; }; #endif // BOX2DDEBUGDRAW_H qml-box2d/.obj/0000755000000000000000000000000012310101160010362 5ustar qml-box2d/box2ddestructionlistener.cpp0000644000000000000000000000310012241175670015324 0ustar /* * box2ddestructionlistener.cpp * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Thorbjørn Lindeijer * * This file is part of the Box2D QML plugin. * * 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. */ #include "box2ddestructionlistener.h" #include "box2djoint.h" #include "box2dfixture.h" Box2DDestructionListener::Box2DDestructionListener(QObject *parent) : QObject(parent) { } void Box2DDestructionListener::SayGoodbye(b2Joint *joint) { if (joint->GetUserData()) { Box2DJoint *temp = toBox2DJoint(joint); temp->nullifyJoint(); delete temp; } } void Box2DDestructionListener::SayGoodbye(b2Fixture *fixture) { emit fixtureDestroyed(toBox2DFixture(fixture)); } qml-box2d/box2dweldjoint.cpp0000664000000000000000000001020312310076376013216 0ustar /* * box2dweldjoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dweldjoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DWeldJoint::Box2DWeldJoint(QObject *parent) : Box2DJoint(parent), mWeldJointDef(), mWeldJoint(0), anchorsAuto(true) { } Box2DWeldJoint::~Box2DWeldJoint() { cleanup(world()); } float Box2DWeldJoint::referenceAngle() const { return mWeldJointDef.referenceAngle; } void Box2DWeldJoint::setReferenceAngle(float referenceAngle) { float referenceAngleRad = referenceAngle * b2_pi / -180; if (qFuzzyCompare(mWeldJointDef.referenceAngle,referenceAngleRad)) return; mWeldJointDef.referenceAngle = referenceAngleRad; emit referenceAngleChanged(); } float Box2DWeldJoint::frequencyHz() const { return mWeldJointDef.frequencyHz; } void Box2DWeldJoint::setFrequencyHz(float frequencyHz) { if (qFuzzyCompare(mWeldJointDef.frequencyHz,frequencyHz)) return; mWeldJointDef.frequencyHz = frequencyHz; if (mWeldJoint) mWeldJoint->SetFrequency(frequencyHz); emit frequencyHzChanged(); } float Box2DWeldJoint::dampingRatio() const { return mWeldJointDef.dampingRatio; } void Box2DWeldJoint::setDampingRatio(float dampingRatio) { if (qFuzzyCompare(mWeldJointDef.dampingRatio,dampingRatio)) return; mWeldJointDef.dampingRatio = dampingRatio; if (mWeldJoint) mWeldJoint->SetDampingRatio(dampingRatio); emit dampingRatioChanged(); } QPointF Box2DWeldJoint::localAnchorA() const { return QPointF(mWeldJointDef.localAnchorA.x * scaleRatio, -mWeldJointDef.localAnchorA.y * scaleRatio); } void Box2DWeldJoint::setLocalAnchorA(const QPointF &localAnchorA) { mWeldJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio,-localAnchorA.y() / scaleRatio); anchorsAuto = false; emit localAnchorAChanged(); } QPointF Box2DWeldJoint::localAnchorB() const { return QPointF(mWeldJointDef.localAnchorB.x * scaleRatio, -mWeldJointDef.localAnchorB.y * scaleRatio); } void Box2DWeldJoint::setLocalAnchorB(const QPointF &localAnchorB) { mWeldJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio,-localAnchorB.y() / scaleRatio); anchorsAuto = false; emit localAnchorBChanged(); } void Box2DWeldJoint::nullifyJoint() { mWeldJoint = 0; } void Box2DWeldJoint::createJoint() { if(anchorsAuto) mWeldJointDef.Initialize(bodyA()->body(), bodyB()->body(),bodyA()->body()->GetWorldCenter()); else { mWeldJointDef.bodyA = bodyA()->body(); mWeldJointDef.bodyB = bodyB()->body(); } mWeldJointDef.collideConnected = collideConnected(); mWeldJoint = static_cast (world()->CreateJoint(&mWeldJointDef)); mWeldJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DWeldJoint::cleanup(b2World *world) { if(!world) { qWarning() << "WeldJoint: There is no world connected"; return; } if (mWeldJoint && bodyA() && bodyB()) { mWeldJoint->SetUserData(0); world->DestroyJoint(mWeldJoint); mWeldJoint = 0; } } b2Joint *Box2DWeldJoint::GetJoint() { return mWeldJoint; } qml-box2d/box2dwheeljoint.cpp0000664000000000000000000001517112310076376013400 0ustar /* * box2drevolutejoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dwheeljoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DWheelJoint::Box2DWheelJoint(QObject *parent) : Box2DJoint(parent), mWheelJointDef(), mWheelJoint(0), anchorsAuto(true) { } Box2DWheelJoint::~Box2DWheelJoint() { cleanup(world()); } float Box2DWheelJoint::dampingRatio() const { if(mWheelJoint) return mWheelJoint->GetSpringDampingRatio(); return mWheelJointDef.dampingRatio; } void Box2DWheelJoint::setDampingRatio(float _dampingRatio) { if(qFuzzyCompare(dampingRatio(),_dampingRatio)) return; if(mWheelJoint) mWheelJoint->SetSpringDampingRatio(_dampingRatio); mWheelJointDef.dampingRatio = _dampingRatio; emit dampingRatioChanged(); } float Box2DWheelJoint::frequencyHz() const { if(mWheelJoint) return mWheelJoint->GetSpringFrequencyHz(); return mWheelJointDef.frequencyHz; } void Box2DWheelJoint::setFrequencyHz(float _frequencyHz) { if(qFuzzyCompare(frequencyHz(),_frequencyHz)) return; if(mWheelJoint) mWheelJoint->SetSpringFrequencyHz(_frequencyHz); mWheelJointDef.frequencyHz = _frequencyHz; emit frequencyHzChanged(); } float Box2DWheelJoint::maxMotorTorque() const { if(mWheelJoint) return mWheelJoint->GetMaxMotorTorque(); return mWheelJointDef.maxMotorTorque; } void Box2DWheelJoint::setMaxMotorTorque(float _maxMotorTorque) { if (qFuzzyCompare(maxMotorTorque(),_maxMotorTorque)) return; mWheelJointDef.maxMotorTorque = _maxMotorTorque; if(mWheelJoint) mWheelJoint->SetMaxMotorTorque(_maxMotorTorque); emit maxMotorTorqueChanged(); } float Box2DWheelJoint::motorSpeed() const { if(mWheelJoint) return mWheelJoint->GetMotorSpeed() * b2_pi / 180; return -mWheelJointDef.motorSpeed * b2_pi / 180; } void Box2DWheelJoint::setMotorSpeed(float _motorSpeed) { float motorSpeedRad = _motorSpeed * b2_pi / -180; if (qFuzzyCompare(motorSpeed(),motorSpeedRad)) return; mWheelJointDef.motorSpeed = motorSpeedRad; if (mWheelJoint) mWheelJoint->SetMotorSpeed(motorSpeedRad); emit motorSpeedChanged(); } bool Box2DWheelJoint::enableMotor() const { if(mWheelJoint) return mWheelJoint->IsMotorEnabled(); return mWheelJointDef.enableMotor; } void Box2DWheelJoint::setEnableMotor(bool _enableMotor) { if (enableMotor() == _enableMotor) return; mWheelJointDef.enableMotor = _enableMotor; if (mWheelJoint) mWheelJoint->EnableMotor(_enableMotor); emit enableMotorChanged(); } QPointF Box2DWheelJoint::localAnchorA() const { return QPointF(mWheelJointDef.localAnchorA.x * scaleRatio, mWheelJointDef.localAnchorA.y * scaleRatio); } void Box2DWheelJoint::setLocalAnchorA(const QPointF &localAnchorA) { mWheelJointDef.localAnchorA = b2Vec2(localAnchorA.x() / scaleRatio, -localAnchorA.y() / scaleRatio); anchorsAuto = false; emit localAnchorAChanged(); } QPointF Box2DWheelJoint::localAnchorB() const { return QPointF(mWheelJointDef.localAnchorB.x * scaleRatio, mWheelJointDef.localAnchorB.y * scaleRatio); } void Box2DWheelJoint::setLocalAnchorB(const QPointF &localAnchorB) { mWheelJointDef.localAnchorB = b2Vec2(localAnchorB.x() / scaleRatio, -localAnchorB.y() / scaleRatio); anchorsAuto = false; emit localAnchorBChanged(); } QPointF Box2DWheelJoint::localAxisA() const { return QPointF(mWheelJointDef.localAxisA.x * scaleRatio, mWheelJointDef.localAxisA.y * scaleRatio); } void Box2DWheelJoint::setLocalAxisA(const QPointF &localAxisA) { mWheelJointDef.localAnchorB = b2Vec2(localAxisA.x() / scaleRatio, -localAxisA.y() / scaleRatio); anchorsAuto = false; emit localAxisAChanged(); } void Box2DWheelJoint::nullifyJoint() { mWheelJoint = 0; } void Box2DWheelJoint::createJoint() { if(anchorsAuto) mWheelJointDef.Initialize(bodyA()->body(), bodyB()->body(), bodyA()->body()->GetWorldCenter(), mWheelJointDef.localAxisA); else { mWheelJointDef.bodyA = bodyA()->body(); mWheelJointDef.bodyB = bodyB()->body(); } mWheelJointDef.collideConnected = collideConnected(); mWheelJoint = static_cast(world()->CreateJoint(&mWheelJointDef)); mWheelJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DWheelJoint::cleanup(b2World *world) { if(!world) { qWarning() << "WheelJoint: There is no world connected"; return; } if (mWheelJoint && bodyA() && bodyB()) { mWheelJoint->SetUserData(0); world->DestroyJoint(mWheelJoint); mWheelJoint = 0; } } b2Joint *Box2DWheelJoint::GetJoint() { return mWheelJoint; } float Box2DWheelJoint::GetJointTranslation() const { if(mWheelJoint) return mWheelJoint->GetJointTranslation() * scaleRatio; return 0; } float Box2DWheelJoint::GetJointSpeed() const { if(mWheelJoint) return mWheelJoint->GetJointSpeed() * scaleRatio; return 0; } QPointF Box2DWheelJoint::GetReactionForce(float32 inv_dt) const { if(mWheelJoint) { b2Vec2 point = mWheelJoint->GetReactionForce(inv_dt); return QPointF(point.x * scaleRatio,point.y * scaleRatio); } return QPointF(); } float Box2DWheelJoint::GetReactionTorque(float32 inv_dt) const { if(mWheelJoint) return mWheelJoint->GetReactionTorque(inv_dt); return 0.0f; } qml-box2d/box2drevolutejoint.h0000664000000000000000000000654012310072714013576 0ustar /* * box2drevolutejoint.h * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #ifndef BOX2DREVOLUTEJOINT_H #define BOX2DREVOLUTEJOINT_H #include "box2djoint.h" #include class b2World; class b2RevoluteJoint; class b2RevoluteJointDef; class Box2DRevoluteJoint : public Box2DJoint { Q_OBJECT Q_PROPERTY(float lowerAngle READ lowerAngle WRITE setLowerAngle NOTIFY lowerAngleChanged) Q_PROPERTY(float upperAngle READ upperAngle WRITE setUpperAngle NOTIFY upperAngleChanged) Q_PROPERTY(float maxMotorTorque READ maxMotorTorque WRITE setMaxMotorTorque NOTIFY maxMotorTorqueChanged) Q_PROPERTY(float motorSpeed READ motorSpeed WRITE setMotorSpeed NOTIFY motorSpeedChanged) Q_PROPERTY(bool enableLimit READ enableLimit WRITE setEnableLimit NOTIFY enableLimitChanged) Q_PROPERTY(bool enableMotor READ enableMotor WRITE setEnableMotor NOTIFY enableMotorChanged) Q_PROPERTY(QPointF localAnchorA READ localAnchorA WRITE setLocalAnchorA NOTIFY localAnchorAChanged) Q_PROPERTY(QPointF localAnchorB READ localAnchorB WRITE setLocalAnchorB NOTIFY localAnchorBChanged) public: explicit Box2DRevoluteJoint(QObject *parent = 0); ~Box2DRevoluteJoint(); float lowerAngle() const; void setLowerAngle(float lowerAngle); float upperAngle() const; void setUpperAngle(float upperAngle); float maxMotorTorque() const; void setMaxMotorTorque(float maxMotorTorque); float motorSpeed() const; void setMotorSpeed(float motorSpeed); bool enableLimit() const; void setEnableLimit(bool enableLimit); bool enableMotor() const; void setEnableMotor(bool enableMotor); QPointF localAnchorA() const; void setLocalAnchorA(const QPointF &localAnchorA); QPointF localAnchorB() const; void setLocalAnchorB(const QPointF &localAnchorB); void nullifyJoint(); void createJoint(); void cleanup(b2World *world); b2Joint * GetJoint(); Q_INVOKABLE float getJointAngle(); Q_INVOKABLE float getJointSpeed(); signals: void lowerAngleChanged(); void upperAngleChanged(); void maxMotorTorqueChanged(); void motorSpeedChanged(); void enableLimitChanged(); void enableMotorChanged(); void localAnchorAChanged(); void localAnchorBChanged(); private: b2RevoluteJointDef mRevoluteJointDef; b2RevoluteJoint *mRevoluteJoint; bool anchorsAuto; }; #endif // BOX2DREVOLUTEJOINT_H qml-box2d/box2dmotorjoint.cpp0000664000000000000000000001022512310076376013427 0ustar /* * box2dmotorjoint.cpp * Copyright (c) 2011 Joonas Erkinheimo * Copyright (c) 2011 Markus Kivioja * * This file is part of the Box2D QML plugin. * * 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. */ #include #include "box2dmotorjoint.h" #include "box2dworld.h" #include "box2dbody.h" Box2DMotorJoint::Box2DMotorJoint(QObject *parent) : Box2DJoint(parent), mMotorJointDef(), mMotorJoint(0) { } Box2DMotorJoint::~Box2DMotorJoint() { cleanup(world()); } QPointF Box2DMotorJoint::linearOffset() const { return QPointF(mMotorJointDef.linearOffset.x * scaleRatio,mMotorJointDef.linearOffset.y * scaleRatio); } void Box2DMotorJoint::setLinearOffset(const QPointF &linearOffset) { if(this->linearOffset() == linearOffset) return; mMotorJointDef.linearOffset = b2Vec2(linearOffset.x() / scaleRatio,-linearOffset.y() / scaleRatio); if(mMotorJoint) mMotorJoint->SetLinearOffset(mMotorJointDef.linearOffset); emit linearOffsetChanged(); } float Box2DMotorJoint::angularOffset() const { return mMotorJointDef.angularOffset * 180 / b2_pi; } void Box2DMotorJoint::setAngularOffset(const float angularOffset) { float angularOffsetRad = angularOffset * ( b2_pi / 180); if(mMotorJointDef.angularOffset == angularOffsetRad) return; mMotorJointDef.angularOffset = angularOffsetRad; if(mMotorJoint) mMotorJoint->SetAngularOffset(angularOffsetRad); emit angularOffsetChanged(); } float Box2DMotorJoint::maxForce() const { return mMotorJointDef.maxForce; } void Box2DMotorJoint::setMaxForce(const float maxForce) { if(mMotorJointDef.maxForce == maxForce) return; mMotorJointDef.maxForce = maxForce; if(mMotorJoint) mMotorJoint->SetMaxForce(maxForce); emit maxForceChanged(); } float Box2DMotorJoint::maxTorque() const { return mMotorJointDef.maxTorque; } void Box2DMotorJoint::setMaxTorque(const float maxTorque) { if(mMotorJointDef.maxTorque == maxTorque) return; mMotorJointDef.maxTorque = maxTorque; if(mMotorJoint) mMotorJoint->SetMaxTorque(maxTorque); emit maxTorqueChanged(); } float Box2DMotorJoint::correctionFactor() const { return mMotorJointDef.correctionFactor; } void Box2DMotorJoint::setCorrectionFactor(const float correctionFactor) { if(mMotorJointDef.correctionFactor == correctionFactor) return; mMotorJointDef.correctionFactor = correctionFactor; if(mMotorJoint) mMotorJoint->SetCorrectionFactor(correctionFactor); emit correctionFactorChanged(); } void Box2DMotorJoint::nullifyJoint() { mMotorJoint = 0; } void Box2DMotorJoint::createJoint() { mMotorJointDef.Initialize(bodyA()->body(),bodyB()->body()); mMotorJointDef.collideConnected = collideConnected(); mMotorJoint = static_cast( world()->CreateJoint(&mMotorJointDef)); mMotorJoint->SetUserData(this); mInitializePending = false; emit created(); } void Box2DMotorJoint::cleanup(b2World *world) { if(!world) { qWarning() << "MotorJoint: There is no world connected"; return; } if (mMotorJoint && bodyA() && bodyB()) { mMotorJoint->SetUserData(0); world->DestroyJoint(mMotorJoint); mMotorJoint = 0; } } b2Joint *Box2DMotorJoint::GetJoint() { return mMotorJoint; }