} // Main(...) private static CheetahDataSet CreateDataSet() { // 1. Creating data set var dataSet = new CheetahDataSet(); // 2. Creating geometry var line1 = new CheetahLine2D(0, 0, 10, 1); var line2 = new CheetahLine2D(10, 0, 10, 11); var line3 = new CheetahLine2D(10, 10, 1, 10); var line4 = new CheetahLine2D(0, 10, 1, 1); // 3. Creating constraints dataSet.AddCoincidence(line1, IdentifiableValueReferences.LineEnd, line2, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line2, IdentifiableValueReferences.LineEnd, line3, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line3, IdentifiableValueReferences.LineEnd, line4, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line4, IdentifiableValueReferences.LineEnd, line1, IdentifiableValueReferences.LineStart); dataSet.AddPerpendicular(line1, line2); dataSet.AddPerpendicular(line2, line3); dataSet.AddParallel(line2, line4); // 4. Now we have geometric model (4 line segments and 7 constraints) // with everything necessary for creating rectangle. // Geometric constraints are not satisfied yet. return(dataSet); } // CreateDataSet()
} // Main(...) static ICollection<CheetahCurve> EvaluationOnTheFirstApplicationOfConstraint(ICheetahSolver solver, CheetahDataSet dataSet) { // 1. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); // 2. Initializing parametric object using data set // On this step we are compiling the model and creating system of equation // After that we will be ready to run the solver if (!parametric.Init(dataSet, null, null)) // If parametric.Init will return FALSE, then there is critical error in the data set // So we are not able to make system of equation and to evaluate the problem // We should cancel the procedure and rebuild data set throw new Exception("Something goes wrong"); // 3. Regenerating constrained model (running solver) // On this step we are solving the system of equation, that we've made in the previous step if (!parametric.Evaluate()) throw new Exception("Something goes wrong"); // 4. Retrieving results var resultGeometry = parametric.GetSolution(true); // 5. We have to clear compiled data parametric.ClearSolver(); return resultGeometry; } // EvaluationOnTheFirstApplicationOfConstraint(...)
static void Main(string[] args) { // 1. Creating data set var dataSet = new CheetahDataSet(); // 2. Creating geometry var line1 = new CheetahLine2D(13, 20, 10, 12); var line2 = new CheetahLine2D(8, 10, 20, 9); // 3. Creating constraints (put end point of line1 on line2) dataSet.AddPointOnCurve(line1, IdentifiableValueReferences.LineEnd, line2); // 4. Creating solver object var solver = new SolverCpu10(); // 5. First we evaluate the system the way as we just have added new constraint var resultGeometry = EvaluationOnTheFirstApplicationOfConstraint(solver, dataSet); // 6. Applying the solution to data set var resultLine1 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line1.Id); var resultLine2 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line2.Id); line1.FillData(resultLine1); line2.FillData(resultLine2); // 7. Just to check, we don't need to do it all the time, because if parametric. // If Evaluate returned true then the problem is solved correctly if (!IsPointOnLine(line1.End, line2)) { throw new Exception("Something goes wrong"); } // 8. Now we are simulating drag resultGeometry = EvaluationOnDragginTheLine(solver, dataSet, line1, line1.End); // 9. Applying the solution to data set resultLine1 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line1.Id); resultLine2 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line2.Id); line1.FillData(resultLine1); line2.FillData(resultLine2); // 10. Just to check again if (!IsPointOnLine(line1.End, line2)) { throw new Exception("Something goes wrong"); } } // Main(...)
static void Main(string[] args) { // 1. Creating data set var dataSet = new CheetahDataSet(); // 2. Creating geometry var line1 = new CheetahLine2D(13, 20, 10, 12); var line2 = new CheetahLine2D(8, 10, 20, 9); // 3. Creating constraints (put end point of line1 on line2) dataSet.AddPointOnCurve(line1, IdentifiableValueReferences.LineEnd, line2); // 4. Creating solver object var solver = new SolverCpu10(); // 5. First we evaluate the system the way as we just have added new constraint var resultGeometry = EvaluationOnTheFirstApplicationOfConstraint(solver, dataSet); // 6. Applying the solution to data set var resultLine1 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line1.Id); var resultLine2 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line2.Id); line1.FillData(resultLine1); line2.FillData(resultLine2); // 7. Just to check, we don't need to do it all the time, because if parametric. // If Evaluate returned true then the problem is solved correctly if (!IsPointOnLine(line1.End, line2)) throw new Exception("Something goes wrong"); // 8. Now we are simulating drag resultGeometry = EvaluationOnDragginTheLine(solver, dataSet, line1, line1.End); // 9. Applying the solution to data set resultLine1 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line1.Id); resultLine2 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line2.Id); line1.FillData(resultLine1); line2.FillData(resultLine2); // 10. Just to check again if (!IsPointOnLine(line1.End, line2)) throw new Exception("Something goes wrong"); } // Main(...)
static void Main(string[] args) { // 1. Creating geometric model var dataSet = new CheetahDataSet(); var entIdList = new List <long>(); CreateGeometricModel(dataSet, entIdList); // 2. Creating solver object var solver = new SolverCpu10(); // 3. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false); const double precision = 1E-15; // Working with much better accuracy then the default 1E-12 CheetahParametricBasic.Settings.Precision = precision; // 4. Initializing parametric object using data set if (!parametric.Init(dataSet, null, null)) { throw new Exception("Something goes wrong"); } // 5. Running constraints solver if (!parametric.Evaluate()) { throw new Exception("Something goes wrong"); } // 6. Retrieving results (we created rectangle with fillets that is "closest" to the initial lines and arcs) var resultGeometry = parametric.GetSolution(true); // 7. Checking that all geometric constraints are satisfied. // Actually, we have no need to check - if Evaluate returns true than everything is OK if (!CheckResults(resultGeometry, entIdList, precision)) { throw new Exception("Something goes wrong"); } GC.Collect(); } // Main(...)
static void Main(string[] args) { const string filePath = "dataset.xml"; // 1. Creating entities and constraints (constraints are not satisfied yet) var dataSet = CreateDataSet(); // 2. Saving data set to xml-file dataSet.SaveToXml(filePath); // 3. Loading data set from xml-file var dataSetFromFile = CheetahDataSet.LoadFromXml(filePath); // 4. Creating solver object var solver = new SolverCpu10(); // 5. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); const double precision = 1E-8; // Working with lower accuracy then default 1E-12 CheetahParametricBasic.Settings.Precision = precision; // 6. Initializing parametric object using data set if (!parametric.Init(dataSetFromFile, null, null)) { throw new Exception("Something goes wrong"); } // 7. Regenerating constrained model (running solver) if (!parametric.Evaluate()) { throw new Exception("Something goes wrong"); } // 8. Retrieving results (we created rectangle that is "closest" to the initial lines) var resultGeometry = parametric.GetSolution(true); GC.Collect(); } // Main(...)
static void Main(string[] args) { // 1. Creating geometric model var dataSet = new CheetahDataSet(); var entIdList = new List<long>(); CreateGeometricModel(dataSet, entIdList); // 2. Creating solver object var solver = new SolverCpu10(); // 3. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false); const double precision = 1E-15; // Working with much better accuracy then the default 1E-12 CheetahParametricBasic.Settings.Precision = precision; // 4. Initializing parametric object using data set if (!parametric.Init(dataSet, null, null)) throw new Exception("Something goes wrong"); // 5. Running constraints solver if (!parametric.Evaluate()) throw new Exception("Something goes wrong"); // 6. Retrieving results (we created rectangle with fillets that is "closest" to the initial lines and arcs) var resultGeometry = parametric.GetSolution(true); // 7. Checking that all geometric constraints are satisfied. // Actually, we have no need to check - if Evaluate returns true than everything is OK if (!CheckResults(resultGeometry, entIdList, precision)) throw new Exception("Something goes wrong"); GC.Collect(); } // Main(...)
} // Main(...) private static CheetahDataSet CreateDataSet() { // 1. Creating data set var dataSet = new CheetahDataSet(); // 2. Creating geometry var line1 = new CheetahLine2D(0, 0, 10, 1); var line2 = new CheetahLine2D(10, 0, 10, 11); var line3 = new CheetahLine2D(10, 10, 1, 10); var line4 = new CheetahLine2D(0, 10, 1, 1); // 3. Creating constraints dataSet.AddCoincidence(line1, IdentifiableValueReferences.LineEnd, line2, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line2, IdentifiableValueReferences.LineEnd, line3, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line3, IdentifiableValueReferences.LineEnd, line4, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line4, IdentifiableValueReferences.LineEnd, line1, IdentifiableValueReferences.LineStart); dataSet.AddPerpendicular(line1, line2); dataSet.AddPerpendicular(line2, line3); dataSet.AddParallel(line2, line4); // 4. Now we have geometric model (4 line segments and 7 constraints) // with everything necessary for creating rectangle. // Geometric constraints are not satisfied yet. return dataSet; } // CreateDataSet()
} // EvaluationOnTheFirstApplicationOfConstraint(...) static ICollection<CheetahCurve> EvaluationOnDragginTheLine(ICheetahSolver solver, CheetahDataSet dataSet, CheetahLine2D draggingLine, CheetahPoint2D draggingPoint) { // 1. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); // 2. Initializing parametric object using data set // On this step we are compiling the model and creating system of equation // After that we will be ready to run the solver // We will drag the line, so we need to specify the curve to drag and the dragging point if (!parametric.Init(dataSet, new[] { draggingLine }, new[] { draggingPoint })) // If parametric.Init will return FALSE, then there is critical error in data set // So we are not able to make system of equation and to evaluate the problem // We should cancel the procedure and rebuild data set throw new Exception("Something goes wrong"); // 3. Now we can drag. We don't need to recompile the model on each drag iteration, // because the model will be the same - only initial value (the drag point) will be changed // We are simulating drag using this loop for (var i = 0; i < 100; i++) { // 4. Our parametric object is initialized by dataSet object // So the current values of the dataSet curves are the initial values of the system // If we will change some value - the initial values will be changed appropriately // All that we need to reinitialize the model by the new point from the screen // is to reset the value for the dragging line end point draggingLine.End.X *= 1.01; draggingLine.End.Y *= 1.05; // 5. Regenerating constrained model (running solver) // On this step we are solving the system of equation, that we've prepared on the previous step // Now we are dragging the curve and, because we do it manually (by mouse), we can not be precise // We don't need to calculate on each step with 10^-12 or greater precision // So we can cheat a little and decrease the precision for drag iterations // That's why we are using parametric.EvaluateFast function if (!parametric.EvaluateFast()) // If parametric.EvaluateFast will return FALSE it usually means that we can not evaluate the system // with this initial values (we have reached maximum number of iterations)/ // It is NOT a critical problem. This situation can appear while we drag some curve // in position that conflict with constraints/ // For example, while we rounding out the arc and can get negative radius, // or squeeze the line to zero length (and get negative length) // In our solver, if we have such a situation - we restore the previous drag iteration solution. throw new Exception("Something goes wrong"); // In this example we don't use results of EvaluateFast/ // In real life they may be retreived and used to update dragging lines on the screen } // 6. Regenerating constrained model (running solver) // Now we "click the mouse button" to end the drag. // We need to evaluate the system with high precision (that's why we use Evaluate instead of EvaluateFast) // We can use last iteration solution as new initial value to evaluate the system much faster // (for this purpose we set recompile parameter to false) if (!parametric.Evaluate(false)) throw new Exception("Something goes wrong"); // 7. Retrieving results var resultGeometry = parametric.GetSolution(true); // 8. We have to clear compiled data parametric.ClearSolver(); return resultGeometry; } // EvaluationOnDragginTheLine(...)
} // Main(...) static ICollection <CheetahCurve> EvaluationOnTheFirstApplicationOfConstraint(ICheetahSolver solver, CheetahDataSet dataSet) { // 1. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); // 2. Initializing parametric object using data set // On this step we are compiling the model and creating system of equation // After that we will be ready to run the solver if (!parametric.Init(dataSet, null, null)) { // If parametric.Init will return FALSE, then there is critical error in the data set // So we are not able to make system of equation and to evaluate the problem // We should cancel the procedure and rebuild data set throw new Exception("Something goes wrong"); } // 3. Regenerating constrained model (running solver) // On this step we are solving the system of equation, that we've made in the previous step if (!parametric.Evaluate()) { throw new Exception("Something goes wrong"); } // 4. Retrieving results var resultGeometry = parametric.GetSolution(true); // 5. We have to clear compiled data parametric.ClearSolver(); return(resultGeometry); } // EvaluationOnTheFirstApplicationOfConstraint(...)
} // EvaluationOnTheFirstApplicationOfConstraint(...) static ICollection <CheetahCurve> EvaluationOnDragginTheLine(ICheetahSolver solver, CheetahDataSet dataSet, CheetahLine2D draggingLine, CheetahPoint2D draggingPoint) { // 1. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); // 2. Initializing parametric object using data set // On this step we are compiling the model and creating system of equation // After that we will be ready to run the solver // We will drag the line, so we need to specify the curve to drag and the dragging point if (!parametric.Init(dataSet, new[] { draggingLine }, new[] { draggingPoint })) { // If parametric.Init will return FALSE, then there is critical error in data set // So we are not able to make system of equation and to evaluate the problem // We should cancel the procedure and rebuild data set throw new Exception("Something goes wrong"); } // 3. Now we can drag. We don't need to recompile the model on each drag iteration, // because the model will be the same - only initial value (the drag point) will be changed // We are simulating drag using this loop for (var i = 0; i < 100; i++) { // 4. Our parametric object is initialized by dataSet object // So the current values of the dataSet curves are the initial values of the system // If we will change some value - the initial values will be changed appropriately // All that we need to reinitialize the model by the new point from the screen // is to reset the value for the dragging line end point draggingLine.End.X *= 1.01; draggingLine.End.Y *= 1.05; // 5. Regenerating constrained model (running solver) // On this step we are solving the system of equation, that we've prepared on the previous step // Now we are dragging the curve and, because we do it manually (by mouse), we can not be precise // We don't need to calculate on each step with 10^-12 or greater precision // So we can cheat a little and decrease the precision for drag iterations // That's why we are using parametric.EvaluateFast function if (!parametric.EvaluateFast()) { // If parametric.EvaluateFast will return FALSE it usually means that we can not evaluate the system // with this initial values (we have reached maximum number of iterations)/ // It is NOT a critical problem. This situation can appear while we drag some curve // in position that conflict with constraints/ // For example, while we rounding out the arc and can get negative radius, // or squeeze the line to zero length (and get negative length) // In our solver, if we have such a situation - we restore the previous drag iteration solution. throw new Exception("Something goes wrong"); } // In this example we don't use results of EvaluateFast/ // In real life they may be retreived and used to update dragging lines on the screen } // 6. Regenerating constrained model (running solver) // Now we "click the mouse button" to end the drag. // We need to evaluate the system with high precision (that's why we use Evaluate instead of EvaluateFast) // We can use last iteration solution as new initial value to evaluate the system much faster // (for this purpose we set recompile parameter to false) if (!parametric.Evaluate(false)) { throw new Exception("Something goes wrong"); } // 7. Retrieving results var resultGeometry = parametric.GetSolution(true); // 8. We have to clear compiled data parametric.ClearSolver(); return(resultGeometry); } // EvaluationOnDragginTheLine(...)
static void Main(string[] args) { // 1. Creating data set var dataSet = new CheetahDataSet(); // 2. Creating geometry var line1 = new CheetahLine2D(0, 0, 10, 1); var line2 = new CheetahLine2D(10, 0, 10, 11); var line3 = new CheetahLine2D(10, 10, 1, 10); var line4 = new CheetahLine2D(0, 10, 1, 1); // 3. Creating constraints dataSet.AddCoincidence(line1, IdentifiableValueReferences.LineEnd, line2, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line2, IdentifiableValueReferences.LineEnd, line3, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line3, IdentifiableValueReferences.LineEnd, line4, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line4, IdentifiableValueReferences.LineEnd, line1, IdentifiableValueReferences.LineStart); dataSet.AddPerpendicular(line1, line2); dataSet.AddPerpendicular(line2, line3); dataSet.AddParallel(line2, line4); // 4. Creating solver object var solver = new SolverCpu10(); // 5. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); const double precision = 1E-14; // Working with better accuracy then default 1E-12 CheetahParametricBasic.Settings.Precision = precision; // 6. Initializing parametric object using data set if (!parametric.Init(dataSet, null, null)) { throw new Exception("Something goes wrong"); } // 7. Regenerating constrained model (running solver) if (!parametric.Evaluate()) { throw new Exception("Something goes wrong"); } // 8. Retrieving results (we created rectangle that is "closest" to the initial lines) var resultGeometry = parametric.GetSolution(true); // 9. We can find corresponding objects by id var resultLine1 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line1.Id); var resultLine2 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line2.Id); var resultLine3 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line3.Id); var resultLine4 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line4.Id); // 10. Now we can check that all constraints are satisfied (line segments form rectangle) if (Math.Abs(resultLine1.End.X - resultLine2.Start.X) > precision || Math.Abs(resultLine1.End.Y - resultLine2.Start.Y) > precision) { throw new Exception("Something goes wrong"); } if (Math.Abs(resultLine2.End.X - resultLine3.Start.X) > precision || Math.Abs(resultLine2.End.Y - resultLine3.Start.Y) > precision) { throw new Exception("Something goes wrong"); } if (Math.Abs(resultLine3.End.X - resultLine4.Start.X) > precision || Math.Abs(resultLine3.End.Y - resultLine4.Start.Y) > precision) { throw new Exception("Something goes wrong"); } if (Math.Abs(resultLine4.End.X - resultLine1.Start.X) > precision || Math.Abs(resultLine4.End.Y - resultLine1.Start.Y) > precision) { throw new Exception("Something goes wrong"); } if (!IsDivisible(resultLine1.PolarAngle - resultLine2.PolarAngle, Math.PI / 2, precision)) { throw new Exception("Something goes wrong"); } if (!IsDivisible(resultLine2.PolarAngle - resultLine3.PolarAngle, Math.PI / 2, precision)) { throw new Exception("Something goes wrong"); } if (!IsDivisible(resultLine2.PolarAngle - resultLine4.PolarAngle, Math.PI, precision)) { throw new Exception("Something goes wrong"); } GC.Collect(); } // Main(...)
} // Main(...) private static void CreateGeometricModel(CheetahDataSet dataSet, ICollection <long> entIdList) { // 1. Creating line segments and appending them to the data set var line1 = new CheetahLine2D(0.5, -0.5, 8.5, 0.5); var line2 = new CheetahLine2D(10.5, 1.5, 9.5, 8.5); var line3 = new CheetahLine2D(9.5, 9.5, 0.5, 10.5); var line4 = new CheetahLine2D(0.5, 8.5, -0.5, 1.5); entIdList.Add(line1.Id); entIdList.Add(line2.Id); entIdList.Add(line3.Id); entIdList.Add(line4.Id); // 2. Creating circle arcs and appending them to the data set var arc1 = new CheetahArc2D(new CheetahPoint2D(1.5, 1.5), -Math.PI, -Math.PI * 0.5, 1.25); var arc2 = new CheetahArc2D(new CheetahPoint2D(9.25, 0.75), -Math.PI * 0.5, 0.0, 0.5); var arc3 = new CheetahArc2D(new CheetahPoint2D(9.5, 9.5), Math.PI * 0.1, Math.PI * 0.5, 1.5); var arc4 = new CheetahArc2D(new CheetahPoint2D(1.2, 8.5), Math.PI * 0.25, Math.PI, 0.75); entIdList.Add(arc1.Id); entIdList.Add(arc2.Id); entIdList.Add(arc3.Id); entIdList.Add(arc4.Id); // 3. Creating geometric constraints // 3.1. Creating coinsident constraints for the end points of arcs amd line segments dataSet.AddCoincidence(arc1, IdentifiableValueReferences.ArcEnd, line1, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line1, IdentifiableValueReferences.LineEnd, arc2, IdentifiableValueReferences.ArcStart); dataSet.AddCoincidence(arc2, IdentifiableValueReferences.ArcEnd, line2, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line2, IdentifiableValueReferences.LineEnd, arc3, IdentifiableValueReferences.ArcStart); dataSet.AddCoincidence(arc3, IdentifiableValueReferences.ArcEnd, line3, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line3, IdentifiableValueReferences.LineEnd, arc4, IdentifiableValueReferences.ArcStart); dataSet.AddCoincidence(arc4, IdentifiableValueReferences.ArcEnd, line4, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line4, IdentifiableValueReferences.LineEnd, arc1, IdentifiableValueReferences.ArcStart); // 3.2. Creating perpendicular constraints between line segments 1 and 2 dataSet.AddPerpendicular(line1, line2); // 3.3. Creating two parallel constraints between line segments 1 and 3 and line segments 2 and 4 dataSet.AddParallel(line1, line3); dataSet.AddParallel(line2, line4); // 3.4. Creating "equal radius" constraints for all arcs dataSet.AddEqual(arc1, arc2); dataSet.AddEqual(arc2, arc3); dataSet.AddEqual(arc3, arc4); // 3.5 Creating tangent constraints on the connection points of arcs and line segments dataSet.AddTangent(arc1, line1); dataSet.AddTangent(arc2, line1); dataSet.AddTangent(arc2, line2); dataSet.AddTangent(arc3, line2); dataSet.AddTangent(arc3, line3); dataSet.AddTangent(arc4, line3); dataSet.AddTangent(arc4, line4); dataSet.AddTangent(arc1, line4); // 4. Geometric model is created, but constraints are not satisfied yet! } // CreateGeometricModel(...)
} // Main(...) private static void CreateGeometricModel(CheetahDataSet dataSet, ICollection<long> entIdList) { // 1. Creating line segments and appending them to the data set var line1 = new CheetahLine2D(0.5, -0.5, 8.5, 0.5); var line2 = new CheetahLine2D(10.5, 1.5, 9.5, 8.5); var line3 = new CheetahLine2D(9.5, 9.5, 0.5, 10.5); var line4 = new CheetahLine2D(0.5, 8.5, -0.5, 1.5); entIdList.Add(line1.Id); entIdList.Add(line2.Id); entIdList.Add(line3.Id); entIdList.Add(line4.Id); // 2. Creating circle arcs and appending them to the data set var arc1 = new CheetahArc2D(new CheetahPoint2D(1.5, 1.5), -Math.PI, -Math.PI * 0.5, 1.25); var arc2 = new CheetahArc2D(new CheetahPoint2D(9.25, 0.75), -Math.PI * 0.5, 0.0, 0.5); var arc3 = new CheetahArc2D(new CheetahPoint2D(9.5, 9.5), Math.PI * 0.1, Math.PI * 0.5, 1.5); var arc4 = new CheetahArc2D(new CheetahPoint2D(1.2, 8.5), Math.PI * 0.25, Math.PI, 0.75); entIdList.Add(arc1.Id); entIdList.Add(arc2.Id); entIdList.Add(arc3.Id); entIdList.Add(arc4.Id); // 3. Creating geometric constraints // 3.1. Creating coinsident constraints for the end points of arcs amd line segments dataSet.AddCoincidence(arc1, IdentifiableValueReferences.ArcEnd, line1, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line1, IdentifiableValueReferences.LineEnd, arc2, IdentifiableValueReferences.ArcStart); dataSet.AddCoincidence(arc2, IdentifiableValueReferences.ArcEnd, line2, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line2, IdentifiableValueReferences.LineEnd, arc3, IdentifiableValueReferences.ArcStart); dataSet.AddCoincidence(arc3, IdentifiableValueReferences.ArcEnd, line3, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line3, IdentifiableValueReferences.LineEnd, arc4, IdentifiableValueReferences.ArcStart); dataSet.AddCoincidence(arc4, IdentifiableValueReferences.ArcEnd, line4, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line4, IdentifiableValueReferences.LineEnd, arc1, IdentifiableValueReferences.ArcStart); // 3.2. Creating perpendicular constraints between line segments 1 and 2 dataSet.AddPerpendicular(line1, line2); // 3.3. Creating two parallel constraints between line segments 1 and 3 and line segments 2 and 4 dataSet.AddParallel(line1, line3); dataSet.AddParallel(line2, line4); // 3.4. Creating "equal radius" constraints for all arcs dataSet.AddEqual(arc1, arc2); dataSet.AddEqual(arc2, arc3); dataSet.AddEqual(arc3, arc4); // 3.5 Creating tangent constraints on the connection points of arcs and line segments dataSet.AddTangent(arc1, line1); dataSet.AddTangent(arc2, line1); dataSet.AddTangent(arc2, line2); dataSet.AddTangent(arc3, line2); dataSet.AddTangent(arc3, line3); dataSet.AddTangent(arc4, line3); dataSet.AddTangent(arc4, line4); dataSet.AddTangent(arc1, line4); // 4. Geometric model is created, but constraints are not satisfied yet! } // CreateGeometricModel(...)
static void Main(string[] args) { // 1. Creating data set var dataSet = new CheetahDataSet(); // 2. Creating geometry var line1 = new CheetahLine2D(0, 0, 10, 1); var line2 = new CheetahLine2D(10, 0, 10, 11); var line3 = new CheetahLine2D(10, 10, 1, 10); var line4 = new CheetahLine2D(0, 10, 1, 1); // 3. Creating constraints dataSet.AddCoincidence(line1, IdentifiableValueReferences.LineEnd, line2, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line2, IdentifiableValueReferences.LineEnd, line3, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line3, IdentifiableValueReferences.LineEnd, line4, IdentifiableValueReferences.LineStart); dataSet.AddCoincidence(line4, IdentifiableValueReferences.LineEnd, line1, IdentifiableValueReferences.LineStart); dataSet.AddPerpendicular(line1, line2); dataSet.AddPerpendicular(line2, line3); dataSet.AddParallel(line2, line4); // 4. Creating solver object var solver = new SolverCpu10(); // 5. Creating parametric object and setting tolerance (by default 1E-12) var parametric = new CheetahParametricBasic(() => solver, false, true, true); const double precision = 1E-14; // Working with better accuracy then default 1E-12 CheetahParametricBasic.Settings.Precision = precision; // 6. Initializing parametric object using data set if (!parametric.Init(dataSet, null, null)) throw new Exception("Something goes wrong"); // 7. Regenerating constrained model (running solver) if (!parametric.Evaluate()) throw new Exception("Something goes wrong"); // 8. Retrieving results (we created rectangle that is "closest" to the initial lines) var resultGeometry = parametric.GetSolution(true); // 9. We can find corresponding objects by id var resultLine1 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line1.Id); var resultLine2 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line2.Id); var resultLine3 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line3.Id); var resultLine4 = (CheetahLine2D)resultGeometry.Single(x => x.Id == line4.Id); // 10. Now we can check that all constraints are satisfied (line segments form rectangle) if (Math.Abs(resultLine1.End.X - resultLine2.Start.X) > precision || Math.Abs(resultLine1.End.Y - resultLine2.Start.Y) > precision) throw new Exception("Something goes wrong"); if (Math.Abs(resultLine2.End.X - resultLine3.Start.X) > precision || Math.Abs(resultLine2.End.Y - resultLine3.Start.Y) > precision) throw new Exception("Something goes wrong"); if (Math.Abs(resultLine3.End.X - resultLine4.Start.X) > precision || Math.Abs(resultLine3.End.Y - resultLine4.Start.Y) > precision) throw new Exception("Something goes wrong"); if (Math.Abs(resultLine4.End.X - resultLine1.Start.X) > precision || Math.Abs(resultLine4.End.Y - resultLine1.Start.Y) > precision) throw new Exception("Something goes wrong"); if (!IsDivisible(resultLine1.PolarAngle - resultLine2.PolarAngle, Math.PI / 2, precision)) throw new Exception("Something goes wrong"); if (!IsDivisible(resultLine2.PolarAngle - resultLine3.PolarAngle, Math.PI / 2, precision)) throw new Exception("Something goes wrong"); if (!IsDivisible(resultLine2.PolarAngle - resultLine4.PolarAngle, Math.PI, precision)) throw new Exception("Something goes wrong"); GC.Collect(); } // Main(...)