Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: New Extrude type Skewed #453

Closed
phkahler opened this issue Jul 30, 2019 · 31 comments
Closed

Suggestion: New Extrude type Skewed #453

phkahler opened this issue Jul 30, 2019 · 31 comments

Comments

@phkahler
Copy link
Member

phkahler commented Jul 30, 2019

In the text window for extrusions there are two options: one-sided and two-sided. I propose adding a 3rd option "skewed". This would create a one-sided extrusion but the path of the extrusion would not have to be perpendicular to the sketch plane. I'm not sure how useful this would be so maybe we should discuss it.

My 2 cents, this adds some ability to create different geometry but may not actually be that useful. I'd hate to see it abused to make things that are already hard to make in SolveSpace.

Implementation:
Low complexity - this is a good item for someone new to the SolveSpace code.
Tasks:

  1. Add a 3rd subtype to the group class.
  2. Add the appropriate checkbox in the text window.
  3. Make sure it is treated as one-sided in all the right places.
  4. Don't apply the perpendicular constraints to the extrusion vector for this subtype. (extrude is already implemented as 3 DoF with 2 internal constraints you don't see).

The image here shows independent constraints that would normally be fixed to 90 degrees. This can be hacked in code by commenting out 2 lines that apply those 2 constraints.

skew

@whitequark
Copy link
Contributor

A simpler counter-proposal: what if we added a checkbox to allow any existing extrusion to be skewed?

@phkahler
Copy link
Member Author

@whitequark Where would the flag be stored then? I've also just thought maybe those constraints are applied at the time the group is created? That might be a problem.

Come to think of it, when are free parameters created? I've got some other stuff in the works that will require some more options and free parameters (up to 3 fp values). It may not be able to work with existing extrusions due to that. Or maybe those parameters would be typed in.

What existing member variables are available for group options?

@whitequark
Copy link
Contributor

What existing member variables are available for group options?

We can just add a new one if an existing one doesn't fit.

@phkahler
Copy link
Member Author

phkahler commented Aug 3, 2019

