dcowden / cadquery

CadQuery-- a parametric cad script framework
Other
432 stars 56 forks source link

Extrude can execute only once on a CQ object, but more than once is needed! #130

Closed huskier closed 8 years ago

huskier commented 8 years ago

I want to get two parts from a 2D sketch with extruding operation; however, once I extrude from the 2D sketch, I cannot extrude again from it, even I use another variable. I tried deepcopy, newObject etc., but no success. The code is as following, and the error reads in freecad module:

Cannot compute Inventor representation for the shape of Shape0_12406284058. Cannot compute Inventor representation for the shape of Shape0_12406284058.

import sys
import cadquery
from Helpers import show
import copy

result0 = cadquery.Workplane("XY").moveTo(-5,-5).lineTo(5,-5).lineTo(5,5).lineTo(-5,5).close()
#result00 = cadquery.Workplane("XY").moveTo(-5,-5).lineTo(5,-5).lineTo(5,5).lineTo(-5,5).close()
#result00 = copy.deepcopy(result0)
#result00 = cadquery.Workplane().newObject(result0)
result00 = result0

result1 = result0.extrude(100)
result2 = result00.extrude(50).translate((100,100,0))

show(result1)
show(result2)
jmwright commented 8 years ago

I don't have time to troubleshoot this more deeply right now, but as you can see from the modified code below, the sketches/wires/edges seem fine. It's just when you try to display the extrusions at the same time that there's a problem. I thought that maybe it was a problem with the solids being improperly combined, so I set the combine to false on the extrude operations. That didn't help.

import sys
import cadquery
from Helpers import show
import copy

result0 = cadquery.Workplane("XY").moveTo(-5,-5).lineTo(5,-5).lineTo(5,5).lineTo(-5,5).close()
#result00 = cadquery.Workplane("XY").moveTo(-5,-5).lineTo(5,-5).lineTo(5,5).lineTo(-5,5).close()
#result00 = copy.deepcopy(result0)
#result00 = cadquery.Workplane().newObject(result0)
result00 = result0
result00 = result0.translate((100, 100, 0))
show(result0)
show(result00)
result1 = result0.extrude(100, combine=False, clean=False)
result2 = result00.extrude(50, combine=False, clean=False)

show(result1)
show(result2)
dcowden commented 8 years ago

wow great research. What a horrible CAD kernel! This type of thing is a great example of how opencasacde is a crappy CAD kernel compared to real ones like Parasolid.

so... at any rate, i agree we need to make a BoundBox function that applies the recommended fix to tessellate the shape...

On Thu, Dec 24, 2015 at 8:41 AM, huskier notifications@github.com wrote:

I want to get two parts from a 2D sketch with extruding operation; however, once I extrude from the 2D sketch, I cannot extrude again from it, even I use another variable I tried deepcopy, newObject etc, but no success The code is as following, and the error reads: Cannot compute Inventor representation for the shape of Shape0_12406284058 Cannot compute Inventor representation for the shape of Shape0_12406284058

import sys import cadquery from Helpers import show import copy

result0 = cadqueryWorkplane("XY")moveTo(-5,-5)lineTo(5,-5)lineTo(5,5)lineTo(-5,5)close()

result00 = cadqueryWorkplane("XY")moveTo(-5,-5)lineTo(5,-5)lineTo(5,5)lineTo(-5,5)close()

result00 = copydeepcopy(result0)

result00 = cadqueryWorkplane()newObject(result0)

result00 = result0

result1 = result0extrude(100) result2 = result00extrude(50)translate((100,100,0))

show(result1) show(result2)

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130.

huskier commented 8 years ago

@dcowden This is another issue.

Extruding operation can be executed only once. Any ideas how could we debug the problem? OR is it implemented on purpose?

huskier commented 8 years ago

After examining the extrude and _extrude code, I've found the reason why extruding operation could be executed only once. The problem is the shared "pendingWires". Once we executed the extruding operation, all the wires is emptied by the current code.

