public VariableVector GetBestConnector(VariableVector farAway) { // Current algorithm: There are 360°/_connectors equal-sized sectors; // the "best connector" is the intersection of a sector center line // nearest to the line from center to farAway. // Other ideas: // - Divide the circumference of the box into equal-sized lengths. // - Like before, but with guaranteed connectors at corners. // - Like before, but with additional guaranteed connectors at edge midpoints. var result = new VariableVector("Connector", _solver); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(input: new[] { farAway.X, farAway.Y, _center.X, _center.Y, _diagonal.X, _diagonal.Y }, output: new[] { result.X, result.Y }, computation: (input, output) => { // float[] inputValues = _input.Select(v => (float) v.Value.Lo).ToArray(); // ... I ignore "input" here and use the fields and local variables ... well ... ... should work ... VectorF centerF = _center.AsVectorF(); VectorF diagonalF = _diagonal.AsVectorF(); var farAwayF = farAway.AsVectorF(); VectorF d = farAwayF - centerF; double angle = Math.Atan2(d.GetY(), d.GetX()); double roundedAngle = NormalizedAngle(Math.Round(angle / _sectorAngle) * _sectorAngle); double diagX = diagonalF.GetX() / 2; double diagY = diagonalF.GetY() / 2; double diagonalAngle = NormalizedAngle(Math.Atan2(diagY, diagX)); double x, y; if (roundedAngle < diagonalAngle) { x = diagX; y = x * Math.Tan(roundedAngle); } else if (roundedAngle < Math.PI - diagonalAngle) { y = diagY; x = y * Math.Tan(Math.PI / 2 - roundedAngle); } else if (roundedAngle < Math.PI + diagonalAngle) { x = -diagX; y = x * Math.Tan(roundedAngle); } else if (roundedAngle < 2 * Math.PI - diagonalAngle) { y = -diagY; x = y * Math.Tan(Math.PI / 2 - roundedAngle); } else { x = diagX; y = x * Math.Tan(roundedAngle); } result.X.Set(centerF.GetX() + x); result.Y.Set(centerF.GetY() + y); }); return(result); }
public void TestUnidirectionalComputationConstraint() { { var solver = new SimpleConstraintSolver(); var x = solver.CreateVariable("x"); var y = solver.CreateVariable("y"); var r = solver.CreateVariable("r"); var phi = solver.CreateVariable("phi"); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { x, y }, new[] { r, phi }, CartesianToPolar); var rx = new Range(20, 40, EPS); x.RestrictRange(rx); var ry = new Range(30, 50, EPS); y.RestrictRange(ry); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(50, 50, EPS), r.Value); } { //var solver = new SimpleConstraintSolver(); //var x = solver.Create("a"); //var y = solver.Create("b"); //var r = solver.Create("r"); //var phi = solver.Create("phi"); //new UnidirectionalComputationConstraint(new[] { x, y }, new[] { r, phi }, CartesianToPolar); } }
public void TestConstraintPropagation() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = solver.CreateVariable("c"); var d = solver.CreateVariable("d"); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { a }, new[] { b }, OneMore); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { b }, new[] { c }, OneMore); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { c }, new[] { d }, OneMore); a.Set(10); solver.Solve(_noAbortCheck); Assert.AreEqual(10, a.GetValue()); Assert.AreEqual(11, b.GetValue()); Assert.AreEqual(12, c.GetValue()); Assert.AreEqual(13, d.GetValue()); } }