SolveSpace Logo SOLVESPACE -- parametric 2d/3d CAD
Examples
Tutorials
Features
Download
Reference
Technology
Library
Forum
Contact
USER FORUM

(you are viewing a thread; or go back to list of threads)

New ratio constraints ideas (by Eric)
I was thinking of some constraints I would be interested in using, something like Angle/Angle ratios, ArcLen/Arclen ratios, or ArcLen/LineLen ratios. Currently I can simulate those constraints by doing some convoluted multi-constraining (Arclength1 = LengthA, LengthA / LengthB ratio, LengthB = ArcLength2 ). But ideally these could be implemented as a single constraint.

I took a look at the code and was wondering the amount of work required to implement these. I prototyped some constraint code in the constrainteq file, but I don't know if I'm on the right track, as I don't have the correct compile environment set up.

case ARCL_ARCL_RATIO: {
EntityBase *arc1 = SK.GetEntity(entityA),
*arc2 = SK.GetEntity(entityB);

// And get the arc1 radius, and the cosine of its angle
EntityBase *ao1 = SK.GetEntity(arc1->point[0]),
*as1 = SK.GetEntity(arc1->point[1]),
*af1 = SK.GetEntity(arc1->point[2]);

ExprVector aos1 = (as1->PointGetExprs()).Minus(ao1->PointGetExprs()),
aof1 = (af1->PointGetExprs()).Minus(ao1->PointGetExprs());
Expr *r1 = aof1.Magnitude();

ExprVector n1 = arc1->Normal()->NormalExprsN();
ExprVector u1 = aos1.WithMagnitude(Expr::From(1.0));
ExprVector v1 = n1.Cross(u1);
// so in our new csys, we start at (1, 0, 0)
Expr *costheta1 = aof1.Dot(u1)->Div(r1);
Expr *sintheta1 = aof1.Dot(v1)->Div(r1);

double thetas1, thetaf1, dtheta1;
arc1->ArcGetAngles(&thetas1, &thetaf1, &dtheta1);
Expr *theta1;
if(dtheta1 < 3*PI/4) {
theta1 = costheta1->ACos();
} else if(dtheta1 < 5*PI/4) {
// As the angle crosses pi, cos theta1 is not invertible;
// so use the sine to stop blowing up
theta1 = Expr::From(PI)->Minus(sintheta1->ASin());
} else {
theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
}

// And get the arc2 radius, and the cosine of its angle
EntityBase *ao2 = SK.GetEntity(arc2->point[0]),
*as2 = SK.GetEntity(arc2->point[1]),
*af2 = SK.GetEntity(arc2->point[2]);

ExprVector aos2 = (as2->PointGetExprs()).Minus(ao2->PointGetExprs()),
aof2 = (af2->PointGetExprs()).Minus(ao2->PointGetExprs());
Expr *r2 = aof2.Magnitude();

ExprVector n2 = arc2->Normal()->NormalExprsN();
ExprVector u2 = aos2.WithMagnitude(Expr::From(1.0));
ExprVector v2 = n2.Cross(u2);
// so in our new csys, we start at (1, 0, 0)
Expr *costheta2 = aof2.Dot(u2)->Div(r2);
Expr *sintheta2 = aof2.Dot(v2)->Div(r2);

double thetas2, thetaf2, dtheta2;
arc2->ArcGetAngles(&thetas2, &thetaf2, &dtheta2);
Expr *theta2;
if(dtheta2 < 3*PI/4) {
theta2 = costheta2->ACos();
} else if(dtheta2 < 5*PI/4) {
// As the angle crosses pi, cos theta2 is not invertible;
// so use the sine to stop blowing up
theta2 = Expr::From(PI)->Minus(sintheta2->ASin());
} else {
theta2 = (Expr::From(2*PI))->Minus(costheta2->ACos());
}
// And write the equation; (r1*theta1) / ( r2*theta2) = some ratio
AddEq(l, (r1->Times(theta1))->Div(r2->Times(theta2))->Minus(exA), 0);
break;
}
case ARC_LINE_LENGTH_RATIO: {
EntityBase *line = SK.GetEntity(entityA),
*arc1 = SK.GetEntity(entityB);

Expr *ll = Distance(workplane, line->point[0], line->point[1]);

// And get the arc1 radius, and the cosine of its angle
EntityBase *ao1 = SK.GetEntity(arc1->point[0]),
*as1 = SK.GetEntity(arc1->point[1]),
*af1 = SK.GetEntity(arc1->point[2]);

ExprVector aos1 = (as1->PointGetExprs()).Minus(ao1->PointGetExprs()),
aof1 = (af1->PointGetExprs()).Minus(ao1->PointGetExprs());
Expr *r1 = aof1.Magnitude();

ExprVector n1 = arc1->Normal()->NormalExprsN();
ExprVector u1 = aos1.WithMagnitude(Expr::From(1.0));
ExprVector v1 = n1.Cross(u1);
// so in our new csys, we start at (1, 0, 0)
Expr *costheta1 = aof1.Dot(u1)->Div(r1);
Expr *sintheta1 = aof1.Dot(v1)->Div(r1);

double thetas1, thetaf1, dtheta1;
arc1->ArcGetAngles(&thetas1, &thetaf1, &dtheta1);
Expr *theta1;
if(dtheta1 < 3*PI/4) {
theta1 = costheta1->ACos();
} else if(dtheta1 < 5*PI/4) {
// As the angle crosses pi, cos theta1 is not invertible;
// so use the sine to stop blowing up
theta1 = Expr::From(PI)->Minus(sintheta1->ASin());
} else {
theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
}

// And write the equation; (r1*theta1) / ( length) = some ratio
AddEq(l, (r1->Times(theta1))->Div(ll)->Minus(exA), 0);
break;
}
Mon Mar 10 2014, 19:11:40
(no subject) (by Jonathan Westhues)
That seems at least roughly correct. The form of the constraint equations sometimes needs some investigation to get good behavior within the numerical method, but I'd guess those would work. If you wanted to make the change for real, then you'd want to move the arc-length routine into a function (Expr *ArcLength(EntityBase *arc) or whatever) to avoid duplication.
Sat Mar 15 2014, 20:50:25
Post a reply to this comment:
Your Name:
Your Email:
Subject:
(no HTML tags; use plain text, and hit Enter for a line break)
Attached file (if you want, 5 MB max):
© 2008-2022 SolveSpace contributors. Most recent update June 2 2022.