diff --git a/cadquery/occ_impl/exporters/dxf.py b/cadquery/occ_impl/exporters/dxf.py index ab8e22208..558d6e235 100644 --- a/cadquery/occ_impl/exporters/dxf.py +++ b/cadquery/occ_impl/exporters/dxf.py @@ -54,28 +54,28 @@ class DxfDocument: .. rubric:: Example usage .. code-block:: python - :caption: Single layer DXF document + :caption: Single layer DXF document - rectangle = cq.Workplane().rect(10, 20) + rectangle = cq.Workplane().rect(10, 20) - dxf = DxfDocument() - dxf.add_shape(rectangle) - dxf.document.saveas("rectangle.dxf") + dxf = DxfDocument() + dxf.add_shape(rectangle) + dxf.document.saveas("rectangle.dxf") .. code-block:: python - :caption: Multilayer DXF document - - rectangle = cq.Workplane().rect(10, 20) - circle = cq.Workplane().circle(3) - - dxf = DxfDocument() - dxf = ( - dxf.add_layer("layer_1", color=2) - .add_layer("layer_2", color=3) - .add_shape(rectangle, "layer_1") - .add_shape(circle, "layer_2") - ) - dxf.document.saveas("rectangle-with-hole.dxf") + :caption: Multilayer DXF document + + rectangle = cq.Workplane().rect(10, 20) + circle = cq.Workplane().circle(3) + + dxf = DxfDocument() + dxf = ( + dxf.add_layer("layer_1", color=2) + .add_layer("layer_2", color=3) + .add_shape(rectangle, "layer_1") + .add_shape(circle, "layer_2") + ) + dxf.document.saveas("rectangle-with-hole.dxf") """ CURVE_TOLERANCE = 1e-9 diff --git a/doc/assy.rst b/doc/assy.rst index 0c8d30dd5..b94c9f976 100644 --- a/doc/assy.rst +++ b/doc/assy.rst @@ -18,21 +18,21 @@ We want to start with defining the model parameters to allow for easy dimension .. code-block:: python - import cadquery as cq + import cadquery as cq - # Parameters - H = 400 - W = 200 - D = 350 + # Parameters + H = 400 + W = 200 + D = 350 - PROFILE = cq.importers.importDXF("vslot-2020_1.dxf").wires() + PROFILE = cq.importers.importDXF("vslot-2020_1.dxf").wires() - SLOT_D = 5 - PANEL_T = 3 + SLOT_D = 5 + PANEL_T = 3 - HANDLE_D = 20 - HANDLE_L = 50 - HANDLE_W = 4 + HANDLE_D = 20 + HANDLE_L = 50 + HANDLE_W = 4 It is interesting to note that the v-slot profile is imported from a DXF file. This way it is very easy to change to other aluminum extrusion type, e.g. Item or Bosch. @@ -45,72 +45,72 @@ Next we want to define functions generating the assembly components based on the .. code-block:: python - def make_vslot(l): - return PROFILE.toPending().extrude(l) + def make_vslot(l): + return PROFILE.toPending().extrude(l) - def make_connector(): - rv = ( - cq.Workplane() - .box(20, 20, 20) - .faces("X").tag("X").end() - rv.faces(">Z").tag("Z").end() + def make_connector(): + rv = ( + cq.Workplane() + .box(20, 20, 20) + .faces("X").tag("X").end() + rv.faces(">Z").tag("Z").end() + + return rv + + + def make_panel(w, h, t, cutout): + rv = ( + cq.Workplane("XZ") + .rect(w, h) + .extrude(t) + .faces(">Y") + .vertices() + .rect(2 * cutout, 2 * cutout) + .cutThruAll() + .faces("Y").edges("%CIRCLE").edges(">Z").tag("hole1") + rv.faces(">Y").edges("%CIRCLE").edges("Y") - .vertices() - .rect(2 * cutout, 2 * cutout) - .cutThruAll() - .faces("Y").edges("%CIRCLE").edges(">Z").tag("hole1") - rv.faces(">Y").edges("%CIRCLE").edges("Y").tag("mate1") - rv.faces("Y").tag("mate1") + rv.faces("Z", "con_tl?Z", "Plane") - .constrain("left@faces@Y", "Axis") - # bottom - .constrain("bottom@faces@Y", "Axis") - .constrain("bottom@faces@>Z", "con_bl?X", "Plane") - # right connectors - .constrain("top@faces@>Z", "con_tr@faces@>X", "Plane") - .constrain("bottom@faces@X", "Plane") - .constrain("left@faces@>Z", "con_tr?Z", "Axis") - .constrain("left@faces@Z", "con_tr@faces@>Z", "Plane") - .constrain("right@faces@X[-4]", "panel@faces@Z", "panel@faces@>Z", "Axis") - # handle - .constrain("panel?hole1", "handle?mate1", "Plane") - .constrain("panel?hole2", "handle?mate2", "Point") - ) + # define the constraints + ( + door + # left profile + .constrain("left@faces@Z", "con_tl?Z", "Plane") + .constrain("left@faces@Y", "Axis") + # bottom + .constrain("bottom@faces@Y", "Axis") + .constrain("bottom@faces@>Z", "con_bl?X", "Plane") + # right connectors + .constrain("top@faces@>Z", "con_tr@faces@>X", "Plane") + .constrain("bottom@faces@X", "Plane") + .constrain("left@faces@>Z", "con_tr?Z", "Axis") + .constrain("left@faces@Z", "con_tr@faces@>Z", "Plane") + .constrain("right@faces@X[-4]", "panel@faces@Z", "panel@faces@>Z", "Axis") + # handle + .constrain("panel?hole1", "handle?mate1", "Plane") + .constrain("panel?hole2", "handle?mate2", "Point") + ) Should you need to do something unusual that is not possible with the string based selectors (e.g. use :py:class:`cadquery.selectors.BoxSelector` or a user-defined selector class), @@ -359,9 +359,10 @@ STEP can be loaded in all CAD tool, e.g. in FreeCAD and the XML be used in other .. code-block:: python :linenos: - door.export("door.step") - door.export("door.xml") -.. image:: _static/door_assy_freecad.png + door.export("door.step") + door.export("door.xml") + +.. image:: _static/door_assy_freecad.png Object locations diff --git a/doc/designprinciples.rst b/doc/designprinciples.rst index e07ca17db..044022a27 100644 --- a/doc/designprinciples.rst +++ b/doc/designprinciples.rst @@ -14,7 +14,7 @@ CadQuery strives to allow scripts to read roughly as a human would describe an o For example, consider this object: -.. image:: _static/quickstart.png +.. image:: _static/quickstart.png A human would describe this as: diff --git a/doc/free-func.rst b/doc/free-func.rst index cc68572ec..51fc9545c 100644 --- a/doc/free-func.rst +++ b/doc/free-func.rst @@ -53,39 +53,39 @@ It begins with defining few edges. .. code-block:: python - edge1 = circle(r) - edge2 = circle(2*r).moved(z=dh) - edge3 = circle(r).moved(z=1.5*dh) + edge1 = circle(r) + edge2 = circle(2*r).moved(z=dh) + edge3 = circle(r).moved(z=1.5*dh) Those edges are used to create the side faces of the final solid using :meth:`~cadquery.occ_impl.shapes.loft`. .. code-block:: python - side = loft(edge1, edge2, edge3) + side = loft(edge1, edge2, edge3) Once the side is there, :meth:`~cadquery.occ_impl.shapes.cap` and :meth:`~cadquery.occ_impl.shapes.fill` are used to define the top and bottom faces. Note that :meth:`~cadquery.occ_impl.shapes.cap` tries to maintain curvature continuity with respect to the context shape. This is not the case for :meth:`~cadquery.occ_impl.shapes.fill`. .. code-block:: python - # bottom face - bottom = fill(side.edges('Z'), side, [(0,0,1.75*dh)]) + # top face with continuous curvature + top = cap(side.edges('>Z'), side, [(0,0,1.75*dh)]) Next, all the faces are assembled into a solid. .. code-block:: python - s = solid(side, bottom, top) + s = solid(side, bottom, top) Finally, the solid is duplicated and placed in the desired locations creating the final compound object. Note various usages of :meth:`~cadquery.Shape.moved`. .. code-block:: python - result = s.moved((-3*r, 0, 0), (3*r, 0, 0)) + result = s.moved((-3*r, 0, 0), (3*r, 0, 0)) In general all the operations are implemented as free functions, with the exception of placement and selection which are strictly related to a specific shape. diff --git a/doc/importexport.rst b/doc/importexport.rst index 5c5581984..6f8aae985 100644 --- a/doc/importexport.rst +++ b/doc/importexport.rst @@ -57,11 +57,11 @@ Importing a DXF profile with default settings and using it within a CadQuery scr .. code-block:: python - import cadquery as cq + import cadquery as cq - result = ( - cq.importers.importDXF("/path/to/dxf/circle.dxf").wires().toPending().extrude(10) - ) + result = ( + cq.importers.importDXF("/path/to/dxf/circle.dxf").wires().toPending().extrude(10) + ) Note the use of the :meth:`Workplane.wires` and :meth:`Workplane.toPending` methods to make the DXF profile ready for use during subsequent operations. Calling ``toPending()`` tells CadQuery to make the edges/wires available @@ -75,9 +75,9 @@ There are no parameters for this method other than the file path to import. .. code-block:: python - import cadquery as cq + import cadquery as cq - result = cq.importers.importStep("/path/to/step/block.stp") + result = cq.importers.importStep("/path/to/step/block.stp") Exporting STEP ############### @@ -92,11 +92,11 @@ since it will be determined from the file extension. Below is an example. .. code-block:: python - # Create a simple object - box = cq.Workplane().box(10, 10, 10) + # Create a simple object + box = cq.Workplane().box(10, 10, 10) - # Export the box - box.export("/path/to/step/box.step") + # Export the box + box.export("/path/to/step/box.step") Non-Default File Extensions ---------------------------- @@ -106,14 +106,14 @@ not recognize the file extension. In that case the export type has to be specifi .. code-block:: python - # Create a simple object - box = cq.Workplane().box(10, 10, 10) + # Create a simple object + box = cq.Workplane().box(10, 10, 10) - # Export the box - box.export("/path/to/step/box.stp", cq.exporters.ExportTypes.STEP) + # Export the box + box.export("/path/to/step/box.stp", cq.exporters.ExportTypes.STEP) - # The export type may also be specified as a literal - box.export("/path/to/step/box2.stp", "STEP") + # The export type may also be specified as a literal + box.export("/path/to/step/box2.stp", "STEP") Setting Extra Options ---------------------- @@ -124,14 +124,14 @@ or the :meth:`Assembly.exportAssembly`` method. .. code-block:: python - # Create a simple object - box = cq.Workplane().box(10, 10, 10) + # Create a simple object + box = cq.Workplane().box(10, 10, 10) - # Export the box, provide additional options with the opt dict - box.export("/path/to/step/box.step", opt={"write_pcurves": False}) + # Export the box, provide additional options with the opt dict + box.export("/path/to/step/box.step", opt={"write_pcurves": False}) - # or equivalently when exporting a lower level Shape object - box.val().export("/path/to/step/box2.step", opt={"write_pcurves": False}) + # or equivalently when exporting a lower level Shape object + box.val().export("/path/to/step/box2.step", opt={"write_pcurves": False}) Exporting Assemblies to STEP @@ -149,17 +149,17 @@ export with all defaults is shown below. .. code-block:: python - import cadquery as cq + import cadquery as cq - # Create a sample assembly - assy = cq.Assembly() - body = cq.Workplane().box(10, 10, 10) - assy.add(body, color=cq.Color(1, 0, 0), name="body") - pin = cq.Workplane().center(2, 2).cylinder(radius=2, height=20) - assy.add(pin, color=cq.Color(0, 1, 0), name="pin") + # Create a sample assembly + assy = cq.Assembly() + body = cq.Workplane().box(10, 10, 10) + assy.add(body, color=cq.Color(1, 0, 0), name="body") + pin = cq.Workplane().center(2, 2).cylinder(radius=2, height=20) + assy.add(pin, color=cq.Color(0, 1, 0), name="pin") - # Save the assembly to STEP - assy.export("out.step") + # Save the assembly to STEP + assy.export("out.step") This will produce a STEP file that is nested with auto-generated object names. The colors of each assembly object will be preserved, but the names that were set for each will not. @@ -173,20 +173,20 @@ fused solids. .. code-block:: python - import cadquery as cq + import cadquery as cq - # Create a sample assembly - assy = cq.Assembly() - body = cq.Workplane().box(10, 10, 10) - assy.add(body, color=cq.Color(1, 0, 0), name="body") - pin = cq.Workplane().center(2, 2).cylinder(radius=2, height=20) - assy.add(pin, color=cq.Color(0, 1, 0), name="pin") + # Create a sample assembly + assy = cq.Assembly() + body = cq.Workplane().box(10, 10, 10) + assy.add(body, color=cq.Color(1, 0, 0), name="body") + pin = cq.Workplane().center(2, 2).cylinder(radius=2, height=20) + assy.add(pin, color=cq.Color(0, 1, 0), name="pin") - # Save the assembly to STEP - assy.export("out.stp", "STEP", mode="fused") + # Save the assembly to STEP + assy.export("out.stp", "STEP", mode="fused") - # Specify additional options such as glue as keyword arguments - assy.export("out_glue.step", mode="fused", glue=True, write_pcurves=False) + # Specify additional options such as glue as keyword arguments + assy.export("out_glue.step", mode="fused", glue=True, write_pcurves=False) Naming ------- @@ -196,12 +196,12 @@ This is done by setting the name property of the assembly before calling :meth:` .. code-block:: python - assy = Assembly(name="my_assembly") - assy.export( - "out.stp", - cq.exporters.ExportTypes.STEP, - mode=cq.exporters.assembly.ExportModes.FUSED, - ) + assy = Assembly(name="my_assembly") + assy.export( + "out.stp", + cq.exporters.ExportTypes.STEP, + mode=cq.exporters.assembly.ExportModes.FUSED, + ) If an assembly name is not specified, a UUID will be used to avoid name conflicts. @@ -212,24 +212,24 @@ It is possible to attach metadata to the assembly that will be included in the S .. code-block:: python - import cadquery as cq - from cadquery.occ_impl.exporters.assembly import exportStepMeta + import cadquery as cq + from cadquery.occ_impl.exporters.assembly import exportStepMeta - # Create a simple assembly - assy = cq.Assembly(name="top-level") - cube_1 = cq.Workplane().box(10.0, 10.0, 10.0) - assy.add(cube_1, name="cube_1", color=cq.Color("green")) + # Create a simple assembly + assy = cq.Assembly(name="top-level") + cube_1 = cq.Workplane().box(10.0, 10.0, 10.0) + assy.add(cube_1, name="cube_1", color=cq.Color("green")) - # Add subshape name, color and layer - assy.addSubshape( - cube_1.faces(">Z").val(), - name="cube_1_top_face", - color=cq.Color("red"), - layer="cube_1_top_face" - ) + # Add subshape name, color and layer + assy.addSubshape( + cube_1.faces(">Z").val(), + name="cube_1_top_face", + color=cq.Color("red"), + layer="cube_1_top_face" + ) - # Export the assembly to STEP with metadata - exportStepMeta(assy, "out.step") + # Export the assembly to STEP with metadata + exportStepMeta(assy, "out.step") Exporting Assemblies to glTF ############################# @@ -241,17 +241,17 @@ export with all defaults is shown below. To export to a binary glTF file, change .. code-block:: python - import cadquery as cq + import cadquery as cq - # Create a sample assembly - assy = cq.Assembly() - body = cq.Workplane().box(10, 10, 10) - assy.add(body, color=cq.Color(1, 0, 0), name="body") - pin = cq.Workplane().center(2, 2).cylinder(radius=2, height=20) - assy.add(pin, color=cq.Color(0, 1, 0), name="pin") + # Create a sample assembly + assy = cq.Assembly() + body = cq.Workplane().box(10, 10, 10) + assy.add(body, color=cq.Color(1, 0, 0), name="body") + pin = cq.Workplane().center(2, 2).cylinder(radius=2, height=20) + assy.add(pin, color=cq.Color(0, 1, 0), name="pin") - # Save the assembly to GLTF - assy.export("out.gltf") + # Save the assembly to GLTF + assy.export("out.gltf") Exporting SVG ############### @@ -278,16 +278,16 @@ Without options: .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10) + result = cq.Workplane().box(10, 10, 10) - result.export("/path/to/file/box.svg") + result.export("/path/to/file/box.svg") Results in: -.. image:: _static/importexport/box_default_options.svg +.. image:: _static/importexport/box_default_options.svg Note that the exporters API figured out the format type from the file extension. The format type can be set explicitly by using :py:class:`exporters.ExportTypes`. @@ -296,30 +296,30 @@ The following is an example of using options to alter the resulting SVG output b .. code-block:: python - import cadquery as cq - from cadquery import exporters - - result = cq.Workplane().box(10, 10, 10) - - result.export( - "/path/to/file/box_custom_options.svg", - opt={ - "width": 300, - "height": 300, - "marginLeft": 10, - "marginTop": 10, - "showAxes": False, - "projectionDir": (0.5, 0.5, 0.5), - "strokeWidth": 0.25, - "strokeColor": (255, 0, 0), - "hiddenColor": (0, 0, 255), - "showHidden": True, - }, - ) + import cadquery as cq + from cadquery import exporters + + result = cq.Workplane().box(10, 10, 10) + + result.export( + "/path/to/file/box_custom_options.svg", + opt={ + "width": 300, + "height": 300, + "marginLeft": 10, + "marginTop": 10, + "showAxes": False, + "projectionDir": (0.5, 0.5, 0.5), + "strokeWidth": 0.25, + "strokeColor": (255, 0, 0), + "hiddenColor": (0, 0, 255), + "showHidden": True, + }, + ) Which results in the following image: -.. image:: _static/importexport/box_custom_options.svg +.. image:: _static/importexport/box_custom_options.svg Exporting with the additional option ``"focus": 25`` results in the following output SVG with perspective: @@ -338,12 +338,12 @@ optimum values that will produce an acceptable mesh. .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10) + result = cq.Workplane().box(10, 10, 10) - result.export("/path/to/file/mesh.stl") + result.export("/path/to/file/mesh.stl") Exporting AMF and 3MF ###################### @@ -359,12 +359,12 @@ optimum values that will produce an acceptable mesh. Note that parameters for co .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10) + result = cq.Workplane().box(10, 10, 10) - result.export("/path/to/file/mesh.amf", tolerance=0.01, angularTolerance=0.1) + result.export("/path/to/file/mesh.amf", tolerance=0.01, angularTolerance=0.1) Exporting TJS @@ -381,17 +381,17 @@ optimum values that will produce an acceptable mesh. .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10) + result = cq.Workplane().box(10, 10, 10) - result.export( - "/path/to/file/mesh.json", - tolerance=0.01, - angularTolerance=0.1, - exportType=exporters.ExportTypes.TJS, - ) + result.export( + "/path/to/file/mesh.json", + tolerance=0.01, + angularTolerance=0.1, + exportType=exporters.ExportTypes.TJS, + ) Note that the export type was explicitly specified as ``TJS`` because the extension that was used for the file name was ``.json``. If the extension ``.tjs`` had been used, CadQuery would have understood to use the ``TJS`` export format. @@ -410,14 +410,14 @@ optimum values that will produce an acceptable mesh. .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10) + result = cq.Workplane().box(10, 10, 10) - result.export( - "/path/to/file/mesh.vrml", tolerance=0.01, angularTolerance=0.1 - ) + result.export( + "/path/to/file/mesh.vrml", tolerance=0.01, angularTolerance=0.1 + ) Exporting DXF ############## @@ -449,26 +449,26 @@ Options See `Units`_. .. code-block:: python - :caption: DXF of workplanes. + :caption: DXF of workplanes. - import cadquery as cq + import cadquery as cq - result = cq.Workplane().box(10, 10, 10).section() + result = cq.Workplane().box(10, 10, 10).section() - exporters.exportDXF(result, "/path/to/file/object.dxf") - # or - result.export("/path/to/file/object.dxf") + exporters.exportDXF(result, "/path/to/file/object.dxf") + # or + result.export("/path/to/file/object.dxf") Sketches can also be directly exported to DXF. .. code-block:: python - :caption: DXF export of sketches. + :caption: DXF export of sketches. - import cadquery as cq + import cadquery as cq - result = cq.Sketch().rect(1,1) + result = cq.Sketch().rect(1,1) - result.export("/path/to/file/object.dxf") + result.export("/path/to/file/object.dxf") Units @@ -491,25 +491,25 @@ doc_units Unit Document units can be set to any :doc:`unit supported by ezdxf `. .. code-block:: python - :caption: DXF document with units set to meters. + :caption: DXF document with units set to meters. - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10).section() + result = cq.Workplane().box(10, 10, 10).section() - exporters.exportDXF( - result, - "/path/to/file/object.dxf", - doc_units=6, # set DXF document units to meters - ) + exporters.exportDXF( + result, + "/path/to/file/object.dxf", + doc_units=6, # set DXF document units to meters + ) - # or + # or - result.export( - "/path/to/file/object.dxf", - opt={"doc_units": 6}, # set DXF document units to meters - ) + result.export( + "/path/to/file/object.dxf", + opt={"doc_units": 6}, # set DXF document units to meters + ) .. _Approximation strategy: @@ -523,9 +523,9 @@ By default, the DXF exporter will output splines exactly as they are represented * ``tolerance``: Acceptable error of the approximation, in document/modelspace units. Defaults to 0.001 (1 thou for inch-scale drawings, 1 µm for mm-scale drawings). .. code-block:: python - :caption: DXF document with curves approximated with cubic splines. + :caption: DXF document with curves approximated with cubic splines. - cq.exporters.exportDXF(result, "/path/to/file/object.dxf", approx="spline") + cq.exporters.exportDXF(result, "/path/to/file/object.dxf", approx="spline") Exporting Other Formats @@ -536,12 +536,12 @@ using the following structure. .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10) + result = cq.Workplane().box(10, 10, 10) - result.export("/path/to/file/object.[file_extension]") + result.export("/path/to/file/object.[file_extension]") Be sure to use the correct file extension so that CadQuery can determine the export format. If in doubt, fall back to setting the type explicitly by using :py:class:`exporters.ExportTypes`. @@ -550,9 +550,9 @@ For example: .. code-block:: python - import cadquery as cq - from cadquery import exporters + import cadquery as cq + from cadquery import exporters - result = cq.Workplane().box(10, 10, 10).section() + result = cq.Workplane().box(10, 10, 10).section() - result.export("/path/to/file/object.dxf", exporters.ExportTypes.DXF) + result.export("/path/to/file/object.dxf", exporters.ExportTypes.DXF) diff --git a/doc/intro.rst b/doc/intro.rst index ac934346f..542a1da53 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -29,7 +29,7 @@ produces a flat plate with a hole in the middle:: width = 2.0 result = Workplane("front").box(width, width, thickness).faces(">Z").hole(thickness) -.. image:: _static/simpleblock.png +.. image:: _static/simpleblock.png That's a bit of a dixie-cup example. But it is pretty similar to a more useful part: a parametric pillow block for a standard 608-size ball bearing:: @@ -49,7 +49,7 @@ standard 608-size ball bearing:: .cboreHole(2.4, 4.4, 2.1) ) -.. image:: _static/pillowblock.png +.. image:: _static/pillowblock.png Lots more examples are available in the :ref:`examples` diff --git a/doc/primer.rst b/doc/primer.rst index c53d2fc96..60549f81c 100644 --- a/doc/primer.rst +++ b/doc/primer.rst @@ -269,7 +269,7 @@ Assemblies Simple models can be combined into complex, possibly nested, assemblies. -.. image:: _static/assy.png +.. image:: _static/assy.png A simple example could look as follows:: @@ -293,7 +293,7 @@ A simple example could look as follows:: Resulting in: -.. image:: _static/simple_assy.png +.. image:: _static/simple_assy.png Note that the locations of the children parts are defined with respect to their parents - in the above example ``part3`` will be located at (-5,-5,20) in the global coordinate system. Assemblies with different colors can be created this way and exported to STEP or the native OCCT xml format. diff --git a/doc/quickstart.rst b/doc/quickstart.rst index 4064cb8cc..55a35f38a 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -15,7 +15,7 @@ If you have not already done so, follow the :ref:`installation`, to install CadQ After installation, run CQ-editor: -.. image:: _static/quickstart/001.png +.. image:: _static/quickstart/001.png Find the CadQuery code editor, on the left side. You'll see that we start out with the script for a simple block. @@ -24,7 +24,7 @@ What we'll accomplish We will build a fully parametric bearing pillow block in this quickstart. Our finished object will look like this: -.. image:: _static/quickstart/000.png +.. image:: _static/quickstart/000.png **We would like our block to have these features:** @@ -51,19 +51,19 @@ with place-holders for the dimensions. Paste this into the code editor: .. code-block:: python :linenos: - height = 60.0 - width = 80.0 - thickness = 10.0 + height = 60.0 + width = 80.0 + thickness = 10.0 - # make the base - result = cq.Workplane("XY").box(height, width, thickness) + # make the base + result = cq.Workplane("XY").box(height, width, thickness) - # Render the solid - show_object(result) + # Render the solid + show_object(result) Press the green Render button in the toolbar to run the script. You should see our base object. -.. image:: _static/quickstart/002.png +.. image:: _static/quickstart/002.png Nothing special, but its a start! @@ -78,26 +78,26 @@ This modification will do the trick: :linenos: :emphasize-lines: 4,10-12 - height = 60.0 - width = 80.0 - thickness = 10.0 - diameter = 22.0 + height = 60.0 + width = 80.0 + thickness = 10.0 + diameter = 22.0 - # make the base - result = ( - cq.Workplane("XY") - .box(height, width, thickness) - .faces(">Z") - .workplane() - .hole(diameter) - ) + # make the base + result = ( + cq.Workplane("XY") + .box(height, width, thickness) + .faces(">Z") + .workplane() + .hole(diameter) + ) - # Render the solid - show_object(result) + # Render the solid + show_object(result) Rebuild your model by clicking the Render button. Your block should look like this: -.. image:: _static/quickstart/003.png +.. image:: _static/quickstart/003.png The code is pretty compact, let's step through it. @@ -136,32 +136,32 @@ Good news!-- we can get the job done with just a few lines of code. Here's the c :linenos: :emphasize-lines: 5,14-17 - height = 60.0 - width = 80.0 - thickness = 10.0 - diameter = 22.0 - padding = 12.0 - - # make the base - result = ( - cq.Workplane("XY") - .box(height, width, thickness) - .faces(">Z") - .workplane() - .hole(diameter) - .faces(">Z") - .workplane() - .rect(height - padding, width - padding, forConstruction=True) - .vertices() - .cboreHole(2.4, 4.4, 2.1) - ) - # Render the solid - show_object(result) + height = 60.0 + width = 80.0 + thickness = 10.0 + diameter = 22.0 + padding = 12.0 + + # make the base + result = ( + cq.Workplane("XY") + .box(height, width, thickness) + .faces(">Z") + .workplane() + .hole(diameter) + .faces(">Z") + .workplane() + .rect(height - padding, width - padding, forConstruction=True) + .vertices() + .cboreHole(2.4, 4.4, 2.1) + ) + # Render the solid + show_object(result) After clicking the Render button to re-execute the model, you should see something like this: - .. image:: _static/quickstart/004.png + .. image:: _static/quickstart/004.png There is quite a bit going on here, so let's break it down a bit. @@ -206,30 +206,30 @@ We can do that using the preset dictionaries in the parameter definition: :linenos: :emphasize-lines: 19-20 - height = 60.0 - width = 80.0 - thickness = 10.0 - diameter = 22.0 - padding = 12.0 - - # make the base - result = ( - cq.Workplane("XY") - .box(height, width, thickness) - .faces(">Z") - .workplane() - .hole(diameter) - .faces(">Z") - .workplane() - .rect(height - padding, width - padding, forConstruction=True) - .vertices() - .cboreHole(2.4, 4.4, 2.1) - .edges("|Z") - .fillet(2.0) - ) - - # Render the solid - show_object(result) + height = 60.0 + width = 80.0 + thickness = 10.0 + diameter = 22.0 + padding = 12.0 + + # make the base + result = ( + cq.Workplane("XY") + .box(height, width, thickness) + .faces(">Z") + .workplane() + .hole(diameter) + .faces(">Z") + .workplane() + .rect(height - padding, width - padding, forConstruction=True) + .vertices() + .cboreHole(2.4, 4.4, 2.1) + .edges("|Z") + .fillet(2.0) + ) + + # Render the solid + show_object(result) **Line 20** fillets the edges using the :py:meth:`cadquery.Workplane.fillet` method. @@ -238,7 +238,7 @@ edges that are parallel to the Z axis ("\|Z"), The finished product looks like this: - .. image:: _static/quickstart/005.png + .. image:: _static/quickstart/005.png Exporting ========= @@ -251,35 +251,35 @@ This can be easily accomplished using the :py:meth:`cadquery.exporters.export` f :linenos: :emphasize-lines: 27-29 - height = 60.0 - width = 80.0 - thickness = 10.0 - diameter = 22.0 - padding = 12.0 - - # make the base - result = ( - cq.Workplane("XY") - .box(height, width, thickness) - .faces(">Z") - .workplane() - .hole(diameter) - .faces(">Z") - .workplane() - .rect(height - padding, width - padding, forConstruction=True) - .vertices() - .cboreHole(2.4, 4.4, 2.1) - .edges("|Z") - .fillet(2.0) - ) - - # Render the solid - show_object(result) - - # Export - cq.exporters.export(result, "result.stl") - cq.exporters.export(result.section(), "result.dxf") - cq.exporters.export(result, "result.step") + height = 60.0 + width = 80.0 + thickness = 10.0 + diameter = 22.0 + padding = 12.0 + + # make the base + result = ( + cq.Workplane("XY") + .box(height, width, thickness) + .faces(">Z") + .workplane() + .hole(diameter) + .faces(">Z") + .workplane() + .rect(height - padding, width - padding, forConstruction=True) + .vertices() + .cboreHole(2.4, 4.4, 2.1) + .edges("|Z") + .fillet(2.0) + ) + + # Render the solid + show_object(result) + + # Export + cq.exporters.export(result, "result.stl") + cq.exporters.export(result.section(), "result.dxf") + cq.exporters.export(result, "result.step") Done! ============ diff --git a/doc/vis.rst b/doc/vis.rst index b5b3d63e7..06382c079 100644 --- a/doc/vis.rst +++ b/doc/vis.rst @@ -13,17 +13,17 @@ and are not tied to any external tool. .. code-block:: python - from cadquery import * - from cadquery.vis import show + from cadquery import * + from cadquery.vis import show - w = Workplane().sphere(1).split(keepBottom=True) - Workplane().sphere(0.5) - r = w.faces('>Z').fillet(0.1) + w = Workplane().sphere(1).split(keepBottom=True) - Workplane().sphere(0.5) + r = w.faces('>Z').fillet(0.1) - # Show the result - show(r, alpha=0.5) + # Show the result + show(r, alpha=0.5) -.. image:: _static/show.PNG +.. image:: _static/show.PNG One can visualize objects of type :class:`~cadquery.Workplane`, :class:`~cadquery.Sketch`, :class:`~cadquery.Assembly`, :class:`~cadquery.Shape`, @@ -53,7 +53,7 @@ One can visualize objects of type :class:`~cadquery.Workplane`, :class:`~cadquer show(w, sk, sh, vecs, locs) -.. image:: _static/show_demo.PNG +.. image:: _static/show_demo.PNG Additionally it is possible to integrate with other libraries using VTK and display any `vtkProp` object. @@ -61,18 +61,18 @@ Additionally it is possible to integrate with other libraries using VTK and disp .. code-block:: python - from cadquery.vis import show - from cadquery.func import torus + from cadquery.vis import show + from cadquery.func import torus - from vtkmodules.vtkRenderingAnnotation import vtkAnnotatedCubeActor + from vtkmodules.vtkRenderingAnnotation import vtkAnnotatedCubeActor - a = vtkAnnotatedCubeActor() - t = torus(5,1) + a = vtkAnnotatedCubeActor() + t = torus(5,1) - show(t, a) + show(t, a) -.. image:: _static/show_vtk.PNG +.. image:: _static/show_vtk.PNG Note that currently the show function is blocking. @@ -85,12 +85,12 @@ camera position and windows size. .. code-block:: python - from cadquery.vis import show - from cadquery.func import box + from cadquery.vis import show + from cadquery.func import box - b = box(1,1,1) + b = box(1,1,1) - show(b, width=800, height=800, screenshot='img.png', zoom=2, roll=-20, elevation=-30, interact=False) + show(b, width=800, height=800, screenshot='img.png', zoom=2, roll=-20, elevation=-30, interact=False) .. warning:: @@ -101,19 +101,19 @@ Sometimes it is desirable to control the camera position precisely. This can be .. code-block:: python - from cadquery.vis import show - from cadquery.func import torus + from cadquery.vis import show + from cadquery.func import torus - R = 10 - r = 1 - h = 2 + R = 10 + r = 1 + h = 2 - t = torus(R, r) + t = torus(R, r) - show(t, position=(R, -R, R/h), roll=-45, zoom=0.9) + show(t, position=(R, -R, R/h), roll=-45, zoom=0.9) -.. image:: _static/show_camera_position.png +.. image:: _static/show_camera_position.png Control points @@ -123,22 +123,22 @@ Control points .. code-block:: python - from cadquery.func import * - from cadquery.vis import * + from cadquery.func import * + from cadquery.vis import * - c = circle(1).toSplines() - spine = spline([(0, 0, 0), (-3, -3, 5)], tgts=[(0, 0, 1), (0, -1, 0)]) - f = sweep(c, spine) + c = circle(1).toSplines() + spine = spline([(0, 0, 0), (-3, -3, 5)], tgts=[(0, 0, 1), (0, -1, 0)]) + f = sweep(c, spine) - show( - f, - ctrlPts(f), - spine.moved(x=7), - ctrlPts(spine.moved(x=7), color="green"), - alpha=0.0, - ) + show( + f, + ctrlPts(f), + spine.moved(x=7), + ctrlPts(spine.moved(x=7), color="green"), + alpha=0.0, + ) -.. image:: _static/ctrl_pts.png +.. image:: _static/ctrl_pts.png Note that for some geometries explicit conversion to spline representation might be needed. :meth:`~cadquery.Shape.toSplines` performs approximate conversion and :meth:`~cadquery.Shape.toNURBS` @@ -152,24 +152,24 @@ Fine-grained control of the appearance of every item can be achieved using :meth .. code-block:: python - from cadquery.vis import * - from cadquery.func import * + from cadquery.vis import * + from cadquery.func import * - show( - style( - torus(10, 2), - color="crimson", - tubes=True, - linewidth=5, - mesh=True, - meshcolor="blue", - tolerance=0.1, - ), - style(box(3, 3, 3), color="green", markersize=0.1, alpha=0.5), - ) + show( + style( + torus(10, 2), + color="crimson", + tubes=True, + linewidth=5, + mesh=True, + meshcolor="blue", + tolerance=0.1, + ), + style(box(3, 3, 3), color="green", markersize=0.1, alpha=0.5), + ) -.. image:: _static/show_styling.png +.. image:: _static/show_styling.png Jupyter/JupterLab @@ -180,9 +180,9 @@ There is also more limited support for displaying :class:`~cadquery.Workplane`, .. code-block:: python - from cadquery import * + from cadquery import * - Workplane().sphere(1).split(keepTop=True) + Workplane().sphere(1).split(keepTop=True) -.. image:: _static/show_jupyter.PNG +.. image:: _static/show_jupyter.PNG