One solution is to add an option isClearPendingWires, and default it to True, and add the following code to the _extrude fuction:

    if isClearPendingWires:
            self.ctx.pendingWires = []  # now all of the wires have been used to create an extrusion
    else:
        pass

and now the functions looks like:

def extrude(self, distance, combine=True, clean=True, isClearPendingWires=True):
def _extrude(self, distance, isClearPendingWires=True):

@dcowden and @jmwright Is it a good idea to add the option isClearPendingWires?

dcowden commented 8 years ago

I think the current way of doing pendingWires is broken. Its very reasonable to expect what you did, IE, after this code:

shouldHavePendingWires = cq.Workplane('XY').circle() obj = shouldHavePendingWires.extrude(1.0)

we really expect 'shouldHavePendingWires to be usable again to extrude .

Though the flagfix you propose would work, I think my initial implementation is poor. We need to do something smarter.

Right now, pendingWires is stored on the CQContext, which is shared for all stack objects after a Workplane() instruction. As you point out, once extruded, the pendingWires list is cleared.

We could simply remove this: self.ctx.pendingWires = []

We would get the behavior we want. But then we would also get a side affect, that this code would work differently than it did:

cq.Workplane('XY').circle(1.0).extrude(1.0).circle(2.0).extrude(1.0)

How should this code function? Honestly if i came across this code, i wouldnt understand the design intent at all.

I think in the above case, the first extrude() should return a CQ object that is NOT a workplane. Workplane('XY').circle(1.0).extrude(1.0) returns a solid. it doesn't make sense to then draw a circle without first selecting a face or workplane.

Sorry i'm rambling a bit, but i think that:

(a) if we assume that each new workplane gets a new set of pending Wires/pending Edges, as it does now, and (b) that pending Wires/edges are never cleared, and (c) that we always return a CQ object and NOT a workplane object after an operation that converts wires to a solid,

then we will get the behavior we want.

On Wed, Dec 30, 2015 at 9:56 AM, huskier notifications@github.com wrote:

After examining the extrude and _extrude code, I've found the reason why extruding operation could be executed only once. The problem is the shared "pendingWires". Once we executed the extruding operation, all the wires is emptied by the current code.

One solution is to add an option isClearPendingWires, and default it to True, and add the following code to the _extrude fuction:

if isClearPendingWires:
        self.ctx.pendingWires = []  # now all of the wires have been used to create an extrusion
else:
    pass

and now the functions looks like:

def extrude(self, distance, combine=True, clean=True, isClearPendingWires=True): def _extrude(self, distance, isClearPendingWires=True):

@dcowden https://github.com/dcowden and @jmwright https://github.com/jmwright Is it a good idea to add the option isClearPendingWires?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-168014909.

huskier commented 8 years ago

@dcowden

I am not sure that I fully understand what you are saying.

One thing is for sure that I don't like the idea that extruding operation returns a Workplane object, and it make more sense if extruding operation returns a CQ object. This applies for other similar operation which returns a solid-like thing, and now returns a Workplane object.

What do you mean that if we change the current behavior of extruding, i.e. return a CQ object, then we could get what we expected?

dcowden commented 8 years ago

I mean that if we simply remove the code that clears the pending wires, all of the scenarios will work as we expect. We may (or may not) need to go and find places that return a workplane when they should return a cq object, but these changes would be welcome because they would be more consistent with how things should work. On Dec 30, 2015 10:24 PM, "huskier" notifications@github.com wrote:

@dcowden https://github.com/dcowden

I am not sure that I fully understanding what you are saying.

One thing is for sure that I don't like the idea that extruding operation returns a Workplane object, and it make more sense if extruding operation returns a CQ object.

What do you mean that if we change the current behavior of extruding, then we could get what we expected?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-168114946.

huskier commented 8 years ago

@dcowden Do you mean that the following function should return a CQ object instead of a Workplane object as they do now? I copied them from your FULL DOCUMENT "3-d operations that require a 2-d workplane to be active".

Workplane.cboreHole(diameter, cboreDiameter, ...) 
Workplane.cskHole(diameter, cskDiameter, ...)
Workplane.hole(diameter[, depth, clean]) 
Workplane.extrude(distance[, combine, clean]) 
Workplane.cut(toCut[, combine, clean])  
Workplane.cutBlind(distanceToCut[, clean])
Workplane.cutThruAll([positive, clean])
Workplane.box(length, width, height[, ...])
Workplane.union([toUnion, combine, clean])
Workplane.combine([clean])

I could change the code so that extrude operation return a CQ object, but I don't know how to deal with the combine part. I mean whether we need to care about combineWithBase if we extrude from wires. In my opinion, we could just create a new CQ object, and don't need to care about the combineWithBase part.

        if combine:
            newS = self._combineWithBase(r)

Meanwhile, we need to change them all together, otherwise other operations would not work(such as cut) if we just change the extrude operation return type.

dcowden commented 8 years ago

Hey sorry i'm trying to re-orient myself on this conversation.

Yes, that's basically waht i mean. I think the current code doesnt pay enough attention to detail about when to return a Workplane and when to return a CQ object. a Workplane object should be returned, philosophically, when there is a conceptually relevant 2-D work plane. After you do a hole() or extrude() operation, i think really you no longer have an active workplane. But that's a matter of opinion i suppose.

My main point, though, was that by doing that, we would force people to stop accumulating pendingWires because once you lose the workplane you lose those.

On Wed, Jan 20, 2016 at 7:49 AM, huskier notifications@github.com wrote:

@dcowden https://github.com/dcowden Do you mean that the following function should return a CQ object instead of a Workplane object as they do now? I copied them from your FULL DOCUMENT "3-d operations that require a 2-d workplane to be active".

Workplane.cboreHole(diameter, cboreDiameter, ...) Workplane.cskHole(diameter, cskDiameter, ...) Workplane.hole(diameter[, depth, clean]) Workplane.extrude(distance[, combine, clean]) Workplane.cut(toCut[, combine, clean]) Workplane.cutBlind(distanceToCut[, clean]) Workplane.cutThruAll([positive, clean]) Workplane.box(length, width, height[, ...]) Workplane.union([toUnion, combine, clean]) Workplane.combine([clean])

I could change the code so that extrude operation return a CQ object, but I don't know how to deal with the combine part. I mean whether we need combineWithBase if we extrude from wires, In my opinion, we could just create a new CQ object, and don't need to care about the combineWithBase part.

    if combine:
        newS = self._combineWithBase(r)

Meanwhile, we need to change them all together, otherwise other operations would not work(such as cut) if we just change the extrude operation return type.

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-173194935.

huskier commented 8 years ago

Then how do we deal with the combining part when we return a CQ object instead of a Workplane object?

dcowden commented 8 years ago

Sorry, i don't understand the question really...

On Thu, Jan 21, 2016 at 11:37 AM, huskier notifications@github.com wrote:

Then how do we deal with the combining part when we return a CQ object instead of a Workplane object?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-173627343.

huskier commented 8 years ago

The current "extrude" function implement is as following, and there is a combine option. If the combine equals True, then the new extruded solid will be combined with the base solid, which will be searched from the current Workplane object.

def extrude(self, distance, combine=True, clean=True):
        r = self._extrude(distance)  
        if combine:
            newS = self._combineWithBase(r)
        else:
            newS = self.newObject([r])
        if clean: newS = newS.clean()
        return newS

My implement is looks like as following, and I don't know how to deal with combine and clean options.

def extrude(self, distance, combine=True, clean=True):
        r = self._extrude(distance) 
        newS = CQ.newObject(self, [r])
        return newS

Maybe I need a large portion of time to consider this issue...

huskier commented 8 years ago

I find a new way for the extruding operation to return a CQ object instead of a Workplane object, that is returning a CQ.newObject(self, newS.vals()) instead of newS at the end of the extrude function. Here is the code.

def extrude(self, distance, combine=True, clean=True):
        r = self._extrude(distance)  
        if combine:
            newS = self._combineWithBase(r)
        else:
            newS = self.newObject([r])
        if clean: newS = newS.clean()
        return CQ.newObject(self, newS.vals())

However, this will fail many test cases, so it is a big action to adjust CQ and Workplane object.

dcowden commented 8 years ago

yes, something along these lines is what i had in mind.

It is a significant change to start returning CQ objects instead of workplanes, but i think it makes more sense conceptually.

but actually, now that i look back at the code, i can see it wont even have the affect we're after. the idea was to return a CQ object instead of a Workplane object, so that pending edges and wires that were hanging around are cleared. But looking at Workplane._addPendingWire, i can see that they are stored on the context, not the workplan object-- so they will persist even if we return a CQ object.

This means we'd need to figure out a way for workplane objects to share pending wires and edges, but then reset them after we've finished with 'workplane' mode.

What i mean is, in this case:

Workplane('XY').lineTo(2,3).lineTo(4,5)

we have three workplane objects, and they all need to share the same set of pending edges. What we could do, is to stop creating new objects for workplanes, and use the same object. then, we could store pending wires and pending edges on the workplane itself.

these would be a lot of chnages-- we'd need to do it on a major revision, since it would break behavior of previous scripts.

On Fri, Jan 22, 2016 at 7:48 AM, huskier notifications@github.com wrote:

I find a new way for the extruding operation to return a CQ object instead of a Workplane object, that is returning a CQ.newObject(self, newS.vals()) instead of newS. Here is the code.

def extrude(self, distance, combine=True, clean=True): r = self._extrude(distance) if combine: newS = self._combineWithBase(r) else: newS = self.newObject([r]) if clean: newS = newS.clean() return CQ.newObject(self, newS.vals())

However, this will fail many test cases.

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-173911217.

huskier commented 8 years ago

I created a branch named "CQ_or_Workplane" on my fork, and am trying to solve the CQ or Workplane object problem. [My fork branch] https://github.com/huskier/cadquery/tree/CQ_or_Workplane

Right now, the following code is as expected: result = cq.Workplane("XY").box(10,10,10).faces(">Y").workplane().rect(10,5).cutBlind(-5)

However, when I expand the chain further result = cq.Workplane("XY").box(10,10,10).faces(">Y").workplane().rect(10,5).cutBlind(-5).faces(">Z").workplane().rect(2,2).cutBlind(-2)

I've got an error which reads "BRep_API: command not done"

I don't know why? But I guess my problem is in the context of "Chaining" and "The Context Solid". [Ref] http://dcowden.github.io/cadquery/primer.html

huskier commented 8 years ago

To debug the code, I dig into the cutBlind() function. To make sure that findSolid() function works OK, I write the following code (note: the last cutBlind function is commented out):

result = cq.Workplane("XY").box(10,10,10).\
              faces(">Y").workplane().rect(10,5).cutBlind(-5).\
              faces(">Z").workplane().rect(2,2)#.cutBlind(-2)
result = result.findSolid()
result = cq.CQ(result)
show(result)

Until now, I've got the expected result.

After re-create the CQ object, I could then do the cutBlind operation: result = result.faces(">Z").workplane().rect(2,2).cutBlind(-2) This time I've got what I want.

However, if I chain them together as one line code, I've got an error "BRep_API: command not done".

result = cq.Workplane("XY").box(10,10,10).\
               faces(">Y").workplane().rect(10,5).cutBlind(-5).\
               faces(">Z").workplane().rect(2,2).cutBlind(-2)

Very weird!

Could you please explain the "ctxSolid", "solidRef", "chain operation", and "The context solid" etc. a little bit more?

dcowden commented 8 years ago

Yes I agree that's weird. I'll have to dig into these examples to understand what's going on.

The context serves as a scope that all cq objects in the chain share. If something is in the context, it means we intend for multiple consecutive operations in the chain should share a value.

The context solid is supposed to represent the 'most recent result' .. IE, the result of the most recent operation. One purpose of this concept was to allow garbage collection of older, intermediate solids that were generated in the chain, to save memory.

Let me illustrate with an example. Consider this code

​result_1 = cq.Workplane("XY").box(10,10,10)

​result_2 = result_1.faces(">Z").workplane().rect(2,2).cutBlind(-2);

show(result_1.val())

show(result_2.val())

The intention of the 'Context Solid' is to produce behavior where both ​the last two lines will display the same object. IE, we track the single solid we are working on, and use the context to make sure that everyone can see the latest version. The idea is (a) to save memory by allowing removing older versions of the solid, and (b) allow it to be less important to hang onto partciular cq variable references to get what you want.

If we eliminate the context solid, then result_1 would still show a cube without a hole.

The idea of the context solid is that there is one 'result' we are continually working on, but of course for many operations, there is not yet a solid. for example, after cq.Workplane("XY").rect(2,2) there is not yet a solid we can use. the findSolid() method finds any solid that is created, with the idea that the first time we create one, it becomes the context solid.

In retrospect, i think this way of working is confusing and limiting. It would be better to just let users build a tree, and allow consuming memory as necessary. that means every cq layer has a complete copy of all of the geometry produced.

Anyway sorry for the rambling answer. that's the thoughts behind it. I may have screwed up the implementation.

For the next CQ, we need to redo this completely. in addition to allowing more memory consumption to keep a complete history of all generated geometry, we also need to add ability to identify each operation, and provide queries that will allow selecting features created by a certain operation. this would be much easier if we save the whole tree. example:

result = ​cq.Workplane("XY").box(10,10,10).faces(">Z").circle(1.).cutBlind(opId="hole")

result2 = result.faces(createdBy="hole" && "<Z" )

Should select the faces that were created by the cutBlind operation ( the bottom and side faces of the hole), and then narrow that down to the lowest in the Z direction ( the bottom of the hole).

I'm still working on how to track which features were created by a single operation-- its kind of difficult and definitely hard to do with FreeCAD but with direct pythonOCC i could .

On Feb 20, 2016 8:19 AM, "huskier" notifications@github.com wrote:

To debug the code, I dig into the cutBlind() function. To make sure that findSolid() function works OK, I write the following code:

result = cq.Workplane("XY").box(10,10,10).\ faces(">Y").workplane().rect(10,5).cutBlind(-5).\ faces(">Z").workplane().rect(2,2)#.cutBlind(-2) result = result.findSolid() result = cq.CQ(result) show(result)

Until now, I've got the expected result.

After re-create the CQ object, I could then do the cutBlind operation: result = result.faces(">Z").workplane().rect(2,2).cutBlind(-2) This time I've got what I want.

However, if I chain them together as one line code, I've got an error "BRep_API: command not done".

result = cq.Workplane("XY").box(10,10,10).\ faces(">Y").workplane().rect(10,5).cutBlind(-5).\ faces(">Z").workplane().rect(2,2).cutBlind(-2)

Very weird!

Could you please explain the "ctxSolid", "solidRef", and "The context solid" etc. a little bit more?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-186593668.

huskier commented 8 years ago

It is beyond my expectation for the last two lines returns the same object. I am learning. In my opinion, the result_1.val() should return a box without a hole, and result_2.val() should return a box with a hole.

result_1 = cq.Workplane("XY").box(10,10,10)
result_2 = result_1.faces(">Z").workplane().rect(2,2).cutBlind(-2)
show(cq.CQ(result_1.val()))
show(cq.CQ(result_2.val()).translate((20,20,0)))