I'd like to add two parameters to extrude that will be adjustable on-diagram or have constraints applied. For those I need to add parameters along with the existing ones in Group::Generate here:

    case Type::EXTRUDE: {
        AddParam(param, h.param(0), gn.x);
        AddParam(param, h.param(1), gn.y);
        AddParam(param, h.param(2), gn.z);

So I'd be adding 3 and 4 which is easy but I have questions.

Don't other parameters get added after this?
Wouldn't adding h,param(3) and (4) mess up existing models that don't have them already?

When is Generate called?
It has to regenerate if the underlying sketch is changed but aren't parameters and constraints preserved with their existing handles? (meaning I would mess up existing models)

My new options would only need these additional parameters if the user enables them in the text window. I'm thinking the new parameters should always exist so they are not lost if the user turns the feature on and off. But that would mess up the dof count right?

@whitequark and @Evil-Spirit can you clarify if this would be an issue and if so, what to do about it?

@whitequark
Copy link
Contributor

I don't think there are any backwards compatibility concerns here. Consider hGroup::param:

inline hParam hGroup::param(int i) const
    { hParam r; r.v = 0x80000000 | (v << 16) | (uint32_t)i; return r; }

Each parameter generated from a group is tagged with the group, so adding new parameters at the end in any group introduces them into unused space.

Wouldn't adding h,param(3) and (4) mess up existing models that don't have them already?

This would happen if these parameters would not be constrained, but since they are constrained perpendicular in all existing extrusions (which your code should take care of elsewhere), they will be computed to the one value they can hold on the earliest regeneration.

If you did not constrain these parameters, then extra care needs to be taken to not mess up existing files; see UpgradeLegacyData in file.cpp to understand how.

I'm thinking the new parameters should always exist so they are not lost if the user turns the feature on and off.

Agreed.

But that would mess up the dof count right?

It wouldn't if when the feature is turned off there's an equation that sets the parameter to a fixed value. (Watch out for sketches becoming overconstrained when this happens--this can cause slowdowns.)

@phkahler
Copy link
Member Author

phkahler commented Aug 3, 2019

This would happen if these parameters would not be constrained, but since they are constrained perpendicular in all existing extrusions (which your code should take care of elsewhere), they will be computed to the one value they can hold on the earliest regeneration.

@whitequark Sorry about that, I wasn't clear what I'm up to. I think the skewed idea that I started with here is not good because I want to add some extrude features that are incompatible with it. I want to keep the 3 parameters and 2 constraint and add two more optional parameters. That raised the concerns in my previous comment.

@whitequark
Copy link
Contributor

I want to keep the 3 parameters and 2 constraint and add two more optional parameters.

Can you explain the nature of this addition?

@phkahler
Copy link
Member Author

phkahler commented Aug 3, 2019

I've added a field to the textbox for "draft angle" which is expected to be just a few degrees. This is something people use to make molds. That's fine, I stored the angle in valA which is currently unused for extrusions and it's not something you'd really want to drag or set on-diagram.

The more complex part will be an option group (check boxes) to add a top feature (none / fillet / chamfer) to the top of the extrusion. This will have a free parameter in the solver for the depth of the chamfer, or the radius of the fillet. Then another option group and parameter for the bottom end of the extrusion.

I was originally going to implement a new group type for complex extrusions, but I think your earlier comment made me realize people might want to add these features to existing models. So it seems good to extend the existing extrude group type. All this assumes an extrusion perpendicular to the sketch, so it's incompatible with "skew" but I think much more useful.

I was going to make a complete prototype first because it's hard to explain how I envision this working.

@whitequark
Copy link
Contributor

"Draft angle" sounds very good to have. I am a bit worried about adding a "top feature" because this seems like a very ad-hoc solution that will not scale well (but which we'll still have to support forever).

@phkahler
Copy link
Member Author

phkahler commented Aug 3, 2019

I'm on the fence about it too, hence the idea to make a usable prototype. The problem is that SS will have a hard time getting fully generalized implementations of these features. Straight extrusions are easy enough to add them to with a few issues.

@whitequark
Copy link
Contributor

Let's see what the prototype looks like.

@phkahler
Copy link
Member Author

Looking for input from @jwesthues

I'm not sure how to handle an extrusion with a draft angle AND fillet/chamfer. I'm thinking we should type the draft angle in the text window, but I wanted to be able to drag entities on the diagram to change the size of the other features. I've got a picture showing the points involved in extruding a single point (P1) with these features.
extrude

P1 is the original point in a sketch. P2 would be the "new" end of a single sided extrusion, moved over due to draft angle. P3 and P4 are then needed for a top feature weather that's a fillet or chamfer. P5 and P6 would be for the bottom feature. A bottom fillet will want to go outward if you're sketching on an existing flat surface.

My thought was to put a copy of the sketch elements through P6 and P4 which the user could drag up and down to change the height/radius. One issue is that there is no way to put entities anywhere other than on the straight vertical line without extensive changes. Another issues is that none of the obvious distances between points actually match the chamfer radius in the presence of a draft angle.

I'm open to ideas in this area. I can write code to create these sorts of surfaces now - without booleans. The problem is how to specify the parameters in the UI.

Here's a shot of a double sided extrusion with two different chamfer depths:
chamfer2

Notice that the lines on the top and bottom have not been offset along with the solid geometry. The circles at the ends of the holes are small for example, because they have not been enlarged. The issue with this is that SS internally wants an extruded point to be a simple mapping of the original point, but creating these surfaces requires new points to be computed from several of the original points.

This is all assuming a straight extrusion, and is in no way a generalized way to modify any given edge on a model.

These are features that would go a long way, but I'm stuck on implementation details. Any thoughts on how this might be implemented from the UI point of view?

@jwesthues
Copy link
Member

As you say, the present entity definitions don't allow you to create that. Nothing stops you from defining new POINT_ types, though the math gets kind of complicated and it might do weird things in the solver.

Commercial CAD tools general have "draft" and "round/chamfer" as separate tools that work on surfaces, not properties of the initial extrusion. I suspect that may be what you really want here, like as separate "draft" and "round/chamfer" groups acting on the existing solid model. That's a huge amount of work to implement completely, but a basic implementation (e.g., supporting only plane faces and linear edges) would be relatively straightforward and quite useful.

@phkahler
Copy link
Member Author

phkahler commented Aug 15, 2019

@jwesthues This is where the disconnect between entities and shells gets painful. Someone else suggested that I create a solid model from a selected edge and subtract that from the existing model. That completely avoids the need to associate the edge with shell surfaces, but dealing with the various possibilities at the ends seems complicated - I'll think about it.

A new POINT_ type is fine, but to create these shapes it needs to be a function of the base point as well as the next and previous point in the loop - weather that's on the same bezier or the next or previous. The core function I used to create the above surfaces is this:

'Vector GetOffsetPt(Vector &pt, Vector &prev, Vector &next, Vector &norm, double d)
{
Vector n1 = norm.Cross(next.Minus(pt)).WithMagnitude(1.0); // prependicular to outgoing segment
Vector n2 = norm.Cross(pt.Minus(prev)).WithMagnitude(1.0); // prependicular to incoming segment
Vector b = n1.Plus(n2).WithMagnitude(1.0); // bisector of the angle

Vector r = pt.Plus(b.ScaledBy(d/n1.Dot(b)));

return r;

}

// Create an extruded surface where each end can be offset by some distance
SSurface SSurface::FromOffsetExtrusionOf(SBezier *sb, SBezier *sbprev, SBezier *sbnext,
Vector t0, Vector t1, Vector n, double d0, double d1) {
SSurface ret = {};

ret.degm = sb->deg;
ret.degn = 1;
Vector pt, pnext, pprev;
int i;
for(i = 0; i <= ret.degm; i++) {
    pt = sb->ctrl[i];
    // we need the next and prebious points - on this curve or the previous or next
    if (i==0) {
        pprev = sbprev->ctrl[sbprev->deg-1];
    } else {
        pprev = sb->ctrl[i-1];
    }
    if (i==sb->deg) {
        pnext = sbnext->ctrl[1];
    } else {
        pnext = sb->ctrl[i+1];
    }

    ret.ctrl[i][0] = (GetOffsetPt(sb->ctrl[i], pprev, pnext,n,d0)).Plus(t0);
    ret.weight[i][0] = sb->weight[i];

    ret.ctrl[i][1] = (GetOffsetPt(sb->ctrl[i], pprev, pnext,n,d1)).Plus(t1);
    ret.weight[i][1] = sb->weight[i];
}

return ret;

}
`
This works correctly for any loop composed of lines and arcs so long as the arcs are parallel to their adjacent entity. It look good for a lot of things too, even if not mathematically perfect. A rounded edge is just going to consist of making the one direction degree 2 and sticking in the unmodified end point.

I've also factored out a nice function to automatically create trim curves for an extrusion of arbitrary number of segments and 2 end caps. So creating something like an extrusion with these features is now pretty easy. The issue is creating equivalent entities in these locations. I have considered creating non-movable entities directly from the shell but that goes against so much (it would be useful for STEP import too).

This just seems so useful I want to make it work, but I don't want it to feel like a hack. Imagine taking extruded text and giving it a draft angle and rounded top just by altering the extrusion a little. I shall continue with some type of demo.

@jwesthues
Copy link
Member

This is where the disconnect between entities and shells gets painful.

Very much so. Eventually, SolveSpace needs to create constraint solver entities from the solid model, the same as commercial CAD tools do. That's relatively straightforward, since the geometry is already fixed at that time--you can just use numerical points, no solver parameters required. (That would augment the existing entities created from extrusions etc., not replace them. Constraints on the existing extrusion entities can define the extrusion depth, but constraints on the entities generated from the solid model could not, since you can't compute the solid model until the depth is fixed.)

You could implement edge rounding / surface drafting / whatever even before that, though, just limited to solid model edges that a corresponding entity already happens to exist for. That's a little more geometry code than you've already implemented, but not by much.

@phkahler
Copy link
Member Author

@whitequark @Evil-Spirit @jwesthues and anyone who uses SolveSpace.

I have pushed changes to my "draft" branch that implements draft angles for extrusions. The default angle is zero and can be changed in the text window for extrusions. I'm looking for feedback on this because the "control cage" of entites around the extrusion is still straight - only the solid created has the angled edges. The intent here is to support creation of molds, not fancy edges so the angle is limited to 20 degrees (which is probably excessive).

This only works 100 percent geometrically correctly for the following:

  1. straight edges
  2. circles
  3. arcs that are parallel to whatever they connect to at their ends
  4. corners rounded with tangent arc tool (which satisfy System::CalculateRank() is slow #386

Other shapes can do fairly well in appearance but are not mathematically perfect. I am looking for feedback on this. In particular the odd behavior this creates with the UI.

On the code side: There are some really useful functions in this that will make all kinds of extrusions possible. The challenge will be in the UI. There is some broken code for creating chamfers in there but that's not accessible from the UI right now.

@phkahler
Copy link
Member Author

I'm closing this because the original idea for skewed extrusion didnt get any positive feedback, and is inferior to some better ideas.

@ruevs
Copy link
Member

ruevs commented Jun 11, 2020

I am not sure how this "slipped" by me - I usually read all issues and comments :-) Anyway...

Skewed extrusions have been possible since at least version 1.9 (17:09:14 Jan 21 2012) - this is the oldest I have handy.

Procedure:

  • Ctrl+N ("File | New")
  • C ("Sketch | Circle") - draw a circle
  • Rotate view with middle button drag or Shift+ right button drag or F3 (for "View | Nearest Isometric | View")
  • 3 ("Sketch | Anywhere in 3d")
  • "Sketch | Workplane"
  • Click on origin. A new "workplane" is created
  • Select the "workplane"
  • 2 ("Sketch | In Workplane")
  • Shift+X ("New Group | Extrude")
  • Rotate view with middle button drag or Shift+ right button drag
  • Enjoy :-)

Here is an example:

SlantedExtrusion.zip

SlantedExtrusion

@ruevs
Copy link
Member

ruevs commented Jun 11, 2020

Hmm there is a bit about this feature it in the reference manual in the "Extrude" section:

A workplane must be active when the group is created, and the extrude path is automatically constrained to be normal to that workplane. This means, for example, that a rectangle is extruded to form a rectangular prism. The extrusion has one degree of freedom, so a single distance constraint will fully constrain it.

But the way this is written does not make it obvious that one can have more than one workplane in a group and extrude perpendicular to one while the drawing is in another one.

@whitequark
Copy link
Contributor

Ohh that's really neat!

@phkahler
Copy link
Member Author

I suspect that was an unintended feature but sometimes those are the best kind ;-) The extrude code will work with any vector, but the comments and the fallback to the loop normal suggests it's supposed to be perpendicular to the sketch normal, but that's rather arbitrary as my suggestion to unconstrain it implied. It's better not to have it constrained at all so you can manipulate the skew in the resulting group. Frustum give you that AND the ability to change the size to make pyramids.

@ruevs
Copy link
Member

ruevs commented Jun 12, 2020

I suspect that was an unintended feature but sometimes those are the best kind ;-)

Maybe.

The extrude code will work with any vector, but the comments and the fallback to the loop normal suggests it's supposed to be perpendicular to the sketch normal, but that's rather arbitrary as my suggestion to unconstrain it implied.

Please give me a URL to the code, I'm rather unfamiliar with this part of it. What is a "loop normal"? (I should read this whole issue carefully :-)

It's better not to have it constrained at all so you can manipulate the skew in the resulting group.

You can manipulate the skew of the resulting group ;-) Just move the extrusion controlling "workplane". It is not very intuitive but it works.

Frustum give you that AND the ability to change the size to make pyramids.

Sure. But then why not "extrude along a bezier path with a second beezier path controlling the scale and twist"?
Something like this:
https://app-help.vectorworks.net/2016/eng/VW2016_Guide/Objects_edit2/Extrude_Along_Path.htm
But much better.
I imagine two points on the sketch following two paths with "speeds" along the paths such that they "start and finish" simultaneously irrespective of the lengths of the two paths. That seems like the most general "extrusion" - all others are special cases of it. It also seems really hard to implement, but I am not at all familiar with these parts of the code :-)

@ruevs
Copy link
Member

ruevs commented Jun 12, 2020

We could call this "Extrude Along Two Paths™" ;-)

@ruevs
Copy link
Member

ruevs commented Jun 12, 2020

I can not find such a feature in professional CAD (have not actually used any of them since AutoCAD 12 under DOS).
Here is a close one:
https://docs.bentley.com/LiveContent/web/MicroStation%20Help-v13/en/SolidbyExtrusionAlong.html
but not quite along two paths.

@phkahler
Copy link
Member Author

@ruevs my intent is to do most of that stuff. For 3D construction I aim for:: Mirror, Frustum, and Extrude along a path. The path concept (in my head) is looking better all the time. Then I hope to add some "features" to standard extrusions: Draft angles, fillets (on top/bottom), and chamfers (top/bottom). Since all of these have had time to bake in my head and a few prototypes have been tried, I can see how certain pieces of code can be shared among them. It's just a problem of having time and doing yet another test or two or three. The path tool might be superior to the ones you linked to above, although I do not intend to allow distortion of the basic shape along the path I might go for changing size and maybe rotation - the UI to get all those working nicely may be a challenge but I've got some really neat ideas in mind. I need to stop hinting at this stuff and get going on it, but it's such a huge project.

@WooterTheTroubleshooter
Copy link

WooterTheTroubleshooter commented Jan 26, 2022

Procedure:

  • Ctrl+N ("File | New")
  • C ("Sketch | Circle") - draw a circle
  • Rotate view with middle button drag or Shift+ right button drag or F3 (for "View | Nearest Isometric | View")
  • 3 ("Sketch | Anywhere in 3d")
  • "Sketch | Workplane"
  • Click on origin. A new "workplane" is created
  • Select the any "workplane"
  • 2 ("Sketch | In Workplane")
  • Shift+X ("New Group | Extrude")
  • Rotate view with middle button drag or Shift+ right button drag
  • Enjoy :-)

I'd like to add for people searching for this. That it is actually possible to select any sketch-in-plane workplane for the extrusion and thus create a constrained skew.
FlexySkew

@phkahler
Copy link
Member Author

phkahler commented Jan 26, 2022

@WooterTheTroubleshooter the technique for making a skewed extrusion is a bit obscure but has been mentioned before. What I want to know is how you appear to be manipulating the workplane used to skew the extrusion after the fact. I am not aware of any way to move such workplanes.

Edit: Got it. On Linux it's shift-left-click-drag. You draw the normal (at the origin in this case) that was created for the workplane.

The downside is that you can't constrain the angle of the skew in the later group. I hope to add a "frustum" extrusion that will allow the skew as well as scaling the "new" end. Both could be constained in the new group. Another option would be to make optional the 2 perpendicular constraints that are added to an extrude group - they keep the direction of the extrusion aligned to the normal of the workplane. I prefer the frustum idea.

@WooterTheTroubleshooter
Copy link

WooterTheTroubleshooter commented Jan 26, 2022

@phkahler It was not that obvious for me, so I thought it would help other people wanting to do something like this.

shift-left-click-drag

I use Shift + W, (based on a point and 2 lines) what does shift-left-click-drag do? So my sketch-in-plane workplane is constrained to the normals of that selection. (Edit: I am actually dragging points on a sketch to influence the skew)

Currently I use it to constrain the skew based on the height of the base model. (So I like the angle to propagate up instead of down)

SkewBasedOnHeight

You can use the existing angle constraints to constrain the workplane to a fixed angle and keep the width the same.

Edit: I think being able to mirror would allow to achieve the frustrum effect. I was trying to abuse the step and rotate towards this goal.

Edit: Forgot to mention. + Clarify not using shift-left-click-drag to manipulate the normal of the workplane, but actually using constraints from the model.

@phkahler
Copy link
Member Author

@WooterTheTroubleshooter ok. Your step by step didnt indicate the workplane was defined using other sketch entities. That explains it.

@WooterTheTroubleshooter
Copy link

WooterTheTroubleshooter commented Jan 26, 2022

@phkahler Here is how one could constrain the angle.
AngleConstraintSkew

Edit: I was actually quoting the procedure posted by @ruevs I will try and clarify.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants