# Contact points confuses me

## Recommended Posts

Finalspace    1147
I am trying to understand how the contact generation works, so i have disassembled box2d lite and visualized the contacts, normals and the clipping planes.

From my understanding of contact point generation it goes like this:

- Find the axis of minimum penetration either on A or B
- Find the reference face by axis of minimum penetration (reference face is always on A)
- Find the incident face (negative axis of minimum penetration)
- Clip incident face against reference face side planes
- Keep points which are behind the reference face plane

Which bugs me a lot, when the minimum penetration axis is found on B then the contact points are sitting on B - not A.
I always though that contact points should be consistent and the contact points does always sit on A but can be projected back to B using (point + normal * distance) when needed.

Image contacts sits on B: (minimum penentration axis is found on B)

Image contacts sits on A (minimum penentration axis is found on A):

This really confuses me, so i have some questions:

- What are proper contact points? When sits there on A and when sits there on B
- Why does box2d lite works with just one contact point (rA and rB is just rA = point - posA and rB = point - posB)?
- Why does box2d lite use two clipping operations?
- What does the following code do? (I know that it determines the face, but what is relativeTol and absolutTol)?
const float relativeTol = 0.95f;
const float absoluteTol = 0.01f;

if (faceA.y > relativeTol * separation + absoluteTol * hA.y)
{
axis = FACE_A_Y;
separation = faceA.y;
normal = dA.y > 0.0f ? RotA.col2 : -RotA.col2;
}

Can you guys shed light into my darkness?

For completeness i attached the modified box2d lite source - for contact visualization.

Thanks,
Final
Edited by Finalspace

##### Share on other sites
Randy Gaul    2762

Yes, you're right in that the points can lay on either A or B. Which one depends on your convention. Erin Catto decided that points are to lay on the axis of minimum separation by convention. This often makes for the most stable configurations for a variety of reasons.

There is a downside. What if the points lay upon A in one frame, and the next frame lay upon B? This can happen when two boxes lay at (nearly) rest on one another. After each integration step the position of the boxes will move ever so slightly, and even if there's no visual difference the axis of minimum penetration can jump from one box to another.

Those lines you highlighted from Box2D Lite are applying an artificial bias to prefer one axis on one shape, compared to another axis on another shape. Christer Ericson has a good article on his website talking about absolute and relative error tolerances. This helps prevents your features from flip-flopping around when there isn't much movement of the rigid bodies. This helps with the term "frame coherency", which I'm sure you're familiar with, and allows contacts to exist for longer periods of time -- that means contacts that live longer converge to appropriate solutions longer.

• "Why does box2d lite works with just one contact point", the constraint solver solves one contact constraint at a time. If there's more than one point of contact it just solves one of them (doesn't matter which in box2d Lite) and then the other. rA and rB are radius vectors from center of mass of A and B to the point of contact.
• "Why does box2d lite use two clipping operations?" Why not? It gets good points to represent points of contact, is really simple to implement, and efficient.
Edited by Randy Gaul

##### Share on other sites
Dirk Gregorius    2757

Contact point creation is an art. You want stable contact points which don't create artificial torques and give the correct dynamic response. For stability you want the contact points to be coherent between frames. Ideally the contact point have a very consistent application point so that the torques are stable and the solver can balance them. If the witness features would change every frame you potentially can get very different contact points. So you favor one face over the other. The line your are quoting doesn't use a direct floating point comparison, but asks if the face is significantly better so that it justifies the potential feature flip. That is all. The paper Randy is refering to can be found here:

http://realtimecollisiondetection.net/pubs/Tolerances/

Why does box2d lite use two clipping operations?

A face in 2D has two side planes. You need to clip against both side planes since otherwise contact points can be outside of the body. In 3D you clip against all side planes. Which is an arbitrary number of planes.

A game might have other requirements than the physics engine and maybe assumes that the contact points are always on the surface of either body. You can translate the contact points in such a case before reporting them.

I gave a talk on contact creation this year. Maybe it gives you some ideas. Note that the suggested solutions are based on my experience over the years what works best.

http://www.valvesoftware.com/company/publications.html

Edited by Dirk Gregorius

##### Share on other sites
Dirk Gregorius    2757

The reference face is not always on A! It is defined by the face that realizes the axis of minimum penetration. The contact solver solves:

dC/dt = ( v2 + w2 x r2 - v1 - w1 x r1 ) * n

It assumes that the contact normal is pointing away from body 1. So dC/dt computes the relative velocity as seen from body 1. If it is larger zero (that means in the direction of the normal) the bodies are separating. They are approaching/penetrating otherwise. So you need to make sure that your contact normal is properly oriented to work correctly with the solver.

Edited by Dirk Gregorius

##### Share on other sites
Finalspace    1147

The reference face is not always on A! It is defined by the face that realizes the axis of minimum penetration. The contact solver solves:

dC/dt = ( v2 + w2 x r2 - v1 - w1 x r1 ) * n

It assumes that the contact normal is pointing away from body 1. So dC/dt computes the relative velocity as seen from body 1. If it is larger zero (that means in the direction of the normal) the bodies are separating. They are approaching/penetrating otherwise. So you need to make sure that your contact normal is properly oriented to work correctly with the solver.

But its better for coherence to project the point back to A when the reference face is on B, right?

Also i have read your presentation / talk about contact creation - really nice. Good work ;)

The only thing which is left - how do i prevent feature flips in SAT? How can i add weighting in SAT to prefer one axis over another?

So i can finally implement a robust contact generator for polygons in 2D ;-)

Edited by Finalspace

##### Share on other sites
Dirk Gregorius    2757

You query the face directions on each polygon:

float s1 = QueryFaceDirection( pPolygon1, pPolygon2 );
if ( s1 > 0 ) return SEPARATED;

float s2 = QueryFaceDirection( pPolygon2, pPolygon1 );
if ( s2 > 0 ) return SEPARATED;

At this point point both s1 and s2 are less than zero! We could now compare like this:

// ... no separating axis found, the polygons are overlapping
if ( s1 < s2 )
CreateContact( pOutManifold, pPolygon1, pPolygon2 ); // s1 is less than s2 -> create manifold with reference face on polygon1
else
CreateContact( pOutManifold, pPolygon2, pPolygon1 ); // s2 is less than s1 -> create manifold with reference face on polygon2

The evil case is if s1 is about the same as s2 (e.g. s1 ~= s2). Due to floating point issues features might flip and this will break coherence. So instead of comparing the two floating point values directly we 'massage' them a bit.

float kRelTol = 0.98f;
float kAbsTol = 0.005f;

if ( s1 < kRelTol * s2 + kAbsTol )
CreateContact( pOutManifold, pPolygon1, pPolygon2 ); // s1 is less than weakened s2 -> create manifold with reference face on polygon1
else
CreateContact( pOutManifold, pPolygon2, pPolygon1 ); // s2 is still less than s1 -> create manifold with reference face on polygon2

Imagine s1 == s2 == -1. By multiplying s2 with a value less than zero and and adding a number we shift it to the right (making it larger). We kind of weaken s2 forcefully for our comparison now and only if s2 is still less than s1 we create a contact on polygon 2. You can think of this as essentially three cases:

1) s1 < s2: Nothing happens and we create a contact point on polygon 1

2) s1 ~ s2: Until s2 becomes significantly less than s2 we still create a contact on polygon 1

3) s1 >> s2: s2 is now significantly less s1 and we create a contact on polygon 2

The key to understand these things are examples. So maybe try some numbers and see what happens! E.g. imagine the case where s2 becomes positive and that this still is working!

HTH,

-Dirk

Edited by Dirk Gregorius

##### Share on other sites
Finalspace    1147

Oh yeah i got much better results now after i rewritten the poly vs poly contact generator ;-) Thanks for the tips!

Also i applied that weighting we was talking about and it works, but only when i do in in the opposite way -> comparing to positive against negative. I want to use that face which has the smallest penetration - not the greatest penetration.

if ( s1 < kRelTol * s2 + kAbsTol ) ...

But its still not correct, the friction force somehow moves the boxes along the perpendicular - like a conveyor belt... just a little bit when a smaller box falls on a bigger one, or really noticable when its the opposide - larger box falls on top of a small one.