I like your idea for the next CQ, which could identify each operation and allow selecting features created by a certain operation. Since it is not easy to track the featuring operation, could we just use different variables to identify each operation? We could just keep the chain as long as what we need, and avoid long chain operations.

result =
cq.Workplane("XY").box(10,10,10).faces(">Z").circle(1.).cutBlind()
result2 = result.faces("<Z" )

To debug my weird problem, I traced back the code, and the calling sequence is as following:

  1. cutBlind(….)
  2. s = solidRef.cut(toCut)
  3. Shape.cast(self.wrapped.cut(solidToCut.wrapped)) [Solid class’s cut fuction] From here, I cannot continue to trace the command “cut”, it just return to "cut" fuction itself like a recursion. I could not jump further for the problem. Any ideas?
dcowden commented 8 years ago

yes, i agree that the way of working you describe makes the most sense. I had some reasons for doing it the way i did, but they were not very strong, and i think the current way is really confusing, not to mention, makes the code much more complex.

in practice, nearly none of the examples and tests take advantage of this difference, so i think changing the functionality won't be too huge of a deal. ( though it will still be a breaking change, so its a CQ 2.0 thing )

yeah, the reason you can't drill further is because you've reached the freecad object itself. you have a python reference, but it is actually a wrapper around the underlying FreeCAD solid object.

On Mon, Feb 22, 2016 at 9:28 AM, huskier notifications@github.com wrote:

It is beyond my expectation for the last two lines returns the same object. I am learning. In my opinion, the result_1.val() should return a box without a hole, and result_2.val() should return a box with a hole.

result_1 = cq.Workplane("XY").box(10,10,10) result_2 = result_1.faces(">Z").workplane().rect(2,2).cutBlind(-2) show(cq.CQ(result_1.val())) show(cq.CQ(result_2.val()).translate((20,20,0)))

I like your idea for the next CQ, which could identify each operation and allow selecting features created by a certain operation. Since it is not easy to track the featuring operation, could we just use different variables to identify each operation? We could just keep the chain as long as what we need, and avoid long chain operations.

result = cq.Workplane("XY").box(10,10,10).faces(">Z").circle(1.).cutBlind() result2 = result.faces("<Z" )

To debug my weird problem, I traced back the code, and the calling sequence is as following:

  1. cutBlind(….)
  2. s = solidRef.cut(toCut)
  3. Shape.cast(self.wrapped.cut(solidToCut.wrapped)) [Solid class’s cut fuction] From here, I cannot continue to trace the command “cut”, it just return to "cut" fuction itself like a recursion. I could not jump further for the problem. Any ideas?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-187203580.

huskier commented 8 years ago

yeah, the reason you can't drill further is because you've reached the freecad object itself. you have a python reference, but it is actually a wrapper around the underlying FreeCAD solid object.

So, is there any practical way to find the root reason of "BRep_API: command not done" error? My current focus is to make extruding function work a proper way, so I could do something useful, such as a parametric instrument box or more practical models.

For CQ 2.0, do you have any timeline, even the rough one? OR, what's your ultimate goal for CQ?

dcowden commented 8 years ago

Ok, you have several questions:

So, is there any practical way to find the root reason of "BRep_API:

command not done" error?

Not any really great way. when you get that error, normally it means 'I see that you supplied parameters that appear valid ( at least, are not null references ), but when when i tried to do the logic, i couldnt. Using OCC directly, you can get the error code,but this is not available due to the freecad layer. Typically it means things like 'produced a non-manifold solid', 'you tried to subtract two solids that dont intersect', things like that. Normally i try to print out the operands individually, and then see if changing any of the values changes things.

For CQ 2.0, do you have any timeline, even the rough one?

Not right now. But you are right that having one would be really, really useful-- in combination with a road map. Its hard to know the timeline because i dont know who all i can count on to help. The first step will be for me to outline the new way of working and/or concepts in some sort of document. After that, it would be nice if some of the community can help with some of the coding.

