In all the cases I investigated so far, I could find a reason for the complaint about redundant constraints. It is more the other way around: In several cases there are redundant constraints, that are not reported.abdullah wrote:Hey guys!! I have a question for you. Do you know of any other case where the sketcher reports a constraint as redundant when you would not expect it to?
Well I am learning how it works, so maybe in the future we can take a look to those cases.In all the cases I investigated so far, I could find a reason for the complaint about redundant constraints. It is more the other way around: In several cases there are redundant constraints, that are not reported.
t is an arrangement to simplify the equations. It is only used to "decide" from which point on the ellipse the distance is to be calculated, is not a parameter to the matrix above. The equation of the distance from point to ellipse is a funtion of t, t is solved numerically using Newton-Raphson, fixing the point of the ellipse closest to our point (and this works fine, tested). Then the gradient of the distance with respect to all the intervening parameters (not t, t is not a parameter of the equation) are calculated and returned. The solver builds the system matrix based on those gradients as above.My hypothesis is, you are using the parameter t together with xp and yp
Your comments are very logical. I think it is not the problem, but I have to find the problem first to know.(I have to admit, I never looked into your code. I am not a c++ programmer. The one time, I had a look into the sketcher code, I was totally lost.) Please correct me, if I am wrong.
Yep, but I would not know how to get the gradient from there...The ellipse-simulation-sketch does not have the t-parameter. It based on the pin and string method for an ellipse construction. And it works.
Yes. I use sage, which uses a hundred of opensource packages including maxima... take a look it is totally worth itBy the way: do you know wxMaxima? This program may be helpful in order to generate the needed expressions.
For an ellipse with the focus points F1, F2 and an arbitrary point S on the shape:I do not blame you. It is too long To me it makes sense, but as a generic functionality that would generate desirable construction lines and points of a geometry constrained to the actual geometry... for those who had technical drawing in high school: Do you know a graphical way of obtaining the focuses of an ellipse, given the ellipse and its center?
The code is very alpha state, meaning that these features are only half implemented, most of them have a placeholder code inhereted from circle modified so that it compiles. The real implementation will come with time, but I have given lower priority to it. First working with whistles, then the whistles...A few things I have noticed with the ellipse:
* when trying to drag the ellipse on the perimeter it jumps like crazy
* once you succeed to drag the shape to enlarge the major axis it simply stops after a short distance. No way to enlarge it more.
* trying to enlarge the minor axis doesn't seem to work at all, however shortening is possible
* if you shortened the minor axis and then drag the ellipse (by moving its center) the old shape is restored
The ellipse angle constraint, being an specific constraint, is pending a major design decision, i.e. how do you continue with the design (specific, general constraints on constructions lines, general constraints in new elements on the ellipse, i.e. Inventor material, quadrants as Normand indicated in this thread). Since then, the angle constraint is there to help me fix the ellipse to see if other constraints (like pointonellipse or line tangent to ellipse converge under angle constraint). More or less the same seems to apply to the separate two major and minor radii specific constraints. This we can discuss separately, not to mix things, in reply to* once you set the "angle" constraint to the ellipse you can enlarge as much as you want along the major axis but with a lot of errors in the output window
.IMO this should be solved and handled differently
enlarging along the minor axis works too but you cannot make it longer than the major axis
The theory is extremely easy, the practice might not be so easy, as the ellipse might be constrained with other constraints. In the process of "swapping" (call it create a new one or assign the magnitudes new major to major, last major to minor, rotate by 90º), all the other constraints shall be "updated" (the angle with respect to major axis will change by 90 degrees in any way because the major is now at 90 degrees with respect to before). Conflicting constraints might arise, Redundant constraints might arise, the solver will be force to numerically solve all those new constraints at the same time, not one after the other, which might not converge easily or not at all... The user might be left with a situation he did not know how he ran into... Anyway, for me this is an "advanced feature", meaning yes we can look into it, but it is going to be with the lowest prio in the Ellipse support.=> as said before the ellipse editing shouldn't limit the user. If the user wants to make the minor axis larger then internally the representation of minor and major axis should silently swap
Reply: currently unimplemented. Constraints... parallel, perpendicular, symmetric, angle, ... are on hold until the design decision is made, as the design decission bears an incredible influence on how the will be implemented. Those were the constraints that exposed (to me) the rigidity of the current approach. By only having selectable a point (center point) and an edge, these requirements could difficultly be met.Limitations:
* in case I want to make a line parallel to the the minor or major axis how would I do that? After trying a couple of minutes I have no way found to do that.
At the most (Jim and Ulrich ideas) of selecting the edge and supposing this means apply the e.g. parallel constraint to the major axis. But then it would not be possible to have a similar way for the minor axis (though one could do a construction line perpendicular to the major axis through center point, point on ellipse on both extremes and the do a parallel to this line).IMO this should be solved and handled differently
Yup, I figured it out from Ulrich's "ellipse simulation". Now seems obvious...For an ellipse with the focus points F1, F2 and an arbitrary point S on the shape:
dist(F1, S) + dist(F2,S) = 2 * a = const (with "a" as the length of the major axis)
So, this means that the distance from the focus to the endpoint on the minor axis is equal to the length of the major axis (because of the symmetry). To construct the focus points make a circle around the endpoint on the minor axis with the radius equal to length of the major axis. The intersection points of this circle and the major axis gives you the focus points.
Code: Select all
F1, F2: Focus points
a: major radius
xF1, yF1, xF2, yF2: coordinates of the Focus-points
The major radius and the four coordinates of the focus points do
fully define an ellipse.
These parameters are easier to handle in the solver equations.
Ellipse equation for a point in the ellipse curve: xp, yp
2*a=sqrt((yF2−yp)^2+(xF2−xp)^2)+sqrt((yF1−yp)^2+(xF1−xp)^2)
Code: Select all
double ConstraintEllipseTangentLine::grad(double *param)
{
double deriv=0.;
if (param == p1x() || param == p1y() ||
param == p2x() || param == p2y() ||
param == e1x() || param == e1y() ||
param == rmaj() || param == rmin() ||
param == phi()) {
// So:
// 1. Starting from the parametric equations, solve for t that has the same tangent slope as the line
// E'(t)=m => two roots t0, t1
// 2. Calculate distance from E(t0) and E(t1) to line => select the one (ts) shortest distance to line
// (this is implicit selection by choosing an appropriate initial guess for Newton-Raphson)
// 3. Calculate the partials of this distance assuming constant t of value ts.
// so first is to select the point (X_0,Y_0) in line to calculate
double X_1 = *p1x();
double Y_1 = *p1y();
double X_2 = *p2x();
double Y_2 = *p2y();
double X_c = *e1x();
double Y_c = *e1y();
double a = *rmaj();
double b = *rmin();
double phip = *phi();
// so first get t for our case (the Eccentric anomally corresponding to the closest point of the ellipse)
int i=0, maxmitr=100;
double h, t1, f, df;
// TODO: ellipse check this error
double error=1e-20;
// TODO: ellipse check this for convergence
double X_0 = ( X_1 + X_2 ) / 2;
double Y_0 = ( Y_1 + Y_2 ) / 2;
double t=atan2(a*(-(X_0-X_c)*sin(phip)+(Y_0-Y_c)*cos(phip)),b*((X_0-X_c)*cos(phip)+(Y_0-Y_c)*sin(phip)));
// Newton-Raphson to get the t0 that corresponds to d.
for (i=1; i<=maxmitr; i++){
f=-(-a*sin(phip)*sin(t) +
b*cos(phip)*cos(t))/(a*sin(t)*cos(phip) + b*sin(phip)*cos(t)) - (Y_1 -
Y_2)/(X_1 - X_2);
df=(-a*sin(phip)*sin(t) + b*cos(phip)*cos(t))*(a*cos(phip)*cos(t)
- b*sin(phip)*sin(t))/pow(a*sin(t)*cos(phip) + b*sin(phip)*cos(t), 2) +
(a*sin(phip)*cos(t) + b*sin(t)*cos(phip))/(a*sin(t)*cos(phip) +
b*sin(phip)*cos(t));
h=f/df;
t1=t-h;
if (fabs(h) < error)
break;
t=t1;
}
// t is the solution for the distance at this point
// TODO: Ellipse implementation: Insert the partials
if (param == p1x())
deriv += ((Y_1 - Y_2)/(X_1 - X_2) + (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/pow(X_1 - X_2, 2))*(-Y_1 + Y_c
+ a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2))/(sqrt(1 + pow(Y_1
- Y_2, 2)/pow(X_1 - X_2, 2))*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2), 2))) + pow(Y_1 - Y_2, 2)*sqrt(pow(-Y_1
+ Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 +
X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2), 2))/(pow(1 +
pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2), 3.0L/2.0L)*pow(X_1 - X_2, 3));
if (param == p1y())
deriv += -(1 + (-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2))*(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2))/(sqrt(1 + pow(Y_1 - Y_2, 2)/pow(X_1 -
X_2, 2))*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) -
(Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1
- X_2), 2))) - (Y_1 - Y_2)*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2), 2))/(pow(1 + pow(Y_1 - Y_2, 2)/pow(X_1
- X_2, 2), 3.0L/2.0L)*pow(X_1 - X_2, 2));
if (param == p2x())
deriv += -(Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))*(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2))/(sqrt(1 + pow(Y_1 - Y_2, 2)/pow(X_1 -
X_2, 2))*pow(X_1 - X_2, 2)*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2), 2))) - pow(Y_1 - Y_2, 2)*sqrt(pow(-Y_1
+ Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 +
X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2), 2))/(pow(1 +
pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2), 3.0L/2.0L)*pow(X_1 - X_2, 3));
if (param == p2y())
deriv += (-X_1 + X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))*(-Y_1 +
Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c
+ a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2))/(sqrt(1 +
pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2))*(X_1 - X_2)*sqrt(pow(-Y_1 + Y_c +
a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2), 2))) + (Y_1 -
Y_2)*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) -
(Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1
- X_2), 2))/(pow(1 + pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2),
3.0L/2.0L)*pow(X_1 - X_2, 2));
if (param == e1x())
deriv += -(Y_1 - Y_2)*(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2))/(sqrt(1 + pow(Y_1 - Y_2, 2)/pow(X_1 -
X_2, 2))*(X_1 - X_2)*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2), 2)));
if (param == e1y())
deriv += (-Y_1 + Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 -
Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 -
X_2))/(sqrt(1 + pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2))*sqrt(pow(-Y_1 + Y_c
+ a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2), 2)));
if (param == rmaj())
deriv += -(-sin(phip)*cos(t) + (Y_1 - Y_2)*cos(phip)*cos(t)/(X_1 -
X_2))*(-Y_1 + Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 -
Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 -
X_2))/(sqrt(1 + pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2))*sqrt(pow(-Y_1 + Y_c
+ a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2), 2)));
if (param == rmin())
deriv += (sin(t)*cos(phip) + (Y_1 - Y_2)*sin(phip)*sin(t)/(X_1 -
X_2))*(-Y_1 + Y_c + a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 -
Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 -
X_2))/(sqrt(1 + pow(Y_1 - Y_2, 2)/pow(X_1 - X_2, 2))*sqrt(pow(-Y_1 + Y_c
+ a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2), 2)));
if (param == phi())
deriv += (a*cos(phip)*cos(t) - b*sin(phip)*sin(t) + (Y_1 -
Y_2)*(a*sin(phip)*cos(t) + b*sin(t)*cos(phip))/(X_1 - X_2))*(-Y_1 + Y_c
+ a*sin(phip)*cos(t) + b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c +
a*cos(phip)*cos(t) - b*sin(phip)*sin(t))/(X_1 - X_2))/(sqrt(1 + pow(Y_1
- Y_2, 2)/pow(X_1 - X_2, 2))*sqrt(pow(-Y_1 + Y_c + a*sin(phip)*cos(t) +
b*sin(t)*cos(phip) - (Y_1 - Y_2)*(-X_1 + X_c + a*cos(phip)*cos(t) -
b*sin(phip)*sin(t))/(X_1 - X_2), 2)));
}
return scale * deriv;
}