private void AddSeparatorsForPair(VertexConstraints constraint1, VertexConstraints constraint2, bool swapDirection) { for (int i = 0; i < 4; ++i) { this.AddSeparatorsForPoint(constraint1.Corners[i], constraint2, swapDirection); } }
private static void MinMaxDistanceForEdge( Vector point, Polygon convexHull, VertexConstraints constraints1, VertexConstraints constraints2, out double minDistanceSqr, out double maxDistanceSqr) { if (convexHull.IsPointInside(point)) { minDistanceSqr = 0; } else { minDistanceSqr = Double.PositiveInfinity; for (int i = 0; i < convexHull.Vertices.Count; ++i) { double distanceSqr = point.DistanceToSegmentSquared( convexHull.Vertices[i], convexHull.Vertices[(i + 1) % convexHull.Vertices.Count]); minDistanceSqr = Math.Min(minDistanceSqr, distanceSqr); } } maxDistanceSqr = 0; foreach (Vector vertex1 in constraints1.Corners) { foreach (Vector vertex2 in constraints2.Corners) { double distanceSqr = point.DistanceToSegmentSquared(vertex1, vertex2); maxDistanceSqr = Math.Max(maxDistanceSqr, distanceSqr); } } }
public LengthAngleSpaceSeparatorSet(VertexConstraints constraint1, VertexConstraints constraint2) { if (constraint1.Freedom < 1e-6 || constraint2.Freedom < 1e-6) throw new ArgumentException("Coord constraints should not be singular."); this.AddSeparatorsForPair(constraint1, constraint2, false); this.AddSeparatorsForPair(constraint2, constraint1, true); }
public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) return false; VertexConstraints objCasted = (VertexConstraints) obj; return objCasted.MinCoord == this.MinCoord && objCasted.MaxCoord == this.MaxCoord; }
public EdgeDescription( VertexConstraints vertexConstraints1, VertexConstraints vertexConstraints2, EdgeConstraints edgeConstraints) { this.VertexConstraints1 = vertexConstraints1; this.VertexConstraints2 = vertexConstraints2; this.EdgeConstraints = edgeConstraints; }
public LengthAngleSpaceSeparatorSet(VertexConstraints constraint1, VertexConstraints constraint2) { if (constraint1.Freedom < 1e-6 || constraint2.Freedom < 1e-6) { throw new ArgumentException("Coord constraints should not be singular."); } this.AddSeparatorsForPair(constraint1, constraint2, false); this.AddSeparatorsForPair(constraint2, constraint1, true); }
private static List <ILengthAngleConstraints> CalculateLengthAngleConstraints(ShapeConstraints shapeConstraints) { List <ILengthAngleConstraints> result = new List <ILengthAngleConstraints>(); for (int i = 0; i < shapeConstraints.ShapeStructure.Edges.Count; ++i) { ShapeEdge edge = shapeConstraints.ShapeStructure.Edges[i]; VertexConstraints vertex1Constraints = shapeConstraints.VertexConstraints[edge.Index1]; VertexConstraints vertex2Constraints = shapeConstraints.VertexConstraints[edge.Index2]; result.Add(BoxSetLengthAngleConstraints.FromVertexConstraints(vertex1Constraints, vertex2Constraints, 1, 16)); } return(result); }
public AllowedLengthAngleChecker( VertexConstraints constraint1, VertexConstraints constraint2, GeneralizedDistanceTransform2D checkingTransform, double lengthRatio, double meanAngle) { this.lengthAngleStatus = new Image2D <byte>(checkingTransform.GridSize.Width, checkingTransform.GridSize.Height); LengthAngleSpaceSeparatorSet separator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2); this.checkingTransform = checkingTransform; // Initial fill for (int i = 0; i < checkingTransform.GridSize.Width; ++i) { double scaledLength = checkingTransform.GridIndexToCoordX(i); double length = scaledLength / lengthRatio; for (int j = 0; j < checkingTransform.GridSize.Height; ++j) { double shiftedAngle = checkingTransform.GridIndexToCoordY(j); double angle = shiftedAngle + meanAngle; if (separator.IsInside(length, angle)) { this.lengthAngleStatus[i, j] = 2; } else if (i == 0 || j == 0 || this.lengthAngleStatus[i - 1, j] == 1 || this.lengthAngleStatus[i, j - 1] == 1) { this.lengthAngleStatus[i, j] = 1; } } } // Fill holes for (int i = 0; i < checkingTransform.GridSize.Width; ++i) { for (int j = 0; j < checkingTransform.GridSize.Height; ++j) { if (lengthAngleStatus[i, j] == 0) { lengthAngleStatus[i, j] = 2; } } } }
public static BoxSetLengthAngleConstraints FromVertexConstraints( VertexConstraints vertexConstraints1, VertexConstraints vertexConstraints2, int maxSplitDepth, double nonSplittableArea) { BoxLengthAngleConstraints overallRange = BoxLengthAngleConstraints.FromVertexConstraints( vertexConstraints1, vertexConstraints2); IEnumerable<VertexConstraints> split1 = GenerateSplit(vertexConstraints1, maxSplitDepth, nonSplittableArea); IEnumerable<VertexConstraints> split2 = GenerateSplit(vertexConstraints2, maxSplitDepth, nonSplittableArea); List<BoxLengthAngleConstraints> childConstraints = new List<BoxLengthAngleConstraints>(); foreach (VertexConstraints childVertexConstraints1 in split1) foreach (VertexConstraints childVertexConstraints2 in split2) childConstraints.Add(BoxLengthAngleConstraints.FromVertexConstraints(childVertexConstraints1, childVertexConstraints2)); return new BoxSetLengthAngleConstraints(childConstraints, overallRange); }
private static IEnumerable<VertexConstraints> GenerateSplit( VertexConstraints constraints, int maxSplitDepth, double nonSplittableArea) { List<VertexConstraints> split = new List<VertexConstraints> { constraints }; int iteration = 0; int splitIndex = 0; while (split[iteration].Area > nonSplittableArea && iteration < maxSplitDepth) { int length = split.Count; for (int i = splitIndex; i < length; ++i) split.AddRange(split[i].Split()); splitIndex = length; ++iteration; } return split.Skip(splitIndex); }
private void AddSeparatorsForPoint(Vector point, VertexConstraints constraint2, bool swapDirection) { this.separatorLists.Add(new List <LengthAngleSpaceSeparator>()); Vector middlePoint = 0.5 * (constraint2.Corners[0] + constraint2.Corners[2]); for (int j = 0; j < 4; ++j) { Vector segmentStart = constraint2.Corners[j]; Vector segmentEnd = constraint2.Corners[(j + 1) % 4]; Vector segmentMiddle = 0.5 * (segmentStart + segmentEnd); Vector allowedPoint = segmentMiddle + (middlePoint - segmentMiddle) * 0.01; Vector allowedVec = allowedPoint - point; double allowedLength = allowedVec.Length; double allowedAngle = Vector.AngleBetween(Vector.UnitX, allowedVec); this.separatorLists[this.separatorLists.Count - 1].Add( new LengthAngleSpaceSeparator(segmentStart, segmentEnd, point, allowedLength, allowedAngle, swapDirection)); } }
private void AddSeparatorsForPoint(Vector point, VertexConstraints constraint2, bool swapDirection) { this.separatorLists.Add(new List<LengthAngleSpaceSeparator>()); Vector middlePoint = 0.5 * (constraint2.Corners[0] + constraint2.Corners[2]); for (int j = 0; j < 4; ++j) { Vector segmentStart = constraint2.Corners[j]; Vector segmentEnd = constraint2.Corners[(j + 1) % 4]; Vector segmentMiddle = 0.5 * (segmentStart + segmentEnd); Vector allowedPoint = segmentMiddle + (middlePoint - segmentMiddle) * 0.01; Vector allowedVec = allowedPoint - point; double allowedLength = allowedVec.Length; double allowedAngle = Vector.AngleBetween(Vector.UnitX, allowedVec); this.separatorLists[this.separatorLists.Count - 1].Add( new LengthAngleSpaceSeparator(segmentStart, segmentEnd, point, allowedLength, allowedAngle, swapDirection)); } }
public AllowedLengthAngleChecker( VertexConstraints constraint1, VertexConstraints constraint2, GeneralizedDistanceTransform2D checkingTransform, double lengthRatio, double meanAngle) { this.lengthAngleStatus = new Image2D<byte>(checkingTransform.GridSize.Width, checkingTransform.GridSize.Height); LengthAngleSpaceSeparatorSet separator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2); this.checkingTransform = checkingTransform; // Initial fill for (int i = 0; i < checkingTransform.GridSize.Width; ++i) { double scaledLength = checkingTransform.GridIndexToCoordX(i); double length = scaledLength / lengthRatio; for (int j = 0; j < checkingTransform.GridSize.Height; ++j) { double shiftedAngle = checkingTransform.GridIndexToCoordY(j); double angle = shiftedAngle + meanAngle; if (separator.IsInside(length, angle)) this.lengthAngleStatus[i, j] = 2; else if (i == 0 || j == 0 || this.lengthAngleStatus[i - 1, j] == 1 || this.lengthAngleStatus[i, j - 1] == 1) this.lengthAngleStatus[i, j] = 1; } } // Fill holes for (int i = 0; i < checkingTransform.GridSize.Width; ++i) { for (int j = 0; j < checkingTransform.GridSize.Height; ++j) { if (lengthAngleStatus[i, j] == 0) lengthAngleStatus[i, j] = 2; } } }
public static BoxSetLengthAngleConstraints FromVertexConstraints( VertexConstraints vertexConstraints1, VertexConstraints vertexConstraints2, int maxSplitDepth, double nonSplittableArea) { BoxLengthAngleConstraints overallRange = BoxLengthAngleConstraints.FromVertexConstraints( vertexConstraints1, vertexConstraints2); IEnumerable <VertexConstraints> split1 = GenerateSplit(vertexConstraints1, maxSplitDepth, nonSplittableArea); IEnumerable <VertexConstraints> split2 = GenerateSplit(vertexConstraints2, maxSplitDepth, nonSplittableArea); List <BoxLengthAngleConstraints> childConstraints = new List <BoxLengthAngleConstraints>(); foreach (VertexConstraints childVertexConstraints1 in split1) { foreach (VertexConstraints childVertexConstraints2 in split2) { childConstraints.Add(BoxLengthAngleConstraints.FromVertexConstraints(childVertexConstraints1, childVertexConstraints2)); } } return(new BoxSetLengthAngleConstraints(childConstraints, overallRange)); }
private static IEnumerable <VertexConstraints> GenerateSplit( VertexConstraints constraints, int maxSplitDepth, double nonSplittableArea) { List <VertexConstraints> split = new List <VertexConstraints> { constraints }; int iteration = 0; int splitIndex = 0; while (split[iteration].Area > nonSplittableArea && iteration < maxSplitDepth) { int length = split.Count; for (int i = splitIndex; i < length; ++i) { split.AddRange(split[i].Split()); } splitIndex = length; ++iteration; } return(split.Skip(splitIndex)); }
public void CalculateShapeTerms(ShapeModel model, ShapeConstraints constraintsSet, Image2D <ObjectBackgroundTerm> result) { if (model == null) { throw new ArgumentNullException("model"); } if (constraintsSet == null) { throw new ArgumentNullException("constraintsSet"); } if (result == null) { throw new ArgumentNullException("result"); } if (model.Structure != constraintsSet.ShapeStructure) { throw new ArgumentException("Shape model and shape constraints correspond to different shape structures."); } if (model != this.shapeModel || result.Rectangle.Size != this.imageSize) { this.SetTarget(model, result.Rectangle.Size); } for (int x = 0; x < imageSize.Width; ++x) { for (int y = 0; y < imageSize.Height; ++y) { result[x, y] = new ObjectBackgroundTerm(Double.PositiveInfinity, 0); } } for (int edgeIndex = 0; edgeIndex < this.shapeModel.Structure.Edges.Count; ++edgeIndex) { ShapeEdge edge = this.shapeModel.Structure.Edges[edgeIndex]; VertexConstraints vertexConstraints1 = constraintsSet.VertexConstraints[edge.Index1]; VertexConstraints vertexConstraints2 = constraintsSet.VertexConstraints[edge.Index2]; EdgeConstraints edgeConstraints = constraintsSet.EdgeConstraints[edgeIndex]; Image2D <ObjectBackgroundTerm> edgeTerms; EdgeDescription edgeDescription = new EdgeDescription( vertexConstraints1, vertexConstraints2, edgeConstraints); if (!this.cachedEdgeTerms.TryGetValue(edgeDescription, out edgeTerms)) { edgeTerms = this.AllocateImage(); this.cachedEdgeTerms.Add(edgeDescription, edgeTerms); Polygon convexHull = constraintsSet.GetConvexHullForVertexPair(edge.Index1, edge.Index2); Parallel.For( 0, imageSize.Width, x => { for (int y = 0; y < imageSize.Height; ++y) { Vector pointAsVec = new Vector(x, y); double minDistanceSqr, maxDistanceSqr; MinMaxDistanceForEdge( pointAsVec, convexHull, vertexConstraints1, vertexConstraints2, out minDistanceSqr, out maxDistanceSqr); edgeTerms[x, y] = new ObjectBackgroundTerm( this.shapeModel.CalculateObjectPenaltyForEdge( minDistanceSqr, edgeConstraints.MaxWidth), this.shapeModel.CalculateBackgroundPenaltyForEdge( maxDistanceSqr, edgeConstraints.MinWidth)); } }); } for (int x = 0; x < imageSize.Width; ++x) { for (int y = 0; y < imageSize.Height; ++y) { result[x, y] = new ObjectBackgroundTerm( Math.Min(result[x, y].ObjectTerm, edgeTerms[x, y].ObjectTerm), Math.Max(result[x, y].BackgroundTerm, edgeTerms[x, y].BackgroundTerm)); } } } }
private void AddSeparatorsForPair(VertexConstraints constraint1, VertexConstraints constraint2, bool swapDirection) { for (int i = 0; i < 4; ++i) this.AddSeparatorsForPoint(constraint1.Corners[i], constraint2, swapDirection); }
public static BoxLengthAngleConstraints FromVertexConstraints(VertexConstraints constraints1, VertexConstraints constraints2) { Range angleRange; Range xRange1 = new Range(constraints1.MinCoord.X, constraints1.MaxCoord.X); Range yRange1 = new Range(constraints1.MinCoord.Y, constraints1.MaxCoord.Y); Range xRange2 = new Range(constraints2.MinCoord.X, constraints2.MaxCoord.X); Range yRange2 = new Range(constraints2.MinCoord.Y, constraints2.MaxCoord.Y); bool xIntersection = xRange1.IntersectsWith(xRange2); bool yIntersection = yRange1.IntersectsWith(yRange2); double minLength = Double.PositiveInfinity, maxLength = 0; if (xIntersection && yIntersection) { // Special case: intersecting rectangles angleRange = new Range(-Math.PI, Math.PI); minLength = 0; } else { // Angle changes from PI to -PI when second constraint is to the left of the first one bool angleSignChanges = constraints1.MinCoord.X > constraints2.MaxCoord.X && yIntersection; double minAngle = angleSignChanges ? -Math.PI : Math.PI; double maxAngle = angleSignChanges ? Math.PI : -Math.PI; foreach (Vector point1 in constraints1.Corners) { foreach (Vector point2 in constraints2.Corners) { double angle = Vector.AngleBetween(new Vector(1, 0), point2 - point1); if (angleSignChanges) { if (angle < 0) { minAngle = Math.Max(minAngle, angle); } else { maxAngle = Math.Min(maxAngle, angle); } } else { minAngle = Math.Min(minAngle, angle); maxAngle = Math.Max(maxAngle, angle); } } } angleRange = new Range(minAngle, maxAngle, angleSignChanges); // One constraint is on top or on bottom of another if (xIntersection) { // 1 on top of 2 if (constraints1.MinCoord.Y > constraints2.MaxCoord.Y) { minLength = Math.Min(minLength, constraints1.MinCoord.Y - constraints2.MaxCoord.Y); } // 2 on top of 1 else { minLength = Math.Min(minLength, constraints2.MinCoord.Y - constraints1.MaxCoord.Y); } } else if (yIntersection) { // 1 to the left of 2 if (constraints1.MaxCoord.X < constraints2.MinCoord.X) { minLength = Math.Min(minLength, constraints2.MinCoord.X - constraints1.MaxCoord.X); } // 2 to the left of 1 else { minLength = Math.Min(minLength, constraints1.MinCoord.X - constraints2.MaxCoord.X); } } } foreach (Vector point1 in constraints1.Corners) { foreach (Vector point2 in constraints2.Corners) { double length = (point1 - point2).Length; minLength = Math.Min(minLength, length); maxLength = Math.Max(maxLength, length); } } Range lengthRange = new Range(minLength, maxLength); return(new BoxLengthAngleConstraints(lengthRange, angleRange)); }
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); } }
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); }
private static void MinMaxDistanceForEdge( Vector point, Polygon convexHull, VertexConstraints constraints1, VertexConstraints constraints2, out double minDistanceSqr, out double maxDistanceSqr) { if (convexHull.IsPointInside(point)) minDistanceSqr = 0; else { minDistanceSqr = Double.PositiveInfinity; for (int i = 0; i < convexHull.Vertices.Count; ++i) { double distanceSqr = point.DistanceToSegmentSquared( convexHull.Vertices[i], convexHull.Vertices[(i + 1) % convexHull.Vertices.Count]); minDistanceSqr = Math.Min(minDistanceSqr, distanceSqr); } } maxDistanceSqr = 0; foreach (Vector vertex1 in constraints1.Corners) { foreach (Vector vertex2 in constraints2.Corners) { double distanceSqr = point.DistanceToSegmentSquared(vertex1, vertex2); maxDistanceSqr = Math.Max(maxDistanceSqr, distanceSqr); } } }
public static BoxLengthAngleConstraints FromVertexConstraints(VertexConstraints constraints1, VertexConstraints constraints2) { Range angleRange; Range xRange1 = new Range(constraints1.MinCoord.X, constraints1.MaxCoord.X); Range yRange1 = new Range(constraints1.MinCoord.Y, constraints1.MaxCoord.Y); Range xRange2 = new Range(constraints2.MinCoord.X, constraints2.MaxCoord.X); Range yRange2 = new Range(constraints2.MinCoord.Y, constraints2.MaxCoord.Y); bool xIntersection = xRange1.IntersectsWith(xRange2); bool yIntersection = yRange1.IntersectsWith(yRange2); double minLength = Double.PositiveInfinity, maxLength = 0; if (xIntersection && yIntersection) { // Special case: intersecting rectangles angleRange = new Range(-Math.PI, Math.PI); minLength = 0; } else { // Angle changes from PI to -PI when second constraint is to the left of the first one bool angleSignChanges = constraints1.MinCoord.X > constraints2.MaxCoord.X && yIntersection; double minAngle = angleSignChanges ? -Math.PI : Math.PI; double maxAngle = angleSignChanges ? Math.PI : -Math.PI; foreach (Vector point1 in constraints1.Corners) { foreach (Vector point2 in constraints2.Corners) { double angle = Vector.AngleBetween(new Vector(1, 0), point2 - point1); if (angleSignChanges) { if (angle < 0) minAngle = Math.Max(minAngle, angle); else maxAngle = Math.Min(maxAngle, angle); } else { minAngle = Math.Min(minAngle, angle); maxAngle = Math.Max(maxAngle, angle); } } } angleRange = new Range(minAngle, maxAngle, angleSignChanges); // One constraint is on top or on bottom of another if (xIntersection) { // 1 on top of 2 if (constraints1.MinCoord.Y > constraints2.MaxCoord.Y) minLength = Math.Min(minLength, constraints1.MinCoord.Y - constraints2.MaxCoord.Y); // 2 on top of 1 else minLength = Math.Min(minLength, constraints2.MinCoord.Y - constraints1.MaxCoord.Y); } else if (yIntersection) { // 1 to the left of 2 if (constraints1.MaxCoord.X < constraints2.MinCoord.X) minLength = Math.Min(minLength, constraints2.MinCoord.X - constraints1.MaxCoord.X); // 2 to the left of 1 else minLength = Math.Min(minLength, constraints1.MinCoord.X - constraints2.MaxCoord.X); } } foreach (Vector point1 in constraints1.Corners) { foreach (Vector point2 in constraints2.Corners) { double length = (point1 - point2).Length; minLength = Math.Min(minLength, length); maxLength = Math.Max(maxLength, length); } } Range lengthRange = new Range(minLength, maxLength); return new BoxLengthAngleConstraints(lengthRange, angleRange); }
public EdgeDescription( VertexConstraints vertexConstraints1, VertexConstraints vertexConstraints2, EdgeConstraints edgeConstraints) { this.VertexConstraints1 = vertexConstraints1; this.VertexConstraints2 = vertexConstraints2; this.EdgeConstraints = edgeConstraints; }