public void TestEdgeLimits7() { VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(10, 10)); VertexConstraints constraint2 = new VertexConstraints(new Vector(5, 5), new Vector(8, 8)); Range lengthRange, angleRange; TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange); }
static void PointIsClosestExperiment( Vector point, VertexConstraints point1Constraints, VertexConstraints point2Constraints, string fileName) { Console.WriteLine(string.Format("Doing experiment for {0}", fileName)); Bitmap image = new Bitmap(320, 240); const int iterations = 200000; using (Graphics graphics = Graphics.FromImage(image)) { for (int i = 0; i < iterations; ++i) { Vector point1 = new Vector( point1Constraints.MinCoord.X + (point1Constraints.MaxCoord.X - point1Constraints.MinCoord.X) * Random.Double(), point1Constraints.MinCoord.Y + (point1Constraints.MaxCoord.Y - point1Constraints.MinCoord.Y) * Random.Double()); Vector point2 = new Vector( point2Constraints.MinCoord.X + (point2Constraints.MaxCoord.X - point2Constraints.MinCoord.X) * Random.Double(), point2Constraints.MinCoord.Y + (point2Constraints.MaxCoord.Y - point2Constraints.MinCoord.Y) * Random.Double()); double distanceSqr, alpha; point.DistanceToSegmentSquared(point1, point2, out distanceSqr, out alpha); alpha = MathHelper.Trunc(alpha, 0, 1); Vector closestPoint = point1 + (point2 - point1) * alpha; const float radius = 2; graphics.FillEllipse( Brushes.Green, (float)closestPoint.X - radius, (float)closestPoint.Y - radius, radius * 2, radius * 2); } graphics.DrawRectangle( Pens.Blue, point1Constraints.CoordRectangle.Left, point1Constraints.CoordRectangle.Top, point1Constraints.CoordRectangle.Width, point1Constraints.CoordRectangle.Height); graphics.DrawRectangle( Pens.Blue, point2Constraints.CoordRectangle.Left, point2Constraints.CoordRectangle.Top, point2Constraints.CoordRectangle.Width, point2Constraints.CoordRectangle.Height); graphics.FillEllipse(Brushes.Red, (float)point.X - 2, (float)point.Y - 2, 4, 4); } image.Save(fileName); }
public void TestEdgeLimits2() { VertexConstraints constraint1 = new VertexConstraints(new Vector(11, -7), new Vector(13, 15)); VertexConstraints constraint2 = new VertexConstraints(new Vector(-10, -10), new Vector(10, 10)); Range lengthRange, angleRange; TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange); Assert.IsTrue(angleRange.Outside); Assert.IsFalse(angleRange.Contains(0)); Assert.IsTrue(angleRange.Contains(Math.PI)); Assert.IsTrue(angleRange.Contains(-Math.PI)); Assert.IsFalse(angleRange.Contains(Math.PI * 0.5)); Assert.IsFalse(angleRange.Contains(-Math.PI * 0.5)); }
public void TestEdgeLimits3() { VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(10, 10)); VertexConstraints constraint2 = new VertexConstraints(new Vector(11, 11), new Vector(12, 16)); Range lengthRange, angleRange; TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange); Assert.IsFalse(angleRange.Outside); Assert.IsTrue(angleRange.Contains(Math.PI * 0.25)); Assert.IsFalse(angleRange.Contains(0)); Assert.IsFalse(angleRange.Contains(Math.PI * 0.5)); Assert.IsFalse(lengthRange.Contains(0)); Assert.IsFalse(lengthRange.Contains(1)); }
public void GenerateVertexConstraintsFromFaces() { foreach (var f in Faces) { var v0 = f.posIndex [0]; var v1 = f.posIndex [1]; var v2 = f.posIndex [2]; var v01 = VertexList [v1] - VertexList [v0]; var v02 = VertexList [v2] - VertexList [v0]; var v12 = VertexList [v2] - VertexList [v1]; VertexConstraints.Add(new VertexConstraint() { Vertex0 = v0, Vertex1 = v1, distance = v01.Norm() }); VertexConstraints.Add(new VertexConstraint() { Vertex0 = v0, Vertex1 = v2, distance = v02.Norm() }); VertexConstraints.Add(new VertexConstraint() { Vertex0 = v1, Vertex1 = v2, distance = v12.Norm() }); } var vc = new List <VertexConstraint> (VertexConstraints); int found = VertexConstraints.Count; for (var i = 0; i < VertexConstraints.Count; i++) { for (var j = i + 1; j < VertexConstraints.Count; j++) { var v0 = VertexConstraints [i].Vertex0; var v1 = VertexConstraints [i].Vertex1; if ((v0 == VertexConstraints [j].Vertex0 && v1 == VertexConstraints [j].Vertex1) || (v1 == VertexConstraints [j].Vertex0 && v0 == VertexConstraints [j].Vertex1)) { vc.Remove(VertexConstraints[j]); } } } VertexConstraints = vc; Console.WriteLine("Found " + found + " .... removed " + (found - VertexConstraints.Count)); }
public void TestVertexConstraintSplitsNonIntersection() { VertexConstraints constraints = new VertexConstraints(new Vector(0, 0), new Vector(1, 1)); List <VertexConstraints> split = constraints.Split(); Assert.IsTrue(split.Count == 4); for (int i = 0; i < split.Count; ++i) { for (int j = i + 1; j < split.Count; ++j) { Range xRange1 = new Range(split[i].MinCoord.X, split[i].MaxCoord.X, false); Range yRange1 = new Range(split[i].MinCoord.Y, split[i].MaxCoord.Y, false); Range xRange2 = new Range(split[j].MinCoord.X, split[j].MaxCoord.X, false); Range yRange2 = new Range(split[j].MinCoord.Y, split[j].MaxCoord.Y, false); Assert.IsFalse(xRange1.IntersectsWith(xRange2) && yRange1.IntersectsWith(yRange2)); } } }
public void TestEdgeLimits4() { const double eps = 0.01; VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(1 - eps, 1 - eps)); VertexConstraints constraint2 = new VertexConstraints(new Vector(1 + eps, 1 + eps), new Vector(2, 2)); Range lengthRange, angleRange; TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange); Assert.IsFalse(angleRange.Outside); Assert.IsTrue(angleRange.Contains(0.01)); Assert.IsFalse(angleRange.Contains(-Math.PI * 0.501)); Assert.IsFalse(angleRange.Contains(-Math.PI)); Assert.IsFalse(angleRange.Contains(Math.PI * 0.501)); Assert.IsFalse(angleRange.Contains(Math.PI)); Assert.IsFalse(lengthRange.Contains(3)); Assert.IsTrue(lengthRange.Contains(0.05)); Assert.IsTrue(lengthRange.Contains(2.8)); }
static void LengthAngleDependenceExperiment( VertexConstraints constraint1, VertexConstraints constraint2, string fileName) { const int GeneratedPointCount = 100000; List <Vector> lengthAnglePoints = new List <Vector>(); double maxLength = 0; for (int i = 0; i < GeneratedPointCount; ++i) { double randomX1 = constraint1.MinCoord.X + Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X); double randomY1 = constraint1.MinCoord.Y + Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y); double randomX2 = constraint2.MinCoord.X + Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X); double randomY2 = constraint2.MinCoord.Y + Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y); Vector vector1 = new Vector(randomX1, randomY1); Vector vector2 = new Vector(randomX2, randomY2); if (vector1 == vector2) { continue; } Vector diff = vector2 - vector1; double length = diff.Length; double angle = Vector.AngleBetween(Vector.UnitX, diff); lengthAnglePoints.Add(new Vector(length, angle)); maxLength = Math.Max(maxLength, length); } //ShapeConstraints constraintSet = ShapeConstraints.CreateFromConstraints( // CreateSimpleShapeModel1(), // new[] { constraint1, constraint2 }, // new[] { new EdgeConstraints(1) }, // 1, // 1); BoxSetLengthAngleConstraints lengthAngleConstraints = BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 2, 0); const int lengthImageSize = 360; const int angleImageSize = 360; double lengthScale = (lengthImageSize - 20) / maxLength; //Image2D<bool> myAwesomeMask = new Image2D<bool>(lengthImageSize, angleImageSize); //LengthAngleSpaceSeparatorSet myAwesomeSeparator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2); //for (int i = 0; i < lengthImageSize; ++i) // for (int j = 0; j < angleImageSize; ++j) // { // double length = i / lengthScale; // double angle = MathHelper.ToRadians(j - 180.0); // if (myAwesomeSeparator.IsInside(length, angle)) // myAwesomeMask[i, j] = true; // } using (Bitmap image = new Bitmap(lengthImageSize, angleImageSize)) using (Graphics graphics = Graphics.FromImage(image)) { graphics.Clear(Color.White); // Draw generated points for (int i = 0; i < lengthAnglePoints.Count; ++i) { DrawLengthAngle(graphics, Pens.Black, lengthAnglePoints[i].X, lengthAnglePoints[i].Y, lengthScale, 1); } // Draw estimated ranges foreach (BoxLengthAngleConstraints child in lengthAngleConstraints.ChildConstraints) { DrawLengthAngleConstraintBox(graphics, Pens.Green, child, lengthScale); } DrawLengthAngleConstraintBox(graphics, new Pen(Color.Red, 2), lengthAngleConstraints.OverallRange, lengthScale); // Draw constraint corners //for (int i = 0; i < 4; ++i) //{ // for (int j = 0; j < 4; ++j) // { // Vector diff = constraint2.Corners[j] - constraint1.Corners[i]; // DrawLengthAngle(diff.Length, Vector.AngleBetween(Vector.UnitX, diff), lengthScale, 5, graphics, Pens.Blue); // } //} // Draw my awesome separation lines //for (int i = 0; i < lengthImageSize - 1; ++i) // for (int j = 0; j < lengthImageSize - 1; ++j) // { // bool border = false; // border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j]; // border |= myAwesomeMask[i, j] != myAwesomeMask[i, j + 1]; // border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j + 1]; // if (border) // image.SetPixel(i, j, Color.Orange); // } //graphics.DrawString( // String.Format("Max length is {0:0.0}", maxLength), SystemFonts.DefaultFont, Brushes.Green, 5, 5); image.Save(fileName); } }
private static void TestEdgeLimitsCommonImpl( VertexConstraints constraint1, VertexConstraints constraint2, out Range lengthRange, out Range angleRange) { BoxSetLengthAngleConstraints lengthAngleConstraints = BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 3, 0); GeneralizedDistanceTransform2D transform = new GeneralizedDistanceTransform2D( new Range(0, 35), new Range(-Math.PI * 2, Math.PI * 2), new Size(2000, 2000)); AllowedLengthAngleChecker allowedLengthAngleChecker = new AllowedLengthAngleChecker(constraint1, constraint2, transform, 1, 0); lengthRange = lengthAngleConstraints.LengthBoundary; angleRange = lengthAngleConstraints.AngleBoundary; const int insideCheckCount = 1000; for (int i = 0; i < insideCheckCount; ++i) { Vector edgePoint1 = constraint1.MinCoord + new Vector( Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X), Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y)); Vector edgePoint2 = constraint2.MinCoord + new Vector( Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X), Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y)); Vector vec = edgePoint2 - edgePoint1; double length = vec.Length; double angle = Vector.AngleBetween(Vector.UnitX, vec); const double tolerance = 1e-10; Assert.IsTrue(lengthAngleConstraints.InRange(length, tolerance, angle, tolerance)); Assert.IsTrue(lengthAngleConstraints.OverallRange.InRange(length, tolerance, angle, tolerance)); Assert.IsTrue(allowedLengthAngleChecker.IsAllowed(length, angle)); } const int outsideCheckCount = 1000; for (int i = 0; i < outsideCheckCount; ++i) { Vector edgePoint1 = constraint1.MinCoord + new Vector( (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.X - constraint1.MinCoord.X), (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y)); Vector edgePoint2 = constraint2.MinCoord + new Vector( (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.X - constraint2.MinCoord.X), (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y)); Vector vec = edgePoint2 - edgePoint1; double length = vec.Length; double angle = Vector.AngleBetween(Vector.UnitX, vec); // We've generated too long edge if (length > transform.RangeX.Right) { continue; } bool definitelyOutside = !lengthAngleConstraints.OverallRange.InRange(length, 1e-6, angle, 1e-6); Assert.IsTrue(!definitelyOutside || !allowedLengthAngleChecker.IsAllowed(length, angle)); Assert.IsTrue(!definitelyOutside || !lengthAngleConstraints.InRange(length, 1e-6, angle, 1e-6)); } }
private static void TestEdgeLimitsCommonImpl( VertexConstraints constraint1, VertexConstraints constraint2, out Range lengthRange, out Range angleRange) { BoxSetLengthAngleConstraints lengthAngleConstraints = BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 3, 0); GeneralizedDistanceTransform2D transform = new GeneralizedDistanceTransform2D( new Range(0, 35), new Range(-Math.PI * 2, Math.PI * 2), new Size(2000, 2000)); AllowedLengthAngleChecker allowedLengthAngleChecker = new AllowedLengthAngleChecker(constraint1, constraint2, transform, 1, 0); lengthRange = lengthAngleConstraints.LengthBoundary; angleRange = lengthAngleConstraints.AngleBoundary; const int insideCheckCount = 1000; for (int i = 0; i < insideCheckCount; ++i) { Vector edgePoint1 = constraint1.MinCoord + new Vector( Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X), Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y)); Vector edgePoint2 = constraint2.MinCoord + new Vector( Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X), Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y)); Vector vec = edgePoint2 - edgePoint1; double length = vec.Length; double angle = Vector.AngleBetween(Vector.UnitX, vec); const double tolerance = 1e-10; Assert.IsTrue(lengthAngleConstraints.InRange(length, tolerance, angle, tolerance)); Assert.IsTrue(lengthAngleConstraints.OverallRange.InRange(length, tolerance, angle, tolerance)); Assert.IsTrue(allowedLengthAngleChecker.IsAllowed(length, angle)); } const int outsideCheckCount = 1000; for (int i = 0; i < outsideCheckCount; ++i) { Vector edgePoint1 = constraint1.MinCoord + new Vector( (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.X - constraint1.MinCoord.X), (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y)); Vector edgePoint2 = constraint2.MinCoord + new Vector( (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.X - constraint2.MinCoord.X), (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y)); Vector vec = edgePoint2 - edgePoint1; double length = vec.Length; double angle = Vector.AngleBetween(Vector.UnitX, vec); // We've generated too long edge if (length > transform.RangeX.Right) continue; bool definitelyOutside = !lengthAngleConstraints.OverallRange.InRange(length, 1e-6, angle, 1e-6); Assert.IsTrue(!definitelyOutside || !allowedLengthAngleChecker.IsAllowed(length, angle)); Assert.IsTrue(!definitelyOutside || !lengthAngleConstraints.InRange(length, 1e-6, angle, 1e-6)); } }
public void TestVertexConstraintSplitsNonIntersection() { VertexConstraints constraints = new VertexConstraints(new Vector(0, 0), new Vector(1, 1)); List<VertexConstraints> split = constraints.Split(); Assert.IsTrue(split.Count == 4); for (int i = 0; i < split.Count; ++i) { for (int j = i + 1; j < split.Count; ++j) { Range xRange1 = new Range(split[i].MinCoord.X, split[i].MaxCoord.X, false); Range yRange1 = new Range(split[i].MinCoord.Y, split[i].MaxCoord.Y, false); Range xRange2 = new Range(split[j].MinCoord.X, split[j].MaxCoord.X, false); Range yRange2 = new Range(split[j].MinCoord.Y, split[j].MaxCoord.Y, false); Assert.IsFalse(xRange1.IntersectsWith(xRange2) && yRange1.IntersectsWith(yRange2)); } } }