public FeatureTransforms(int targetCol, int operand0, int operand1, XForm xformType) { _targetCol = targetCol; _operandCols = new int[2]; _operandCols[0] = operand0; _operandCols[1] = operand1; _xformType = xformType; }
public XGraphicsPdfRenderer(XForm form, XGraphics gfx) { this.form = form; this.colorMode = form.Owner.Options.ColorMode; this.gfx = gfx; this.content = new StringBuilder(); form.pdfRenderer = this; this.gfxState = new PdfGraphicsState(this); }
private void DisplaysShapeProperies(XForm xform) { this.txtWidth.Text = xform.Width.Value.ToString(); this.txtHeight.Text = xform.Height.Value.ToString(); this.txtLocPinX.Text = xform.LocPinX.Value.ToString(); this.txtLocPinY.Text = xform.LocPinY.Value.ToString(); this.txtAngle.Text = xform.Angle.Value.ToString(); this.txtPinX.Text = xform.PinX.Value.ToString(); this.txtPinY.Text = xform.PinY.Value.ToString(); this.chkFlipX.Checked = xform.FlipX.Value == BOOL.True; this.chkFlipY.Checked = xform.FlipY.Value == BOOL.True; }
public static void DrawShape(XForm xform, Shape shape, System.Drawing.Color c) { switch (shape.ShapeType) { case ShapeType.e_circleShape: { Vector x = xform.Position; float r = (new CircleShape(shape)).Radius; float segments = 16; double increment = 2 * Math.PI / segments; Gl.glColor3ub(c.R, c.G, c.B); Gl.glBegin(Gl.GL_LINE_LOOP); for (double i = 0, theta = 0; i < segments; ++i, theta += increment) { Vector d = new Vector(r * (float)Math.Cos(theta), r * (float)Math.Sin(theta)); Vector v = x + d; Gl.glVertex2f(v.X, v.Y); } Gl.glEnd(); //Draw a line from the circle's center to it's right side //so we can visually inspect rotations. Gl.glBegin(Gl.GL_LINES); Gl.glVertex2f(x.X, x.Y); Vector ax = xform.Rotation.col1; Gl.glVertex2f(x.X + r * ax.X, x.Y + r * ax.Y); Gl.glEnd(); } break; case ShapeType.e_polygonShape: { Gl.glColor3ub(c.R, c.G, c.B); Gl.glBegin(Gl.GL_LINE_LOOP); foreach (Vector vertex in (new PolyShape(shape)).Vertices) { Vector vertprime = xform.Rotation * vertex + xform.Position; Gl.glVertex2f(vertprime.X, vertprime.Y); } Gl.glEnd(); } break; } }
/// @see Shape.ComputeAABB public override void ComputeAABB(out AABB aabb, ref XForm xf) { Vector2 lower = MathUtils.Multiply(ref xf, _vertices[0]); Vector2 upper = lower; for (int i = 1; i < _vertexCount; ++i) { Vector2 v = MathUtils.Multiply(ref xf, _vertices[i]); lower = Vector2.Min(lower, v); upper = Vector2.Max(upper, v); } Vector2 r = new Vector2(_radius, _radius); aabb.lowerBound = lower - r; aabb.upperBound = upper + r; }
public override void ViewDidLoad() { base.ViewDidLoad(); var validator = new XForm<UITextField> { Inputs = new [] { new XUITextField { Name = I18n.FieldEmail, FieldView = inputEmail, Validators = new [] { new XValidatorRequired { Message = I18n.ValidationRequired } }, } } }; skipButton.TouchUpInside += (sender, e) => DismissViewController(true, null); forgotPasswordButton.TouchUpInside += (sender, e) => { if ( validator.Validate() ) { ShowHud(); ServiceProviderUser.Instance.ForgotPassword( inputEmail.Text, result => { HideHud(); DismissViewController(true, null); ShowAlert(I18n.SuccessMessageForgotPassword); }, errorMessage => { HideHud(); ShowAlert(errorMessage); } ); } else { ShowAlert(string.Join("\n",validator.Errors)); } }; }
/// <summary> /// Create XForm from FormTypeModel /// </summary> /// <param name="formTypeModel"></param> /// <returns></returns> public XForm Create(FormTypeModel formTypeModel) { var form = new XForm(); form.Id = formTypeModel.Guid; form.FormName = formTypeModel.Name; form.CreatedBy = formTypeModel.CreatedBy; form.Created = DateTime.Now; form.ChangedBy = formTypeModel.CreatedBy; form.Changed = DateTime.Now; form.AllowAnonymousPost = formTypeModel.FormCanBeSentWithoutLoggingIn; form.AllowMultiplePost = formTypeModel.SamePersonCanSendTheFormSeveralTimes; form.Document = new SerializableXmlDocument(); form.Document.LoadXml(_formSerializer.Serialize(formTypeModel).ToString()); return form; }
static void FindIncidentEdge(out FixedArray2<ClipVertex> c, PolygonShape poly1, ref XForm xf1, int edge1, PolygonShape poly2, ref XForm xf2) { c = new FixedArray2<ClipVertex>(); int count1 = poly1._vertexCount; int count2 = poly2._vertexCount; Debug.Assert(0 <= edge1 && edge1 < count1); // Get the normal of the reference edge in poly2's frame. Vector2 normal1 = MathUtils.MultiplyT(ref xf2.R, MathUtils.Multiply(ref xf1.R, poly1._normals[edge1])); // Find the incident edge on poly2. int index = 0; float minDot = Settings.b2_FLT_MAX; for (int i = 0; i < count2; ++i) { float dot = Vector2.Dot(normal1, poly2._normals[i]); if (dot < minDot) { minDot = dot; index = i; } } // Build the clip vertices for the incident edge. int i1 = index; int i2 = i1 + 1 < count2 ? i1 + 1 : 0; var cv0 = c[0]; cv0.v = MathUtils.Multiply(ref xf2, poly2._vertices[i1]); cv0.id.Features.ReferenceEdge = (byte)edge1; cv0.id.Features.IncidentEdge = (byte)i1; cv0.id.Features.IncidentVertex = 0; c[0] = cv0; var cv1 = c[1]; cv1.v = MathUtils.Multiply(ref xf2, poly2._vertices[i2]); cv1.id.Features.ReferenceEdge = (byte)edge1; cv1.id.Features.IncidentEdge = (byte)i2; cv1.id.Features.IncidentVertex = 1; c[1] = cv1; }
// Find the separation between poly1 and poly2 for a give edge normal on poly1. static float EdgeSeparation(PolygonShape poly1, ref XForm xf1, int edge1, PolygonShape poly2, ref XForm xf2) { int count1 = poly1._vertexCount; int count2 = poly2._vertexCount; Debug.Assert(0 <= edge1 && edge1 < count1); // Convert normal from poly1's frame into poly2's frame. Vector2 normal1World = MathUtils.Multiply(ref xf1.R, poly1._normals[edge1]); Vector2 normal1 = MathUtils.MultiplyT(ref xf2.R, normal1World); // Find support vertex on poly2 for -normal. int index = 0; float minDot = Settings.b2_FLT_MAX; for (int i = 0; i < count2; ++i) { float dot = Vector2.Dot(poly2._vertices[i], normal1); if (dot < minDot) { minDot = dot; index = i; } } Vector2 v1 = MathUtils.Multiply(ref xf1, poly1._vertices[edge1]); Vector2 v2 = MathUtils.Multiply(ref xf2, poly2._vertices[index]); float separation = Vector2.Dot(v2 - v1, normal1World); return separation; }
/// Compute the collision manifold between two polygons. public static void CollidePolygons(ref Manifold manifold, PolygonShape polyA, ref XForm xfA, PolygonShape polyB, ref XForm xfB) { manifold._pointCount = 0; float totalRadius = polyA._radius + polyB._radius; int edgeA = 0; float separationA = FindMaxSeparation(out edgeA, polyA, ref xfA, polyB, ref xfB); if (separationA > totalRadius) return; int edgeB = 0; float separationB = FindMaxSeparation(out edgeB, polyB, ref xfB, polyA, ref xfA); if (separationB > totalRadius) return; PolygonShape poly1; // reference polygon PolygonShape poly2; // incident polygon XForm xf1, xf2; int edge1; // reference edge byte flip; float k_relativeTol = 0.98f; float k_absoluteTol = 0.001f; if (separationB > k_relativeTol * separationA + k_absoluteTol) { poly1 = polyB; poly2 = polyA; xf1 = xfB; xf2 = xfA; edge1 = edgeB; manifold._type = ManifoldType.FaceB; flip = 1; } else { poly1 = polyA; poly2 = polyB; xf1 = xfA; xf2 = xfB; edge1 = edgeA; manifold._type = ManifoldType.FaceA; flip = 0; } FixedArray2<ClipVertex> incidentEdge; FindIncidentEdge(out incidentEdge, poly1, ref xf1, edge1, poly2, ref xf2); int count1 = poly1._vertexCount; Vector2 v11 = poly1._vertices[edge1]; Vector2 v12 = edge1 + 1 < count1 ? poly1._vertices[edge1+1] : poly1._vertices[0]; Vector2 dv = v12 - v11; Vector2 localNormal = MathUtils.Cross(dv, 1.0f); localNormal.Normalize(); Vector2 planePoint = 0.5f * (v11 + v12); Vector2 sideNormal = MathUtils.Multiply(ref xf1.R, v12 - v11); sideNormal.Normalize(); Vector2 frontNormal = MathUtils.Cross(sideNormal, 1.0f); v11 = MathUtils.Multiply(ref xf1, v11); v12 = MathUtils.Multiply(ref xf1, v12); float frontOffset = Vector2.Dot(frontNormal, v11); float sideOffset1 = -Vector2.Dot(sideNormal, v11); float sideOffset2 = Vector2.Dot(sideNormal, v12); // Clip incident edge against extruded edge1 side edges. FixedArray2<ClipVertex> clipPoints1; FixedArray2<ClipVertex> clipPoints2; int np; // Clip to box side 1 np = ClipSegmentToLine(out clipPoints1, ref incidentEdge, -sideNormal, sideOffset1); if (np < 2) return; // Clip to negative box side 1 np = ClipSegmentToLine(out clipPoints2, ref clipPoints1, sideNormal, sideOffset2); if (np < 2) { return; } // Now clipPoints2 contains the clipped points. manifold._localPlaneNormal = localNormal; manifold._localPoint = planePoint; int pointCount = 0; for (int i = 0; i < Settings.b2_maxManifoldPoints; ++i) { float separation = Vector2.Dot(frontNormal, clipPoints2[i].v) - frontOffset; if (separation <= totalRadius) { ManifoldPoint cp = manifold._points[pointCount]; cp.LocalPoint = MathUtils.MultiplyT(ref xf2, clipPoints2[i].v); cp.Id = clipPoints2[i].id; cp.Id.Features.Flip = flip; manifold._points[pointCount] = cp; ++pointCount; } } manifold._pointCount = pointCount; }
/// Compute the collision manifold between a polygon and a circle. public static void CollidePolygonAndCircle(ref Manifold manifold, PolygonShape polygon, ref XForm xf1, CircleShape circle, ref XForm xf2) { manifold._pointCount = 0; // Compute circle position in the frame of the polygon. Vector2 c = MathUtils.Multiply(ref xf2, circle._p); Vector2 cLocal = MathUtils.MultiplyT(ref xf1, c); // Find the min separating edge. int normalIndex = 0; float separation = -Settings.b2_FLT_MAX; float radius = polygon._radius + circle._radius; int vertexCount = polygon._vertexCount; for (int i = 0; i < vertexCount; ++i) { float s = Vector2.Dot(polygon._normals[i], cLocal - polygon._vertices[i]); if (s > radius) { // Early out. return; } if (s > separation) { separation = s; normalIndex = i; } } // Vertices that subtend the incident face. int vertIndex1 = normalIndex; int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; Vector2 v1 = polygon._vertices[vertIndex1]; Vector2 v2 = polygon._vertices[vertIndex2]; // If the center is inside the polygon ... if (separation < Settings.b2_FLT_EPSILON) { manifold._pointCount = 1; manifold._type = ManifoldType.FaceA; manifold._localPlaneNormal = polygon._normals[normalIndex]; manifold._localPoint = 0.5f * (v1 + v2); var p0 = manifold._points[0]; p0.LocalPoint = circle._p; p0.Id.Key = 0; manifold._points[0] = p0; return; } // Compute barycentric coordinates float u1 = Vector2.Dot(cLocal - v1, v2 - v1); float u2 = Vector2.Dot(cLocal - v2, v1 - v2); if (u1 <= 0.0f) { if (Vector2.DistanceSquared(cLocal, v1) > radius * radius) { return; } manifold._pointCount = 1; manifold._type = ManifoldType.FaceA; manifold._localPlaneNormal = cLocal - v1; manifold._localPlaneNormal.Normalize(); manifold._localPoint = v1; var p0b = manifold._points[0]; p0b.LocalPoint = circle._p; p0b.Id.Key = 0; manifold._points[0] = p0b; } else if (u2 <= 0.0f) { if (Vector2.DistanceSquared(cLocal, v2) > radius * radius) { return; } manifold._pointCount = 1; manifold._type = ManifoldType.FaceA; manifold._localPlaneNormal = cLocal - v2; manifold._localPlaneNormal.Normalize(); manifold._localPoint = v2; var p0c = manifold._points[0]; p0c.LocalPoint = circle._p; p0c.Id.Key = 0; manifold._points[0] = p0c; } else { Vector2 faceCenter = 0.5f * (v1 + v2); float separation2 = Vector2.Dot(cLocal - faceCenter, polygon._normals[vertIndex1]); if (separation2 > radius) { return; } manifold._pointCount = 1; manifold._type = ManifoldType.FaceA; manifold._localPlaneNormal = polygon._normals[vertIndex1]; manifold._localPoint = faceCenter; var p0d = manifold._points[0]; p0d.LocalPoint = circle._p; p0d.Id.Key = 0; manifold._points[0] = p0d; } }
/// @see Shape.TestPoint public override bool TestPoint(ref XForm xf, Vector2 p) { Vector2 pLocal = MathUtils.MultiplyT(ref xf.R, p - xf.Position); for (int i = 0; i < _vertexCount; ++i) { float dot = Vector2.Dot(_normals[i], pLocal - _vertices[i]); if (dot > 0.0f) { return false; } } return true; }
/// <summary> /// Gets the resource name of the specified form within this page or form. /// </summary> internal string GetFormName(XForm form) { if (this.page != null) return this.page.GetFormName(form); else return this.form.GetFormName(form); }
// We need separation create/destroy functions from the ructor/destructor because // the destructor cannot access the allocator or broad-phase (no destructor arguments allowed by C++). internal void Create(BroadPhase broadPhase, Body body, ref XForm xf, FixtureDef def) { _userData = def.userData; _friction = def.friction; _restitution = def.restitution; _density = def.density; _body = body; _next = null; _filter = def.filter; _isSensor = def.isSensor; _shape = def.shape.Clone(); // Create proxy in the broad-phase. AABB aabb; _shape.ComputeAABB(out aabb, ref xf); _proxyId = broadPhase.CreateProxy(ref aabb, this); }
void InitValidator() { var validatorRequired = new XValidatorRequired { Message = I18n.ValidationRequired }; Validator = new XForm<UITextView> { Inputs = new [] { new XUITextViewField { Name = I18n.FieldFeature, FieldView = fieldFeature, Validators = new [] { validatorRequired }, }, new XUITextViewField { Name = I18n.FieldBenefit, FieldView = fieldBenefit, Validators = new [] { validatorRequired }, } } }; }
/// <summary> /// Gets the resource name of the specified form within this page or form. /// </summary> internal string GetFormName(XForm form) { if (_page != null) return _page.GetFormName(form); return _form.GetFormName(form); }
internal void SynchronizeFixtures() { XForm xf1 = new XForm(); xf1.R.Set(_sweep.a0); xf1.Position = _sweep.c0 - MathUtils.Multiply(ref xf1.R, _sweep.localCenter); BroadPhase broadPhase = _world._contactManager._broadPhase; for (Fixture f = _fixtureList; f != null; f = f._next) { f.Synchronize(broadPhase, ref xf1, ref _xf); } }
/// Get the body transform for the body's origin. /// @return the world transform of the body's origin. public void GetXForm(out XForm xf) { xf = _xf; }
public SeparationFunction(ref SimplexCache cache, Shape shapeA, ref XForm transformA, Shape shapeB, ref XForm transformB) { _localPoint = Vector2.Zero; _shapeA = shapeA; _shapeB = shapeB; int count = cache.count; Debug.Assert(0 < count && count < 3); if (count == 1) { _type = SeparationFunctionType.Points; Vector2 localPointA = _shapeA.GetVertex(cache.indexA[0]); Vector2 localPointB = _shapeB.GetVertex(cache.indexB[0]); Vector2 pointA = MathUtils.Multiply(ref transformA, localPointA); Vector2 pointB = MathUtils.Multiply(ref transformB, localPointB); _axis = pointB - pointA; _axis.Normalize(); } else if (cache.indexB[0] == cache.indexB[1]) { // Two points on A and one on B _type = SeparationFunctionType.FaceA; Vector2 localPointA1 = _shapeA.GetVertex(cache.indexA[0]); Vector2 localPointA2 = _shapeA.GetVertex(cache.indexA[1]); Vector2 localPointB = _shapeB.GetVertex(cache.indexB[0]); _localPoint = 0.5f * (localPointA1 + localPointA2); _axis = MathUtils.Cross(localPointA2 - localPointA1, 1.0f); _axis.Normalize(); Vector2 normal = MathUtils.Multiply(ref transformA.R, _axis); Vector2 pointA = MathUtils.Multiply(ref transformA, _localPoint); Vector2 pointB = MathUtils.Multiply(ref transformB, localPointB); float s = Vector2.Dot(pointB - pointA, normal); if (s < 0.0f) { _axis = -_axis; } } else if (cache.indexA[0] == cache.indexA[1]) { // Two points on B and one on A. _type = SeparationFunctionType.FaceB; Vector2 localPointA = shapeA.GetVertex(cache.indexA[0]); Vector2 localPointB1 = shapeB.GetVertex(cache.indexB[0]); Vector2 localPointB2 = shapeB.GetVertex(cache.indexB[1]); _localPoint = 0.5f * (localPointB1 + localPointB2); _axis = MathUtils.Cross(localPointB2 - localPointB1, 1.0f); _axis.Normalize(); Vector2 normal = MathUtils.Multiply(ref transformB.R, _axis); Vector2 pointB = MathUtils.Multiply(ref transformB, _localPoint); Vector2 pointA = MathUtils.Multiply(ref transformA, localPointA); float s = Vector2.Dot(pointA - pointB, normal); if (s < 0.0f) { _axis = -_axis; } } else { // Two points on B and two points on A. // The faces are parallel. Vector2 localPointA1 = _shapeA.GetVertex(cache.indexA[0]); Vector2 localPointA2 = _shapeA.GetVertex(cache.indexA[1]); Vector2 localPointB1 = _shapeB.GetVertex(cache.indexB[0]); Vector2 localPointB2 = _shapeB.GetVertex(cache.indexB[1]); Vector2 pA = MathUtils.Multiply(ref transformA, localPointA1); Vector2 dA = MathUtils.Multiply(ref transformA.R, localPointA2 - localPointA1); Vector2 pB = MathUtils.Multiply(ref transformB, localPointB1); Vector2 dB = MathUtils.Multiply(ref transformB.R, localPointB2 - localPointB1); float a = Vector2.Dot(dA, dA); float e = Vector2.Dot(dB, dB); Vector2 r = pA - pB; float c = Vector2.Dot(dA, r); float f = Vector2.Dot(dB, r); float b = Vector2.Dot(dA, dB); float denom = a * e - b * b; float s = 0.0f; if (denom != 0.0f) { s = MathUtils.Clamp((b * f - c * e) / denom, 0.0f, 1.0f); } float t = (b * s + f) / e; if (t < 0.0f) { t = 0.0f; s = MathUtils.Clamp(-c / a, 0.0f, 1.0f); } else if (t > 1.0f) { t = 1.0f; s = MathUtils.Clamp((b - c) / a, 0.0f, 1.0f); } Vector2 localPointA = localPointA1 + s * (localPointA2 - localPointA1); Vector2 localPointB = localPointB1 + t * (localPointB2 - localPointB1); if (s == 0.0f || s == 1.0f) { _type = SeparationFunctionType.FaceB; _axis = MathUtils.Cross(localPointB2 - localPointB1, 1.0f); _axis.Normalize(); _localPoint = localPointB; Vector2 normal = MathUtils.Multiply(ref transformB.R, _axis); Vector2 pointA = MathUtils.Multiply(ref transformA, localPointA); Vector2 pointB = MathUtils.Multiply(ref transformB, localPointB); float sgn = Vector2.Dot(pointA - pointB, normal); if (sgn < 0.0f) { _axis = -_axis; } } else { _type = SeparationFunctionType.FaceA; _axis = MathUtils.Cross(localPointA2 - localPointA1, 1.0f); _axis.Normalize(); _localPoint = localPointA; Vector2 normal = MathUtils.Multiply(ref transformA.R, _axis); Vector2 pointA = MathUtils.Multiply(ref transformA, localPointA); Vector2 pointB = MathUtils.Multiply(ref transformB, localPointB); float sgn = Vector2.Dot(pointB - pointA, normal); if (sgn < 0.0f) { _axis = -_axis; } } } }
public float Evaluate(ref XForm transformA, ref XForm transformB) { switch (_type) { case SeparationFunctionType.Points: { Vector2 axisA = MathUtils.MultiplyT(ref transformA.R, _axis); Vector2 axisB = MathUtils.MultiplyT(ref transformB.R, -_axis); Vector2 localPointA = _shapeA.GetSupportVertex(axisA); Vector2 localPointB = _shapeB.GetSupportVertex(axisB); Vector2 pointA = MathUtils.Multiply(ref transformA, localPointA); Vector2 pointB = MathUtils.Multiply(ref transformB, localPointB); float separation = Vector2.Dot(pointB - pointA, _axis); return separation; } case SeparationFunctionType.FaceA: { Vector2 normal = MathUtils.Multiply(ref transformA.R, _axis); Vector2 pointA = MathUtils.Multiply(ref transformA, _localPoint); Vector2 axisB = MathUtils.MultiplyT(ref transformB.R, -normal); Vector2 localPointB = _shapeB.GetSupportVertex(axisB); Vector2 pointB = MathUtils.Multiply(ref transformB, localPointB); float separation = Vector2.Dot(pointB - pointA, normal); return separation; } case SeparationFunctionType.FaceB: { Vector2 normal = MathUtils.Multiply(ref transformB.R, _axis); Vector2 pointB = MathUtils.Multiply(ref transformB, _localPoint); Vector2 axisA = MathUtils.MultiplyT(ref transformA.R, -normal); Vector2 localPointA = _shapeA.GetSupportVertex(axisA); Vector2 pointA = MathUtils.Multiply(ref transformA, localPointA); float separation = Vector2.Dot(pointA - pointB, normal); return separation; } default: Debug.Assert(false); return 0.0f; } }
internal void ReadCache( ref SimplexCache cache, Shape shapeA, ref XForm transformA, Shape shapeB, ref XForm transformB) { Debug.Assert(0 <= cache.count && cache.count <= 3); // Copy data from cache. _count = cache.count; for (int i = 0; i < _count; ++i) { SimplexVertex v = _v[i]; v.indexA = cache.indexA[i]; v.indexB = cache.indexB[i]; Vector2 wALocal = shapeA.GetVertex(v.indexA); Vector2 wBLocal = shapeB.GetVertex(v.indexB); v.wA = MathUtils.Multiply(ref transformA, wALocal); v.wB = MathUtils.Multiply(ref transformB, wBLocal); v.w = v.wB - v.wA; v.a = 0.0f; _v[i] = v; } // Compute the new simplex metric, if it is substantially different than // old metric then flush the simplex. if (_count > 1) { float metric1 = cache.metric; float metric2 = GetMetric(); if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < Settings.b2_FLT_EPSILON) { // Reset the simplex. _count = 0; } } // If the cache is empty or invalid ... if (_count == 0) { SimplexVertex v = _v[0]; v.indexA = 0; v.indexB = 0; Vector2 wALocal = shapeA.GetVertex(0); Vector2 wBLocal = shapeB.GetVertex(0); v.wA = MathUtils.Multiply(ref transformA, wALocal); v.wB = MathUtils.Multiply(ref transformB, wBLocal); v.w = v.wB - v.wA; _v[0] = v; _count = 1; } }
// Find the max separation between poly1 and poly2 using edge normals from poly1. static float FindMaxSeparation( out int edgeIndex, PolygonShape poly1, ref XForm xf1, PolygonShape poly2, ref XForm xf2) { edgeIndex = -1; int count1 = poly1._vertexCount; // Vector pointing from the centroid of poly1 to the centroid of poly2. Vector2 d = MathUtils.Multiply(ref xf2, poly2._centroid) - MathUtils.Multiply(ref xf1, poly1._centroid); Vector2 dLocal1 = MathUtils.MultiplyT(ref xf1.R, d); // Find edge normal on poly1 that has the largest projection onto d. int edge = 0; float maxDot = -Settings.b2_FLT_MAX; for (int i = 0; i < count1; ++i) { float dot = Vector2.Dot(poly1._normals[i], dLocal1); if (dot > maxDot) { maxDot = dot; edge = i; } } // Get the separation for the edge normal. float s = EdgeSeparation(poly1, ref xf1, edge, poly2, ref xf2); // Check the separation for the previous edge normal. int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1; float sPrev = EdgeSeparation(poly1, ref xf1, prevEdge, poly2, ref xf2); // Check the separation for the next edge normal. int nextEdge = edge + 1 < count1 ? edge + 1 : 0; float sNext = EdgeSeparation(poly1, ref xf1, nextEdge, poly2, ref xf2); // Find the best edge and the search direction. int bestEdge; float bestSeparation; int increment; if (sPrev > s && sPrev > sNext) { increment = -1; bestEdge = prevEdge; bestSeparation = sPrev; } else if (sNext > s) { increment = 1; bestEdge = nextEdge; bestSeparation = sNext; } else { edgeIndex = edge; return s; } // Perform a local search for the best edge normal. for ( ; ; ) { if (increment == -1) edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1; else edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0; s = EdgeSeparation(poly1, ref xf1, edge, poly2, ref xf2); if (s > bestSeparation) { bestEdge = edge; bestSeparation = s; } else { break; } } edgeIndex = bestEdge; return bestSeparation; }
/// 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. public void SetAsBox(float hx, float hy, Vector2 center, float angle) { _vertexCount = 4; _vertices[0] = new Vector2(-hx, -hy); _vertices[1] = new Vector2( hx, -hy); _vertices[2] = new Vector2( hx, hy); _vertices[3] = new Vector2(-hx, hy); _normals[0] = new Vector2(0.0f, -1.0f); _normals[1] = new Vector2(1.0f, 0.0f); _normals[2] = new Vector2(0.0f, 1.0f); _normals[3] = new Vector2(-1.0f, 0.0f); _centroid = center; XForm xf = new XForm(); xf.Position = center; xf.R.Set(angle); // Transform vertices and normals. for (int i = 0; i < _vertexCount; ++i) { _vertices[i] = MathUtils.Multiply(ref xf, _vertices[i]); _normals[i] = MathUtils.Multiply(ref xf.R, _normals[i]); } }
/// @see Shape.TestSegment public override SegmentCollide TestSegment( ref XForm transform, out float lambda, out Vector2 normal, ref Segment segment, float maxLambda) { lambda = 0.0f; normal = Vector2.Zero; Vector2 position = transform.Position + MathUtils.Multiply(ref transform.R, _p); Vector2 s = segment.p1 - position; float b = Vector2.Dot(s, s) - _radius * _radius; // Does the segment start inside the circle? if (b < 0.0f) { return SegmentCollide.StartsInside; } // Solve quadratic equation. Vector2 r = segment.p2 - segment.p1; float c = Vector2.Dot(s, r); float rr = Vector2.Dot(r, r); float sigma = c * c - rr * b; // Check for negative discriminant and short segment. if (sigma < 0.0f || rr < Settings.b2_FLT_EPSILON) { return SegmentCollide.Miss; } // Find the point of intersection of the line with the circle. float a = -(c + (float)Math.Sqrt((double)sigma)); // Is the intersection point on the segment? if (0.0f <= a && a <= maxLambda * rr) { a /= rr; lambda = a; normal = s + a * r; normal.Normalize(); return SegmentCollide.Hit; } return SegmentCollide.Miss; }
internal void Synchronize(BroadPhase broadPhase, ref XForm transform1, ref XForm transform2) { if (_proxyId == BroadPhase.NullProxy) { return; } // Compute an AABB that covers the swept shape (may miss some rotation effect). AABB aabb1, aabb2; _shape.ComputeAABB(out aabb1, ref transform1); _shape.ComputeAABB(out aabb2, ref transform2); AABB aabb = new AABB(); aabb.Combine(ref aabb1, ref aabb2); broadPhase.MoveProxy(_proxyId, ref aabb); }
/// <summary> /// Implements the interface because the primary function is internal. /// </summary> string IContentStream.GetFormName(XForm form) { return(GetFormName(form)); }
/// Compute the collision manifold between two circles. public static void CollideCircles(ref Manifold manifold, CircleShape circle1, ref XForm xf1, CircleShape circle2, ref XForm xf2) { manifold._pointCount = 0; Vector2 p1 = MathUtils.Multiply(ref xf1, circle1._p); Vector2 p2 = MathUtils.Multiply(ref xf2, circle2._p); Vector2 d = p2 - p1; float distSqr = Vector2.Dot(d, d); float radius = circle1._radius + circle2._radius; if (distSqr > radius * radius) { return; } manifold._type = ManifoldType.Circles; manifold._localPoint = circle1._p; manifold._localPlaneNormal = Vector2.Zero; manifold._pointCount = 1; var p0 = manifold._points[0]; p0.LocalPoint = circle2._p; p0.Id.Key = 0; manifold._points[0] = p0; }
/// @see Shape.TestSegment public override SegmentCollide TestSegment(ref XForm xf, out float lambda, out Vector2 normal, ref Segment segment, float maxLambda) { lambda = 0; normal = Vector2.Zero; float lower = 0.0f, upper = maxLambda; Vector2 p1 = MathUtils.MultiplyT(ref xf.R, segment.p1 - xf.Position); Vector2 p2 = MathUtils.MultiplyT(ref xf.R, segment.p2 - xf.Position); Vector2 d = p2 - p1; int index = -1; for (int i = 0; i < _vertexCount; ++i) { // p = p1 + a * d // dot(normal, p - v) = 0 // dot(normal, p1 - v) + a * dot(normal, d) = 0 float numerator = Vector2.Dot(_normals[i], _vertices[i] - p1); float denominator = Vector2.Dot(_normals[i], d); if (denominator == 0.0f) { if (numerator < 0.0f) { return SegmentCollide.Miss; } } 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; } } if (upper < lower) { return SegmentCollide.Miss; } } Debug.Assert(0.0f <= lower && lower <= maxLambda); if (index >= 0) { lambda = lower; normal = MathUtils.Multiply(ref xf.R, _normals[index]); return SegmentCollide.Hit; } lambda = 0; return SegmentCollide.StartsInside; }
/// @see Shape.TestPoint public override bool TestPoint(ref XForm transform, Vector2 p) { Vector2 center = transform.Position + MathUtils.Multiply(ref transform.R, _p); Vector2 d = p - center; return Vector2.Dot(d, d) <= _radius * _radius; }
public FixedArray2<Vector2> _points; ///< world contact point (point of intersection) #endregion Fields #region Constructors /// 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. public WorldManifold(ref Manifold manifold, ref XForm xfA, float radiusA, ref XForm xfB, float radiusB) { _normal = Vector2.Zero; _points = new FixedArray2<Vector2>(); if (manifold._pointCount == 0) { return; } switch (manifold._type) { case ManifoldType.Circles: { Vector2 pointA = MathUtils.Multiply(ref xfA, manifold._localPoint); Vector2 pointB = MathUtils.Multiply(ref xfB, manifold._points[0].LocalPoint); Vector2 normal = new Vector2(1.0f, 0.0f); if (Vector2.DistanceSquared(pointA, pointB) > Settings.b2_FLT_EPSILON * Settings.b2_FLT_EPSILON) { normal = pointB - pointA; normal.Normalize(); } _normal = normal; Vector2 cA = pointA + radiusA * normal; Vector2 cB = pointB - radiusB * normal; _points[0] = 0.5f * (cA + cB); } break; case ManifoldType.FaceA: { Vector2 normal = MathUtils.Multiply(ref xfA.R, manifold._localPlaneNormal); Vector2 planePoint = MathUtils.Multiply(ref xfA, manifold._localPoint); // Ensure normal points from A to B. _normal = normal; for (int i = 0; i < manifold._pointCount; ++i) { Vector2 clipPoint = MathUtils.Multiply(ref xfB, manifold._points[i].LocalPoint); Vector2 cA = clipPoint + (radiusA - Vector2.Dot(clipPoint - planePoint, normal)) * normal; Vector2 cB = clipPoint - radiusB * normal; _points[i] = 0.5f * (cA + cB); } } break; case ManifoldType.FaceB: { Vector2 normal = MathUtils.Multiply(ref xfB.R, manifold._localPlaneNormal); Vector2 planePoint = MathUtils.Multiply(ref xfB, manifold._localPoint); // Ensure normal points from A to B. _normal = -normal; for (int i = 0; i < manifold._pointCount; ++i) { Vector2 clipPoint = MathUtils.Multiply(ref xfA, manifold._points[i].LocalPoint); Vector2 cA = clipPoint - radiusA * normal; Vector2 cB = clipPoint + (radiusB - Vector2.Dot(clipPoint - planePoint, normal)) * normal; _points[i] = 0.5f * (cA + cB); } } break; } }
/// @see Shape.ComputeAABB public override void ComputeAABB(out AABB aabb, ref XForm transform) { Vector2 p = transform.Position + MathUtils.Multiply(ref transform.R, _p); aabb.lowerBound = new Vector2(p.X - _radius, p.Y - _radius); aabb.upperBound = new Vector2(p.X + _radius, p.Y + _radius); }
/// <summary> /// Creates the broad phase /// </summary> /// <param name="broadPhase">The broad phase</param> /// <param name="body">The body</param> /// <param name="xf">The xf</param> /// <param name="def">The def</param> public void Create(BroadPhase broadPhase, Body body, XForm xf, FixtureDef def) { UserData = def.UserData; Friction = def.Friction; Restitution = def.Restitution; Density = def.Density; Body = body; Next = null; Filter = def.Filter; IsSensor = def.IsSensor; ShapeType = def.Type; // Allocate and initialize the child shape. switch (ShapeType) { case ShapeType.CircleShape: { CircleShape circle = new CircleShape(); CircleDef circleDef = (CircleDef)def; circle.Position = circleDef.LocalPosition; circle.Radius = circleDef.Radius; Shape = circle; } break; case ShapeType.PolygonShape: { PolygonShape polygon = new PolygonShape(); PolygonDef polygonDef = (PolygonDef)def; polygon.Set(polygonDef.Vertices, polygonDef.VertexCount); Shape = polygon; } break; case ShapeType.EdgeShape: { EdgeShape edge = new EdgeShape(); EdgeDef edgeDef = (EdgeDef)def; edge.Set(edgeDef.Vertex1, edgeDef.Vertex2); Shape = edge; } break; default: Box2DxDebug.Assert(false); break; } // Create proxy in the broad-phase. Aabb aabb; Shape.ComputeAabb(out aabb, xf); bool inRange = broadPhase.InRange(aabb); // You are creating a shape outside the world box. Box2DxDebug.Assert(inRange); if (inRange) { ProxyId = broadPhase.CreateProxy(aabb, this); } else { ProxyId = PairManager.NullProxy; } }