Maybe i made some mistakes here? I dont see any errors at all (Keep in mind that the contact.distance is negative - not positive - so the clamping is a bit different):

@Override
public void solveVelocities(float dt, Arbiter[] arbiters, int numArbiters, int iterations) {
for (int iteration = 0; iteration < iterations; iteration++) {
for (int arbiterIndex = 0; arbiterIndex < numArbiters; arbiterIndex++) {
Arbiter arbiter = arbiters[arbiterIndex];
Body bodyA = arbiter.bodyA;
Body bodyB = arbiter.bodyB;
for (int contactIndex = 0; contactIndex < arbiter.numContacts; contactIndex++) {
Contact contact = arbiter.contacts[contactIndex];
Vec2f normal = contact.normal;
Vec2f vA = bodyA.vel;
Vec2f vB = bodyB.vel;
Vec2f vAB = new Vec2f();

// Relative velocity on contact = vB + cross(wB, rB) - vA - cross(wA, rA);
vAB.sub(vA).sub(Vec2f.cross(bodyA.angularVel, contact.rA));

// Normal impulse
float projRelVel = vAB.dot(normal);
float bias = BAUMGARTE / dt * Math.min(contact.distance + PhysicsEngine.MIN_PENETRATION_DISTANCE, 0f);
float normalImpulse = (projRelVel + bias) * contact.normalMass;
float newNormalImpulse = Math.min(contact.normalImpulse + normalImpulse, 0.0f);
normalImpulse = newNormalImpulse - contact.normalImpulse;
contact.normalImpulse = newNormalImpulse;
Vec2f impulseN = new Vec2f(normal).multScalar(normalImpulse);
bodyA.applyImpulse(impulseN, contact.rA);
bodyB.applyImpulse(impulseN.multScalar(-1f), contact.rB);

// 2nd. Relative velocity on contact = vB + cross(wB, rB) - vA - cross(wA, rA);
vAB.sub(vA).sub(Vec2f.cross(bodyA.angularVel, contact.rA));

// Tangent impulse
final float maxFriction = arbiter.friction * contact.normalImpulse;
Vec2f tangent = Vec2f.cross(normal, 1.0f);
float projTangentVel = vAB.dot(tangent);
float tangentImpulse = projTangentVel * contact.tangentMass;
float newTangentImpulse = Scalar.clamp(contact.tangentImpulse + tangentImpulse, maxFriction, -maxFriction);
tangentImpulse = newTangentImpulse - contact.tangentImpulse;
contact.tangentImpulse = newTangentImpulse;
Vec2f impulseT = new Vec2f(tangent).multScalar(tangentImpulse);
bodyA.applyImpulse(impulseT, contact.rA);
bodyB.applyImpulse(impulseT.multScalar(-1f), contact.rB);
}
}
}
}
Edited by Finalspace

##### Share on other sites
Dirk Gregorius    2757

You need to take the deepest penetration since otherwise you will need resolve it correctly. What you describe sounds like a bug which you need to debug. Disable stabilization, check friction, inertia, etc. I have written quite a bit about this in other posts here...

Edited by Dirk Gregorius

##### Share on other sites
Finalspace    1147
Done. I have disabled stabilization and the friction as well - now the problem is fully visible after some frames.

