USER FORUM

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

**Internals: constraints, revolve and extrude**

*(by Paul)*

I've been reading code in surface.cpp and I'm thinking about trying to implement new features. Playing with some sketches raised the following questions:

Draw a couple squares and then extrude into a new group. When dragging a vertex or edge on the top, the only thing that can be changed is the height of the extrusion. Dragging a point on the bottom can change the dimensions on the underlying sketch - the size of the base of the extrusion. Trying to drag an edge on the bottom does nothing. If I uncheck "shown" for the extruded group the sketch edges become available for dragging while still showing the extruded part.

Similarly, when using the lathe to create a new group, there are points and edges coincident with the original sketch elements. The points can be moved but not the edges. By unchecking the lathe group, the underlying sketch elements are visible and both points and edges can be dragged.

I guess I'm looking for clarification as to what's going on here. In particular, when exactly are these functions called:

SShell::MakeFromExtrusionOf()

SShell::MakeFromRevolutionOf()

When you use a distance constraint to fix the height of an extrusion, what is actually constrained and in which group? I can envision all the control points for the surfaces being constrained (very complex, many constraints) and moving or constraining the height doesn't actually require calling MakeFromExtrusionOf again. But that seems like a lot of complexity.

When moving a point in the extrusion or lathe group, the sketch is modified as well. What's going on here? What is leading and what is following? Are the surfaces constantly regenerated or are the control points all moving in a coordinated way via internal constraints?

While I'm asking questions about internals, why are all surfaces trimmed? I suppose some parts of the code just assume every surface is trimmed. Also, it looks like the trim curves might be in 3-space and not u,v is this correct?

Thanks!

Draw a couple squares and then extrude into a new group. When dragging a vertex or edge on the top, the only thing that can be changed is the height of the extrusion. Dragging a point on the bottom can change the dimensions on the underlying sketch - the size of the base of the extrusion. Trying to drag an edge on the bottom does nothing. If I uncheck "shown" for the extruded group the sketch edges become available for dragging while still showing the extruded part.

Similarly, when using the lathe to create a new group, there are points and edges coincident with the original sketch elements. The points can be moved but not the edges. By unchecking the lathe group, the underlying sketch elements are visible and both points and edges can be dragged.

I guess I'm looking for clarification as to what's going on here. In particular, when exactly are these functions called:

SShell::MakeFromExtrusionOf()

SShell::MakeFromRevolutionOf()

When you use a distance constraint to fix the height of an extrusion, what is actually constrained and in which group? I can envision all the control points for the surfaces being constrained (very complex, many constraints) and moving or constraining the height doesn't actually require calling MakeFromExtrusionOf again. But that seems like a lot of complexity.

When moving a point in the extrusion or lathe group, the sketch is modified as well. What's going on here? What is leading and what is following? Are the surfaces constantly regenerated or are the control points all moving in a coordinated way via internal constraints?

While I'm asking questions about internals, why are all surfaces trimmed? I suppose some parts of the code just assume every surface is trimmed. Also, it looks like the trim curves might be in 3-space and not u,v is this correct?

Thanks!

**(no subject)**

*(by EvilSpirit)*

The first part about dragging: we are tried to solve this and prioritize using functions like ChooseFromHoverToDrag and Choose FromHoverToSelect. I think there is a lot of problems we have introduced since we are made this changes.

When we are constraining the height of extrusion, we are constraining distance between two points. Every point has an ExprVector to express the point's position. When we are writing ExprVector for the extruded copies of the orginal points (which we are drawn "by hand"), we are performing shifting of original points by ExprVector which depends on the extrusion length parameter and direction(direction cojnstrained to be perpendicular). Look at Group::Generate(case Type::EXTRUDE) and EntityBase::PointGetExprs(case Type::POINT_N_ROT_TRANS). So, when we are constraining extrusion length, we are just adding one more equation to the extrusion group. All the constraining and dragging performed with using of entities, there are no any geometry involved into this process.