OR, what's your ultimate goal for CQ?

I want CQ to be the only open source, and most useful programmatic cad program. The intent is to spread the toolset so that the concept of CAD modules that are programs, not STL files, becomes more widespread. I imagine a world in which very complex models are created because people share the source for lots of building blocks-- all the while enjoying the ability to merge,fork, and diff them because they are plain-text, not some proprietary format.

In the longer term, I plan to create a parametric build service. The beginnings are there today: parametricparts.com. The site's goal is to offer a platform that people can use to execute scripts without necessarily installing the latest version of the tools. That site will use docker containers to provide ability to run any version of CQ script, and in addition other ;) scripts like OpenSCAD and FreeCAD. Kind of like a 'parse.com' sort of thing, but for CAD scripts rather than javascript, if you will.

On Tue, Feb 23, 2016 at 7:22 AM, huskier notifications@github.com wrote:

yeah, the reason you can't drill further is because you've reached the freecad object itself. you have a python reference, but it is actually a wrapper around the underlying FreeCAD solid object.

So, is there any practical way to find the root reason of "BRep_API: command not done" error? My current focus is to make extruding function work a proper way, so I could do something useful, such as a parametric instrument box or more practical models.

For CQ 2.0, do you have any timeline, even the rough one? OR, what's your ultimate goal for CQ?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-187678829.

huskier commented 8 years ago

Thanks for your explanation. I'd like to help a bit if I have time, for I'm really like the concept of the software.

For the issue, I've found a way to get it worked. Just comment out the line of

s.ctx = self.ctx

in the CQ class' workplane method. Then the following code could get the expected result.

result = cq.Workplane("XY").box(10,10,10).\
               faces(">Y").workplane().rect(10,5).cutBlind(-5).\
               faces(">Z").workplane().rect(2,2).cutBlind(-2)

The side effect is that this makes "loft" operation unhappy. I've got at least 5 ERRORs for the test in the package.

Traceback (most recent call last): File "E:\siom-work\zybao\github\cadquery\tests\TestCadQuery.py", line 263, in testLoftCombine .workplane(offset=3.0).rect(0.75,0.5).loft(combine=True) File "E:\siom-work\zybao\github\cadquery\cadquery\cq.py", line 2351, in loft r = Solid.makeLoft(wiresToLoft, ruled) File "E:\siom-work\zybao\github\cadquery\cadquery\freecad_impl\shapes.py", line 739, in makeLoft return Shape.cast(FreeCADPart.makeLoft([i.wrapped for i in listOfWire], True, ruled)) OCCError: Need at least two vertices, edges or wires to create loft face

Another side effect is that the following code works weired!

s1 = cq.Workplane("XY")
currentS = s1.rect(2.0,2.0).extrude(0.5)
toCut = s1.rect(1.0,1.0).extrude(0.5)
currentS.cut(toCut.val())
#self.assertEqual(10,currentS.faces().size())
show(toCut)

To make the last code block works properly, we have to define two "Workplane"s like this:

s1 = cq.Workplane("XY")
s2 = cq.Workplane("XY")
currentS = s1.rect(2.0,2.0).extrude(0.5)
toCut = s2.rect(1.0,1.0).extrude(0.5)
currentS.cut(toCut.val())
#self.assertEqual(10,currentS.faces().size())
show(toCut)

Could you please help a little bit for the loft operation? It's all about CQContext!

dcowden commented 8 years ago

yeah, the 'weird' code definitely doesnt work right-- you shouldnt have to define two workplanes.

i'll be honest, at this point, it seems like the right thing to do is to just start the process of changing things to work correctly, which IMO means we need some pretty fundamental changes to how CQ is organized. I think we're going to go nuts trying to make small changes to get what we want.

I have a lot on my plate at the moment. I'll try to have a look soon at this to see what i can find out. My fear is that there will not be an 'easy' solution to get what you want-- but the good news is that I think we're completely aligned on what exactly we want.