It seems the box starts to rotate just a bit after each step, so the face normals will rotate as well - therefore the box moves to the side :-(

I have written out the rA and rB points, including the normal and the rotations as well. Even after the second iteration (number of iteration is set to 10) the problem starts to grow...

rA and rB are calculated like this:

// Build contact normal in world space (rotation is already applied)
Vec2f contactWorldB = new Vec2f(contactWorldA).addMultScalar(contact.normal, contact.distance);

// Get relative distance from center of mass to contact point
contact.rA.set(contactWorldA).sub(bodyA.pos);
contact.rB.set(contactWorldB).sub(bodyB.pos);

rA: (-40.00000000, 39.50000000), rB: (-40.00000000, -40.50000000), n: (-0.00000000, 1.00000000), qA: 0.00000000, qB: 0.00000000
rA: (40.00000000, 39.50000000), rB: (40.00000000, -40.50000000), n: (-0.00000000, 1.00000000), qA: 0.00000000, qB: 0.00000000
rA: (-39.97592163, 39.47250366), rB: (-39.97561646, -40.53096008), n: (-0.00060170, 0.99999982), qA: 0.00051578, qB: 0.00060170
rA: (39.97967529, 39.52061462), rB: (39.97998047, -40.47596741), n: (-0.00060170, 0.99999982), qA: 0.00051578, qB: 0.00060170
rA: (-39.97558594, 39.47183228), rB: (-39.97503662, -40.53170776), n: (-0.00061663, 0.99999982), qA: 0.00052872, qB: 0.00061663
rA: (39.97915649, 39.52113342), rB: (39.97970581, -40.47537231), n: (-0.00061663, 0.99999982), qA: 0.00052872, qB: 0.00061663
rA: (-39.97546387, 39.47122192), rB: (-39.97448730, -40.53239441), n: (-0.00062977, 0.99999982), qA: 0.00054004, qB: 0.00062977
rA: (39.97869873, 39.52157593), rB: (39.97967529, -40.47486877), n: (-0.00062977, 0.99999982), qA: 0.00054004, qB: 0.00062977
rA: (-39.97561646, 39.47062683), rB: (-39.97393799, -40.53305054), n: (-0.00064291, 0.99999982), qA: 0.00055136, qB: 0.00064291
rA: (39.97827148, 39.52203369), rB: (39.97994995, -40.47431946), n: (-0.00064291, 0.99999982), qA: 0.00055136, qB: 0.00064291
rA: (-39.97595215, 39.47003174), rB: (-39.97341919, -40.53370667), n: (-0.00065604, 0.99999976), qA: 0.00056267, qB: 0.00065604
rA: (39.97781372, 39.52249146), rB: (39.98034668, -40.47377014), n: (-0.00065604, 0.99999976), qA: 0.00056267, qB: 0.00065604
rA: (-39.97653198, 39.46942139), rB: (-39.97290039, -40.53440857), n: (-0.00066918, 0.99999976), qA: 0.00057399, qB: 0.00066918
rA: (39.97735596, 39.52291870), rB: (39.98098755, -40.47329712), n: (-0.00066918, 0.99999976), qA: 0.00057399, qB: 0.00066918
rA: (-39.97726440, 39.46882629), rB: (-39.97235107, -40.53506470), n: (-0.00068231, 0.99999976), qA: 0.00058530, qB: 0.00068231
rA: (39.97692871, 39.52337646), rB: (39.98184204, -40.47276306), n: (-0.00068231, 0.99999976), qA: 0.00058530, qB: 0.00068231
rA: (-39.97827148, 39.46823120), rB: (-39.97180176, -40.53573608), n: (-0.00069545, 0.99999976), qA: 0.00059662, qB: 0.00069545
rA: (39.97647095, 39.52383423), rB: (39.98291016, -40.47222900), n: (-0.00069545, 0.99999976), qA: 0.00059662, qB: 0.00069545
rA: (-39.97952271, 39.46762085), rB: (-39.97128296, -40.53642273), n: (-0.00070859, 0.99999976), qA: 0.00060794, qB: 0.00070859
rA: (39.97604370, 39.52427673), rB: (39.98428345, -40.47171021), n: (-0.00070859, 0.99999976), qA: 0.00060794, qB: 0.00070859
rA: (-39.98101807, 39.46701050), rB: (-39.97076416, -40.53710938), n: (-0.00072172, 0.99999976), qA: 0.00061925, qB: 0.00072172
rA: (39.97558594, 39.52471924), rB: (39.98583984, -40.47120667), n: (-0.00072172, 0.99999976), qA: 0.00061925, qB: 0.00072172
rA: (-39.98272705, 39.46641541), rB: (-39.97021484, -40.53776550), n: (-0.00073486, 0.99999970), qA: 0.00063057, qB: 0.00073486
rA: (39.97512817, 39.52517700), rB: (39.98764038, -40.47065735), n: (-0.00073486, 0.99999970), qA: 0.00063057, qB: 0.00073486
rA: (-39.98471069, 39.46582031), rB: (-39.96969604, -40.53843689), n: (-0.00074800, 0.99999970), qA: 0.00064189, qB: 0.00074800
rA: (39.97467041, 39.52563477), rB: (39.98968506, -40.47012329), n: (-0.00074800, 0.99999970), qA: 0.00064189, qB: 0.00074800
rA: (-39.98693848, 39.46520996), rB: (-39.96914673, -40.53912354), n: (-0.00076114, 0.99999970), qA: 0.00065322, qB: 0.00076114
rA: (39.97424316, 39.52607727), rB: (39.99200439, -40.46961975), n: (-0.00076114, 0.99999970), qA: 0.00065322, qB: 0.00076114
rA: (-39.98941040, 39.46461487), rB: (-39.96862793, -40.53979492), n: (-0.00077429, 0.99999970), qA: 0.00066454, qB: 0.00077429
rA: (39.97381592, 39.52653503), rB: (39.99459839, -40.46908569), n: (-0.00077429, 0.99999970), qA: 0.00066454, qB: 0.00077429
rA: (-39.99209595, 39.46401978), rB: (-39.96807861, -40.54045105), n: (-0.00078743, 0.99999970), qA: 0.00067587, qB: 0.00078743
rA: (39.97335815, 39.52699280), rB: (39.99737549, -40.46853638), n: (-0.00078743, 0.99999970), qA: 0.00067587, qB: 0.00078743
rA: (-39.99511719, 39.46340942), rB: (-39.96755981, -40.54112244), n: (-0.00080059, 0.99999970), qA: 0.00068720, qB: 0.00080059
rA: (39.97290039, 39.52743530), rB: (40.00045776, -40.46803284), n: (-0.00080059, 0.99999970), qA: 0.00068720, qB: 0.00080059
rA: (-39.99838257, 39.46281433), rB: (-39.96701050, -40.54177856), n: (-0.00081374, 0.99999964), qA: 0.00069853, qB: 0.00081374
rA: (39.97244263, 39.52789307), rB: (40.00378418, -40.46749878), n: (-0.00081374, 0.99999964), qA: 0.00069853, qB: 0.00081374
rA: (-40.00189209, 39.46221924), rB: (-39.96649170, -40.54246521), n: (-0.00082690, 0.99999964), qA: 0.00070987, qB: 0.00082690
rA: (39.97201538, 39.52835083), rB: (40.00741577, -40.46697998), n: (-0.00082690, 0.99999964), qA: 0.00070987, qB: 0.00082690
rA: (-40.00567627, 39.46163940), rB: (-39.96594238, -40.54310608), n: (-0.00084006, 0.99999964), qA: 0.00072121, qB: 0.00084006
rA: (39.97155762, 39.52882385), rB: (40.01129150, -40.46641541), n: (-0.00084006, 0.99999964), qA: 0.00072121, qB: 0.00084006
rA: (-40.00979614, 39.46102905), rB: (-39.96542358, -40.54379272), n: (-0.00085323, 0.99999964), qA: 0.00073256, qB: 0.00085323
rA: (39.97113037, 39.52926636), rB: (40.01550293, -40.46589661), n: (-0.00085323, 0.99999964), qA: 0.00073256, qB: 0.00085323
rA: (-40.01416016, 39.46043396), rB: (-39.96490479, -40.54444885), n: (-0.00086640, 0.99999964), qA: 0.00074391, qB: 0.00086640
rA: (39.97067261, 39.52973938), rB: (40.01992798, -40.46533203), n: (-0.00086640, 0.99999964), qA: 0.00074391, qB: 0.00086640
rA: (-40.01882935, 39.45982361), rB: (-39.96435547, -40.54513550), n: (-0.00087958, 0.99999964), qA: 0.00075527, qB: 0.00087958
rA: (39.97021484, 39.53018188), rB: (40.02465820, -40.46482849), n: (-0.00087958, 0.99999964), qA: 0.00075527, qB: 0.00087958
rA: (-40.02377319, 39.45922852), rB: (-39.96380615, -40.54579163), n: (-0.00089276, 0.99999958), qA: 0.00076663, qB: 0.00089276
rA: (39.96978760, 39.53063965), rB: (40.02975464, -40.46429443), n: (-0.00089276, 0.99999958), qA: 0.00076663, qB: 0.00089276
rA: (-40.02905273, 39.45861816), rB: (-39.96328735, -40.54647827), n: (-0.00090595, 0.99999958), qA: 0.00077800, qB: 0.00090595
rA: (39.96932983, 39.53109741), rB: (40.03509521, -40.46376038), n: (-0.00090595, 0.99999958), qA: 0.00077800, qB: 0.00090595
rA: (-40.03109741, 39.45800781), rB: (-39.95922852, -40.54716492), n: (-0.00091915, 0.99999958), qA: 0.00078937, qB: 0.00091915
rA: (39.96533203, 39.53153992), rB: (40.03720093, -40.46324158), n: (-0.00091915, 0.99999958), qA: 0.00078937, qB: 0.00091915
rA: (-40.03152466, 39.45742798), rB: (-39.95321655, -40.54779053), n: (-0.00093235, 0.99999958), qA: 0.00080075, qB: 0.00093235
rA: (39.95944214, 39.53199768), rB: (40.03771973, -40.46270752), n: (-0.00093235, 0.99999958), qA: 0.00080075, qB: 0.00093235
rA: (-40.03198242, 39.45681763), rB: (-39.94696045, -40.54847717), n: (-0.00094555, 0.99999958), qA: 0.00081213, qB: 0.00094555
rA: (39.95324707, 39.53244019), rB: (40.03823853, -40.46218872), n: (-0.00094555, 0.99999958), qA: 0.00081213, qB: 0.00094555
rA: (-40.03244019, 39.45622253), rB: (-39.94039917, -40.54913330), n: (-0.00095875, 0.99999952), qA: 0.00082352, qB: 0.00095875
rA: (39.94677734, 39.53291321), rB: (40.03881836, -40.46162415), n: (-0.00095875, 0.99999952), qA: 0.00082352, qB: 0.00095875
rA: (-40.03289795, 39.45561218), rB: (-39.93353271, -40.54980469), n: (-0.00097196, 0.99999952), qA: 0.00083491, qB: 0.00097196
rA: (39.93997192, 39.53334045), rB: (40.03933716, -40.46113586), n: (-0.00097196, 0.99999952), qA: 0.00083491, qB: 0.00097196
rA: (-40.03332520, 39.45500183), rB: (-39.92630005, -40.55049133), n: (-0.00098516, 0.99999952), qA: 0.00084630, qB: 0.00098516
rA: (39.93289185, 39.53378296), rB: (40.03988647, -40.46058655), n: (-0.00098516, 0.99999952), qA: 0.00084630, qB: 0.00098516
rA: (-40.03378296, 39.45439148), rB: (-39.91876221, -40.55116272), n: (-0.00099837, 0.99999952), qA: 0.00085769, qB: 0.00099837
rA: (39.92541504, 39.53421021), rB: (40.04040527, -40.46009827), n: (-0.00099837, 0.99999952), qA: 0.00085769, qB: 0.00099837
rA: (-40.03424072, 39.45378113), rB: (-39.91091919, -40.55183411), n: (-0.00101158, 0.99999946), qA: 0.00086909, qB: 0.00101158
rA: (39.91763306, 39.53466797), rB: (40.04095459, -40.45953369), n: (-0.00101158, 0.99999946), qA: 0.00086909, qB: 0.00101158
rA: (-40.03469849, 39.45317078), rB: (-39.90270996, -40.55250549), n: (-0.00102479, 0.99999946), qA: 0.00088050, qB: 0.00102479
rA: (39.90948486, 39.53509521), rB: (40.04147339, -40.45904541), n: (-0.00102479, 0.99999946), qA: 0.00088050, qB: 0.00102479
rA: (-40.03515625, 39.45256042), rB: (-39.89419556, -40.55317688), n: (-0.00103800, 0.99999946), qA: 0.00089190, qB: 0.00103800
rA: (39.90106201, 39.53553772), rB: (40.04202271, -40.45851135), n: (-0.00103800, 0.99999946), qA: 0.00089190, qB: 0.00103800
rA: (-40.03558350, 39.45195007), rB: (-39.88525391, -40.55384827), n: (-0.00105121, 0.99999946), qA: 0.00090331, qB: 0.00105121
rA: (39.89224243, 39.53596497), rB: (40.04254150, -40.45802307), n: (-0.00105121, 0.99999946), qA: 0.00090331, qB: 0.00105121
rA: (-40.03604126, 39.45133972), rB: (-39.87600708, -40.55451965), n: (-0.00106443, 0.99999940), qA: 0.00091473, qB: 0.00106443
rA: (39.88305664, 39.53640747), rB: (40.04306030, -40.45748901), n: (-0.00106443, 0.99999940), qA: 0.00091473, qB: 0.00106443
rA: (-40.03646851, 39.45072937), rB: (-39.86636353, -40.55519104), n: (-0.00107764, 0.99999940), qA: 0.00092615, qB: 0.00107764
rA: (39.87353516, 39.53684998), rB: (40.04364014, -40.45697021), n: (-0.00107764, 0.99999940), qA: 0.00092615, qB: 0.00107764
rA: (-40.03692627, 39.45011902), rB: (-39.85644531, -40.55586243), n: (-0.00109086, 0.99999940), qA: 0.00093757, qB: 0.00109086
rA: (39.86367798, 39.53727722), rB: (40.04415894, -40.45646667), n: (-0.00109086, 0.99999940), qA: 0.00093757, qB: 0.00109086
rA: (-40.03735352, 39.44950867), rB: (-39.84609985, -40.55653381), n: (-0.00110408, 0.99999940), qA: 0.00094900, qB: 0.00110409
rA: (39.85345459, 39.53771973), rB: (40.04467773, -40.45593262), n: (-0.00110408, 0.99999940), qA: 0.00094900, qB: 0.00110409
rA: (-40.03781128, 39.44891357), rB: (-39.83544922, -40.55717468), n: (-0.00111731, 0.99999940), qA: 0.00096044, qB: 0.00111731
rA: (39.84289551, 39.53816223), rB: (40.04522705, -40.45539856), n: (-0.00111731, 0.99999940), qA: 0.00096044, qB: 0.00111731
rA: (-40.03826904, 39.44830322), rB: (-39.82443237, -40.55784607), n: (-0.00113053, 0.99999934), qA: 0.00097188, qB: 0.00113053
rA: (39.83193970, 39.53858948), rB: (40.04577637, -40.45491028), n: (-0.00113053, 0.99999934), qA: 0.00097188, qB: 0.00113053
rA: (-40.03872681, 39.44769287), rB: (-39.81298828, -40.55851746), n: (-0.00114376, 0.99999934), qA: 0.00098332, qB: 0.00114376
rA: (39.82055664, 39.53903198), rB: (40.04629517, -40.45437622), n: (-0.00114376, 0.99999934), qA: 0.00098332, qB: 0.00114376
rA: (-40.03918457, 39.44709778), rB: (-39.80117798, -40.55915833), n: (-0.00115699, 0.99999934), qA: 0.00099478, qB: 0.00115699
rA: (39.80883789, 39.53947449), rB: (40.04684448, -40.45384216), n: (-0.00115699, 0.99999934), qA: 0.00099478, qB: 0.00115699
rA: (-40.03961182, 39.44648743), rB: (-39.78894043, -40.55982971), n: (-0.00117023, 0.99999934), qA: 0.00100623, qB: 0.00117023
rA: (39.79672241, 39.53990173), rB: (40.04736328, -40.45333862), n: (-0.00117023, 0.99999934), qA: 0.00100623, qB: 0.00117023
rA: (-40.04006958, 39.44587708), rB: (-39.77633667, -40.56050110), n: (-0.00118346, 0.99999928), qA: 0.00101770, qB: 0.00118346
rA: (39.78417969, 39.54034424), rB: (40.04788208, -40.45278931), n: (-0.00118346, 0.99999928), qA: 0.00101770, qB: 0.00118346
rA: (-40.04052734, 39.44528198), rB: (-39.76336670, -40.56114197), n: (-0.00119670, 0.99999928), qA: 0.00102917, qB: 0.00119670
rA: (39.77127075, 39.54078674), rB: (40.04843140, -40.45227051), n: (-0.00119670, 0.99999928), qA: 0.00102917, qB: 0.00119670
rA: (-40.04098511, 39.44467163), rB: (-39.74996948, -40.56181335), n: (-0.00120994, 0.99999928), qA: 0.00104065, qB: 0.00120994
rA: (39.75796509, 39.54122925), rB: (40.04898071, -40.45173645), n: (-0.00120994, 0.99999928), qA: 0.00104065, qB: 0.00120994
rA: (-40.04141235, 39.44406128), rB: (-39.73614502, -40.56248474), n: (-0.00122319, 0.99999923), qA: 0.00105213, qB: 0.00122319
rA: (39.74426270, 39.54165649), rB: (40.04949951, -40.45123291), n: (-0.00122319, 0.99999923), qA: 0.00105213, qB: 0.00122319
rA: (-40.04187012, 39.44346619), rB: (-39.72195435, -40.56311035), n: (-0.00123643, 0.99999923), qA: 0.00106362, qB: 0.00123644
rA: (39.73016357, 39.54209900), rB: (40.05004883, -40.45069885), n: (-0.00123643, 0.99999923), qA: 0.00106362, qB: 0.00123644
rA: (-40.04232788, 39.44287109), rB: (-39.70733643, -40.56375122), n: (-0.00124969, 0.99999923), qA: 0.00107512, qB: 0.00124969
rA: (39.71557617, 39.54254150), rB: (40.05053711, -40.45016479), n: (-0.00124969, 0.99999923), qA: 0.00107512, qB: 0.00124969
rA: (-40.04278564, 39.44226074), rB: (-39.69235229, -40.56442261), n: (-0.00126294, 0.99999923), qA: 0.00108663, qB: 0.00126294
rA: (39.70068359, 39.54296875), rB: (40.05111694, -40.44966125), n: (-0.00126294, 0.99999923), qA: 0.00108663, qB: 0.00126294
rA: (-40.04324341, 39.44168091), rB: (-39.67691040, -40.56503296), n: (-0.00127620, 0.99999917), qA: 0.00109814, qB: 0.00127620
rA: (39.68536377, 39.54342651), rB: (40.05166626, -40.44908142), n: (-0.00127620, 0.99999917), qA: 0.00109814, qB: 0.00127620
rA: (-40.04370117, 39.44107056), rB: (-39.66107178, -40.56568909), n: (-0.00128946, 0.99999917), qA: 0.00110966, qB: 0.00128946
rA: (39.66958618, 39.54385376), rB: (40.05218506, -40.44857788), n: (-0.00128946, 0.99999917), qA: 0.00110966, qB: 0.00128946
rA: (-40.04415894, 39.44047546), rB: (-39.64480591, -40.56632996), n: (-0.00130272, 0.99999917), qA: 0.00112119, qB: 0.00130272
rA: (39.65338135, 39.54429626), rB: (40.05270386, -40.44804382), n: (-0.00130272, 0.99999917), qA: 0.00112119, qB: 0.00130272
rA: (-40.04461670, 39.43988037), rB: (-39.62805176, -40.56697083), n: (-0.00131599, 0.99999911), qA: 0.00113273, qB: 0.00131599
rA: (39.63671875, 39.54475403), rB: (40.05328369, -40.44747925), n: (-0.00131599, 0.99999911), qA: 0.00113273, qB: 0.00131599
rA: (-40.04507446, 39.43928528), rB: (-39.61087036, -40.56761169), n: (-0.00132927, 0.99999911), qA: 0.00114428, qB: 0.00132927
rA: (39.61959839, 39.54518127), rB: (40.05380249, -40.44697571), n: (-0.00132927, 0.99999911), qA: 0.00114428, qB: 0.00132927
rA: (-40.04550171, 39.43869019), rB: (-39.59320068, -40.56823730), n: (-0.00134254, 0.99999911), qA: 0.00115583, qB: 0.00134254
rA: (39.60208130, 39.54562378), rB: (40.05435181, -40.44642639), n: (-0.00134254, 0.99999911), qA: 0.00115583, qB: 0.00134254
rA: (-40.04595947, 39.43809509), rB: (-39.57516479, -40.56887817), n: (-0.00135582, 0.99999911), qA: 0.00116740, qB: 0.00135582
rA: (39.58410645, 39.54605103), rB: (40.05487061, -40.44593811), n: (-0.00135582, 0.99999911), qA: 0.00116740, qB: 0.00135582
rA: (-40.04641724, 39.43750000), rB: (-39.55664063, -40.56950378), n: (-0.00136911, 0.99999905), qA: 0.00117897, qB: 0.00136911
rA: (39.56564331, 39.54649353), rB: (40.05538940, -40.44538879), n: (-0.00136911, 0.99999905), qA: 0.00117897, qB: 0.00136911
rA: (-40.04687500, 39.43692017), rB: (-39.53768921, -40.57011414), n: (-0.00138240, 0.99999905), qA: 0.00119056, qB: 0.00138240
rA: (39.54681396, 39.54695129), rB: (40.05599976, -40.44480896), n: (-0.00138240, 0.99999905), qA: 0.00119056, qB: 0.00138240
rA: (-40.04733276, 39.43632507), rB: (-39.51821899, -40.57075500), n: (-0.00139569, 0.99999905), qA: 0.00120215, qB: 0.00139569
rA: (39.52740479, 39.54737854), rB: (40.05648804, -40.44430542), n: (-0.00139569, 0.99999905), qA: 0.00120215, qB: 0.00139569
rA: (-40.04779053, 39.43571472), rB: (-39.49835205, -40.57139587), n: (-0.00140899, 0.99999899), qA: 0.00121376, qB: 0.00140899
rA: (39.50759888, 39.54780579), rB: (40.05700684, -40.44378662), n: (-0.00140899, 0.99999899), qA: 0.00121376, qB: 0.00140899
rA: (-40.04824829, 39.43510437), rB: (-39.47799683, -40.57205200), n: (-0.00142229, 0.99999899), qA: 0.00122537, qB: 0.00142229
rA: (39.48733521, 39.54823303), rB: (40.05755615, -40.44325256), n: (-0.00142229, 0.99999899), qA: 0.00122537, qB: 0.00142229
rA: (-40.04870605, 39.43452454), rB: (-39.45715332, -40.57263184), n: (-0.00143560, 0.99999899), qA: 0.00123700, qB: 0.00143560
rA: (39.46655273, 39.54867554), rB: (40.05810547, -40.44270325), n: (-0.00143560, 0.99999899), qA: 0.00123700, qB: 0.00143560
rA: (-40.04916382, 39.43391418), rB: (-39.43579102, -40.57328796), n: (-0.00144891, 0.99999893), qA: 0.00124864, qB: 0.00144892
rA: (39.44531250, 39.54908752), rB: (40.05865479, -40.44219971), n: (-0.00144891, 0.99999893), qA: 0.00124864, qB: 0.00144892
rA: (-40.04962158, 39.43330383), rB: (-39.41397095, -40.57392883), n: (-0.00146223, 0.99999893), qA: 0.00126028, qB: 0.00146223
rA: (39.42355347, 39.54951477), rB: (40.05917358, -40.44166565), n: (-0.00146223, 0.99999893), qA: 0.00126028, qB: 0.00146223
rA: (-40.05007935, 39.43270874), rB: (-39.39166260, -40.57453918), n: (-0.00147556, 0.99999893), qA: 0.00127194, qB: 0.00147556
rA: (39.40133667, 39.54994202), rB: (40.05972290, -40.44113159), n: (-0.00147556, 0.99999893), qA: 0.00127194, qB: 0.00147556
rA: (-40.05053711, 39.43211365), rB: (-39.36886597, -40.57516479), n: (-0.00148889, 0.99999887), qA: 0.00128361, qB: 0.00148889
rA: (39.37860107, 39.55036926), rB: (40.06024170, -40.44061279), n: (-0.00148889, 0.99999887), qA: 0.00128361, qB: 0.00148889
rA: (-40.05102539, 39.43150330), rB: (-39.34561157, -40.57580566), n: (-0.00150222, 0.99999887), qA: 0.00129530, qB: 0.00150222
rA: (39.35540771, 39.55079651), rB: (40.06082153, -40.44007874), n: (-0.00150222, 0.99999887), qA: 0.00129530, qB: 0.00150222
rA: (-40.05145264, 39.43090820), rB: (-39.32177734, -40.57641602), n: (-0.00151556, 0.99999887), qA: 0.00130699, qB: 0.00151556
rA: (39.33169556, 39.55122375), rB: (40.06134033, -40.43954468), n: (-0.00151556, 0.99999887), qA: 0.00130699, qB: 0.00151556
rA: (-40.05191040, 39.43031311), rB: (-39.29751587, -40.57704163), n: (-0.00152891, 0.99999881), qA: 0.00131870, qB: 0.00152891
rA: (39.30752563, 39.55165100), rB: (40.06188965, -40.43902588), n: (-0.00152891, 0.99999881), qA: 0.00131870, qB: 0.00152891
rA: (-40.05239868, 39.42971802), rB: (-39.27273560, -40.57765198), n: (-0.00154226, 0.99999881), qA: 0.00133042, qB: 0.00154226
rA: (39.28277588, 39.55207825), rB: (40.06240845, -40.43847656), n: (-0.00154226, 0.99999881), qA: 0.00133042, qB: 0.00154226
rA: (-40.05285645, 39.42912292), rB: (-39.24743652, -40.57826233), n: (-0.00155562, 0.99999881), qA: 0.00134216, qB: 0.00155562
rA: (39.25750732, 39.55250549), rB: (40.06289673, -40.43794250), n: (-0.00155562, 0.99999881), qA: 0.00134216, qB: 0.00155562
rA: (-40.05328369, 39.42854309), rB: (-39.22158813, -40.57885742), n: (-0.00156899, 0.99999875), qA: 0.00135391, qB: 0.00156899
rA: (39.23184204, 39.55293274), rB: (40.06350708, -40.43742371), n: (-0.00156899, 0.99999875), qA: 0.00135391, qB: 0.00156899
rA: (-40.05377197, 39.42794800), rB: (-39.19528198, -40.57945251), n: (-0.00158236, 0.99999875), qA: 0.00136567, qB: 0.00158236
rA: (39.20556641, 39.55335999), rB: (40.06402588, -40.43687439), n: (-0.00158236, 0.99999875), qA: 0.00136567, qB: 0.00158236
rA: (-40.05422974, 39.42733765), rB: (-39.16839600, -40.58007813), n: (-0.00159574, 0.99999875), qA: 0.00137744, qB: 0.00159574
rA: (39.17877197, 39.55377197), rB: (40.06457520, -40.43635559), n: (-0.00159574, 0.99999875), qA: 0.00137744, qB: 0.00159574
rA: (-40.05471802, 39.42674255), rB: (-39.14105225, -40.58068848), n: (-0.00160912, 0.99999869), qA: 0.00138923, qB: 0.00160912
rA: (39.15145874, 39.55418396), rB: (40.06509399, -40.43583679), n: (-0.00160912, 0.99999869), qA: 0.00138923, qB: 0.00160912
rA: (-40.05514526, 39.42613220), rB: (-39.11306763, -40.58131409), n: (-0.00162252, 0.99999869), qA: 0.00140104, qB: 0.00162252
rA: (39.12362671, 39.55461121), rB: (40.06567383, -40.43528748), n: (-0.00162252, 0.99999869), qA: 0.00140104, qB: 0.00162252
rA: (-40.05563354, 39.42553711), rB: (-39.08462524, -40.58189392), n: (-0.00163592, 0.99999869), qA: 0.00141286, qB: 0.00163592
rA: (39.09524536, 39.55502319), rB: (40.06622314, -40.43475342), n: (-0.00163592, 0.99999869), qA: 0.00141286, qB: 0.00163592
rA: (-40.05609131, 39.42494202), rB: (-39.05560303, -40.58248901), n: (-0.00164932, 0.99999863), qA: 0.00142469, qB: 0.00164933
rA: (39.06628418, 39.55543518), rB: (40.06674194, -40.43423462), n: (-0.00164932, 0.99999863), qA: 0.00142469, qB: 0.00164933
rA: (-40.05657959, 39.42434692), rB: (-39.02606201, -40.58308411), n: (-0.00166274, 0.99999863), qA: 0.00143654, qB: 0.00166274
rA: (39.03680420, 39.55586243), rB: (40.06729126, -40.43368530), n: (-0.00166274, 0.99999863), qA: 0.00143654, qB: 0.00166274
rA: (-40.05703735, 39.42375183), rB: (-38.99594116, -40.58367920), n: (-0.00167616, 0.99999857), qA: 0.00144841, qB: 0.00167616
rA: (39.00671387, 39.55627441), rB: (40.06777954, -40.43315125), n: (-0.00167616, 0.99999857), qA: 0.00144841, qB: 0.00167616
rA: (-40.05749512, 39.42315674), rB: (-38.96524048, -40.58427429), n: (-0.00168959, 0.99999857), qA: 0.00146029, qB: 0.00168960
rA: (38.97616577, 39.55668640), rB: (40.06838989, -40.43263245), n: (-0.00168959, 0.99999857), qA: 0.00146029, qB: 0.00168960
rA: (-40.05795288, 39.42254639), rB: (-38.93402100, -40.58489990), n: (-0.00170303, 0.99999857), qA: 0.00147219, qB: 0.00170303
rA: (38.94500732, 39.55709839), rB: (40.06890869, -40.43209839), n: (-0.00170303, 0.99999857), qA: 0.00147219, qB: 0.00170303
rA: (-40.05844116, 39.42195129), rB: (-38.90222168, -40.58547974), n: (-0.00171648, 0.99999851), qA: 0.00148411, qB: 0.00171648
rA: (38.91326904, 39.55749512), rB: (40.06945801, -40.43159485), n: (-0.00171648, 0.99999851), qA: 0.00148411, qB: 0.00171648
rA: (-40.05889893, 39.42134094), rB: (-38.86984253, -40.58607483), n: (-0.00172994, 0.99999851), qA: 0.00149604, qB: 0.00172994
rA: (38.88095093, 39.55790710), rB: (40.06997681, -40.43104553), n: (-0.00172994, 0.99999851), qA: 0.00149604, qB: 0.00172994
rA: (-40.05935669, 39.42074585), rB: (-38.83682251, -40.58665466), n: (-0.00174340, 0.99999851), qA: 0.00150799, qB: 0.00174340
rA: (38.84808350, 39.55830383), rB: (40.07058716, -40.43052673), n: (-0.00174340, 0.99999851), qA: 0.00150799, qB: 0.00174340
rA: (-40.05984497, 39.42013550), rB: (-38.80331421, -40.58724976), n: (-0.00175688, 0.99999845), qA: 0.00151996, qB: 0.00175688
rA: (38.81460571, 39.55870056), rB: (40.07110596, -40.43002319), n: (-0.00175688, 0.99999845), qA: 0.00151996, qB: 0.00175688
rA: (-40.06033325, 39.41952515), rB: (-38.76919556, -40.58786011), n: (-0.00177036, 0.99999845), qA: 0.00153195, qB: 0.00177036
rA: (38.78054810, 39.55911255), rB: (40.07165527, -40.42947388), n: (-0.00177036, 0.99999845), qA: 0.00153195, qB: 0.00177036
rA: (-40.06079102, 39.41893005), rB: (-38.73449707, -40.58843994), n: (-0.00178385, 0.99999839), qA: 0.00154395, qB: 0.00178386
rA: (38.74591064, 39.55952454), rB: (40.07217407, -40.42890930), n: (-0.00178385, 0.99999839), qA: 0.00154395, qB: 0.00178386
rA: (-40.06124878, 39.41833496), rB: (-38.69915771, -40.58900452), n: (-0.00179736, 0.99999839), qA: 0.00155597, qB: 0.00179736
rA: (38.71069336, 39.55990601), rB: (40.07272339, -40.42843628), n: (-0.00179736, 0.99999839), qA: 0.00155597, qB: 0.00179736
rA: (-40.06173706, 39.41775513), rB: (-38.66326904, -40.58953857), n: (-0.00181087, 0.99999833), qA: 0.00156802, qB: 0.00181087
rA: (38.67483521, 39.56033325), rB: (40.07327271, -40.42784119), n: (-0.00181087, 0.99999833), qA: 0.00156802, qB: 0.00181087
rA: (-40.06219482, 39.41714478), rB: (-38.62673950, -40.59014893), n: (-0.00182439, 0.99999833), qA: 0.00158008, qB: 0.00182439
rA: (38.63839722, 39.56072998), rB: (40.07382202, -40.42732239), n: (-0.00182439, 0.99999833), qA: 0.00158008, qB: 0.00182439
rA: (-40.06268311, 39.41654968), rB: (-38.58963013, -40.59071350), n: (-0.00183793, 0.99999833), qA: 0.00159216, qB: 0.00183793
rA: (38.60134888, 39.56112671), rB: (40.07437134, -40.42680359), n: (-0.00183793, 0.99999833), qA: 0.00159216, qB: 0.00183793
rA: (-40.06314087, 39.41596985), rB: (-38.55184937, -40.59124756), n: (-0.00185147, 0.99999827), qA: 0.00160426, qB: 0.00185147
rA: (38.56369019, 39.56153870), rB: (40.07492065, -40.42625427), n: (-0.00185147, 0.99999827), qA: 0.00160426, qB: 0.00185147
rA: (-40.06362915, 39.41537476), rB: (-38.51351929, -40.59181213), n: (-0.00186503, 0.99999827), qA: 0.00161639, qB: 0.00186503
rA: (38.52539063, 39.56195068), rB: (40.07546997, -40.42570496), n: (-0.00186503, 0.99999827), qA: 0.00161639, qB: 0.00186503
rA: (-40.06411743, 39.41477966), rB: (-38.47457886, -40.59237671), n: (-0.00187859, 0.99999821), qA: 0.00162853, qB: 0.00187859
rA: (38.48651123, 39.56234741), rB: (40.07601929, -40.42515564), n: (-0.00187859, 0.99999821), qA: 0.00162853, qB: 0.00187859
rA: (-40.06460571, 39.41419983), rB: (-38.43502808, -40.59292603), n: (-0.00189217, 0.99999821), qA: 0.00164069, qB: 0.00189217
rA: (38.44702148, 39.56274414), rB: (40.07656860, -40.42465210), n: (-0.00189217, 0.99999821), qA: 0.00164069, qB: 0.00189217
rA: (-40.06509399, 39.41362000), rB: (-38.39480591, -40.59344482), n: (-0.00190576, 0.99999821), qA: 0.00165288, qB: 0.00190576
rA: (38.40686035, 39.56317139), rB: (40.07711792, -40.42404175), n: (-0.00190576, 0.99999821), qA: 0.00165288, qB: 0.00190576
rA: (-40.06555176, 39.41300964), rB: (-38.35391235, -40.59403992), n: (-0.00191936, 0.99999815), qA: 0.00166509, qB: 0.00191936
rA: (38.36602783, 39.56355286), rB: (40.07760620, -40.42355347), n: (-0.00191936, 0.99999815), qA: 0.00166509, qB: 0.00191936
rA: (-40.06604004, 39.41241455), rB: (-38.31240845, -40.59455872), n: (-0.00193297, 0.99999815), qA: 0.00167732, qB: 0.00193298
rA: (38.32461548, 39.56393433), rB: (40.07821655, -40.42300415), n: (-0.00193297, 0.99999815), qA: 0.00167732, qB: 0.00193298
rA: (-40.06652832, 39.41180420), rB: (-38.27029419, -40.59512329), n: (-0.00194660, 0.99999809), qA: 0.00168957, qB: 0.00194660
rA: (38.28256226, 39.56431580), rB: (40.07876587, -40.42247009), n: (-0.00194660, 0.99999809), qA: 0.00168957, qB: 0.00194660
rA: (-40.06701660, 39.41117859), rB: (-38.22750854, -40.59571838), n: (-0.00196024, 0.99999809), qA: 0.00170185, qB: 0.00196024
rA: (38.23983765, 39.56468201), rB: (40.07931519, -40.42198181), n: (-0.00196024, 0.99999809), qA: 0.00170185, qB: 0.00196024
rA: (-40.06747437, 39.41059875), rB: (-38.18405151, -40.59620667), n: (-0.00197389, 0.99999803), qA: 0.00171415, qB: 0.00197389
rA: (38.19650269, 39.56507874), rB: (40.07986450, -40.42141724), n: (-0.00197389, 0.99999803), qA: 0.00171415, qB: 0.00197389
rA: (-40.06796265, 39.40998840), rB: (-38.13998413, -40.59677124), n: (-0.00198756, 0.99999803), qA: 0.00172648, qB: 0.00198756
rA: (38.15252686, 39.56546021), rB: (40.08047485, -40.42088318), n: (-0.00198756, 0.99999803), qA: 0.00172648, qB: 0.00198756
rA: (-40.06845093, 39.40937805), rB: (-38.09524536, -40.59733582), n: (-0.00200123, 0.99999797), qA: 0.00173883, qB: 0.00200124
rA: (38.10778809, 39.56582642), rB: (40.08096313, -40.42036438), n: (-0.00200123, 0.99999797), qA: 0.00173883, qB: 0.00200124
rA: (-40.06893921, 39.40878296), rB: (-38.04983521, -40.59785461), n: (-0.00201493, 0.99999797), qA: 0.00175120, qB: 0.00201493
rA: (38.06243896, 39.56620789), rB: (40.08151245, -40.41984558), n: (-0.00201493, 0.99999797), qA: 0.00175120, qB: 0.00201493
rA: (-40.06942749, 39.40817261), rB: (-38.00372314, -40.59841919), n: (-0.00202863, 0.99999791), qA: 0.00176360, qB: 0.00202864
rA: (38.01641846, 39.56658936), rB: (40.08206177, -40.41929626), n: (-0.00202863, 0.99999791), qA: 0.00176360, qB: 0.00202864
rA: (-40.06991577, 39.40759277), rB: (-37.95697021, -40.59890747), n: (-0.00204236, 0.99999791), qA: 0.00177602, qB: 0.00204236
rA: (37.96972656, 39.56698608), rB: (40.08261108, -40.41873169), n: (-0.00204236, 0.99999791), qA: 0.00177602, qB: 0.00204236
rA: (-40.07040405, 39.40698242), rB: (-37.90954590, -40.59947205), n: (-0.00205609, 0.99999791), qA: 0.00178847, qB: 0.00205609
rA: (37.92236328, 39.56735229), rB: (40.08319092, -40.41821289), n: (-0.00205609, 0.99999791), qA: 0.00178847, qB: 0.00205609
rA: (-40.07089233, 39.40638733), rB: (-37.86138916, -40.59997559), n: (-0.00206985, 0.99999785), qA: 0.00180095, qB: 0.00206985
rA: (37.87426758, 39.56771851), rB: (40.08374023, -40.41767883), n: (-0.00206985, 0.99999785), qA: 0.00180095, qB: 0.00206985
rA: (-40.07138062, 39.40577698), rB: (-37.81253052, -40.60050964), n: (-0.00208361, 0.99999785), qA: 0.00181345, qB: 0.00208361
rA: (37.82546997, 39.56808472), rB: (40.08425903, -40.41714478), n: (-0.00208361, 0.99999785), qA: 0.00181345, qB: 0.00208361
rA: (-40.07186890, 39.40518188), rB: (-37.76303101, -40.60101318), n: (-0.00209740, 0.99999779), qA: 0.00182598, qB: 0.00209740
rA: (37.77603149, 39.56845093), rB: (40.08480835, -40.41662598), n: (-0.00209740, 0.99999779), qA: 0.00182598, qB: 0.00209740
rA: (-40.07238770, 39.40458679), rB: (-37.71282959, -40.60151672), n: (-0.00211120, 0.99999779), qA: 0.00183854, qB: 0.00211120
rA: (37.72589111, 39.56883240), rB: (40.08541870, -40.41606140), n: (-0.00211120, 0.99999779), qA: 0.00183854, qB: 0.00211120
rA: (-40.07287598, 39.40399170), rB: (-37.66192627, -40.60202026), n: (-0.00212501, 0.99999774), qA: 0.00185113, qB: 0.00212502
rA: (37.67504883, 39.56919861), rB: (40.08596802, -40.41552734), n: (-0.00212501, 0.99999774), qA: 0.00185113, qB: 0.00212502
rA: (-40.07336426, 39.40339661), rB: (-37.61026001, -40.60252380), n: (-0.00213885, 0.99999774), qA: 0.00186375, qB: 0.00213885
rA: (37.62347412, 39.56958008), rB: (40.08651733, -40.41496277), n: (-0.00213885, 0.99999774), qA: 0.00186375, qB: 0.00213885
rA: (-40.07385254, 39.40280151), rB: (-37.55795288, -40.60301208), n: (-0.00215270, 0.99999768), qA: 0.00187639, qB: 0.00215270
rA: (37.57125854, 39.56994629), rB: (40.08709717, -40.41441345), n: (-0.00215270, 0.99999768), qA: 0.00187639, qB: 0.00215270
rA: (-40.07437134, 39.40222168), rB: (-37.50494385, -40.60348511), n: (-0.00216657, 0.99999768), qA: 0.00188907, qB: 0.00216657
rA: (37.51828003, 39.57032776), rB: (40.08767700, -40.41384888), n: (-0.00216657, 0.99999768), qA: 0.00188907, qB: 0.00216657
rA: (-40.07485962, 39.40162659), rB: (-37.45117188, -40.60398865), n: (-0.00218046, 0.99999762), qA: 0.00190177, qB: 0.00218046
rA: (37.46459961, 39.57069397), rB: (40.08825684, -40.41331482), n: (-0.00218046, 0.99999762), qA: 0.00190177, qB: 0.00218046
rA: (-40.07534790, 39.40103149), rB: (-37.39663696, -40.60446167), n: (-0.00219436, 0.99999762), qA: 0.00191451, qB: 0.00219436
rA: (37.41012573, 39.57106018), rB: (40.08877563, -40.41276550), n: (-0.00219436, 0.99999762), qA: 0.00191451, qB: 0.00219436
rA: (-40.07586670, 39.40042114), rB: (-37.34143066, -40.60498047), n: (-0.00220829, 0.99999756), qA: 0.00192727, qB: 0.00220829
rA: (37.35494995, 39.57141113), rB: (40.08932495, -40.41224670), n: (-0.00220829, 0.99999756), qA: 0.00192727, qB: 0.00220829
rA: (-40.07635498, 39.39981079), rB: (-37.28546143, -40.60546875), n: (-0.00222223, 0.99999756), qA: 0.00194007, qB: 0.00222223
rA: (37.29904175, 39.57176208), rB: (40.08987427, -40.41168213), n: (-0.00222223, 0.99999756), qA: 0.00194007, qB: 0.00222223
rA: (-40.07687378, 39.39921570), rB: (-37.22879028, -40.60594177), n: (-0.00223620, 0.99999750), qA: 0.00195290, qB: 0.00223620
rA: (37.24246216, 39.57211304), rB: (40.09051514, -40.41113281), n: (-0.00223620, 0.99999750), qA: 0.00195290, qB: 0.00223620
rA: (-40.07736206, 39.39860535), rB: (-37.17132568, -40.60643005), n: (-0.00225018, 0.99999750), qA: 0.00196576, qB: 0.00225019
rA: (37.18505859, 39.57244873), rB: (40.09103394, -40.41061401), n: (-0.00225018, 0.99999750), qA: 0.00196576, qB: 0.00225019
rA: (-40.07788086, 39.39799500), rB: (-37.11312866, -40.60691833), n: (-0.00226419, 0.99999744), qA: 0.00197866, qB: 0.00226419
rA: (37.12689209, 39.57279968), rB: (40.09158325, -40.41007996), n: (-0.00226419, 0.99999744), qA: 0.00197866, qB: 0.00226419
rA: (-40.07839966, 39.39739990), rB: (-37.05419922, -40.60737610), n: (-0.00227822, 0.99999738), qA: 0.00199159, qB: 0.00227822
rA: (37.06799316, 39.57315063), rB: (40.09213257, -40.40951538), n: (-0.00227822, 0.99999738), qA: 0.00199159, qB: 0.00227822
rA: (-40.07891846, 39.39678955), rB: (-36.99453735, -40.60784912), n: (-0.00229227, 0.99999738), qA: 0.00200455, qB: 0.00229227
rA: (37.00839233, 39.57348633), rB: (40.09274292, -40.40898132), n: (-0.00229227, 0.99999738), qA: 0.00200455, qB: 0.00229227
rA: (-40.07940674, 39.39616394), rB: (-36.93402100, -40.60835266), n: (-0.00230634, 0.99999732), qA: 0.00201755, qB: 0.00230634
rA: (36.94799805, 39.57382202), rB: (40.09332275, -40.40844727), n: (-0.00230634, 0.99999732), qA: 0.00201755, qB: 0.00230634
rA: (-40.07992554, 39.39555359), rB: (-36.87277222, -40.60882568), n: (-0.00232043, 0.99999732), qA: 0.00203059, qB: 0.00232044
rA: (36.88677979, 39.57415771), rB: (40.09387207, -40.40789795), n: (-0.00232043, 0.99999732), qA: 0.00203059, qB: 0.00232044
rA: (-40.08044434, 39.39494324), rB: (-36.81079102, -40.60928345), n: (-0.00233455, 0.99999726), qA: 0.00204366, qB: 0.00233455
rA: (36.82482910, 39.57449341), rB: (40.09442139, -40.40736389), n: (-0.00233455, 0.99999726), qA: 0.00204366, qB: 0.00233455
rA: (-40.08096313, 39.39434814), rB: (-36.74801636, -40.60972595), n: (-0.00234869, 0.99999726), qA: 0.00205676, qB: 0.00234870
rA: (36.76211548, 39.57482910), rB: (40.09503174, -40.40681458), n: (-0.00234869, 0.99999726), qA: 0.00205676, qB: 0.00234870
rA: (-40.08145142, 39.39375305), rB: (-36.68438721, -40.61015320), n: (-0.00236286, 0.99999720), qA: 0.00206990, qB: 0.00236286
rA: (36.69857788, 39.57516479), rB: (40.09558105, -40.40626526), n: (-0.00236286, 0.99999720), qA: 0.00206990, qB: 0.00236286
rA: (-40.08200073, 39.39315796), rB: (-36.62005615, -40.61059570), n: (-0.00237705, 0.99999720), qA: 0.00208309, qB: 0.00237705
rA: (36.63427734, 39.57551575), rB: (40.09616089, -40.40568542), n: (-0.00237705, 0.99999720), qA: 0.00208309, qB: 0.00237705
rA: (-40.08251953, 39.39254761), rB: (-36.55490112, -40.61103821), n: (-0.00239127, 0.99999714), qA: 0.00209630, qB: 0.00239127
rA: (36.56912231, 39.57583618), rB: (40.09667969, -40.40513611), n: (-0.00239127, 0.99999714), qA: 0.00209630, qB: 0.00239127
rA: (-40.08303833, 39.39193726), rB: (-36.48895264, -40.61148071), n: (-0.00240551, 0.99999708), qA: 0.00210956, qB: 0.00240551
rA: (36.50326538, 39.57617188), rB: (40.09729004, -40.40457153), n: (-0.00240551, 0.99999708), qA: 0.00210956, qB: 0.00240551
rA: (-40.08352661, 39.39134216), rB: (-36.42214966, -40.61189270), n: (-0.00241978, 0.99999708), qA: 0.00212286, qB: 0.00241978
rA: (36.43661499, 39.57650757), rB: (40.09793091, -40.40400696), n: (-0.00241978, 0.99999708), qA: 0.00212286, qB: 0.00241978
rA: (-40.08407593, 39.39073181), rB: (-36.35464478, -40.61233521), n: (-0.00243408, 0.99999702), qA: 0.00213620, qB: 0.00243408
rA: (36.36907959, 39.57682800), rB: (40.09844971, -40.40345764), n: (-0.00243408, 0.99999702), qA: 0.00213620, qB: 0.00243408

Something must be wrong with the contact generator... again... damn.

I think i am so close to get a fully working and robust system. So it must be something really stupid.

Can you please have a look at the contact generator? - all the relevant code is there and its awfully simple:

And i uploaded a small video showing the issue:

Thanks,
Final
Edited by Finalspace

##### Share on other sites
Randy Gaul    2762

For some reason your boxes aren't pushing apart from one another even though there seems to be significant penetration. Are you handling the bias term appropriately? With no friction you should not have any torque if you land one box onto another from such a short height, if you have enough solver iterations.

Try checking your code against the code in Box2D Lite. There you have a full working example and should be able to identify any hard to catch mathematical errors (like forgetting to normalize something, or scale something).

I'd look at your source code but just don't have the time, so if you're stuck you have to keep trying new avenues of debugging.

Edit: Oh you disabled stabilization? Well then of course you're going to get results like this. If one point is solved without proper convergence you will get a divergent simulation, and without bias it cannot get enough energy to correct the slightly uneven contact points.

Usually when debugging this kind of code it's good to disable features and isolate problems, but that won't help you if you don't understand how this will impact the simulation (as in since you don't know what to expect you don't know what is correct).

Edited by Randy Gaul

##### Share on other sites
Finalspace    1147

For some reason your boxes aren't pushing apart from one another even though there seems to be significant penetration. Are you handling the bias term appropriately? With no friction you should not have any torque if you land one box onto another from such a short height, if you have enough solver iterations.

Try checking your code against the code in Box2D Lite. There you have a full working example and should be able to identify any hard to catch mathematical errors (like forgetting to normalize something, or scale something).

I'd look at your source code but just don't have the time, so if you're stuck you have to keep trying new avenues of debugging.

Edit: Oh you disabled stabilization? Well then of course you're going to get results like this. If one point is solved without proper convergence you will get a divergent simulation, and without bias it cannot get enough energy to correct the slightly uneven contact points.

Usually when debugging this kind of code it's good to disable features and isolate problems, but that won't help you if you don't understand how this will impact the simulation (as in since you don't know what to expect you don't know what is correct).

Even with re-enabled stabilization the side moving is still doing its thing - but it takes a lot longer to move the boxes.

Also i have 10 solver iterations whichs should be enough to get it stable for such a simple case.

Edited by Finalspace

##### Share on other sites
Finalspace    1147

I uploaded a video showing the contact generator results:

It looks totally fine - all points even when the reference face is on B, points are projected back to A.

Edited by Finalspace

##### Share on other sites
Dirk Gregorius    2757

Looks good from what I can see there.

##### Share on other sites
Finalspace    1147

After looking at the r1 and r2 points in box2d lite - this problem is also present when warmstarting is disabled, but its visually not noticeable because the  entire coordinates are tiny compared to my pixel based system (30 times smaller than my implementation) and if i enable warmstarting in box2d lite the issue is totally gone (r1 and r2 are always the same).

So basically to solve this issue i have to implement warm starting as well - which should be fairly easy, because i already have saved the previous contacts.

Also i should scale down my world entirely by a factor of 30 or 50 - so that floating point errors gets tiny so that its not noticeable at all ;-)

A lot of work for the renderer i must do here... arghhh.

Edited by Finalspace

##### Share on other sites
Finalspace    1147

Incredible!!!

Applying warm starting does solving this issue completely - even with my pixel based coordinates.

Thanks for all the tips i got from you guys ;-)

##### Share on other sites
Finalspace    1147

It was too early to get happy... i tested stacking boxes, the problem is still there :-(

##### Share on other sites
Finalspace    1147

This time.... i finally solved it completely.

It was a bad combination of minimum penetration distance (slop) and baumgarte parameter. Now it stabilizes perfectly.

// NOTE: Baumgarte and minimum penetration must fit together
public static final float MIN_PENETRATION_DISTANCE = 0.1f;
public static final float BAUMGARTE = 0.3f;

I will upload some results later ;-)