The next. When extrusion group is active and we are hovering some of the previous 2d sketch group entitiy, we can change it position by using EntityBase::PointForceTo(case Type::POINT_IN_2D). Drag is performed using GraphicsWindow::UpdateDraggedPoint and usually paired with calling of SolveSpaceUI::MarkGroupDirtyByEntity. So, beacuase of this, the next call of SolveSpaceUI::GenerateAll perform solving the previous group sketch and can cause moving of some entities in case if they are not fully constrained.

About trimming. The NURBS surfaces (4x4 3d points) assumed to be infinite. So, we must crop it to represent finite surfaces. We can use 2d curves in uv space of the NURBS surface, or we should use 3d surfaces in 3d space. The 3d curves in space for trimming is not suitable, because they can not lay exactly on surface.

When we are constraining the height of extrusion, we are constraining distance between two points. Every point has an ExprVector to express the point's position. When we are writing ExprVector for the extruded copies of the orginal points (which we are drawn "by hand"), we are performing shifting of original points by ExprVector which depends on the extrusion length parameter and direction(direction cojnstrained to be perpendicular). Look at Group::Generate(case Type::EXTRUDE) and EntityBase::PointGetExprs(case Type::POINT_N_ROT_TRANS). So, when we are constraining extrusion length, we are just adding one more equation to the extrusion group. All the constraining and dragging performed with using of entities, there are no any geometry involved into this process.

The next. When extrusion group is active and we are hovering some of the previous 2d sketch group entitiy, we can change it position by using EntityBase::PointForceTo(case Type::POINT_IN_2D). Drag is performed using GraphicsWindow::UpdateDraggedPoint and usually paired with calling of SolveSpaceUI::MarkGroupDirtyByEntity. So, beacuase of this, the next call of SolveSpaceUI::GenerateAll perform solving the previous group sketch and can cause moving of some entities in case if they are not fully constrained.

About trimming. The NURBS surfaces (4x4 3d points) assumed to be infinite. So, we must crop it to represent finite surfaces. We can use 2d curves in uv space of the NURBS surface, or we should use 3d surfaces in 3d space. The 3d curves in space for trimming is not suitable, because they can not lay exactly on surface.

**(no subject)**

*(by Jonathan Westhues)*

As to the trim curves: all surfaces are trimmed by curves expressed in (x, y, z). This has the disadvantage that you note, that the trim curves don't lie exactly in the surface. I preferred that to trim curves in (u, v), which have the disadvantage that the edge where two surfaces intersect will be different for each surface, requiring extra logic to generate a watertight mesh. This problem is fundamental to NURBS, since the intersection between two NURBS surfaces isn't in general a NURBS curve.

And in case it's not clear from EvilSpirit's answer: the user drags entities, and the surfaces follow the entities. The user never directly drags a surface. Particular surfaces may appear or disappear entirely as an extrusion used in some Boolean operation is dragged, depending how the geometry intersects.

And in case it's not clear from EvilSpirit's answer: the user drags entities, and the surfaces follow the entities. The user never directly drags a surface. Particular surfaces may appear or disappear entirely as an extrusion used in some Boolean operation is dragged, depending how the geometry intersects.

**(no subject)**

*(by Paul)*

>> Every point has an ExprVector to express the point's position. When we are writing ExprVector for the extruded copies of the orginal points (which we are drawn "by hand"), we are performing shifting of original points by ExprVector which depends on the extrusion length parameter

This is what I thought was going on. Reading the code, all new points locations are calculated strictly by class methods and read very much like geometric constructions. That allows the underlying relationships to be stored so points can be updated when the underlying points they're constructed from are moved. It's a really elegant system, but I feel funny when thinking about the underlying complexity sometimes ;-)