I feel like if i could just spend a solid day or so, i coudl sketch out a framework for a new way of working, which coudl be a basis for iterating.

What if i create a CQ 2.0 branch this weekend, that we can iterate on without fear of breaking 1.x?

On Thu, Feb 25, 2016 at 8:42 AM, huskier notifications@github.com wrote:

Thanks for your explanation. I'd like to help a bit if I have time, for I'm really like the concept of the software.

For the issue, I've found a way to get it worked. Just comment out the line of

s.ctx = self.ctx

in the CQ class' workplane method. Then the following code could get the expected result.

result = cq.Workplane("XY").box(10,10,10).\ faces(">Y").workplane().rect(10,5).cutBlind(-5).\ faces(">Z").workplane().rect(2,2).cutBlind(-2)

The side effect is that this makes "loft" operation unhappy. I've got at least 5 ERRORs for the test in the package.

Traceback (most recent call last): File "E:\siom-work\zybao\github\cadquery\tests\TestCadQuery.py", line 263, in testLoftCombine .workplane(offset=3.0).rect(0.75,0.5).loft(combine=True) File "E:\siom-work\zybao\github\cadquery\cadquery\cq.py", line 2351, in loft r = Solid.makeLoft(wiresToLoft, ruled) File "E:\siom-work\zybao\github\cadquery\cadquery\freecad_impl\shapes.py", line 739, in makeLoft return Shape.cast(FreeCADPart.makeLoft([i.wrapped for i in listOfWire], True, ruled)) OCCError: Need at least two vertices, edges or wires to create loft face

Another side effect is that the following code works weired!

s1 = cq.Workplane("XY") currentS = s1.rect(2.0,2.0).extrude(0.5) toCut = s1.rect(1.0,1.0).extrude(0.5) currentS.cut(toCut.val())

self.assertEqual(10,currentS.faces().size())

show(toCut)

To make the last code block works properly, we have to define two "Workplane"s like this:

s1 = cq.Workplane("XY") s2 = cq.Workplane("XY") currentS = s1.rect(2.0,2.0).extrude(0.5) toCut = s2.rect(1.0,1.0).extrude(0.5) currentS.cut(toCut.val())

self.assertEqual(10,currentS.faces().size())

show(toCut)

Could you please help a little bit for the loft operation?

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-188789069.

huskier commented 8 years ago

I'm looking forward to your pretty framework and the CQ 2.0 branch. I am here at your service, and please feel free to assign me some work once you sketch the framework.

Thanks a lot!

dcowden commented 8 years ago

Ok, i have created a cadquery 2.0 branch. I pretty much gutted the project and replaced it only with some sketches and documentation in the readme.md about my thoughts on the next version.

https://github.com/dcowden/cadquery/tree/2_0_branch

Its not much, but i hope that the thoughts in the readme help communicate what i'm thinking for the next version.

Feel free to chime in/edit/add. I know we can use a lot more of the 0.3 codebase than what's in there: i just cleaned everything out so its easy to see what's new and what's not.

On Thu, Feb 25, 2016 at 7:38 PM, huskier notifications@github.com wrote:

I'm looking forward to your pretty framework and the CQ 2.0 branch. I am here at your service, and please feel free to assign me some work once you sketch the framework.

Thanks a lot!

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-189053389.

huskier commented 8 years ago

Thanks for your effort. I'd like to help a little bit whenever I have time.

dcowden commented 8 years ago

yep. I have a busy couple of weeks coming up at work. I plan to work more to get the objects to the point where the implementation path is more clear. then i think you'll be able to jump in.

On Mon, Feb 29, 2016 at 8:32 AM, huskier notifications@github.com wrote:

Thanks for your effort. I'd like to help a little bit whenever I have time.

— Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/130#issuecomment-190212419.

huskier commented 8 years ago

thanks!