BTW, there is no "extrusion length parameter" specified by the user. Is there an internal one to specify the distance between the planes? One of the things I wanted to try is adding a scale factor and origin for extrusions. The user would need to select a point in the sketch, and a scale factor (in the text window?) and the new end of the extrusion would be scaled by that amount (this is easy to do as a geometric construction if an origin is given). This would allow easy creation of frustums or parts with draft angles. Perhaps it could be done by letting the user specify a length ratio between a line on the new and old ends of the extrusion, much like height is specified by adding a distance constraint.

FYI the other thing I'm thinking about is revolution through angles less than 360 degrees. This would allow certain things to be created without NURBS booleans. I'm thinking that the angle needs to be specified for this at least in a first attempt. It would be even better if the angle could be modified after (like an arc is a plane by dragging points or adding a constraint) but that depends on how the new points are constructed. Lathe surfaces are created in four 90 degree sections, but it might be nice not to use so many. I can see using just one for up to 120 degrees. I should look at how arcs in a sketch handle it - are they always 4 sections or something else?

This is what I thought was going on. Reading the code, all new points locations are calculated strictly by class methods and read very much like geometric constructions. That allows the underlying relationships to be stored so points can be updated when the underlying points they're constructed from are moved. It's a really elegant system, but I feel funny when thinking about the underlying complexity sometimes ;-)

BTW, there is no "extrusion length parameter" specified by the user. Is there an internal one to specify the distance between the planes? One of the things I wanted to try is adding a scale factor and origin for extrusions. The user would need to select a point in the sketch, and a scale factor (in the text window?) and the new end of the extrusion would be scaled by that amount (this is easy to do as a geometric construction if an origin is given). This would allow easy creation of frustums or parts with draft angles. Perhaps it could be done by letting the user specify a length ratio between a line on the new and old ends of the extrusion, much like height is specified by adding a distance constraint.

FYI the other thing I'm thinking about is revolution through angles less than 360 degrees. This would allow certain things to be created without NURBS booleans. I'm thinking that the angle needs to be specified for this at least in a first attempt. It would be even better if the angle could be modified after (like an arc is a plane by dragging points or adding a constraint) but that depends on how the new points are constructed. Lathe surfaces are created in four 90 degree sections, but it might be nice not to use so many. I can see using just one for up to 120 degrees. I should look at how arcs in a sketch handle it - are they always 4 sections or something else?

**(no subject)**

*(by Jonathan Westhues)*

There's no explicit extrusion depth parameter, just the translation vector between the original sketch and the other face of the extrusion. That vector is automatically constrained normal to the plane of the extruded sketch. The user can then set the remaining DOF with a constraint, like on the length of an extruded line, distance from an extruded point to a plane, etc.

When we test surfaces for intersection, we first do a coarse test against the axis-aligned bounding box of the surface's control points (since a NURBS surface lies within that AABB). The smaller the arc, the tighter the AABB fits. So there's an optimal max angle for speed, since too big makes the AABB tests useless but too small means we test lots of little pieces.

When we test surfaces for intersection, we first do a coarse test against the axis-aligned bounding box of the surface's control points (since a NURBS surface lies within that AABB). The smaller the arc, the tighter the AABB fits. So there's an optimal max angle for speed, since too big makes the AABB tests useless but too small means we test lots of little pieces.

**(no subject)**

*(by EvilSpirit)*

> BTW, there is no "extrusion length parameter" specified by the user

yes, I mean, shift(xyz) is like implicit directcion and its length. Since we can't modify direction of extrusion, this can be represented as single parameter.

> One of the things I wanted to try is adding a scale factor and origin for extrusions. The user would need to select a point in the sketch, and a scale factor (in the text window?)

In general case, you should intoduce new parameter for it and after we can constrian this group in native way (we can add ratio constraint or angle constraint or the other way to constrain this free dof)

> This would allow easy creation of frustums or parts with draft angles.

Actually, to perform this in best way, we should introduce equidistant operation for the original sketch. Using scale will not work as it should in some(most) cases. Scale will work only with rectangles and circles.

yes, I mean, shift(xyz) is like implicit directcion and its length. Since we can't modify direction of extrusion, this can be represented as single parameter.

> One of the things I wanted to try is adding a scale factor and origin for extrusions. The user would need to select a point in the sketch, and a scale factor (in the text window?)

In general case, you should intoduce new parameter for it and after we can constrian this group in native way (we can add ratio constraint or angle constraint or the other way to constrain this free dof)

> This would allow easy creation of frustums or parts with draft angles.

Actually, to perform this in best way, we should introduce equidistant operation for the original sketch. Using scale will not work as it should in some(most) cases. Scale will work only with rectangles and circles.

**(no subject)**

*(by Paul)*

Scaling will work for everything because everything is a NURBS curve. The idea is to select a point of origin - call it O - in the sketch. This is the point that will be translated perpendicular to the plane of the sketch. All other control points will be scaled relative to that.

The code to extrude a surface at its core is this line:

ret.ctrl[i][1] = (sb->ctrl[i]).Plus(t1);

What I propose amounts to this:

ret.ctrl[i][1] = (O.Plus(sb->ctrl[i].Minus(O).ScaledBy(scale)).Plus(t1);

It should resize the entire sketch to create the new end of the extrusion. It would be most flexible if scale were a free parameter with a default value of 1.0. Then the user could use several different methods to constrain it - length ration, point on line, angle, etc...

Another option: I'm not sure how often people would want a skewed extrusion, but one could also drop the automatic constraints that make t0 and t1 perpendicular to the plane. The user could add a couple of perpendicular constraints themselves if that's what they wanted. Perhaps the perpendicular constraints could be visible (as if the user created them) so they could be deleted if you want to skew the extrusion.

Double sided extrusions would probably want to be done as a mirror image which would require twice as many NURBS, but it could still be coded as a single surface.

The code to extrude a surface at its core is this line:

ret.ctrl[i][1] = (sb->ctrl[i]).Plus(t1);

What I propose amounts to this:

ret.ctrl[i][1] = (O.Plus(sb->ctrl[i].Minus(O).ScaledBy(scale)).Plus(t1);

It should resize the entire sketch to create the new end of the extrusion. It would be most flexible if scale were a free parameter with a default value of 1.0. Then the user could use several different methods to constrain it - length ration, point on line, angle, etc...

Another option: I'm not sure how often people would want a skewed extrusion, but one could also drop the automatic constraints that make t0 and t1 perpendicular to the plane. The user could add a couple of perpendicular constraints themselves if that's what they wanted. Perhaps the perpendicular constraints could be visible (as if the user created them) so they could be deleted if you want to skew the extrusion.

Double sided extrusions would probably want to be done as a mirror image which would require twice as many NURBS, but it could still be coded as a single surface.

**(no subject)**

*(by EvilSpirit)*

> Scaling will work for everything because everything is a NURBS curve

I am not mean what this is not possible, I mean the result will be not like the user except from it. Look at https://github.com/whitequark/solvespace/issues/73 for illustrations.

I am not mean what this is not possible, I mean the result will be not like the user except from it. Look at https://github.com/whitequark/solvespace/issues/73 for illustrations.

**(no subject)**

*(by Paul)*

@EvilSpirit I think we are on the same page. Shrinking the sketch by a constant factor does not create uniform draft angles the way offsetting the perimeter by a fixed amount does. It does create draft angles though and may be sufficient for that use in some cases. There are also other uses for simply scaling like that in an extrude but I'm not sure how often people would want that. Given that there are only two operations (extrude and lathe) that can be used to create solids (shells) in solvespace, I thought adding some flexibility to those may go a long way without much effort to implement.

I like the idea of a more general lofting function too. I think all of these are potentially good ideas.

I like the idea of a more general lofting function too. I think all of these are potentially good ideas.

**Post a reply to this comment:**