├── .gitignore ├── .travis.yml ├── CONTRIBUTORS ├── HEADER ├── LICENSE ├── README.markdown ├── api_examples ├── __init__.py ├── constraint_check.py ├── design_advanced_functions.py ├── design_file_connections.py ├── dxf_import_all_layers.py ├── get_mass_properties.py ├── load_file2.py ├── load_sketch.py ├── merge_designs.py ├── profile_sketcher.py ├── programmatic_generation.py ├── split_design.py ├── switch_subdesign.py ├── test_tilepart_widget.py └── upgrade_script.py ├── dev_tools ├── __init__.py ├── acyclicdirectedgraph.py ├── enum.py ├── genericfile.py ├── hierarchy.py └── virtual_structure.py ├── get_popupcad.sh ├── install_dependencies.sh ├── popupcad.py ├── popupcad ├── __init__.py ├── algorithms │ ├── __init__.py │ ├── body_detection.py │ ├── csg_shapely.py │ ├── design_documentation.py │ ├── getjoints.py │ ├── keepout.py │ ├── manufacturing_functions.py │ ├── minimal_enclosing_circle.py │ ├── modify_device.py │ ├── morphology.py │ ├── points.py │ ├── python_syntax_formatter.py │ ├── removability.py │ ├── spline_functions.py │ ├── toolclearance.py │ ├── triangulate.py │ └── web.py ├── basic_functions.py ├── constraints │ ├── __init__.py │ ├── constraint.py │ ├── constraint_support.py │ ├── constraint_system.py │ └── constraints.py ├── filetypes │ ├── __init__.py │ ├── classtools.py │ ├── design.py │ ├── genericlaminate.py │ ├── genericshapebase.py │ ├── genericshapes.py │ ├── laminate.py │ ├── layer.py │ ├── layerdef.py │ ├── listwidgetitem.py │ ├── material2.py │ ├── operation2.py │ ├── operationoutput.py │ ├── popupcad_file.py │ ├── program.py │ ├── sketch.py │ ├── solidworksimport.py │ ├── undoredo.py │ ├── userdata.py │ └── validators.py ├── geometry │ ├── __init__.py │ ├── line.py │ └── vertex.py ├── global_settings.py ├── graphics2d │ ├── __init__.py │ ├── graphicsitems.py │ ├── graphicsscene.py │ ├── graphicsview.py │ ├── interactive.py │ ├── interactiveedge.py │ ├── interactivevertex.py │ ├── interactivevertexbase.py │ ├── modes.py │ ├── proto.py │ ├── static.py │ ├── svg_support.py │ └── text.py ├── graphics3d │ ├── __init__.py │ └── gl_viewer.py ├── guis │ ├── __init__.py │ ├── actions.py │ ├── editor.py │ ├── editor_menu_system_generator.py │ ├── icons.py │ ├── sketcher.py │ └── sketcher_menu_system_generator.py ├── manufacturing │ ├── __init__.py │ ├── bufferop3.py │ ├── cleanup2.py │ ├── cleanup3.py │ ├── code_exec_op.py │ ├── cross_section.py │ ├── dummy_operation1.py │ ├── fill.py │ ├── freeze.py │ ├── hole_operation.py │ ├── hollow.py │ ├── joint_operation3.py │ ├── laminateoperation2.py │ ├── layerop2.py │ ├── multivalueoperation3.py │ ├── nulloperation.py │ ├── shiftflip3.py │ ├── simplesketchoperation.py │ ├── simplify2.py │ ├── sub_operation2.py │ ├── transform_external.py │ └── transform_internal.py ├── materials │ ├── __init__.py │ └── materials.py ├── supportfiles │ ├── AC1009.dxf │ ├── AC1015.dxf │ ├── AC1018.dxf │ ├── AC1021.dxf │ ├── AC1024.dxf │ ├── AC1027.dxf │ ├── editor_menu.yaml │ ├── icons │ │ ├── 3dview.png │ │ ├── angle.png │ │ ├── autosupport.png │ │ ├── broom.png │ │ ├── bufferop.png │ │ ├── circle.png │ │ ├── cleanup.png │ │ ├── coincident.png │ │ ├── convex_hull.png │ │ ├── customsupport.png │ │ ├── distance.png │ │ ├── distancex.png │ │ ├── distancey.png │ │ ├── dotdotdot.png │ │ ├── equal.png │ │ ├── export.png │ │ ├── firstpass.png │ │ ├── getjoints.png │ │ ├── getjoints2.png │ │ ├── hand.png │ │ ├── hingefoldop.png │ │ ├── horizontal.png │ │ ├── icons.png │ │ ├── identifybodies.png │ │ ├── import.png │ │ ├── layerop.png │ │ ├── layers.png │ │ ├── layers3.png │ │ ├── line.png │ │ ├── locate.png │ │ ├── metaop.png │ │ ├── new.png │ │ ├── open.png │ │ ├── operations.png │ │ ├── outersheet.png │ │ ├── outerweb.png │ │ ├── parallel.png │ │ ├── perpendicular.png │ │ ├── placeop.png │ │ ├── pointer.png │ │ ├── pointline.png │ │ ├── pointline2.png │ │ ├── points.png │ │ ├── polygon.png │ │ ├── polygons.png │ │ ├── polyline.png │ │ ├── popupcad.png │ │ ├── popupcad2.png │ │ ├── printapede.png │ │ ├── quit.png │ │ ├── rectangle.png │ │ ├── redo.png │ │ ├── refresh.png │ │ ├── removability.png │ │ ├── save.png │ │ ├── save2.png │ │ ├── scrap.png │ │ ├── secondpass.png │ │ ├── shiftflip.png │ │ ├── shiftflip2.png │ │ ├── showconstraints.png │ │ ├── simplify.png │ │ ├── text.png │ │ ├── triangulate.png │ │ ├── undo.png │ │ └── vertical.png │ ├── materials.yaml │ ├── printapede.ico │ ├── sketcher_menu.yaml │ ├── test_files │ │ ├── basic_operations.cad │ │ └── pendulum.cad │ └── virtual_structure.yaml └── widgets │ ├── __init__.py │ ├── dragndroplist.py │ ├── dragndroptree.py │ ├── export_widget.py │ ├── listeditor.py │ ├── listmanager.py │ ├── materialselection.py │ ├── materialselection2.py │ ├── operationlist.py │ ├── operationnetwork.py │ ├── render_widget.py │ ├── table_common.py │ ├── table_editor_delegate.py │ ├── table_editor_popup.py │ ├── tablewidget.py │ ├── textwindow.py │ ├── userinput.py │ └── widgetcommon.py ├── popupcad_deprecated ├── __init__.py └── locateoperation3.py ├── popupcad_gazebo ├── __init__.py ├── enhanced_grid.py ├── gazebo_controller.py ├── gazebo_plugins │ ├── CMakeLists.txt │ ├── libmodel_vel.so │ ├── model_vel.cc │ └── msgs │ │ ├── CMakeLists.txt │ │ ├── libvelocity_msgs.so │ │ └── velocity_message.proto ├── gradient.py ├── image.py ├── laminate_adders.py ├── perlin_noise.py ├── terrain_generation.py ├── tree_node.py └── userinput.py ├── popupcad_manufacturing_plugins ├── __init__.py └── manufacturing │ ├── __init__.py │ ├── autoweb4.py │ ├── customsupport4.py │ ├── identifybodies2.py │ ├── identifyrigidbodies2.py │ ├── keepout3.py │ ├── outersheet3.py │ ├── removability2.py │ ├── scrapoperation2.py │ └── supportcandidate4.py ├── popupcad_microrobotics ├── __init__.py ├── generatealignmentlayup.py └── tilepart.py ├── popupcad_tests ├── __init__.py ├── load_test_files.py └── test_gui.py ├── qt ├── QtCore.py ├── QtGui.py ├── QtSvg.py ├── __init__.py └── qt_hacks.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | #ignore thumbnails created by windows 2 | Thumbs.db 3 | #Ignore files build by Visual Studio 4 | *.obj 5 | *.exe 6 | *.pdb 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *_i.c 12 | *_p.c 13 | *.ncb 14 | *.suo 15 | *.tlb 16 | *.tlh 17 | *.bak 18 | *.cache 19 | *.ilk 20 | *.log 21 | [Bb]in 22 | [Dd]ebug*/ 23 | *.lib 24 | *.sbr 25 | obj/ 26 | [Rr]elease*/ 27 | _ReSharper*/ 28 | [Tt]est[Rr]esult* 29 | *.pyc 30 | popupcad/export/*.png 31 | popupcad/export/*.svg 32 | build 33 | popupcad/docs/source/modules.rst 34 | popupcad/docs/source/popupcad.algorithms.rst 35 | popupcad/docs/source/popupcad.constraints.rst 36 | popupcad/docs/source/popupcad.convert.rst 37 | popupcad/docs/source/popupcad.filetypes.rst 38 | popupcad/docs/source/popupcad.geometry.rst 39 | popupcad/docs/source/popupcad.graphics2d.rst 40 | popupcad/docs/source/popupcad.graphics3d.rst 41 | popupcad/docs/source/popupcad.manufacturing.rst 42 | popupcad/docs/source/popupcad.materials.rst 43 | popupcad/docs/source/popupcad.pypoly2tri.rst 44 | popupcad/docs/source/popupcad.rst 45 | popupcad/docs/source/popupcad.supportfiles.rst 46 | popupcad/docs/source/popupcad.widgets.rst 47 | dist/* 48 | settings.popupcad 49 | *~ 50 | log.txt 51 | popupcad_gazebo/gazebo_plugins/build/* 52 | popupcad_gazebo/gazebo_plugins/CMakeFiles/* 53 | popupcad_gazebo/gazebo_plugins/msgs/*.pb.cc 54 | popupcad_gazebo/gazebo_plugins/msgs/*.pb.h 55 | popupcad_gazebo/gazebo_plugins/msgs/CMakeFiles 56 | popupcad_gazebo/gazebo_plugins/msgs/CMakeCache.txt 57 | popupcad_gazebo/gazebo_plugins/msgs/*.cmake 58 | popupcad_gazebo/gazebo_plugins/msgs/Makefile 59 | popupcad_gazebo/gazebo_plugins/CMakeCache.txt 60 | popupcad_gazebo/gazebo_plugins/*.cmake 61 | popupcad_gazebo/gazebo_plugins/Makefile 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: required 3 | #branches: 4 | # only: 5 | # - pyqt4_only 6 | python: 7 | # We don't actually use the Travis Python, but this keeps it organized. 8 | # - "2.6" 9 | # - "2.7" 10 | # - "3.3" 11 | # - "3.4" 12 | - "3.5" 13 | # command to install dependencies 14 | #install: 15 | # - chmod +rx install_dependencies.sh 16 | # - ./install_dependencies.sh 17 | # - source ~/.bashrc 18 | # - source activate test-environment 19 | 20 | #before_install: 21 | # - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16" 22 | 23 | install: 24 | - sudo apt-get update 25 | #- sudo apt-get -y install xfvb 26 | # We do this conditionally because it saves us some downloading if the 27 | # version is the same. 28 | - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 29 | - bash miniconda.sh -b -p $HOME/miniconda 30 | - export PATH="$HOME/miniconda/bin:$PATH" 31 | - hash -r 32 | - conda config --set always_yes yes --set changeps1 no 33 | - conda update conda 34 | # Useful for debugging any issues with conda 35 | - conda info -a 36 | 37 | # Replace dep1 dep2 ... with your dependencies 38 | - conda create -n test-environment python=$TRAVIS_PYTHON_VERSION setuptools cython pyyaml shapely numpy scipy sympy pyopengl pyqt pyqtgraph matplotlib 39 | - source activate test-environment 40 | - pip install pypoly2tri ezdxf idealab_tools 41 | # - python setup.py install 42 | - export PYTHONPATH=$PYTHONPATH:$HOME/ 43 | 44 | #before_script: 45 | # - "export DISPLAY=:99.0" 46 | # - export DISPLAY=localhost:1.0 47 | # - xvfb-run -a bash .misc/tests.sh 48 | # - "sh -e /etc/init.d/xvfb start" 49 | # - sleep 3 # give xvfb some time to start 50 | 51 | # command to run tests 52 | script: 53 | # - python popupcad_tests/test_gui.py --qt4 54 | - python popupcad_tests/load_test_files.py --qt4 55 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Daniel M. Aukes 2 | Aaron Gokaslan 3 | Andrew Pullin -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | Written by Daniel M. Aukes and CONTRIBUTORS 2 | Email: danaukesasu.edu. 3 | Please see LICENSE for full license. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2013-2015 President and Fellows of Harvard College 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | What is popupCAD? 2 | ================= 3 | 4 | popupCAD is a program which makes it incredibly easy to make multi-layer design files. popupCAD designs generally end up being cut out by a laser cutter, 3D printer, or CNC Mill. 5 | 6 | How does it work? 7 | ================== 8 | popupCAD allows you to operate between all of your design layers at once, using standard constructive solid geometry(CSG) operations. Operations such as union, intersection, and difference form the core of how you create new geometries from existing ones. 9 | 10 | 11 | How do I create my first laminate? 12 | ==================================== 13 | You can draw or import a sketch, and then apply that sketch to whatever layers you want. You can draw a sketch using the sketch tool, which allows you to create accurately dimensioned polygons and lines. 14 | 15 | Please visit [www.popupcad.org/](http://www.popupcad.org/) for more info. -------------------------------------------------------------------------------- /api_examples/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import constraint_check 9 | from . import design_advanced_functions 10 | from . import design_file_connections 11 | from . import get_mass_properties 12 | from . import load_file2 13 | from . import load_sketch 14 | from . import merge_designs 15 | from . import programmatic_generation 16 | from . import split_design 17 | from . import switch_subdesign 18 | from . import upgrade_script 19 | -------------------------------------------------------------------------------- /api_examples/constraint_check.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | #import sympy 10 | def supply_vertices(): 11 | return sketch.operationgeometry[0].vertices() 12 | 13 | if __name__=='__main__': 14 | 15 | sketch = popupcad.filetypes.sketch.Sketch.load_yaml('C:/Users/danaukes/Desktop/74837632.sketch') 16 | sys = sketch.constraintsystem 17 | sys.link_vertex_builder(supply_vertices) 18 | sys.cleanup() 19 | del sys.generator 20 | sys.update() 21 | 22 | constraint = sys.constraints[-1] -------------------------------------------------------------------------------- /api_examples/design_advanced_functions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | def remap_subdesign_ids(design): 8 | subdesigns_orig = design.subdesigns.copy() 9 | subdesign_mapping = [] 10 | subdesigns_new = {} 11 | for key,subdesign in subdesigns_orig.items(): 12 | new_sketch = subdesign.copy(identical = False) 13 | subdesigns_new[new_sketch.id] = new_sketch 14 | subdesign_mapping.append((key,new_sketch.id)) 15 | 16 | for oldref, newref in subdesign_mapping: 17 | design.replace_subdesign_refs(oldref,newref) 18 | 19 | design.subdesigns = subdesigns_new 20 | return subdesign_mapping 21 | 22 | def remap_sketch_ids(design): 23 | sub_sketches_orig = design.sketches.copy() 24 | sketch_mapping = [] 25 | sub_sketches_new = {} 26 | for key,sketch in sub_sketches_orig.items(): 27 | new_sketch = sketch.copy(identical = False) 28 | sub_sketches_new[new_sketch.id] = new_sketch 29 | sketch_mapping.append((key,new_sketch.id)) 30 | 31 | for oldref, newref in sketch_mapping: 32 | design.replace_sketch_refs_force(oldref,newref) 33 | 34 | design.sketches = sub_sketches_new 35 | return sketch_mapping 36 | 37 | def strip_locates(design): 38 | for ii in range(len(design.operations))[::-1]: 39 | op = design.operations[ii] 40 | if hasattr(op,'locationgeometry'): 41 | design.pop_operation(ii) 42 | 43 | def remap_operation_ids(design): 44 | op_mapping = [] 45 | sub_ops_new = [] 46 | for op in design.operations: 47 | new_op = op.copy_wrapper() 48 | new_op.id = id(new_op) 49 | sub_ops_new.append(new_op) 50 | op_mapping.append((op,new_op)) 51 | 52 | design.operations = sub_ops_new 53 | 54 | for oldref,newref in [(op1.id,op2.id) for op1,op2 in op_mapping]: 55 | design.replace_op_refs2(oldref,newref) 56 | 57 | return op_mapping 58 | 59 | def switch_layer_defs(design,layerdef_new): 60 | for ii,op in enumerate(design.operations): 61 | if hasattr(op,'switch_layer_defs'): 62 | design.operations[ii]=op.switch_layer_defs(design.return_layer_definition(),layerdef_new) 63 | 64 | def external_to_internal_transform_outer(design,subdesign,sketch_mapping,op_mapping): 65 | op_mapping2 = [] 66 | 67 | from popupcad.manufacturing.transform_external import TransformExternal 68 | sketch_mapping_dict = dict(sketch_mapping) 69 | op_mapping_dict = dict([(item1.id,item2.id) for item1,item2 in op_mapping]) 70 | for ii,op in enumerate(design.operations): 71 | if isinstance(op, TransformExternal): 72 | if op.design_links['subdesign'][0] == subdesign.id: 73 | new = op.to_internal_transform(sketch_mapping_dict,op_mapping_dict) 74 | design.operations[ii]=new 75 | op_mapping2.append((op.id,new.id)) 76 | 77 | for oldref,newref in op_mapping2: 78 | design.replace_op_refs2(oldref,newref) 79 | 80 | def remap_sub(subdesign): 81 | #reassign new ids to subdesign sketches and remap their use within the subdesign 82 | 83 | debug = True 84 | 85 | subdesign_mapping = remap_subdesign_ids(subdesign) 86 | sketch_mapping = remap_sketch_ids(subdesign) 87 | strip_locates(subdesign) 88 | op_mapping = remap_operation_ids(subdesign) 89 | if debug: 90 | subdesign.save_yaml('C:/Users/danaukes/desktop/test.cad') 91 | return subdesign_mapping,sketch_mapping,op_mapping 92 | 93 | 94 | def merge_designs(design,subdesign,index): 95 | debug = True 96 | subdesign_mapping,sketch_mapping,op_mapping = remap_sub(subdesign) 97 | 98 | design.subdesigns.update(subdesign.subdesigns) 99 | design.sketches.update(subdesign.sketches) 100 | if debug: 101 | design.save_yaml('C:/Users/danaukes/desktop/test2.cad') 102 | 103 | switch_layer_defs(subdesign,design.return_layer_definition()) 104 | if debug: 105 | subdesign.save_yaml('C:/Users/danaukes/desktop/test3.cad') 106 | 107 | design.operations = design.operations[:index]+subdesign.operations+design.operations[index:] 108 | if debug: 109 | design.save_yaml('C:/Users/danaukes/desktop/test4.cad') 110 | 111 | return subdesign_mapping,sketch_mapping,op_mapping 112 | 113 | 114 | -------------------------------------------------------------------------------- /api_examples/design_file_connections.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import networkx 9 | import matplotlib.pyplot as plt 10 | plt.ion() 11 | 12 | 13 | import os 14 | import sys 15 | import yaml 16 | import popupcad 17 | import glob 18 | import pygraphviz 19 | 20 | def fix(*args): 21 | return os.path.normpath(os.path.join(*args)) 22 | 23 | def get_subfiles_r(d,parent_name,dg): 24 | for key,subdesign in d.subdesigns.items(): 25 | subdesign_name = subdesign.get_basename() 26 | subdesign_name = os.path.splitext(subdesign_name)[0] 27 | dg.add_node(subdesign_name) 28 | dg.add_edge(parent_name,subdesign_name) 29 | get_subfiles_r(subdesign,subdesign_name,dg) 30 | 31 | def get_subfiles(filename,dg): 32 | print(filename) 33 | full_filename = fix(filename) 34 | d = popupcad.filetypes.design.Design.load_yaml(full_filename,upgrade=False) 35 | design_name = d.get_basename() 36 | design_name = os.path.splitext(design_name)[0] 37 | 38 | parent_name = d.get_basename() 39 | parent_name = os.path.splitext(parent_name)[0] 40 | get_subfiles_r(d,parent_name,dg) 41 | 42 | def get_directory(directory_name,dg): 43 | globstring = fix(directory_name,'*.cad') 44 | files = glob.glob(globstring) 45 | print(files) 46 | for filename in files[:]: 47 | get_subfiles(filename,dg) 48 | 49 | def plot_dg(dg): 50 | plt.figure() 51 | # pos = networkx.spring_layout(dg) 52 | pos = networkx.pygraphviz_layout(dg,'dot') 53 | networkx.draw_networkx_labels(dg,pos) 54 | networkx.draw(dg,pos,arrows=True) 55 | plt.show() 56 | 57 | def make_pdf(dg): 58 | agraph = networkx.to_agraph(dg) 59 | agraph.graph_attr['overlap']='false' 60 | agraph.graph_attr['splines']='true' 61 | agraph.graph_attr['rankdir']='LR' 62 | agraph.graph_attr['ranksep']='.1' 63 | agraph.draw('test.pdf',prog='dot') 64 | 65 | def save_dg(dg, filename=None): 66 | if filename is None: 67 | filename='graph1.yaml' 68 | nodes = dg.nodes() 69 | edges = dg.edges() 70 | 71 | nodes = list(set(nodes)) 72 | edges = list(set(edges)) 73 | 74 | with open(filename,'w') as f: 75 | yaml.dump({'nodes':nodes,'edges':edges},f) 76 | 77 | # agraph = networkx.to_agraph(dg) 78 | # agraph.graph_attr['overlap']='false' 79 | # agraph.graph_attr['splines']='true' 80 | # agraph.graph_attr['rankdir']='LR' 81 | # agraph.graph_attr['ranksep']='.1' 82 | # agraph.write('test.dot') 83 | 84 | def make_dg(path): 85 | dg = networkx.DiGraph() 86 | if os.path.isdir(path): 87 | get_directory(path,dg) 88 | elif os.path.isfile(path): 89 | get_subfiles(path,dg) 90 | return dg 91 | 92 | if __name__=='__main__': 93 | 94 | if len(sys.argv)>1: 95 | path = sys.argv[1] 96 | 97 | dg = make_dg(path) 98 | plot_dg(dg) 99 | # save_dg(dg) 100 | make_pdf(dg) 101 | -------------------------------------------------------------------------------- /api_examples/dxf_import_all_layers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Script written by Nick Gravish 4 | Please see LICENSE for full license. 5 | 6 | 7 | dxf_import_all_layers.py 8 | 9 | This script demonstrates how to interact with and load sketches from DFX layers. Calling this script with the 10 | filename for a DXF as an argument will save a .CAD file to the DXF's directory with sketches generated from 11 | the DXF layers. 12 | 13 | """ 14 | 15 | import popupcad 16 | import ezdxf 17 | import popupcad.filetypes.sketch 18 | import sys 19 | 20 | import qt.QtCore as qc 21 | import qt.QtGui as qg 22 | 23 | 24 | from popupcad.filetypes.genericshapes import GenericPolyline 25 | from popupcad.filetypes.genericshapes import GenericPoly 26 | from popupcad.filetypes.genericshapes import GenericLine 27 | 28 | def import_dxf_layer_geometry(dxf, layername): 29 | entities = dxf.entities 30 | generics = [] 31 | for entity in entities: 32 | if entity.dxf.layer in layername: 33 | if isinstance(entity, ezdxf.modern.graphics.Line): 34 | import numpy 35 | points = numpy.array( 36 | [entity.dxf.start[:2], entity.dxf.end[:2]]) 37 | generics.append( 38 | GenericLine.gen_from_point_lists( 39 | points.tolist(), 40 | [])) 41 | elif isinstance(entity, ezdxf.modern.graphics.LWPolyline): 42 | import numpy 43 | points = numpy.array([item for item in entity.get_points()]) 44 | points = points[:, :2] 45 | if entity.closed: 46 | generics.append(GenericPoly.gen_from_point_lists(points.tolist(), [])) 47 | else: 48 | generics.append(GenericPolyline.gen_from_point_lists(points.tolist(), [])) 49 | elif isinstance(entity, ezdxf.modern.graphics.Point): 50 | from popupcad.geometry.vertex import DrawnPoint 51 | point = DrawnPoint(numpy.array(entity.get_dxf_attrib('location')[:2])) 52 | generics.append(point) 53 | elif isinstance(entity, ezdxf.modern.graphics.Spline): 54 | knots = entity.get_knot_values() 55 | control_points = entity.get_control_points() 56 | weights = entity.get_weights() 57 | n = len(control_points) - 1 58 | domain = popupcad.algorithms.spline_functions.make_domain(knots, n * 5) 59 | points = popupcad.algorithms.spline_functions.interpolated_points(control_points, knots, weights, 60 | domain) 61 | points = points[:, :2] 62 | if entity.closed: 63 | generics.append(GenericPoly.gen_from_point_lists(points.tolist(), [])) 64 | else: 65 | generics.append(GenericPolyline.gen_from_point_lists(points.tolist(), [])) 66 | 67 | # print(points) 68 | else: 69 | print(entity) 70 | 71 | new = popupcad.filetypes.sketch.Sketch.new() 72 | new.addoperationgeometries(generics) 73 | newsketchname = layername + '.sketch' 74 | new.updatefilename(newsketchname) 75 | 76 | return new 77 | 78 | # for testing 79 | # filename = '/Users/nickgravish/popupCAD_files/sketches/Scissor02.dxf' 80 | 81 | if __name__ == '__main__': 82 | 83 | filename = sys.argv[1] # get the filename passed in 84 | 85 | # create the base CAD design file 86 | design = popupcad.filetypes.design.Design.new() 87 | design.define_layers(popupcad.filetypes.layerdef.LayerDef(*popupcad.filetypes.material2.default_sublaminate)) 88 | 89 | 90 | # load dxf file and select layer names 91 | import ezdxf.modern 92 | 93 | dxf = ezdxf.readfile(filename) 94 | layer_names = [layer.dxf.name for layer in dxf.layers] 95 | 96 | # loop through layer names and load geometry 97 | for layer in layer_names: 98 | # create the sketch 99 | sketch = import_dxf_layer_geometry(dxf, layer) 100 | 101 | # add the sketch to the design file 102 | design.sketches[sketch.id] = sketch 103 | 104 | # save cad file 105 | design.save_yaml(filename + '.cad') 106 | 107 | # to visualize the result, but can be commented out. 108 | app = qg.QApplication(sys.argv) 109 | editor = popupcad.guis.editor.Editor() 110 | editor.load_design(design) 111 | editor.show() 112 | sys.exit(app.exec_()) 113 | -------------------------------------------------------------------------------- /api_examples/get_mass_properties.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | 10 | import qt.QtCore as qc 11 | import qt.QtGui as qg 12 | 13 | if __name__ =='__main__': 14 | import sys 15 | app = qg.QApplication(sys.argv) 16 | # design = popupcad.filetypes.design.Design.open() 17 | filename = 'C:\\Users\\danb0b\\downloads\\robot2.cad' 18 | design = popupcad.filetypes.design.Design.load_yaml(filename) 19 | design.reprocessoperations() 20 | outputs = design.operations[-1].output 21 | volume = [] 22 | mass = [] 23 | center_of_mass = [] 24 | I = [] 25 | for o in outputs[6:25]: 26 | volume_ii,mass_ii,center_of_mass_ii,I_ii = o.generic_laminate().mass_properties() 27 | volume.append(volume_ii) 28 | mass.append(mass_ii) 29 | center_of_mass.append(center_of_mass_ii) 30 | I.append(I_ii) 31 | # sys.exit(app.exec_()) -------------------------------------------------------------------------------- /api_examples/load_file2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sys 9 | import popupcad 10 | import time 11 | 12 | import qt.QtCore as qc 13 | import qt.QtGui as qg 14 | 15 | if __name__=='__main__': 16 | 17 | t0 = time.time() 18 | 19 | app = qg.QApplication(sys.argv) 20 | # directory = 'C:/Users/danaukes/Desktop' 21 | # filename = 'slow_file.cad' 22 | #filename = 'SLL01.cad' 23 | # full_filename = os.path.normpath(os.path.join(directory,filename)) 24 | # d = popupcad.filetypes.design.Design.load_yaml(full_filename) 25 | d = popupcad.filetypes.design.Design.open() 26 | t1 = time.time() 27 | print('loaded file:',t1-t0) 28 | d.reprocessoperations(debugprint=True) 29 | t2 = time.time() 30 | print('processed file:',t2-t1) 31 | d.reprocessoperations([d.operations[-1]],debugprint=True) 32 | t3 = time.time() 33 | print('processed operation:',t3-t2) 34 | #a=d.operations[0].output[0] 35 | #b=a.generic_laminate() 36 | #v,m,com,I = b.mass_properties() 37 | #all_sketches = [sketch for id,sketch in d.sketches.items()] 38 | #first_sketch = all_sketches[0] 39 | #first_shape = first_sketch.operationgeometry[0] 40 | #vertex_list = first_shape.exteriorpoints() 41 | 42 | #g1 = d.operations[0].output[0].generic_laminate() 43 | #g2 = d.operations[1].output[0].generic_laminate() 44 | #all_sketches = [sketch for id,sketch in d.sketches.items()] 45 | #first_sketch = all_sketches[0] 46 | #first_shape = first_sketch.operationgeometry[0] 47 | 48 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /api_examples/load_sketch.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | from popupcad.guis.sketcher import Sketcher 10 | import sys 11 | 12 | import qt.QtCore as qc 13 | import qt.QtGui as qg 14 | 15 | if __name__=='__main__': 16 | 17 | app = qg.QApplication(sys.argv) 18 | sketch = popupcad.filetypes.sketch.Sketch.load_yaml('testpoints.sketch') 19 | mw = Sketcher(None, sketch) 20 | #mw.loadsketch(sketch) 21 | #mw.show() 22 | geom1 = mw.sketch.operationgeometry[0] 23 | geom2 = mw.sketch.operationgeometry[1] 24 | 25 | #item = mw.scene.itemAt(-17239.488120, 29782.449730) 26 | 27 | #sys.exit(app.exec_()) 28 | -------------------------------------------------------------------------------- /api_examples/merge_designs.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | #import sys 8 | # 9 | #import qt.QtCore as qc 10 | #import qt.QtGui as qg 11 | #app = qg.QApplication(sys.argv[0]) 12 | 13 | import popupcad 14 | import api_examples.design_advanced_functions as design_advanced_functions 15 | #from popupcad.manufacturing.dummy_operation1 import DummyOp1 16 | 17 | from popupcad.filetypes.design import Design 18 | from popupcad.manufacturing.sub_operation2 import SubOperation2 19 | #from popupcad.manufacturing.transform_external import TransformExternal 20 | #from popupcad.manufacturing.transform_internal import TransformInternal 21 | 22 | #design = Design.open() 23 | #subdesign = Design.open() 24 | if __name__=='__main__': 25 | 26 | #get design 27 | design = Design.load_yaml('C:/Users/danaukes/Dropbox/zhis sentinal 11 files/modified/sentinal 11 manufacturing_R07.cad') 28 | #subdesign = Design.load_yaml('C:/Users/danaukes/popupCAD_files/designs/hinges/supported_hinge_half1.cad') 29 | design = design.upgrade() 30 | 31 | #get subdesign 32 | subdesign = design.subdesigns[230308440] 33 | 34 | #upgrade is unnecessary if subdesign is a child of design 35 | #subdesign = subdesign.upgrade() 36 | 37 | #ensure subdesign is a totally separate copy 38 | 39 | subdesign = subdesign.copy_yaml() 40 | 41 | subdesign_mapping,sketch_mapping,op_mapping = design_advanced_functions.merge_designs(design,subdesign,0) 42 | 43 | design_advanced_functions.external_to_internal_transform_outer(design,subdesign,sketch_mapping,op_mapping) 44 | 45 | #if the subdesigns subdesigns can also be found in the design, switch back to them 46 | # this could cause a problem if they are different versions of the same file, so use this feature cautiously. 47 | for oldref, newref in subdesign_mapping: 48 | if oldref in design.subdesigns: 49 | design.replace_subdesign_refs(newref,oldref) 50 | design.subdesigns.pop(newref) 51 | 52 | if subdesign.id in design.subdesigns: 53 | design.subdesigns.pop(subdesign.id) 54 | 55 | design_out = 'C:/Users/danaukes/Dropbox/zhis sentinal 11 files/modified/sentinal 11 manufacturing_R08.cad' 56 | design.save_yaml(design_out) 57 | -------------------------------------------------------------------------------- /api_examples/profile_sketcher.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | if __name__=='__main__': 10 | 11 | import sys 12 | 13 | 14 | import qt.QtCore as qc 15 | import qt.QtGui as qg 16 | 17 | app = qg.QApplication([sys.argv[0]]) 18 | import popupcad 19 | 20 | item1 = popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists([(0,0),(1,0),(0,1)],[]) 21 | item2 = popupcad.filetypes.genericshapes.GenericPoly.gen_from_point_lists([(0,0),(1,0),(0,1)],[]) 22 | item2.shift((3,0)) 23 | 24 | fixed_vertices =[item1.get_exterior()[0]] 25 | 26 | constraint1 = popupcad.filetypes.constraints.fixed([item.id for item in fixed_vertices],[item.getpos() for item in fixed_vertices]) 27 | constraint_sys = popupcad.filetypes.constraints.ConstraintSystem() 28 | constraint_sys.add_constraint(constraint1) 29 | 30 | sketch = popupcad.filetypes.sketch.Sketch.new() 31 | sketch.constraintsystem = constraint_sys 32 | sketcher = popupcad.guis.sketcher.Sketcher(None,sketch) 33 | sketch = sketcher.sketch 34 | 35 | graphics_item1 = item1.outputinteractive() 36 | graphics_item2 = item2.outputinteractive() 37 | 38 | sketcher.scene.addItem(graphics_item1) 39 | sketcher.scene.addItem(graphics_item2) 40 | 41 | for ii in range(1): 42 | graphics_item1.generic.constrained_shift((-.1,-.1),sketch.constraintsystem) 43 | graphics_item1.updateshape() 44 | 45 | for ii in range(1): 46 | graphics_item2.generic.constrained_shift((-.1,-.1),sketch.constraintsystem) 47 | graphics_item2.updateshape() 48 | 49 | sketcher.show() 50 | # sys.exit(app.exec_()) -------------------------------------------------------------------------------- /api_examples/switch_subdesign.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sys 9 | import popupcad 10 | 11 | import qt.QtCore as qc 12 | import qt.QtGui as qg 13 | if __name__=='__main__': 14 | 15 | app = qg.QApplication(sys.argv[0]) 16 | 17 | filename_from = 'C:/Users/danaukes/Dropbox/zhis sentinal 11 files/modified/sentinal 11 manufacturing_R08.cad' 18 | filename_to = 'C:/Users/danaukes/Dropbox/zhis sentinal 11 files/modified/sentinal 11 manufacturing_R09.cad' 19 | 20 | d = popupcad.filetypes.design.Design.load_yaml(filename_from) 21 | 22 | widget = qg.QDialog() 23 | layout = qg.QVBoxLayout() 24 | layout1 = qg.QHBoxLayout() 25 | layout2 = qg.QHBoxLayout() 26 | list1 = qg.QListWidget() 27 | list2 = qg.QListWidget() 28 | button_ok = qg.QPushButton('Ok') 29 | button_cancel = qg.QPushButton('Cancel') 30 | 31 | subdesign_list = list(d.subdesigns.values()) 32 | 33 | for item in subdesign_list: 34 | list1.addItem(str(item)) 35 | list2.addItem(str(item)) 36 | 37 | layout1.addWidget(list1) 38 | layout1.addWidget(list2) 39 | layout2.addWidget(button_ok) 40 | layout2.addWidget(button_cancel) 41 | layout.addLayout(layout1) 42 | layout.addLayout(layout2) 43 | widget.setLayout(layout) 44 | button_ok.pressed.connect(widget.accept) 45 | button_cancel.pressed.connect(widget.reject) 46 | 47 | if widget.exec_(): 48 | if len(list1.selectedIndexes())==1 and len(list2.selectedIndexes())==1: 49 | ii_from = list1.selectedIndexes()[0].row() 50 | ii_to = list2.selectedIndexes()[0].row() 51 | print(ii_from,ii_to) 52 | 53 | d.replace_subdesign_refs(subdesign_list[ii_from].id,subdesign_list[ii_to].id) 54 | d.subdesigns.pop(subdesign_list[ii_from].id) 55 | d.save_yaml(filename_to) 56 | 57 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /api_examples/test_tilepart_widget.py: -------------------------------------------------------------------------------- 1 | 2 | import qt.QtGui as qg 3 | import popupcad 4 | from popupcad_manufacturing_plugins.manufacturing.tilepart import TilePart 5 | import os 6 | import sys 7 | 8 | # file to load and work with 9 | myfolder = '/Users/nickgravish/popupCAD_files/designs' 10 | design_file = 'Transmissions.cad' #'robobee_interference_hinge.cad' 11 | 12 | if __name__=='__main__': 13 | 14 | app = qg.QApplication(sys.argv) 15 | 16 | design = popupcad.filetypes.design.Design.load_yaml(os.path.join(myfolder, design_file)) 17 | design.reprocessoperations(debugprint=True) ## IMPORTANT 18 | #part_opref, sheet_opref, sketch_bounding_box, N, scale, x_gap, y_gap, support_offset 19 | 20 | release = design.operations[-3].id 21 | part_opref = design.operations[-2].id 22 | sheet_opref = design.operations[-1].id 23 | sketch_id = 4762336016 #4751474000 24 | 25 | scaling = popupcad.csg_processing_scaling 26 | sketch_bounding_box = design.sketches[sketch_id].output_csg()[0].bounds # may break if multiple sketches 27 | sketch_bounding_box = [geom/scaling for geom in sketch_bounding_box] 28 | 29 | N = 10 30 | scale = 1. 31 | x_gap = 0. 32 | y_gap = 0. 33 | support_offset = 0. 34 | 35 | new = TilePart(part_opref, release, sheet_opref, sketch_bounding_box, N, scale, x_gap, y_gap, support_offset) 36 | 37 | design.addoperation(new) 38 | new.operate(design) 39 | 40 | ################## show the new design 41 | 42 | editor = popupcad.guis.editor.Editor() 43 | editor.load_design(design) 44 | editor.show() 45 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /api_examples/upgrade_script.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import os 9 | import popupcad 10 | import time 11 | import glob 12 | import shutil 13 | import time 14 | # 15 | #import qt.QtCore as qc 16 | #import qt.QtGui as qg 17 | 18 | if __name__=='__main__': 19 | t_0 = time.time() 20 | #app = qg.QApplication(sys.argv) 21 | top_directory = 'C:/Users/danaukes/popupcad_files' 22 | failures_directory = 'C:/Users/danaukes/Desktop/failures' 23 | filenames = [] 24 | for directory,subdirectory,files in os.walk(top_directory): 25 | filenames.extend(glob.glob(directory+'/*.cad')) 26 | print(filenames) 27 | 28 | failed = [] 29 | passed = [] 30 | 31 | for filename in filenames: 32 | print(filename) 33 | full_filename = os.path.normpath(os.path.join(directory,filename)) 34 | try: 35 | d = popupcad.filetypes.design.Design.load_yaml(full_filename) 36 | # d.reprocessoperations() 37 | # d.save_yaml(full_filename) 38 | passed.append(full_filename) 39 | except: 40 | failed.append(full_filename) 41 | 42 | t_final = time.time() 43 | t_total = t_final - t_0 44 | #if not os.path.exists(failures_directory): 45 | # os.mkdir(failures_directory) 46 | # 47 | #for filename in failed: 48 | # basename = os.path.split(filename)[1] 49 | # newfilename = os.path.join(failures_directory,basename) 50 | # shutil.move(filename,newfilename) 51 | -------------------------------------------------------------------------------- /dev_tools/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | #load external modules 9 | 10 | import multiprocessing 11 | import numpy 12 | import popupcad 13 | import yaml -------------------------------------------------------------------------------- /dev_tools/enum.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | def enum(**enums): 10 | e = type('Enum', (), enums) 11 | e.dict = enums 12 | return e 13 | -------------------------------------------------------------------------------- /get_popupcad.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt-get update 3 | sudo apt-get install -y git 4 | git config --global user.name "LastName, Firstname" 5 | git config --global user.email "email@address.com" 6 | cd ~ 7 | git clone https://github.com/popupcad/popupcad.git 8 | cd ~/popupcad 9 | git checkout pyqt4_only 10 | git pull 11 | echo "export PYTHONPATH=\$PYTHONPATH:~/popupcad" >> ~/.bashrc 12 | source ~/.bashrc 13 | -------------------------------------------------------------------------------- /install_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$TRAVIS_PYTHON_VERSION" == "" ]]; then 4 | export TRAVIS_PYTHON_VERSION=3.5; 5 | fi 6 | 7 | sudo apt-get update 8 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 9 | bash miniconda.sh -b -p $HOME/miniconda 10 | 11 | export PATH=$HOME/miniconda/bin:$PATH 12 | echo "export PATH="\$HOME/miniconda/bin:\$PATH"" >> ~/.bashrc 13 | 14 | hash -r 15 | conda config --set always_yes yes --set changeps1 no 16 | conda update conda 17 | conda info -a 18 | 19 | conda create -n test-environment python=$TRAVIS_PYTHON_VERSION setuptools cython pyyaml shapely numpy scipy sympy pyopengl pyqt pyqtgraph matplotlib 20 | source activate test-environment 21 | 22 | pip install pypoly2tri ezdxf 23 | 24 | 25 | -------------------------------------------------------------------------------- /popupcad.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sys 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | 12 | #must import sympy before pyqtgraph 13 | import sympy 14 | #must import pyqtgraph before creating app 15 | import pyqtgraph 16 | 17 | app = qg.QApplication([sys.argv[0]]) 18 | import popupcad 19 | program = popupcad.filetypes.program.Program(app, *sys.argv) 20 | app.exec_() 21 | sys.exit() -------------------------------------------------------------------------------- /popupcad/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | #from __future__ import absolute_import 8 | 9 | import sys 10 | 11 | from shapely import speedups 12 | 13 | # necessary for homebrewed libgeos which does not work with speedups for some reason. 14 | if sys.platform != 'darwin': 15 | if speedups.available: 16 | speedups.enable() 17 | 18 | from .global_settings import * 19 | 20 | from . import algorithms 21 | from . import filetypes 22 | from . import geometry 23 | from . import graphics2d 24 | from . import graphics3d 25 | from . import guis 26 | from . import manufacturing 27 | from . import materials 28 | from . import widgets 29 | 30 | import yaml 31 | try: 32 | with open(user_materials_filename) as f: 33 | user_materials = yaml.load(f,Loader=yaml.FullLoader) 34 | except FileNotFoundError: 35 | pass 36 | 37 | try: 38 | with open(custom_settings_filename) as f: 39 | custom_settings = yaml.load(f,Loader=yaml.FullLoader) 40 | 41 | popupcad_module=sys.modules[__name__] 42 | for key in custom_settings: 43 | if hasattr(popupcad_module,key): 44 | setattr(popupcad_module,key,custom_settings[key]) 45 | except FileNotFoundError: 46 | pass 47 | 48 | ##load external modules 49 | # 50 | #import ezdxf 51 | #import numpy 52 | #import pypoly2tri 53 | #import pyqtgraph 54 | #import scipy.optimize 55 | #import scipy.spatial 56 | #import shapely 57 | #import sympy 58 | #import yaml 59 | 60 | #import idealab_tools.virtual_structure 61 | #commands = idealab_tools.virtual_structure.load_commands(os.path.normpath(os.path.join(supportfiledir,'virtual_structure.yaml'))) 62 | #idealab_tools.virtual_structure.run_commands(commands) -------------------------------------------------------------------------------- /popupcad/algorithms/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from . import body_detection 8 | from . import csg_shapely 9 | from . import design_documentation 10 | from . import getjoints 11 | from . import keepout 12 | from . import manufacturing_functions 13 | from . import minimal_enclosing_circle 14 | from . import modify_device 15 | from . import morphology 16 | from . import points 17 | from . import python_syntax_formatter 18 | from . import removability 19 | from . import spline_functions 20 | from . import toolclearance 21 | from . import triangulate 22 | from . import web 23 | 24 | -------------------------------------------------------------------------------- /popupcad/algorithms/body_detection.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import numpy 9 | import popupcad 10 | 11 | def find_minimum_xy(geom): 12 | points = numpy.array(geom.exteriorpoints()) 13 | min_x, min_y = points.min(0) 14 | return min_x, min_y 15 | 16 | 17 | def sort_lams(lams, values): 18 | dtype = [('x', float), ('y', float)] 19 | mins = numpy.array(values, dtype) 20 | ii_mins = mins.argsort(order=['x', 'y']) 21 | lam_out = [lams[ii] for ii in ii_mins] 22 | return lam_out 23 | 24 | 25 | def find(generic_laminate): 26 | generic = generic_laminate.geoms 27 | layerdef = generic_laminate.layerdef 28 | from popupcad.filetypes.laminate import Laminate 29 | 30 | layer_dict = dict([(geom.id, layer) for layer, geoms in generic.items() for geom in geoms]) 31 | geom_dict = dict([(geom.id, geom) for layer, geoms in generic.items() for geom in geoms]) 32 | geom_dict_whole = geom_dict.copy() 33 | 34 | laminates = [] 35 | values = [] 36 | while len(geom_dict) > 0: 37 | laminate = Laminate(layerdef) 38 | key = list(geom_dict.keys())[0] 39 | gs = findallconnectedneighborgeoms(key,generic_laminate,geom_dict,layerdef) 40 | geom_mins = numpy.array( 41 | [find_minimum_xy(geom_dict_whole[geom_id]) for geom_id in gs]) 42 | values.append(tuple(geom_mins.min(0))) 43 | for item_id in gs: 44 | geom = geom_dict_whole[item_id] 45 | if geom.is_valid_bool(): 46 | laminate.insertlayergeoms(layer_dict[item_id], [geom.to_shapely(scaling = popupcad.csg_processing_scaling)]) 47 | laminates.append(laminate) 48 | laminates = sort_lams(laminates, values) 49 | return laminates 50 | 51 | 52 | def findallconnectedneighborgeoms( 53 | geomid, 54 | generic_laminate, 55 | geom_dict, 56 | layerdef): 57 | '''find all the connected shapes''' 58 | connectedgeomids = [geomid] 59 | testids = [geomid] 60 | while len(testids) > 0: 61 | result = findconnectedneighborgeoms( 62 | testids.pop(), 63 | generic_laminate, 64 | geom_dict, 65 | layerdef) 66 | result = list(set(result) - set(connectedgeomids)) 67 | testids.extend(result) 68 | connectedgeomids.extend(result) 69 | [geom_dict.pop(item) for item in connectedgeomids] 70 | return connectedgeomids 71 | 72 | 73 | def findconnectedneighborgeoms(geomid, generic_laminate, geom_dict, layerdef): 74 | '''find geoms in neighboring layers which are overlapping''' 75 | validneighbors = [] 76 | geom = geom_dict[geomid] 77 | if geom.is_valid_bool(): 78 | geom = geom.to_shapely(scaling = popupcad.csg_processing_scaling) 79 | layer = findgeomlayerinstep(geomid, generic_laminate) 80 | neighbors = layerdef.connected_neighbors(layer) 81 | for neighbor in neighbors: 82 | for item in generic_laminate.geoms[neighbor]: 83 | if item.is_valid_bool(): 84 | shapelygeom = item.to_shapely(scaling = popupcad.csg_processing_scaling) 85 | result = geom.intersection(shapelygeom) 86 | if not result.is_empty: 87 | validneighbors.append(item.id) 88 | return validneighbors 89 | 90 | 91 | def findgeomlayerinstep(geomid, generic_laminate): 92 | '''Find the layer of a laminate a given shape is in''' 93 | for layer, geoms in generic_laminate.geoms.items(): 94 | if geomid in [geom.id for geom in geoms]: 95 | return layer 96 | -------------------------------------------------------------------------------- /popupcad/algorithms/csg_shapely.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import shapely.geometry as sg 9 | import popupcad 10 | 11 | filter_list = [sg.Polygon,sg.LineString,sg.Point] 12 | 13 | class GeometryNotHandled(Exception): 14 | pass 15 | 16 | def entity_is_handled(entity): 17 | return any([isinstance(entity,item) for item in filter_list]) 18 | 19 | def iscollection(item): 20 | collections = [ 21 | sg.MultiPolygon, 22 | sg.GeometryCollection, 23 | sg.MultiLineString, 24 | sg.multilinestring.MultiLineString, 25 | sg.MultiPoint] 26 | iscollection = [isinstance(item, cls) for cls in collections] 27 | return any(iscollection) 28 | 29 | def extract_individual_entities_recursive(list_in,entity_in): 30 | if iscollection(entity_in): 31 | [extract_individual_entities_recursive(list_in,item) for item in entity_in.geoms] 32 | else: 33 | list_in.append(entity_in) 34 | 35 | def extract_individual_entities(entities): 36 | entities_out = [] 37 | [extract_individual_entities_recursive(entities_out,item) for item in entities] 38 | return entities_out 39 | 40 | def condition_shapely_entities(*entities): 41 | entities = extract_individual_entities(entities) 42 | entities = [item for item in entities if any([isinstance(item,classitem) for classitem in filter_list])] 43 | entities = [item for item in entities if not item.is_empty] 44 | # entities = [item for item in entities if not item.is_valid] 45 | return entities 46 | 47 | def get_shapely_vertices(entity,scaling = 1.0): 48 | import shapely.geometry as sg 49 | import numpy 50 | 51 | if isinstance(entity,sg.Polygon): 52 | exterior = (numpy.array([coord for coord in entity.exterior.coords])*scaling).tolist() 53 | interiors = [(numpy.array([coord for coord in interior.coords])*scaling).tolist() 54 | for interior in entity.interiors] 55 | 56 | elif isinstance(entity,sg.LineString) or isinstance(entity,sg.Point): 57 | exterior = (numpy.array([coord for coord in entity.coords])*scaling).tolist() 58 | interiors = [] 59 | else: 60 | raise GeometryNotHandled() 61 | 62 | return exterior, interiors 63 | 64 | def to_generic(entity): 65 | import shapely.geometry as sg 66 | from popupcad.filetypes.genericshapes import GenericPoly, GenericPolyline 67 | from popupcad.geometry.vertex import DrawnPoint 68 | from popupcad.geometry.vertex import ShapeVertex 69 | 70 | exterior_p, interiors_p = get_shapely_vertices(entity,1/popupcad.csg_processing_scaling) 71 | exterior = [ShapeVertex(point) for point in exterior_p] 72 | interiors= [[ShapeVertex(point) for point in interior] for interior in interiors_p] 73 | 74 | if isinstance(entity, sg.Polygon): 75 | subclass = GenericPoly 76 | elif isinstance(entity, sg.LineString): 77 | subclass = GenericPolyline 78 | elif isinstance(entity, sg.Point): 79 | s = DrawnPoint(exterior_p[0]) 80 | return s 81 | else: 82 | raise GeometryNotHandled() 83 | return subclass(exterior, interiors) 84 | 85 | def unary_union_safe(listin): 86 | '''try to perform a unary union. if that fails, fall back to iterative union''' 87 | import shapely 88 | import shapely.ops as so 89 | 90 | try: 91 | return so.unary_union(listin) 92 | except (shapely.geos.TopologicalError, ValueError): 93 | print('Unary Union Failed. Falling Back...') 94 | workinglist = listin[:] 95 | try: 96 | result = workinglist.pop(0) 97 | for item in workinglist: 98 | try: 99 | newresult = result.union(item) 100 | result = newresult 101 | except (shapely.geos.TopologicalError, ValueError): 102 | raise 103 | return result 104 | except IndexError: 105 | # return sg.GeometryCollection() 106 | raise 107 | -------------------------------------------------------------------------------- /popupcad/algorithms/design_documentation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import os 8 | 9 | template = \ 10 | '''--- 11 | {0} 12 | --- 13 | ''' 14 | 15 | def process_output(output, filename_in, destination): 16 | 17 | generic = output.csg.to_generic_laminate() 18 | 19 | png_image_file = generic.raster(filename_in,'png',destination) 20 | png_image_file = os.path.split(png_image_file)[1] 21 | 22 | svg_image_file = generic.to_svg(filename_in+'.svg',destination) 23 | svg_image_file = os.path.split(svg_image_file)[1] 24 | 25 | name = str(output) 26 | 27 | output_dict = {} 28 | output_dict['name'] = name 29 | output_dict['svg_image_file'] = svg_image_file 30 | output_dict['png_image_file'] = png_image_file 31 | output_dict['description'] = output.description 32 | output_dict['cut_files'] = ['cut-dummy1.svg','cut-dummy2.svg'] 33 | return output_dict 34 | 35 | def process_operation(operation, ii, destination): 36 | name = str(operation) 37 | 38 | outputs = [] 39 | for jj, out in enumerate(operation.output): 40 | filename = '{0:02.0f}_{1:02.0f}'.format(ii, jj) 41 | outputs.append(process_output(out, filename, destination)) 42 | 43 | output = {} 44 | output['name'] = name 45 | # output['description'] = operation.description 46 | output['description'] = 'This is a fake operation description. I am not about to make a separate description for each op, but the description might be about this long.' 47 | output['svg_image_file'] = outputs[0]['svg_image_file'] 48 | output['png_image_file'] = outputs[0]['png_image_file'] 49 | output['cut_files'] = outputs[0]['cut_files'] 50 | output['outputs'] = outputs[1:] 51 | return output 52 | 53 | def process_design(design,subdir,slugified_name): 54 | title = slugified_name 55 | operations = [process_operation(operation, ii, subdir) for ii, operation in enumerate(design.operations)] 56 | 57 | ii = design.operation_index(design.main_operation[0]) 58 | 59 | output = {} 60 | output['title'] = title 61 | output['description'] = 'This is a leg design, which is meant to be attached to the body of a robot. It is a 2-dof mechanism, so requires inputs from two motors. Operation 10 and 12 include the necessary cut files for creating this two-laminate device.' 62 | output['category'] = 'Parts.Legs.2DOFLegs' 63 | output['tags'] = ['parts','legs','2dof_robot_legs'] 64 | output['operations'] = operations 65 | output['svg_image_file'] = operations[ii]['svg_image_file'] 66 | output['png_image_file'] = operations[ii]['png_image_file'] 67 | output['cad_file'] = slugified_name 68 | return output 69 | 70 | def format_template(design_dict): 71 | import yaml 72 | output = template.format(yaml.dump(design_dict)) 73 | return output 74 | -------------------------------------------------------------------------------- /popupcad/algorithms/getjoints.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | import numpy 10 | 11 | def getjoints(geoms,roundvalue): 12 | from popupcad.geometry.vertex import ShapeVertex 13 | from popupcad.filetypes.genericshapes import GenericLine 14 | 15 | tolerance = 10**(-roundvalue) 16 | 17 | lines = [] 18 | 19 | for geom in geoms: 20 | p = geom.exteriorpoints() 21 | lines.extend(zip(p, p[1:] + p[:1])) 22 | for interior in geom.interiorpoints(): 23 | lines.extend(zip(interior, interior[1:] + interior[:1])) 24 | 25 | l3 = popupcad.algorithms.points.distance_of_lines(lines, [0, 0]) 26 | l4 = popupcad.algorithms.points.distance_of_lines(lines, [10 * tolerance, 0]) 27 | l5 = popupcad.algorithms.points.distance_of_lines(lines, [10 * tolerance, 10 * tolerance]) 28 | l6 = popupcad.algorithms.points.distance_of_lines(lines, [0, 10 * tolerance]) 29 | l7 = popupcad.algorithms.points.distance_of_lines(lines, [10 * tolerance, 20 * tolerance]) 30 | 31 | m = numpy.c_[l3, l4, l5, l6, l7] 32 | m = m.round(roundvalue) 33 | m2 = [tuple(items) for items in m.tolist()] 34 | m3 = list(set(m2)) 35 | # jj = numpy.searchsorted(m3,m2) 36 | index_to_unique = [m3.index(item) for item in m2] 37 | indeces_to_orig = [[] for item in m3] 38 | [indeces_to_orig[item].append(ii) for ii, item in enumerate(index_to_unique)] 39 | 40 | newsegments = [] 41 | for segments in indeces_to_orig: 42 | if len(segments) > 1: 43 | a = [lines[ii] for ii in segments] 44 | vertices = [] 45 | [vertices.extend(item) for item in a[1:]] 46 | ordered_vertices = popupcad.algorithms.points.order_vertices(vertices,a[0],tolerance=tolerance) 47 | segs = list(zip(ordered_vertices[:-1], ordered_vertices[1:])) 48 | midpoints = popupcad.algorithms.points.segment_midpoints(segs) 49 | count = [0 for item in midpoints] 50 | for ii in segments: 51 | for jj, point in enumerate(midpoints): 52 | if popupcad.algorithms.points.point_within_line(point,lines[ii],tolerance=tolerance): 53 | count[jj] += 1 54 | newsegments.extend([seg for count_ii, seg in zip(count, segs) if count_ii > 1]) 55 | 56 | generic_lines = [GenericLine([ShapeVertex(v1), ShapeVertex(v2)], []) for v1, v2 in newsegments] 57 | generic_lines = [item for item in generic_lines if len(item.get_exterior()) == 2] 58 | return generic_lines 59 | -------------------------------------------------------------------------------- /popupcad/algorithms/keepout.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from popupcad.filetypes.layer import Layer 8 | from popupcad.filetypes.laminate import Laminate 9 | 10 | 11 | def laserkeepout(laminatein): 12 | '''calculate the keepout for an input laminate assuming laser cutting''' 13 | layers = laminatein.layerdef.layers 14 | laminateout = laminatein.unarylayeroperation('union', layers, layers) 15 | return laminateout 16 | 17 | 18 | def millkeepout(laminatein): 19 | '''calculate the keepout for an input laminate assuming milling''' 20 | l = Layer([]) 21 | laminateout = Laminate(laminatein.layerdef) 22 | for ii, geoms in enumerate(laminatein[::-1]): 23 | l = l.union(geoms) 24 | laminateout[-1 - ii] = l 25 | return laminateout 26 | 27 | 28 | def millflipkeepout(laminatein): 29 | '''calculate the keepout for an input laminate assuming milling & part flipping''' 30 | l1 = millkeepout(laminatein) 31 | l2 = millkeepout(laminatein.flip()).flip() 32 | lout = l1.intersection(l2) 33 | return lout 34 | -------------------------------------------------------------------------------- /popupcad/algorithms/modify_device.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from popupcad.filetypes.laminate import Laminate 8 | import popupcad 9 | 10 | 11 | def modify_device( 12 | device, 13 | support_sketch, 14 | support_width, 15 | support_out, 16 | holes_radius, 17 | cut_width): 18 | '''from a user-input support sketch, modify a device to be compatible with the given support design.''' 19 | layers = device.layerdef.layers 20 | support_out1 = device.buffer(support_out) 21 | support_out2 = support_out1.difference(device) 22 | support_width = support_sketch.buffer(support_width / 2) 23 | support_pieces = support_width.intersection(support_out2) 24 | 25 | holes_1 = support_pieces.buffer(holes_radius) 26 | holes_2 = holes_1.unarylayeroperation('union', layers, layers) 27 | holes = holes_2.difference(holes_1.buffer(1e-3 * popupcad.csg_processing_scaling)) 28 | device_with_holes = device.difference(holes) 29 | 30 | cut_width = support_sketch.buffer(cut_width / 2) 31 | cuts_1 = cut_width.intersection(support_out2) 32 | cuts_2 = cuts_1.unarylayeroperation('union', layers, layers) 33 | # cuts_3 = cuts_2.difference(cuts_1) 34 | # cuts= cuts_3.unarylayeroperation('union',layers,layers) 35 | 36 | # return the support, the cuts which will remove the support from the 37 | # device, and the modified device 38 | return device_with_holes, support_width, cuts_2 39 | -------------------------------------------------------------------------------- /popupcad/algorithms/morphology.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | def cleanup(ls1, value, resolution): 10 | closing = ls1.buffer(-value, resolution=resolution) 11 | opening = closing.buffer(2 * value, resolution=resolution) 12 | closing2 = opening.buffer(-value, resolution=resolution) 13 | return closing2 14 | 15 | 16 | def simplify(ls1, value): 17 | closing = ls1.simplify(value) 18 | return closing 19 | -------------------------------------------------------------------------------- /popupcad/algorithms/removability.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from popupcad.filetypes.layer import Layer 8 | from popupcad.filetypes.laminate import Laminate 9 | 10 | def one_way_up(laminatein): 11 | l = Layer([]) 12 | laminateout = Laminate(laminatein.layerdef) 13 | for ii, geoms in enumerate(laminatein): 14 | l = l.union(geoms) 15 | laminateout[ii] = l 16 | laminateout = modify_up(laminateout) 17 | return laminateout 18 | 19 | 20 | def one_way_down(laminatein): 21 | return one_way_up(laminatein.flip()).flip() 22 | 23 | 24 | def two_way(laminatein): 25 | layers = laminatein.layerdef.layers 26 | laminateout = laminatein.unarylayeroperation('union', layers, layers) 27 | return laminateout 28 | 29 | 30 | def modify_up(removabilityin): 31 | layers = removabilityin.layerdef.layers 32 | for layer1, layer2 in zip(layers[:-1], layers[1:]): 33 | if layer1.is_adhesive or layer2.is_adhesive: 34 | removabilityin.layer_sequence[layer1] = removabilityin.layer_sequence[ 35 | layer1].union(removabilityin.layer_sequence[layer2]) 36 | return removabilityin 37 | 38 | 39 | def generate_removable_scrap(device, sheet, tol=1e-5, device_buffer=0): 40 | # scrap = sheet.difference(device) 41 | # smaller_scrap = scrap.buffer(-tol) 42 | removability_up = one_way_up(device) 43 | removability_down = one_way_down(device) 44 | removability_both = two_way(device) 45 | not_removable_region = ( 46 | removability_up.cleanup(tol)).intersection( 47 | removability_down.cleanup(tol)) 48 | not_removable_scrap_region = not_removable_region.difference( 49 | device.cleanup(tol)) 50 | not_removable_scrap_region = not_removable_region.cleanup(tol) 51 | 52 | if device_buffer > 0: 53 | buffered_device = device.buffer(device_buffer) 54 | else: 55 | buffered_device = device 56 | all_scrap = sheet.difference(buffered_device) 57 | removable_scrap = all_scrap.difference( 58 | not_removable_scrap_region.buffer(tol)) 59 | two_way_scrap = removable_scrap.difference(removability_both.buffer(tol)) 60 | directionally_removable_scrap = removable_scrap.difference( 61 | two_way_scrap.buffer(tol)) 62 | up_scrap = directionally_removable_scrap.intersection( 63 | removability_up.buffer(-tol)) 64 | down_scrap = directionally_removable_scrap.intersection( 65 | removability_down.buffer(-tol)) 66 | return two_way_scrap, up_scrap.buffer(-tol), down_scrap.buffer(-tol) 67 | 68 | 69 | def more_removable_mod(bleed, device, sheet, tol=1e-5): 70 | two_way_scrap, up_scrap, down_scrap = generate_removable_scrap( 71 | device, sheet, tol) 72 | up_bleed = two_way((up_scrap.buffer(bleed)).intersection(two_way_scrap)) 73 | down_bleed = two_way( 74 | (down_scrap.buffer(bleed)).intersection(two_way_scrap)) 75 | up_bleed = up_bleed.difference(down_bleed.buffer(tol)) 76 | down_bleed = down_bleed.difference(up_bleed.buffer(tol)) 77 | two_way_scrap_mod = two_way_scrap.difference( 78 | up_bleed).difference(down_bleed) 79 | up_scrap_mod = up_scrap.union(up_bleed.buffer(tol)) 80 | down_scrap_mod = down_scrap.union(down_bleed.buffer(tol)) 81 | return two_way_scrap_mod, up_scrap_mod, down_scrap_mod 82 | -------------------------------------------------------------------------------- /popupcad/algorithms/spline_functions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import numpy 9 | import matplotlib.pyplot as plt 10 | 11 | def N0(i,knots): 12 | if i==numpy.array(knots).argmax()-1: 13 | def f(q): 14 | return (q>=knots[i])*(q<=knots[i+1])*1 15 | else: 16 | def f(q): 17 | return (q>=knots[i])*(q', connectionstyle = 'arc3,rad=0')) 89 | 90 | def control_from_fit_points(fp,p,plot = True): 91 | import scipy.linalg 92 | 93 | r = len(fp)-1 94 | middle = numpy.r_[1:r] 95 | knots = numpy.r_[[0]*(p+1),middle,[r]*(p+1)] 96 | m = len(knots)-1 97 | n = m-p-1 98 | w = [1]*(n+1) 99 | 100 | domain = numpy.r_[0:r+1] 101 | y = calc_spline(knots,n,w,domain) 102 | yi = scipy.linalg.pinv(y) 103 | 104 | fp = numpy.array(fp) 105 | 106 | cp2 = yi.dot(fp) 107 | if plot: 108 | plt.plot(domain,y) 109 | 110 | return cp2,knots 111 | 112 | if __name__=='__main__': 113 | cp = [[0.0, 0.0], [0.3333333333333333, 0.0], [1.423076923076923, -0.4230769230769232], [0.5192307692307694, 1.480769230769231], [2.5, 0.4999999999999999], [1.480769230769231, 2.519230769230769], [3.576923076923078, 1.423076923076924], [2.666666666666667, 3.0], [3.0, 3.0]] 114 | fp = [[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [2.0, 1.0], [2.0, 2.0], [3.0, 2.0], [3.0, 3.0]] 115 | knots = [0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0] 116 | 117 | w = [1]*len(cp) 118 | # w[4]=3 119 | points = cp 120 | n = len(points)-1 121 | 122 | domain = make_domain(knots,600) 123 | y = calc_spline(knots,n,w,domain) 124 | plt.plot(domain,y) 125 | plt.figure() 126 | plot_labeled_points(numpy.array(cp)) 127 | points = interpolated_points(points,knots,w,domain) 128 | plt.plot(*points.T) 129 | -------------------------------------------------------------------------------- /popupcad/algorithms/toolclearance.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from popupcad.filetypes.layer import Layer 8 | from popupcad.filetypes.laminate import Laminate 9 | from popupcad.algorithms.keepout import laserkeepout, millkeepout, millflipkeepout 10 | 11 | 12 | def laserclearance(laminatein): 13 | return laserkeepout(laminatein) 14 | 15 | 16 | def millclearance(laminatein): 17 | l1 = laserkeepout(laminatein) 18 | l2 = millkeepout(laminatein) 19 | l3 = l1.difference(l2) 20 | return l3 21 | 22 | 23 | def millflipclearance(laminatein): 24 | l1 = laserkeepout(laminatein) 25 | l2 = millflipkeepout(laminatein) 26 | l3 = l1.difference(l2) 27 | return l3 28 | -------------------------------------------------------------------------------- /popupcad/algorithms/triangulate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.filetypes.genericshapes import GenericShapeBase 9 | from popupcad.filetypes.genericshapes import GenericPoly 10 | from scipy.spatial import Delaunay 11 | 12 | 13 | def convex_hull(vertices): 14 | '''Create a convex polygon from given points''' 15 | delaunay = Delaunay(vertices) 16 | 17 | cvx = delaunay.convex_hull.copy() 18 | lastrow = cvx[0] 19 | iis = range(len(cvx)) 20 | for ii in iis[1:-1]: 21 | lastindex = lastrow[1] 22 | findop = (cvx[ii:] == lastindex).nonzero() 23 | 24 | jj = findop[0][0] + ii 25 | 26 | cvx[(ii, jj), :] = cvx[(jj, ii), :] 27 | if findop[1][0] == 1: 28 | cvx[ii, (1, 0)] = cvx[ii, (0, 1)] 29 | 30 | lastrow = cvx[ii] 31 | 32 | lastindex = lastrow[1] 33 | findop = (cvx[-1] == lastindex).nonzero() 34 | if findop[0][0] == 1: 35 | cvx[-1, (1, 0)] = cvx[-1, (0, 1)] 36 | 37 | polyindeces = cvx[:, 0] 38 | polypoints = delaunay.points[polyindeces, :].tolist() 39 | poly = GenericPoly.gen_from_point_lists(polypoints, []) 40 | return poly 41 | 42 | 43 | def triangulate(vertices): 44 | '''Create the triangulation of a set of points, and output the resulting triangles''' 45 | from scipy.spatial import Delaunay 46 | d = Delaunay(vertices) 47 | polys = d.points[d.vertices].tolist() 48 | genericpolys = [GenericPoly.gen_from_point_lists(poly,[]) for poly in polys] 49 | return genericpolys 50 | -------------------------------------------------------------------------------- /popupcad/algorithms/web.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.filetypes.genericshapes import GenericPoly 9 | from popupcad.filetypes.laminate import Laminate 10 | import numpy 11 | import popupcad 12 | 13 | def supportsheet(layerdef, lsin, value): 14 | allext = [] 15 | for layer, layer_geometry in lsin.layer_sequence.items(): 16 | for geom in layer_geometry.geoms: 17 | geom2 = popupcad.algorithms.csg_shapely.to_generic(geom) 18 | allext.extend(geom2.exteriorpoints(scaling = popupcad.csg_processing_scaling)) 19 | allext = numpy.array(allext) 20 | minx = allext[:, 0].min() - value 21 | miny = allext[:, 1].min() - value 22 | maxx = allext[:, 0].max() + value 23 | maxy = allext[:, 1].max() + value 24 | exterior = [[minx, miny], [maxx, miny], [maxx, maxy], [minx, maxy]] 25 | exterior_scaled = (numpy.array(exterior)/popupcad.csg_processing_scaling).tolist() 26 | geom = GenericPoly.gen_from_point_lists(exterior_scaled, []) 27 | geom = geom.to_shapely(scaling = popupcad.csg_processing_scaling) 28 | ls = Laminate(layerdef) 29 | [ls.replacelayergeoms(layer, [geom]) for layer in layerdef.layers] 30 | return ls, exterior[0] 31 | 32 | 33 | def find_outer(ls, minpoint): 34 | import popupcad.algorithms.points as points 35 | lsouter = Laminate(ls.layerdef) 36 | lsinner = Laminate(ls.layerdef) 37 | for layer, layer_geometry in ls.layer_sequence.items(): 38 | outergeoms = [] 39 | innergeoms = [] 40 | for geom in layer_geometry.geoms: 41 | if points.pointinpoints( 42 | minpoint, 43 | popupcad.algorithms.csg_shapely.to_generic(geom).exteriorpoints(scaling = popupcad.csg_processing_scaling), 44 | popupcad.distinguishable_number_difference): 45 | outergeoms.append(geom) 46 | else: 47 | innergeoms.append(geom) 48 | lsouter.replacelayergeoms(layer, outergeoms) 49 | lsinner.replacelayergeoms(layer, innergeoms) 50 | return lsouter, lsinner 51 | 52 | 53 | def firstpass(robot, keepout, layerdef): 54 | firstpass = keepout.difference(robot) 55 | return firstpass 56 | 57 | 58 | def generate_web(robot, keepout, layerdef, value_outer, value_inner): 59 | buffered_keepout = keepout.buffer(value_inner) 60 | robot_support, minpoint = supportsheet(layerdef, robot, value_outer) 61 | buffered_web = robot_support.difference(buffered_keepout) 62 | outer_web, inner_elements = find_outer(buffered_web, minpoint) 63 | return robot_support, outer_web, inner_elements, buffered_keepout 64 | 65 | 66 | def autosupport(robot, keepout, layerdef, value_inner, value_gap, cut_out): 67 | import popupcad 68 | cleanup = 1e-3 *popupcad.csg_processing_scaling 69 | buffered_keepout = keepout.buffer(value_inner) 70 | allsupport = buffered_keepout.difference(keepout) 71 | invalidsupport = keepout.difference(robot) 72 | buffered_invalidsupport = invalidsupport.buffer(-cleanup) 73 | buffered_invalidsupport = buffered_invalidsupport.buffer( 74 | value_gap + 75 | cleanup) 76 | valid_support = allsupport.difference(buffered_invalidsupport) 77 | buffered_valid_support = valid_support.buffer(cleanup) 78 | k2 = keepout.buffer(cut_out) 79 | k3 = k2.difference(keepout) 80 | return buffered_valid_support, k3 81 | -------------------------------------------------------------------------------- /popupcad/basic_functions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | def return_formatted_time( 10 | specificity='second', 11 | small_separator='-', 12 | big_separator='_'): 13 | import time 14 | 15 | a = time.localtime() 16 | args = a.tm_year, a.tm_mon, a.tm_mday, a.tm_hour, a.tm_min, a.tm_sec 17 | kwargs = {'ss': small_separator, 'bs': big_separator} 18 | if specificity == 'year': 19 | b = '{0:04d}'.format(*args, **kwargs) 20 | elif specificity == 'month': 21 | b = '{0:04d}{ss}{1:02d}'.format(*args, **kwargs) 22 | elif specificity == 'day': 23 | b = '{0:04d}{ss}{1:02d}{ss}{2:02d}'.format(*args, **kwargs) 24 | elif specificity == 'hour': 25 | b = '{0:04d}{ss}{1:02d}{ss}{2:02d}{bs}{3:02d}'.format(*args, **kwargs) 26 | elif specificity == 'minute': 27 | b = '{0:04d}{ss}{1:02d}{ss}{2:02d}{bs}{3:02d}{ss}{4:02d}'.format( 28 | * 29 | args, 30 | **kwargs) 31 | elif specificity == 'second': 32 | b = '{0:04d}{ss}{1:02d}{ss}{2:02d}{bs}{3:02d}{ss}{4:02d}{ss}{5:02d}'.format( 33 | * 34 | args, 35 | **kwargs) 36 | return b 37 | -------------------------------------------------------------------------------- /popupcad/constraints/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import constraint 9 | from . import constraints 10 | from . import constraint_support 11 | from . import constraint_system -------------------------------------------------------------------------------- /popupcad/constraints/constraint_support.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sympy 9 | 10 | class Variable(sympy.Symbol): 11 | pass 12 | 13 | class UnknownType(Exception): 14 | pass 15 | 16 | class WrongArguments(Exception): 17 | pass 18 | 19 | class SymbolicVertex(object): 20 | 21 | def __init__(self, id): 22 | self.id = id 23 | 24 | def p(self): 25 | p_x = Variable(str(self) + '_x') 26 | p_y = Variable(str(self) + '_y') 27 | return sympy.Matrix([p_x, p_y, 0]) 28 | 29 | def __hash__(self): 30 | return self.id 31 | 32 | def __eq__(self, other): 33 | if isinstance(self, type(other)): 34 | return self.id == other.id 35 | return False 36 | 37 | def __lt__(self, other): 38 | return self.id < other.id 39 | 40 | def __str__(self): 41 | return 'vertex' + str(self.id) 42 | 43 | 44 | class SymbolicLine(object): 45 | 46 | def __init__(self, v1, v2): 47 | self.vertex1 = v1 48 | self.vertex2 = v2 49 | 50 | def p1(self): 51 | return self.vertex1.p() 52 | 53 | def p2(self): 54 | return self.vertex2.p() 55 | 56 | def v(self): 57 | return self.p2() - self.p1() 58 | 59 | def lv(self): 60 | v = self.v() 61 | return (v.dot(v))**.5 62 | -------------------------------------------------------------------------------- /popupcad/filetypes/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import classtools 9 | from . import design 10 | from . import popupcad_file 11 | from . import genericlaminate 12 | from . import genericshapebase 13 | from . import genericshapes 14 | from . import laminate 15 | from . import layer 16 | from . import layerdef 17 | from . import listwidgetitem 18 | from . import material2 19 | #from . import operation 20 | from . import operation2 21 | from . import operationoutput 22 | from . import program 23 | #from . import programsettings 24 | from . import sketch 25 | from . import solidworksimport 26 | from . import undoredo 27 | from . import userdata 28 | from . import validators 29 | -------------------------------------------------------------------------------- /popupcad/filetypes/classtools.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | class ClassTools(object): 10 | 11 | def copyattrs(self, source, names): 12 | for name in names: 13 | setattr(self, name, getattr(source, name)) 14 | 15 | def copyvalues(self, *args, **kwargs): 16 | self.copyattrs(*args, **kwargs) 17 | 18 | def copyclasses(self, source, names, function): 19 | for name in names: 20 | classin = getattr(source, name) 21 | classout = function(classin) 22 | setattr(self, name, classout) 23 | 24 | def init_copy(self, arglist, kwarglist): 25 | args = [getattr(self, name) for name in arglist] 26 | kwargs = dict([(name, getattr(self, name)) for name in kwarglist]) 27 | return type(self)(*args, **kwargs) 28 | -------------------------------------------------------------------------------- /popupcad/filetypes/layer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import shapely.geometry as sg 8 | import popupcad 9 | 10 | 11 | class Layer(object): 12 | 13 | def __init__(self, geoms): 14 | self.geoms = geoms 15 | 16 | def union(self, layer): 17 | return self.binaryoperation(layer, 'union') 18 | 19 | def difference(self, layer): 20 | return self.binaryoperation(layer, 'difference') 21 | 22 | def intersection(self, layer): 23 | return self.binaryoperation(layer, 'intersection') 24 | 25 | def symmetric_difference(self, layer): 26 | return self.binaryoperation(layer, 'symmetric_difference') 27 | 28 | def buffer(self, value, **kwargs): 29 | if not 'resolution' in kwargs: 30 | kwargs['resolution'] = popupcad.default_buffer_resolution 31 | return self.valueoperation('buffer', value, **kwargs) 32 | 33 | def add_geoms(self, geoms): 34 | self.geoms.extend(geoms) 35 | 36 | def promote(self, layerdef): 37 | from popupcad.filetypes.laminate import Laminate 38 | lsout = Laminate(layerdef) 39 | for layer in layerdef.layers: 40 | lsout.replacelayergeoms(layer, self.geoms) 41 | return lsout 42 | 43 | @classmethod 44 | def unary_union(cls, layers): 45 | geoms = [geom for layer in layers for geom in layer.geoms] 46 | result1 = popupcad.algorithms.csg_shapely.unary_union_safe(geoms) 47 | result2 = popupcad.algorithms.csg_shapely.condition_shapely_entities(result1) 48 | return cls(result2) 49 | 50 | def binaryoperation(self, layer2, functionname): 51 | sourcegeoms = self.geoms 52 | operationgeoms = layer2.geoms 53 | 54 | if sourcegeoms == []: 55 | sourcegeom = sg.Polygon() 56 | else: 57 | sourcegeom = popupcad.algorithms.csg_shapely.unary_union_safe(sourcegeoms) 58 | 59 | if operationgeoms == []: 60 | operationgeom = sg.Polygon() 61 | else: 62 | operationgeom = popupcad.algorithms.csg_shapely.unary_union_safe(operationgeoms) 63 | 64 | function = getattr(sourcegeom, functionname) 65 | newgeom = function(operationgeom) 66 | 67 | result1 = popupcad.algorithms.csg_shapely.unary_union_safe([newgeom]) 68 | result2 = popupcad.algorithms.csg_shapely.condition_shapely_entities(result1) 69 | return type(self)(result2) 70 | 71 | def valueoperation(self, functionname, *args, **kwargs): 72 | sourcegeoms = self.geoms 73 | 74 | if sourcegeoms == []: 75 | sourcegeom = sg.Polygon() 76 | else: 77 | sourcegeom = popupcad.algorithms.csg_shapely.unary_union_safe(sourcegeoms) 78 | 79 | function = getattr(sourcegeom, functionname) 80 | newgeom = function(*args, **kwargs) 81 | result1 = popupcad.algorithms.csg_shapely.unary_union_safe([newgeom]) 82 | result2 = popupcad.algorithms.csg_shapely.condition_shapely_entities(result1) 83 | return type(self)(result2) 84 | 85 | def isEmpty(self): 86 | return len(self.geoms) == 0 87 | -------------------------------------------------------------------------------- /popupcad/filetypes/layerdef.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import popupcad 8 | 9 | class LayerDef(object): 10 | 11 | def __init__(self, *args): 12 | self.layers = list(args) 13 | 14 | def copy(self): 15 | layers = [layer.copy() for layer in self.layers] 16 | new = type(self)(*layers) 17 | return new 18 | 19 | def upgrade(self): 20 | layers = [layer.upgrade() for layer in self.layers] 21 | new = type(self)(*layers) 22 | return new 23 | 24 | def addlayer(self, layer): 25 | self.layers.append(layer) 26 | del self.z_values 27 | 28 | def calc_z_values(self): 29 | zvalue = {} 30 | zval = 0. 31 | for layer in self.layers[::1]: 32 | zvalue[layer] = zval 33 | zval += layer.thickness 34 | return zvalue 35 | 36 | def __repr__(self): 37 | string = 'Laminate' 38 | return string 39 | 40 | def getlayer(self, ref): 41 | dict1 = dict([(item.id, item) for item in self.layers]) 42 | return dict1[ref] 43 | 44 | def getlayer_ii(self, ref): 45 | layer = self.getlayer(ref) 46 | return self.layers.index(layer) 47 | 48 | def neighbors(self, layer): 49 | '''Find the layers above and below a given layer''' 50 | ii = self.layers.index(layer) 51 | neighbors = [] 52 | if ii > 0: 53 | neighbors.append(self.layers[ii - 1]) 54 | if ii < len(self.layers) - 1: 55 | neighbors.append(self.layers[ii + 1]) 56 | return neighbors 57 | 58 | def connected_neighbors(self, layer): 59 | neighbors = self.neighbors(layer) 60 | connected = [neighbor for neighbor in neighbors if (neighbor.is_adhesive or layer.is_adhesive)] 61 | return connected 62 | 63 | @property 64 | def z_values2(self): 65 | zvalues = {} 66 | z = 0. 67 | for layer in self.layers: 68 | zvalues[layer] = {'lower':z} 69 | zvalues[layer]['mid']=z+layer.thickness/2 70 | z += layer.thickness 71 | zvalues[layer]['upper'] = z 72 | return zvalues 73 | 74 | @property 75 | def z_values(self): 76 | try: 77 | return self._z_values 78 | except AttributeError: 79 | self._z_values = self.calc_z_values() 80 | return self._z_values 81 | 82 | @z_values.deleter 83 | def z_values(self): 84 | try: 85 | del self._z_values 86 | except AttributeError: 87 | pass 88 | 89 | -------------------------------------------------------------------------------- /popupcad/filetypes/listwidgetitem.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt.QtCore as qc 9 | import qt.QtGui as qg 10 | 11 | class ListWidgetItem(qg.QListWidgetItem): 12 | 13 | def __init__(self, data, *args, **kwargs): 14 | super(ListWidgetItem, self).__init__(str(data), *args, **kwargs) 15 | self.customdata = data 16 | self.setData(qc.Qt.UserRole, data) 17 | 18 | def setCustomData(self, data): 19 | self.setData(qc.Qt.UserRole, data) 20 | 21 | def readCustomData(self): 22 | return self.data(qc.Qt.UserRole) 23 | -------------------------------------------------------------------------------- /popupcad/filetypes/material2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | class Material2(object): 9 | editable = ['*'] 10 | 11 | def __init__(self,name,color,thickness,E1,E2,density,poisson,is_adhesive,is_rigid,is_conductive,is_flexible): 12 | self.name = name 13 | self.color = color 14 | self.thickness = thickness 15 | self.E1 = E1 16 | self.E2 = E2 17 | self.density = density 18 | self.poisson = poisson 19 | self.is_adhesive = is_adhesive 20 | self.is_rigid = is_rigid 21 | self.is_conductive = is_conductive 22 | self.is_flexible = is_flexible 23 | 24 | self.id = id(self) 25 | 26 | def __str__(self): 27 | return self.name 28 | 29 | def __repr__(self): 30 | return str(self) 31 | 32 | def copy(self,identical = True): 33 | try: 34 | self.is_flexible 35 | except AttributeError: 36 | if not (self.is_adhesive or self.is_conductive or self.is_rigid): 37 | self.is_flexible = True 38 | else: 39 | self.is_flexible = False 40 | 41 | new = type(self)(self.name,self.color,self.thickness,self.E1,self.E2,self.density,self.poisson,self.is_adhesive,self.is_rigid,self.is_conductive,self.is_flexible) 42 | 43 | if identical: 44 | new.id = self.id 45 | return new 46 | 47 | def upgrade(self): 48 | try: 49 | self.is_flexible 50 | except AttributeError: 51 | if not (self.is_adhesive or self.is_conductive or self.is_rigid): 52 | self.is_flexible = True 53 | else: 54 | self.is_flexible = False 55 | return self 56 | 57 | def scale_length(self,factor): 58 | self.thickness *= factor 59 | 60 | def to_foldable(self): 61 | from foldable_robotics.dynamics_info import MaterialProperty 62 | prop = MaterialProperty(self.name,self.color,self.thickness,self.E1,self.E2,self.density,self.poisson,self.is_adhesive,self.is_rigid,self.is_conductive,self.is_flexible) 63 | return prop 64 | 65 | import popupcad 66 | import yaml 67 | 68 | with open(popupcad.internal_materials_filename) as f: 69 | material_defaults = yaml.load(f,Loader=yaml.FullLoader) 70 | 71 | 72 | default_sublaminate_keys = material_defaults['default_sublaminate_keys'] 73 | default_material_types = material_defaults['default_material_types'] 74 | 75 | #rigid = Material2('rigid',(.5,.5,.5,.5),.1,1,1,1,.5,False,True,False) 76 | #adhesive = Material2('adhesive',(.5,.5,.5,.5),.1,1,1,1,.5,True,False,False) 77 | #flexible = Material2('flexible',(.5,.5,.5,.5),.1,1,1,1,.5,False,False,False) 78 | # 79 | #default_sublaminate_keys = ['rigid','adhesive','flexible','adhesive','rigid'] 80 | # 81 | #default_material_types = {} 82 | #default_material_types['rigid'] = rigid 83 | #default_material_types['adhesive'] = adhesive 84 | #default_material_types['flexible'] = flexible 85 | 86 | # 87 | default_materials = list(default_material_types.values()) 88 | default_sublaminate = [default_material_types[key].copy(identical=False) for key in default_sublaminate_keys] 89 | 90 | #material_defaults = {} 91 | #material_defaults['default_sublaminate_keys'] = default_sublaminate_keys 92 | #material_defaults['default_material_types'] = default_material_types 93 | # 94 | #import popupcad 95 | #import yaml 96 | 97 | #with open(popupcad.internal_materials_filename,'w') as f: 98 | # yaml.dump(material_defaults,f) 99 | 100 | def gen_n_colors(l,alpha=None): 101 | import matplotlib.cm 102 | cm = matplotlib.cm.plasma 103 | if l>1: 104 | colors = numpy.array([cm(ii/(l-1)) for ii in range(l)]) 105 | else: 106 | colors = numpy.array([cm(1)]) 107 | if alpha is not None: 108 | colors[:,3] = alpha 109 | colors = [tuple(item) for item in colors] 110 | return colors 111 | 112 | def generate_n_materials(n): 113 | materials = [] 114 | colors = gen_n_colors(n) 115 | for ii in range(n): 116 | name = 'generic_{:02.0f}'.format(ii) 117 | material = Material2(name,colors[ii],1,1,1,1,0,False,False,False,False) 118 | materials.append(material) 119 | return materials -------------------------------------------------------------------------------- /popupcad/filetypes/operationoutput.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from popupcad.filetypes.userdata import UserData 8 | 9 | 10 | class OperationOutput(UserData): 11 | 12 | def __init__(self, csg, name, parent=None): 13 | super(OperationOutput, self).__init__() 14 | self.csg = csg 15 | self.name = name 16 | self.parent = parent 17 | 18 | def generic_laminate(self): 19 | try: 20 | return self._generic_laminate 21 | except AttributeError: 22 | self._generic_laminate = self.csg.to_generic_laminate() 23 | return self._generic_laminate 24 | 25 | def controlpoints(self): 26 | try: 27 | return self._controlpoints 28 | except AttributeError: 29 | self.update_controls() 30 | return self._controlpoints 31 | 32 | def controllines(self): 33 | try: 34 | return self._controllines 35 | except AttributeError: 36 | self.update_controls() 37 | return self._controllines 38 | 39 | def controlpolygons(self): 40 | try: 41 | return self._control_polygons 42 | except AttributeError: 43 | self.update_controls() 44 | return self._control_polygons 45 | 46 | def update_controls(self): 47 | self._controlpoints, self._controllines, self._control_polygons = self.getcontrols( 48 | self.generic_laminate()) 49 | 50 | @staticmethod 51 | def getcontrols(genericgeometry): 52 | from popupcad.geometry.line import ReferenceLine 53 | from popupcad.geometry.vertex import ReferenceVertex 54 | vertices = [] 55 | unique_geoms = [] 56 | all_geoms = [] 57 | lines = [] 58 | for layer, geoms in genericgeometry.geoms.items(): 59 | all_geoms.extend(geoms) 60 | for geom in geoms: 61 | p = geom.points() 62 | vertices.extend(p) 63 | lines.extend(geom.segmentpoints()) 64 | 65 | for geom in all_geoms: 66 | is_unique = True 67 | for geom2 in unique_geoms: 68 | if geom.is_equal(geom2): 69 | is_unique = False 70 | break 71 | if is_unique: 72 | unique_geoms.append(geom) 73 | 74 | vertices = list(set(vertices)) 75 | controlpoints = [ReferenceVertex(p) for p in vertices] 76 | 77 | lines = list(set(lines)) 78 | lines2 = [(vertices.index(p1), vertices.index(p2)) for p1, p2 in lines] 79 | controllines = [ 80 | ReferenceLine( 81 | controlpoints[ii], 82 | controlpoints[jj]) for ii, 83 | jj in lines2] 84 | return controlpoints, controllines, unique_geoms 85 | 86 | def edit(self, *args, **kwargs): 87 | if self.parent is not None: 88 | self.parent.edit(*args, **kwargs) 89 | 90 | def display_geometry_2d(self): 91 | try: 92 | return self._display_geometry_2d 93 | except AttributeError: 94 | self._display_geometry_2d = self.generic_laminate().to_static() 95 | return self._display_geometry_2d 96 | 97 | @property 98 | def triangles_by_layer(self): 99 | try: 100 | return self._triangles_by_layer 101 | except AttributeError: 102 | self._triangles_by_layer = self.generic_laminate().to_triangles() 103 | return self._triangles_by_layer 104 | 105 | def description_get(self): 106 | try: 107 | return self._description 108 | except AttributeError: 109 | self._description = '' 110 | return self._description 111 | 112 | def description_set(self, value): 113 | self._description = value 114 | 115 | description = property(description_get, description_set) 116 | 117 | def edit_description(self): 118 | 119 | import qt.QtCore as qc 120 | import qt.QtGui as qg 121 | result, ok = qg.QInputDialog.getText( 122 | None, 'description', 'label', text=self.description) 123 | if ok: 124 | self.description = result 125 | -------------------------------------------------------------------------------- /popupcad/filetypes/popupcad_file.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import popupcad 8 | from dev_tools.genericfile import GenericFile 9 | 10 | class popupCADFile(GenericFile): 11 | 12 | @classmethod 13 | def get_parent_program_name(self): 14 | return popupcad.program_name 15 | 16 | @classmethod 17 | def get_parent_program_version(self): 18 | return popupcad.version 19 | 20 | def backup(self,folder = None,backupstring = '_backup_'): 21 | import os 22 | import glob 23 | import popupcad 24 | 25 | if folder is None: 26 | folder = self.dirname 27 | basename = self.get_basename() 28 | filename = os.path.normpath(os.path.join(folder,basename)) 29 | filename = os.path.splitext(filename)[0] 30 | 31 | searchstring = (filename+backupstring+'*.'+self.defaultfiletype) 32 | existingfiles = glob.glob(searchstring) 33 | existingfiles.sort(reverse=True) 34 | 35 | for item in existingfiles[popupcad.backup_limit-1:]: 36 | os.remove(item) 37 | 38 | time = popupcad.basic_functions.return_formatted_time(specificity = 'minute') 39 | 40 | backupfilename = filename+backupstring+time+'.'+self.defaultfiletype 41 | 42 | self.save_yaml(backupfilename, update_filename=False) 43 | -------------------------------------------------------------------------------- /popupcad/filetypes/program.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import sys 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | import popupcad 12 | import logging 13 | import traceback 14 | import popupcad.guis.icons 15 | import importlib 16 | 17 | class Program(object): 18 | 19 | def __init__(self, app, *args, **kwargs): 20 | 21 | args = list(args) 22 | 23 | self.app = app 24 | self.app.setWindowIcon(popupcad.guis.icons.get_icons()['printapede']) 25 | self.editor = popupcad.guis.editor.Editor() 26 | 27 | if len(args) > 1 and not '--' in args[-1]: 28 | self.editor.open_filename(filename=args[-1]) 29 | self.editor.show() 30 | self.editor.move_center() 31 | 32 | self.logger = logging.Logger('popupCAD',level=logging.DEBUG) 33 | handler = logging.FileHandler(filename=popupcad.error_log_filename,mode='w') 34 | self.logger.addHandler(handler) 35 | 36 | self.excepthook_internal = sys.excepthook 37 | sys.excepthook = self.excepthook 38 | 39 | for plugin_name in popupcad.plugins+popupcad.user_plugins: 40 | try: 41 | plugin =importlib.import_module(plugin_name) 42 | plugin.initialize(self) 43 | except ImportError: 44 | print(plugin_name+' Not Found') 45 | 46 | def excepthook(self,exctype,value,tb): 47 | if exctype is not SystemExit: 48 | message = '''{}: {}'''.format(str(exctype),str(value)) 49 | print(message) 50 | 51 | tbmessage = traceback.format_tb(tb) 52 | tbmessage = ' '.join(tbmessage) 53 | 54 | # logger = logging.getLogger('popupCAD') 55 | self.logger.error(message) 56 | self.logger.debug('\n'+tbmessage) 57 | 58 | self.editor.error_log.appendText(message+'\n'+tbmessage) 59 | self.excepthook_internal(exctype,value,tb) 60 | mb = qg.QMessageBox() 61 | mb.setText(message) 62 | mb.exec_() 63 | 64 | 65 | -------------------------------------------------------------------------------- /popupcad/filetypes/undoredo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | class UndoRedo(object): 10 | 11 | def __init__(self, get_current_method, load_method): 12 | self.get_current_method = get_current_method 13 | self.load_method = load_method 14 | # self.restartundoqueue() 15 | 16 | def restartundoqueue(self): 17 | file1 = self.get_current_method() 18 | self.undoqueue = [file1.copy()] 19 | self.index = 0 20 | 21 | def savesnapshot(self): 22 | file1 = self.get_current_method() 23 | self.undoqueue = self.undoqueue[:self.index + 1] 24 | self.undoqueue.append(file1.copy()) 25 | self.index = len(self.undoqueue) - 1 26 | 27 | def loadindex(self, ii): 28 | self.load_method(self.undoqueue[ii]) 29 | self.index = ii 30 | 31 | def undo(self): 32 | self.index -= 1 33 | if self.index < 0: 34 | self.index = 0 35 | self.load_method(self.undoqueue[self.index]) 36 | 37 | def redo(self): 38 | self.index += 1 39 | m = len(self.undoqueue) 40 | if self.index >= m: 41 | self.index = m - 1 42 | self.load_method(self.undoqueue[self.index]) 43 | -------------------------------------------------------------------------------- /popupcad/filetypes/userdata.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | class UserData(object): 10 | name = 'UserData' 11 | 12 | def __init__(self, customname=''): 13 | self.setcustomname(customname) 14 | 15 | def __str__(self): 16 | return self.buildviewdata() 17 | 18 | def __repr__(self): 19 | return self.buildviewdata() 20 | 21 | def edit(self, *args, **kwargs): 22 | print('edited') 23 | 24 | def setcustomname(self, name): 25 | self.customname = name 26 | 27 | def getcustomname(self): 28 | return self.customname 29 | 30 | def buildviewdata(self): 31 | if self.customname == '': 32 | return self.name 33 | else: 34 | return self.customname + '(' + self.name + ')' 35 | -------------------------------------------------------------------------------- /popupcad/filetypes/validators.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | 12 | class StrictDoubleValidator(qg.QDoubleValidator): 13 | 14 | def validate(self, input_value, pos): 15 | state, input_value, pos = super(StrictDoubleValidator, self).validate(str(input_value), pos) 16 | 17 | if input_value == '' or input_value == '.': 18 | return self.Intermediate, input_value, pos 19 | if state != self.Acceptable: 20 | return self.Invalid, input_value, pos 21 | return self.Acceptable, input_value, pos 22 | -------------------------------------------------------------------------------- /popupcad/geometry/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import line 9 | from . import vertex 10 | -------------------------------------------------------------------------------- /popupcad/geometry/line.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from popupcad.constraints.constraint_support import SymbolicLine 8 | 9 | 10 | class Line(object): 11 | 12 | def __init__(self, v1, v2): 13 | super(Line, self).__init__() 14 | self.vertex1 = v1 15 | self.vertex2 = v2 16 | 17 | def vertices(self): 18 | return [self.vertex1, self.vertex2] 19 | 20 | def constrained_shift(self, dxdy, constraintsystem): 21 | constraintsystem.constrained_shift( 22 | [(self.vertex1, dxdy), (self.vertex2, dxdy)]) 23 | 24 | def constraints_ref(self): 25 | try: 26 | return self._constraints_ref 27 | except AttributeError: 28 | self._constraints_ref = SymbolicLine( 29 | self.vertex1.constraints_ref(), 30 | self.vertex2.constraints_ref()) 31 | return self._constraints_ref 32 | 33 | def vertex_constraints_ref(self): 34 | return [self.vertex1.constraints_ref(), self.vertex2.constraints_ref()] 35 | 36 | def gen_interactive(self): 37 | from popupcad.graphics2d.interactiveedge import InteractiveEdge 38 | v = InteractiveEdge(self) 39 | v.updateshape() 40 | return v 41 | 42 | 43 | class ShapeLine(Line): 44 | pass 45 | 46 | 47 | class ReferenceLine(Line): 48 | 49 | def gen_interactive(self): 50 | from popupcad.graphics2d.interactiveedge import ReferenceInteractiveEdge 51 | v = ReferenceInteractiveEdge(self) 52 | v.updateshape() 53 | return v 54 | -------------------------------------------------------------------------------- /popupcad/global_settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sys 9 | import os 10 | 11 | from . import basic_functions 12 | 13 | if hasattr(sys, 'frozen'): 14 | localpath = os.path.normpath( 15 | os.path.join( 16 | os.path.dirname( 17 | sys.executable), 18 | '')) 19 | else: 20 | localpath = sys.modules['popupcad'].__path__[0] 21 | 22 | supportfiledir = os.path.normpath(os.path.join(localpath, 'supportfiles')) 23 | iconfile = os.path.normpath(os.path.join(supportfiledir, 'printapede.ico')) 24 | test_file_dir = os.path.normpath(os.path.join(supportfiledir, 'test_files')) 25 | graphics_scene_background_color = (.8,.8,.8,1) 26 | 27 | flip_y = True 28 | 29 | user_home_dir = os.path.expanduser('~') 30 | 31 | deprecated_internal_argument_scaling = 1e3 32 | view_scaling = 1e3 33 | csg_processing_scaling = 1e3 34 | triangulation_scaling = 1e3 35 | 36 | geometry_round_value = 8 37 | distinguishable_number_difference = 10**(-geometry_round_value) 38 | undistinguishable_number_difference = 10**(-geometry_round_value - 1) 39 | 40 | SI_length_scaling = 1000 41 | 42 | inkscape_mm_conversion = 1. / 282.22293 43 | coreldraw_mm_conversion = 1. / 264.581 44 | solidworks_mm_conversion = 1000 45 | 46 | zoom_max = 1. 47 | zoom_min = 1e-6 48 | zoom_scale_factor = 1.2 49 | view_initial_size = 10, 10 50 | 51 | version = basic_functions.return_formatted_time( 52 | specificity='day', 53 | small_separator='.', 54 | big_separator='.') 55 | 56 | default_buffer_resolution = 4 57 | 58 | gui_default_decimals = 6 59 | 60 | gui_infinity = 8 61 | gui_negative_infinity = -1*10**(gui_infinity) 62 | gui_positive_infinity = 10**(gui_infinity) 63 | 64 | program_name = 'popupCAD' 65 | upgrade_tool_name = 'popupCAD Upgrade Tool' 66 | description = 'popupCAD: A design tool for developing laminate devices' 67 | classifiers = [ 68 | 'Programming Language :: Python', 69 | 'Programming Language :: Python :: 3'] 70 | author = 'Daniel M. Aukes' 71 | author_email = 'danaukes@seas.harvard.edu' 72 | url = 'http://www.popupcad.com' 73 | update_url = 'http://www.popupcad.org/docs/download/' 74 | #import uuid 75 | # uuid.uuid4() 76 | windows_uuid = '{875b89db-f819-48bf-9be4-ec93f57f29c2}' 77 | 78 | popupcad_dirname = 'popupCAD_files' 79 | popupcad_home_path = os.path.normpath(os.path.join(user_home_dir,popupcad_dirname)) 80 | 81 | backup_timeout = 1000 * 60 * 5 82 | #backup_timeout = 1000 * 2 83 | backup_limit = 10 84 | #backup_limit = 3 85 | 86 | designdir = os.path.normpath(os.path.join(popupcad_home_path, 'designs')) 87 | importdir = os.path.normpath(os.path.join(popupcad_home_path, 'import')) 88 | exportdir = os.path.normpath(os.path.join(popupcad_home_path, 'export')) 89 | sketchdir = os.path.normpath(os.path.join(popupcad_home_path, 'sketches')) 90 | shapedir = os.path.normpath(os.path.join(popupcad_home_path, 'shapes')) 91 | backupdir = os.path.normpath(os.path.join(popupcad_home_path, 'backup')) 92 | 93 | user_materials_filename = os.path.normpath(os.path.join(popupcad_home_path,'materials.yaml')) 94 | internal_materials_filename = os.path.normpath(os.path.join(supportfiledir,'materials.yaml')) 95 | error_log_filename = os.path.normpath(os.path.join(popupcad_home_path,'log.txt')) 96 | 97 | lastdir = popupcad_home_path 98 | lastdesigndir = designdir 99 | lastsketchdir = sketchdir 100 | lastimportdir = importdir 101 | lastshapedir = shapedir 102 | 103 | subdirectories = [ 104 | popupcad_home_path, 105 | designdir, 106 | importdir, 107 | exportdir, 108 | sketchdir, 109 | shapedir, 110 | backupdir] 111 | 112 | for path in subdirectories: 113 | if not os.path.isdir(path): 114 | os.mkdir(path) 115 | 116 | toolbar_icon_size = 36 117 | nominal_width = 1280 118 | nominal_height = 720 119 | 120 | text_approximation = 2 121 | 122 | custom_settings_filename = os.path.normpath(os.path.join(popupcad_home_path,'settings.yaml')) 123 | plugins = ['popupcad_manufacturing_plugins','popupcad_gazebo','popupcad_microrobotics'] 124 | user_plugins = [] 125 | user_materials = [] 126 | -------------------------------------------------------------------------------- /popupcad/graphics2d/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import interactiveedge 9 | from . import graphicsitems 10 | from . import graphicsscene 11 | from . import graphicsview 12 | from . import interactive 13 | from . import modes 14 | from . import proto 15 | from . import static 16 | from . import svg_support 17 | from . import interactivevertex 18 | -------------------------------------------------------------------------------- /popupcad/graphics2d/graphicsitems.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | class Common(object): 10 | z_value = 0 11 | isDeletable = False 12 | 13 | def allchildren(self): 14 | return self.childItems() 15 | 16 | def softdelete(self): 17 | if self.isDeletable: 18 | self.harddelete() 19 | 20 | def harddelete(self): 21 | for child in self.allchildren(): 22 | child.setParentItem(None) 23 | child.harddelete() 24 | del child 25 | self.setParentItem(None) 26 | self.removefromscene() 27 | del self 28 | 29 | def removefromscene(self): 30 | try: 31 | self.scene().removeItem(self) 32 | except AttributeError: 33 | pass 34 | 35 | def constraintsystem(self): 36 | return self.scene().sketch.constraintsystem 37 | 38 | def sketch(self): 39 | return self.scene().sketch 40 | 41 | 42 | class CommonShape(object): 43 | 44 | def create_selectable_edge_loop(self): 45 | from popupcad.geometry.line import ShapeLine 46 | self.selectableedges = [] 47 | exterior = self.generic.get_exterior() 48 | for handle1, handle2 in zip(exterior, exterior[1:] + exterior[0:1]): 49 | genericline = ShapeLine(handle1, handle2) 50 | item = genericline.gen_interactive() 51 | self.selectableedges.append(item) 52 | 53 | def create_selectable_edge_path(self): 54 | from popupcad.geometry.line import ShapeLine 55 | self.selectableedges = [] 56 | exterior = self.generic.get_exterior() 57 | for handle1, handle2 in zip(exterior[:-1], exterior[1:]): 58 | genericline = ShapeLine(handle1, handle2) 59 | item = genericline.gen_interactive() 60 | self.selectableedges.append(item) 61 | 62 | def create_selectable_edges(self): 63 | self.create_selectable_edge_loop() 64 | 65 | def updateshape(self): 66 | path = self.painterpath() 67 | self.setPath(path) 68 | self.update() 69 | -------------------------------------------------------------------------------- /popupcad/graphics2d/interactivevertex.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | #import popupcad.graphics2d.modes as modes 12 | #from popupcad.graphics2d.graphicsitems import Common 13 | from popupcad.graphics2d.interactivevertexbase import InteractiveVertexBase 14 | 15 | 16 | class InteractiveVertex(InteractiveVertexBase): 17 | radius = 10 18 | z_below = 100 19 | z_above = 105 20 | 21 | def __init__(self, *args, **kwargs): 22 | super(InteractiveVertex, self).__init__(*args, **kwargs) 23 | self.connectedinteractive = None 24 | 25 | def setconnection(self, connectedinteractive): 26 | self.connectedinteractive = connectedinteractive 27 | 28 | def hoverEnterEvent(self, event): 29 | qg.QGraphicsEllipseItem.hoverEnterEvent(self, event) 30 | if self.connectedinteractive is not None: 31 | self.setZValue(self.z_above) 32 | self.updatestate(self.states.state_hover) 33 | 34 | def hoverLeaveEvent(self, event): 35 | qg.QGraphicsEllipseItem.hoverLeaveEvent(self, event) 36 | self.setZValue(self.z_below) 37 | self.updatestate(self.states.state_neutral) 38 | 39 | def mouseMoveEvent(self, event): 40 | if self.connectedinteractive.mode is not None: 41 | if self.connectedinteractive.mode == self.connectedinteractive.modes.mode_edit: 42 | super(InteractiveVertex, self).mouseMoveEvent(event) 43 | 44 | def mousePressEvent(self, event): 45 | modifiers = int(event.modifiers()) 46 | shiftpressed = modifiers & qc.Qt.ShiftModifier 47 | ctrlpressed = modifiers & qc.Qt.ControlModifier 48 | remove = ctrlpressed and shiftpressed 49 | if remove: 50 | if self.connectedinteractive is not None: 51 | self.connectedinteractive.removevertex(self) 52 | self.removefromscene() 53 | else: 54 | super(InteractiveVertex, self).mousePressEvent(event) 55 | 56 | 57 | class InteractiveShapeVertex(InteractiveVertex): 58 | radius = 10 59 | z_below = 100 60 | z_above = 105 61 | 62 | 63 | class ReferenceInteractiveVertex(InteractiveVertex): 64 | radius = 10 65 | z_below = 100 66 | z_above = 105 67 | 68 | 69 | class DrawingPoint(InteractiveVertexBase): 70 | isDeletable = True 71 | radius = 5 72 | z_below = 101 73 | z_above = 105 74 | 75 | def __init__(self, *args, **kwargs): 76 | super(DrawingPoint, self).__init__(*args, **kwargs) 77 | 78 | def refreshview(self): 79 | pass 80 | 81 | def copy(self): 82 | genericcopy = self.get_generic().copy(identical=False) 83 | return genericcopy.outputinteractive() 84 | 85 | 86 | class StaticDrawingPoint(InteractiveVertexBase): 87 | radius = 5 88 | z_below = 100 89 | z_above = 105 90 | 91 | def __init__(self, *args, **kwargs): 92 | super(StaticDrawingPoint, self).__init__(*args, **kwargs) 93 | 94 | def refreshview(self): 95 | pass 96 | -------------------------------------------------------------------------------- /popupcad/graphics2d/modes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | class Modes(object): 10 | modelist = [] 11 | 12 | def __init__(self): 13 | [setattr(self, item, item) for item in self.modelist] 14 | 15 | 16 | class InteractiveModes(Modes): 17 | modelist = [] 18 | modelist.append('mode_defined') 19 | modelist.append('mode_edit') 20 | modelist.append('mode_selectable_edges') 21 | modelist.append('mode_render') 22 | 23 | 24 | class EdgeVertexStates(Modes): 25 | modelist = [] 26 | modelist.append('state_hover') 27 | modelist.append('state_neutral') 28 | modelist.append('state_pressed') 29 | 30 | 31 | class EdgeVertexModes(Modes): 32 | modelist = [] 33 | modelist.append('mode_normal') 34 | modelist.append('mode_edit') 35 | modelist.append('mode_select') 36 | modelist.append('mode_render') 37 | -------------------------------------------------------------------------------- /popupcad/graphics2d/static.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | from popupcad.graphics2d.graphicsitems import Common 12 | from popupcad.graphics2d.graphicsitems import CommonShape 13 | 14 | 15 | class Static(Common): 16 | pen_color = (.2, .2, .2, 1) 17 | linewidth = 1.0 18 | style = qc.Qt.SolidLine 19 | capstyle = qc.Qt.RoundCap 20 | joinstyle = qc.Qt.RoundJoin 21 | brush_color = (.5, .5, .5, .25) 22 | brushpattern = qc.Qt.SolidPattern 23 | 24 | z_value = 10 25 | isDeletable = False 26 | 27 | def __init__(self, generic, *args, **kwargs): 28 | 29 | try: 30 | self.pen_color = kwargs.pop('pen_color ') 31 | except KeyError: 32 | pass 33 | try: 34 | self.brush_color = kwargs.pop('brush_color') 35 | except KeyError: 36 | pass 37 | 38 | self.generic = generic 39 | super(Static, self).__init__(*args, **kwargs) 40 | self.setZValue(self.z_value) 41 | self.setAcceptHoverEvents(True) 42 | self.setselectable(False) 43 | pen = qg.QPen( 44 | qg.QColor.fromRgbF( 45 | *self.pen_color), 46 | self.linewidth, 47 | self.style, 48 | self.capstyle, 49 | self.joinstyle) 50 | pen.setCosmetic(True) 51 | self.setPen(pen) 52 | brush = qg.QBrush( 53 | qg.QColor.fromRgbF( 54 | *self.brush_color), 55 | self.brushpattern) 56 | self.setBrush(brush) 57 | self.refreshview() 58 | self.updateshape() 59 | 60 | def painterpath(self): 61 | return self.generic.painterpath() 62 | 63 | def exteriorpoints(self,scaling = 1): 64 | return self.generic.exteriorpoints(scaling) 65 | 66 | def setselectable(self, test): 67 | self.selectable = test 68 | 69 | def refreshview(self): 70 | self.setEnabled(True) 71 | self.setZValue(self.z_value) 72 | 73 | self.setFlag(self.ItemIsMovable, False) 74 | self.setFlag(self.ItemIsSelectable, False) 75 | self.setFlag(self.ItemIsFocusable, False) 76 | 77 | if self.selectable: 78 | self.setFlag(self.ItemIsSelectable, True) 79 | 80 | 81 | class StaticPoly(Static, CommonShape, qg.QGraphicsPathItem): 82 | pass 83 | 84 | 85 | class StaticCircle(Static, CommonShape, qg.QGraphicsPathItem): 86 | pass 87 | 88 | 89 | class StaticRect2Point(Static, CommonShape, qg.QGraphicsPathItem): 90 | pass 91 | 92 | 93 | class StaticPath(Static, CommonShape, qg.QGraphicsPathItem): 94 | 95 | def __init__(self, *args, **kwargs): 96 | super(StaticPath, self).__init__(*args, **kwargs) 97 | self.setBrush(qg.QBrush(qc.Qt.NoBrush)) 98 | 99 | 100 | class StaticLine(Static, CommonShape, qg.QGraphicsPathItem): 101 | 102 | def __init__(self, *args, **kwargs): 103 | super(StaticLine, self).__init__(*args, **kwargs) 104 | self.setBrush(qg.QBrush(qc.Qt.NoBrush)) 105 | -------------------------------------------------------------------------------- /popupcad/graphics3d/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | #from . import qglwidget 9 | from . import gl_viewer 10 | -------------------------------------------------------------------------------- /popupcad/guis/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import sketcher 9 | from . import editor 10 | #from . import icons don't import automatically because it contains qt code. 11 | from . import actions -------------------------------------------------------------------------------- /popupcad/guis/icons.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import os 9 | import glob 10 | 11 | import qt.QtCore as qc 12 | import qt.QtGui as qg 13 | import popupcad 14 | 15 | #necessary to implement this as a function because otherwise in some cases loading this package fails because qt hasn't been loaded first 16 | def get_icons(): 17 | filenames = glob.glob(os.path.join(popupcad.supportfiledir,'icons','*.png')) 18 | 19 | icons = {} 20 | for filename in filenames: 21 | key = os.path.split(filename)[1] 22 | key = os.path.splitext(key)[0] 23 | icons[key] = qg.QIcon(filename) 24 | return icons 25 | -------------------------------------------------------------------------------- /popupcad/manufacturing/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from . import bufferop3 8 | from . import cleanup2 9 | from . import cleanup3 10 | from . import code_exec_op 11 | from . import cross_section 12 | from . import dummy_operation1 13 | from . import fill 14 | from . import freeze 15 | from . import hole_operation 16 | from . import hollow 17 | #from . import joint_operation2 18 | from . import joint_operation3 19 | from . import laminateoperation2 20 | from . import layerop2 21 | #from . import locateoperation3 22 | from . import multivalueoperation3 23 | from . import nulloperation 24 | #from . import placeop8 25 | #from . import shiftflip3 26 | from . import shiftflip3 27 | from . import simplesketchoperation 28 | from . import simplify2 29 | #from . import sub_operation 30 | from . import sub_operation2 31 | #from . import transform 32 | from . import transform_internal 33 | from . import transform_external 34 | -------------------------------------------------------------------------------- /popupcad/manufacturing/bufferop3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | 12 | class BufferOperation3(MultiValueOperation3): 13 | name = 'Dilate-Erode' 14 | show = [] 15 | # function = 'buffer' 16 | valuenames = ['Buffer', 'Resolution'] 17 | defaults = [0., popupcad.default_buffer_resolution] 18 | 19 | def operate(self, design): 20 | link, output = self.operation_links['parent'][0] 21 | ls1 = design.op_from_ref(link).output[output].csg 22 | return ls1.buffer( 23 | self.values[0] * 24 | popupcad.csg_processing_scaling, 25 | resolution=int( 26 | self.values[1])) 27 | -------------------------------------------------------------------------------- /popupcad/manufacturing/cleanup2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | class Cleanup2(MultiValueOperation3): 12 | name = 'Cleanup' 13 | show = [] 14 | # function = 'buffer' 15 | valuenames = ['Buffer', 'Resolution'] 16 | defaults = [0.0001, 1] 17 | 18 | def operate(self, design): 19 | operation_ref, output_index = self.operation_links['parent'][0] 20 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 21 | return popupcad.algorithms.morphology.cleanup(ls1, self.values[0] * popupcad.csg_processing_scaling, int(self.values[1])) 22 | -------------------------------------------------------------------------------- /popupcad/manufacturing/cleanup3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | 12 | class Cleanup3(MultiValueOperation3): 13 | name = 'New Cleanup' 14 | show = [] 15 | # function = 'buffer' 16 | valuenames = ['Buffer', 'Resolution'] 17 | defaults = [0.0001, 1] 18 | 19 | def operate(self, design): 20 | operation_ref, output_index = self.operation_links['parent'][0] 21 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 22 | 23 | value = self.values[0] *popupcad.csg_processing_scaling 24 | res = int(self.values[1]) 25 | 26 | ls11 = popupcad.algorithms.manufacturing_functions.cleanup3(ls1,value,res) 27 | return ls11 28 | -------------------------------------------------------------------------------- /popupcad/manufacturing/code_exec_op.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | #import popupcad 9 | from popupcad.filetypes.operation2 import Operation2 10 | from popupcad.widgets.userinput import UserInputIDE 11 | 12 | class CodeExecOperation(Operation2): 13 | name = 'Code Execution Operation' 14 | code = "" 15 | 16 | def __init__(self, *args): 17 | super(CodeExecOperation, self).__init__() 18 | self.id = id(self) 19 | self.editdata(*args) 20 | 21 | def copy(self): 22 | new = type(self)(self.code) 23 | new.id = self.id 24 | new.customname = self.customname 25 | return new 26 | 27 | def editdata(self, code): 28 | super(CodeExecOperation, self).editdata({}, {}, {}) 29 | self.code = code 30 | 31 | @classmethod 32 | def buildnewdialog(cls, design, currentop): 33 | mw = UserInputIDE() 34 | mw.setWindowTitle('Internal Python IDE') 35 | mw.te.setReadOnly(False) 36 | return mw 37 | 38 | def buildeditdialog(self, design): 39 | mw = UserInputIDE() 40 | mw.setWindowTitle('Internal Python IDE') 41 | mw.te.setReadOnly(False) 42 | mw.te.setPlainText(self.code) 43 | return mw 44 | 45 | def operate(self, design): 46 | result = None 47 | my_locals = {'design':design,'result':result} 48 | exec(self.code,globals(),my_locals) 49 | # print(my_loc`als) 50 | result = my_locals['result'] 51 | return result -------------------------------------------------------------------------------- /popupcad/manufacturing/cross_section.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | from popupcad.filetypes.operation2 import Operation2 12 | from popupcad.widgets.listmanager import SketchListManager 13 | from popupcad.widgets.dragndroptree import DraggableTreeWidget 14 | from popupcad.filetypes.design import NoOperation 15 | import popupcad 16 | 17 | 18 | class Dialog(qg.QDialog): 19 | 20 | def __init__(self, design, operations, operation_index, sketch=None): 21 | super(Dialog, self).__init__() 22 | SketchListManager(design) 23 | self.optree = DraggableTreeWidget() 24 | self.optree.linklist(operations) 25 | self.sketchwidget = SketchListManager(design) 26 | 27 | button1 = qg.QPushButton('Ok') 28 | button1.clicked.connect(self.accept) 29 | button2 = qg.QPushButton('Cancel') 30 | button2.clicked.connect(self.reject) 31 | layout2 = qg.QHBoxLayout() 32 | layout2.addWidget(button1) 33 | layout2.addWidget(button2) 34 | 35 | layout = qg.QVBoxLayout() 36 | layout.addWidget(self.optree) 37 | layout.addWidget(self.sketchwidget) 38 | layout.addLayout(layout2) 39 | 40 | self.setLayout(layout) 41 | 42 | for ii in range(self.sketchwidget.itemlist.count()): 43 | item = self.sketchwidget.itemlist.item(ii) 44 | if item.value == sketch: 45 | item.setSelected(True) 46 | 47 | try: 48 | self.optree.selectIndeces([operation_index]) 49 | except NoOperation: 50 | pass 51 | 52 | def acceptdata(self): 53 | operation_links = {} 54 | operation_links['source'] = [self.optree.currentRefs()[0]] 55 | 56 | sketch_links = {} 57 | try: 58 | sketch_links['cross_section'] = [ 59 | self.sketchwidget.itemlist.selectedItems()[0].value.id] 60 | except IndexError: 61 | pass 62 | 63 | return operation_links, sketch_links, 100 64 | 65 | 66 | class CrossSection(Operation2): 67 | name = 'Cross-Section' 68 | 69 | def __init__(self, *args, **kwargs): 70 | super(CrossSection, self).__init__() 71 | self.id = id(self) 72 | self.editdata(*args, **kwargs) 73 | 74 | def copy(self): 75 | new = type(self)( 76 | self.operation_links, 77 | self.sketch_links, 78 | self.scale_value) 79 | new.id = self.id 80 | new.customname = self.customname 81 | return new 82 | 83 | def editdata(self, operation_links, sketch_links, scale_value): 84 | super(CrossSection, self).editdata(operation_links, sketch_links, {}) 85 | self.scale_value = scale_value 86 | 87 | def operate(self, design): 88 | parent_ref, parent_index = self.operation_links['source'][0] 89 | parent = design.op_from_ref(parent_ref).output[parent_index].csg 90 | sketch = design.sketches[self.sketch_links['cross_section'][0]] 91 | layerdef = design.return_layer_definition() 92 | return popupcad.algorithms.manufacturing_functions.cross_section( 93 | layerdef, 94 | sketch, 95 | parent, 96 | self.scale_value) 97 | 98 | @classmethod 99 | def buildnewdialog(cls, design, currentop): 100 | dialog = Dialog(design, design.operations, (currentop, 0)) 101 | return dialog 102 | 103 | def buildeditdialog(self, design): 104 | op_ref, output_index = self.operation_links['source'][0] 105 | try: 106 | op_index = design.operation_index(op_ref) 107 | except NoOperation: 108 | op_index = None 109 | 110 | sketch = design.sketches[self.sketch_links['cross_section'][0]] 111 | dialog = Dialog( 112 | design, 113 | design.prioroperations(self), 114 | (op_index, 115 | output_index), 116 | sketch) 117 | return dialog 118 | -------------------------------------------------------------------------------- /popupcad/manufacturing/dummy_operation1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.filetypes.operation2 import Operation2 9 | 10 | class DummyOp1(Operation2): 11 | name = 'None' 12 | 13 | def __init__(self,laminate): 14 | super(DummyOp1, self).__init__() 15 | self.editdata({}, {}, {}) 16 | self.id = id(self) 17 | self.laminate = laminate 18 | 19 | def copy(self): 20 | new = type(self)() 21 | new.id = self.id 22 | new.customname = self.customname 23 | return new 24 | 25 | def operate(self, design): 26 | return self.laminate 27 | 28 | -------------------------------------------------------------------------------- /popupcad/manufacturing/fill.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | #import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | class Fill(MultiValueOperation3): 12 | name = 'Fill' 13 | show = [] 14 | valuenames = [] 15 | defaults = [] 16 | 17 | def operate(self, design): 18 | operation_ref, output_index = self.operation_links['parent'][0] 19 | generic = design.op_from_ref(operation_ref).output[output_index].generic_laminate() 20 | generic2 = generic.fill() 21 | return generic2.to_csg() 22 | -------------------------------------------------------------------------------- /popupcad/manufacturing/freeze.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.filetypes.laminate import Laminate 9 | from popupcad.filetypes.operation2 import Operation2 10 | 11 | import popupcad 12 | 13 | import qt.QtCore as qc 14 | import qt.QtGui as qg 15 | 16 | from popupcad.widgets.dragndroptree import DraggableTreeWidget 17 | from popupcad.filetypes.design import NoOperation 18 | 19 | 20 | class Dialog(qg.QDialog): 21 | 22 | def __init__(self, design, operations, selectedop=None, outputref=0): 23 | super(Dialog, self).__init__() 24 | 25 | self.design = design 26 | 27 | self.le1 = DraggableTreeWidget() 28 | self.le1.linklist(operations) 29 | if selectedop is not None: 30 | self.le1.selectIndeces([(selectedop, outputref)]) 31 | 32 | layout = qg.QVBoxLayout() 33 | layout.addWidget(qg.QLabel('Operation to Flatten')) 34 | layout.addWidget(self.le1) 35 | 36 | button1 = qg.QPushButton('Ok') 37 | button2 = qg.QPushButton('Cancel') 38 | 39 | layout2 = qg.QHBoxLayout() 40 | layout2.addWidget(button1) 41 | layout2.addWidget(button2) 42 | 43 | layout.addLayout(layout2) 44 | 45 | self.setLayout(layout) 46 | 47 | button1.clicked.connect(self.accept) 48 | button2.clicked.connect(self.reject) 49 | 50 | def acceptdata(self): 51 | ref, ii = self.le1.currentRefs()[0] 52 | generic = self.design.op_from_ref(ref).output[ii].generic_laminate() 53 | return ref, ii, generic 54 | 55 | 56 | class Freeze(Operation2): 57 | name = 'Freeze' 58 | 59 | def __init__(self, *args): 60 | super(Freeze, self).__init__() 61 | self.id = id(self) 62 | self.editdata(*args) 63 | 64 | def editdata(self, operation_link1, outputref, generic): 65 | super(Freeze, self).editdata({},{},{}) 66 | self.operation_link1 = operation_link1 67 | self.generic = generic 68 | self.outputref = outputref 69 | 70 | def copy(self): 71 | new = type(self)(self.operation_link1, self.outputref, self.generic) 72 | new.id = self.id 73 | new.customname = self.customname 74 | return new 75 | 76 | def operate(self, design): 77 | layerdef = design.return_layer_definition() 78 | csg = Laminate(layerdef) 79 | for layer in layerdef.layers: 80 | shapelygeoms = [geom.to_shapely(scaling = popupcad.csg_processing_scaling) for geom in self.generic.geoms[layer] if geom.is_valid_bool()] 81 | csg.insertlayergeoms(layer, shapelygeoms) 82 | return csg 83 | 84 | @classmethod 85 | def buildnewdialog(cls, design, currentop): 86 | dialog = Dialog(design, design.operations, currentop) 87 | return dialog 88 | 89 | def buildeditdialog(self, design): 90 | try: 91 | selectedindex = design.operation_index(self.operation_link1) 92 | except NoOperation: 93 | selectedindex = None 94 | operations = design.prioroperations(self) 95 | dialog = Dialog( 96 | design, 97 | operations, 98 | selectedindex, 99 | outputref=self.outputref) 100 | return dialog 101 | -------------------------------------------------------------------------------- /popupcad/manufacturing/hollow.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | #import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | class Hollow(MultiValueOperation3): 12 | name = 'Hollow' 13 | show = [] 14 | valuenames = [] 15 | defaults = [] 16 | 17 | def operate(self, design): 18 | operation_ref, output_index = self.operation_links['parent'][0] 19 | generic = design.op_from_ref(operation_ref).output[output_index].generic_laminate() 20 | generic2 = generic.hollow() 21 | return generic2.to_csg() 22 | -------------------------------------------------------------------------------- /popupcad/manufacturing/nulloperation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.filetypes.operation2 import Operation2 9 | from popupcad.filetypes.laminate import Laminate 10 | 11 | 12 | class NullOp(Operation2): 13 | name = 'None' 14 | 15 | def __init__(self): 16 | super(NullOp, self).__init__() 17 | self.editdata({}, {}, {}) 18 | self.id = id(self) 19 | 20 | def copy(self): 21 | new = type(self)() 22 | new.id = self.id 23 | new.customname = self.customname 24 | return new 25 | 26 | def operate(self, design): 27 | laminate = Laminate(design.return_layer_definition()) 28 | return laminate 29 | 30 | @classmethod 31 | def new(cls, parent, design, currentop, newsignal): 32 | operation = cls() 33 | newsignal.emit(operation) 34 | 35 | def edit(self, parent, design, editedsignal): 36 | pass 37 | -------------------------------------------------------------------------------- /popupcad/manufacturing/simplify2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | 12 | class Simplify2(MultiValueOperation3): 13 | name = 'Simplify' 14 | show = [] 15 | # function = 'buffer' 16 | valuenames = ['Tolerance'] 17 | defaults = [0.01, 1] 18 | 19 | def operate(self, design): 20 | operation_ref, output_index = self.operation_links['parent'][0] 21 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 22 | return popupcad.algorithms.morphology.simplify( 23 | ls1, 24 | self.values[0] * 25 | popupcad.csg_processing_scaling) 26 | -------------------------------------------------------------------------------- /popupcad/materials/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from . import materials 9 | -------------------------------------------------------------------------------- /popupcad/materials/materials.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | class Material(object): 9 | display = ['color', 'thickness'] 10 | editable = ['*'] 11 | name = 'material' 12 | color = (0., 0., 0., .2) 13 | thickness = .025 14 | is_rigid=False 15 | is_adhesive=False 16 | 17 | def __init__(self, thickness=None): 18 | if thickness is not None: 19 | self.thickness = thickness 20 | self.id = id(self) 21 | 22 | def __str__(self): 23 | return self.name 24 | 25 | def __repr__(self): 26 | return str(self) 27 | 28 | # def __hash__(self): 29 | # return self.id 30 | # 31 | # def __eq__(self, other): 32 | # if isinstance(other, type(self)): 33 | # return self.id == other.id 34 | # return False 35 | 36 | def upgrade(self): 37 | from popupcad.filetypes.material2 import Material2 38 | new = Material2(self.name,self.color,self.thickness,E1 = 1,E2 = 1,density = 1,poisson = .5,is_adhesive = self.is_adhesive,is_rigid = self.is_rigid,is_conductive = False) 39 | new.id = self.id 40 | return new 41 | 42 | def copy(self): 43 | from popupcad.filetypes.material2 import Material2 44 | new = Material2(self.name,self.color,self.thickness,E1 = 1,E2 = 1,density = 1,poisson = .5,is_adhesive = self.is_adhesive,is_rigid = self.is_rigid,is_conductive = False) 45 | return new 46 | 47 | class Carbon_0_90_0(Material): 48 | is_rigid = True 49 | name = 'Carbon(0-90-0)' 50 | color = (.2, 0.2, 0.2, .2) 51 | 52 | class Pyralux(Material): 53 | is_adhesive = True 54 | name = 'Pyralux' 55 | color = (175. / 256, 81. / 256, 81. / 256, .2) 56 | 57 | class Kapton(Material): 58 | name = 'Kapton' 59 | color = (1., 1., 0., .2) 60 | 61 | class Cardboard(Material): 62 | name = 'Cardboard' 63 | color = (1., 0., 0., .2) 64 | 65 | class SMP(Material): 66 | name = 'SMP' 67 | color = (.75, 1, .75, .2) 68 | 69 | class Silicone(Material): 70 | name = 'Silicone' 71 | color = (.75, .75, .75, .2) 72 | 73 | class Aluminum(Material): 74 | is_rigid = True 75 | name = 'Aluminum' 76 | color = (.75, .75, .75, .2) 77 | 78 | class Copper(Material): 79 | is_rigid = True 80 | name = 'Copper' 81 | color = (1., .5, .16, .2) 82 | 83 | class FR4(Material): 84 | is_rigid = True 85 | name = 'FR4' 86 | color = (1., .85, .36, .2) 87 | 88 | class Velcro(Material): 89 | name = 'Velcro' 90 | color = (0., .5, .5, .2) 91 | 92 | class Dummy(Material): 93 | name = 'Dummy' 94 | color = (0.5, .5, .5, .2) 95 | 96 | available_materials = [ 97 | Carbon_0_90_0, 98 | Pyralux, 99 | Kapton, 100 | Cardboard, 101 | Silicone, 102 | Velcro, 103 | Dummy, 104 | Aluminum, 105 | Copper, 106 | FR4, 107 | SMP] 108 | # available_materials.sort() 109 | 110 | if __name__ == '__main__': 111 | from popupcad.filetypes.layerdef import LayerDef 112 | sublaminate = LayerDef( 113 | Carbon_0_90_0(), 114 | Pyralux(), 115 | Kapton(), 116 | Pyralux(), 117 | Carbon_0_90_0()) 118 | -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/3dview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/3dview.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/angle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/angle.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/autosupport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/autosupport.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/broom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/broom.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/bufferop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/bufferop.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/circle.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/cleanup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/cleanup.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/coincident.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/coincident.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/convex_hull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/convex_hull.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/customsupport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/customsupport.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/distance.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/distancex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/distancex.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/distancey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/distancey.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/dotdotdot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/dotdotdot.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/equal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/equal.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/export.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/firstpass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/firstpass.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/getjoints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/getjoints.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/getjoints2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/getjoints2.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/hand.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/hingefoldop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/hingefoldop.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/horizontal.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/icons.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/identifybodies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/identifybodies.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/import.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/layerop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/layerop.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/layers.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/layers3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/layers3.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/line.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/locate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/locate.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/metaop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/metaop.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/new.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/open.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/operations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/operations.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/outersheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/outersheet.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/outerweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/outerweb.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/parallel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/parallel.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/perpendicular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/perpendicular.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/placeop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/placeop.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/pointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/pointer.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/pointline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/pointline.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/pointline2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/pointline2.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/points.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/points.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/polygon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/polygon.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/polygons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/polygons.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/polyline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/polyline.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/popupcad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/popupcad.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/popupcad2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/popupcad2.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/printapede.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/printapede.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/quit.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/rectangle.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/redo.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/refresh.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/removability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/removability.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/save.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/save2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/save2.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/scrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/scrap.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/secondpass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/secondpass.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/shiftflip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/shiftflip.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/shiftflip2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/shiftflip2.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/showconstraints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/showconstraints.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/simplify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/simplify.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/text.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/triangulate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/triangulate.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/undo.png -------------------------------------------------------------------------------- /popupcad/supportfiles/icons/vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/icons/vertical.png -------------------------------------------------------------------------------- /popupcad/supportfiles/materials.yaml: -------------------------------------------------------------------------------- 1 | default_material_types: 2 | adhesive: !!python/object:popupcad.filetypes.material2.Material2 3 | E1: 1 4 | E2: 1 5 | color: !!python/tuple [0.68359375, 0.31640625, 0.31640625, 0.5] 6 | density: 1 7 | id: 43436632 8 | is_adhesive: true 9 | is_conductive: false 10 | is_rigid: false 11 | is_flexible: false 12 | name: adhesive 13 | poisson: 0.5 14 | thickness: 0.025 15 | flexible: !!python/object:popupcad.filetypes.material2.Material2 16 | E1: 1 17 | E2: 1 18 | color: !!python/tuple [1., 1., 0., .5] 19 | density: 1 20 | id: 43434840 21 | is_adhesive: false 22 | is_conductive: false 23 | is_rigid: false 24 | is_flexible: true 25 | name: flexible 26 | poisson: 0.5 27 | thickness: 0.025 28 | rigid: !!python/object:popupcad.filetypes.material2.Material2 29 | E1: 1 30 | E2: 1 31 | color: !!python/tuple [.2, 0.2, 0.2, .5] 32 | density: 1 33 | id: 43405096 34 | is_adhesive: false 35 | is_conductive: false 36 | is_rigid: true 37 | is_flexible: false 38 | name: rigid 39 | poisson: 0.5 40 | thickness: 0.025 41 | default_sublaminate_keys: [rigid, adhesive, flexible, adhesive, rigid] 42 | -------------------------------------------------------------------------------- /popupcad/supportfiles/printapede.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad/supportfiles/printapede.ico -------------------------------------------------------------------------------- /popupcad/supportfiles/virtual_structure.yaml: -------------------------------------------------------------------------------- 1 | - - make_new_module 2 | - [popupcad.filetypes.constraints] 3 | - - make_new_module 4 | - [popupcad.manufacturing.placeop8] 5 | - - make_new_module 6 | - [popupcad.manufacturing.locateoperation3] 7 | - - remap_class 8 | - [popupcad_deprecated.placeop8.PlaceOperation8, popupcad.manufacturing.placeop8.PlaceOperation8] 9 | - - remap_class 10 | - [popupcad_deprecated.locateoperation3.LocateOperation3, popupcad.manufacturing.locateoperation3.LocateOperation3] 11 | - - remap_class 12 | - [popupcad.constraints.constraint_system.ConstraintSystem, popupcad.filetypes.constraints.ConstraintSystem] 13 | - - remap_class 14 | - [popupcad.constraints.constraints.FixedConstraint, popupcad.filetypes.constraints.fixed] 15 | - - remap_class 16 | - [popupcad.constraints.constraints.HorizontalConstraint, popupcad.filetypes.constraints.horizontal] 17 | - - remap_class 18 | - [popupcad.constraints.constraints.VerticalConstraint, popupcad.filetypes.constraints.vertical] 19 | - - remap_class 20 | - [popupcad.constraints.constraints.DistanceConstraint, popupcad.filetypes.constraints.distance] 21 | - - remap_class 22 | - [popupcad.constraints.constraints.CoincidentConstraint, popupcad.filetypes.constraints.coincident] 23 | - - remap_class 24 | - [popupcad.constraints.constraints.XDistanceConstraint, popupcad.filetypes.constraints.distancex] 25 | - - remap_class 26 | - [popupcad.constraints.constraints.YDistanceConstraint, popupcad.filetypes.constraints.distancey] 27 | - - remap_class 28 | - [popupcad.constraints.constraints.AngleConstraint, popupcad.filetypes.constraints.angle] 29 | - - remap_class 30 | - [popupcad.constraints.constraints.ParallelLinesConstraint, popupcad.filetypes.constraints.parallel] 31 | - - remap_class 32 | - [popupcad.constraints.constraints.EqualLengthLinesConstraint, popupcad.filetypes.constraints.equal] 33 | - - remap_class 34 | - [popupcad.constraints.constraints.PerpendicularLinesConstraint, popupcad.filetypes.constraints.perpendicular] 35 | - - remap_class 36 | - [popupcad.constraints.constraints.PointLineDistanceConstraint, popupcad.filetypes.constraints.PointLine] 37 | - - remap_class 38 | - [popupcad.constraints.constraints.LineMidpointConstraint, popupcad.filetypes.constraints.LineMidpoint] 39 | - - remap_class 40 | - [popupcad.constraints.constraint_support.SymbolicLine, popupcad.filetypes.constraints.SymbolicLine] 41 | - - remap_class 42 | - [popupcad.constraints.constraint_support.SymbolicVertex, popupcad.filetypes.constraints.SymbolicVertex] 43 | -------------------------------------------------------------------------------- /popupcad/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from . import listeditor 8 | from . import materialselection 9 | from . import textwindow 10 | from . import dragndroplist 11 | from . import dragndroptree 12 | from . import listmanager 13 | from . import materialselection 14 | from . import materialselection2 15 | from . import widgetcommon 16 | from . import render_widget 17 | -------------------------------------------------------------------------------- /popupcad/widgets/export_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import qt.QtCore as qc 8 | import qt.QtGui as qg 9 | import qt.QtSvg as qs 10 | import popupcad 11 | #from math import pi, sin, cos 12 | #import numpy 13 | import os 14 | 15 | #from popupcad.filetypes.validators import StrictDoubleValidator 16 | 17 | class DxfExportWidget(qg.QDialog): 18 | 19 | def __init__(self,folder = None,show_separate_layers=True): 20 | if folder is None: 21 | folder = popupcad.exportdir 22 | super(DxfExportWidget, self).__init__() 23 | 24 | button_accept = qg.QPushButton('Ok') 25 | button_reject= qg.QPushButton('Cancel') 26 | 27 | self.separate_layers = qg.QCheckBox('One layer per file') 28 | 29 | self.dirbox = qg.QLineEdit() 30 | self.dirbox.setText(folder) 31 | self.dirbutton = qg.QPushButton('...') 32 | layout0 = qg.QHBoxLayout() 33 | layout0.addWidget(self.dirbox) 34 | layout0.addWidget(self.dirbutton) 35 | layout2 = qg.QHBoxLayout() 36 | layout2.addWidget(button_accept) 37 | layout2.addWidget(button_reject) 38 | layout3 = qg.QVBoxLayout() 39 | layout3.addLayout(layout0) 40 | if show_separate_layers: 41 | layout3.addWidget(self.separate_layers) 42 | layout3.addLayout(layout2) 43 | 44 | self.dirbutton.clicked.connect(self.selectExport) 45 | button_accept.clicked.connect(self.accept) 46 | button_reject.clicked.connect(self.reject) 47 | self.setLayout(layout3) 48 | 49 | def selectExport(self): 50 | directorypath = qg.QFileDialog.getExistingDirectory(self,"Select Directory",self.dirbox.text()) 51 | if directorypath!='': 52 | directorypath = os.path.normpath(directorypath) 53 | self.dirbox.setText(directorypath) 54 | 55 | def accept_data(self): 56 | data = {} 57 | data['directory'] = self.dirbox.text() 58 | data['separate_layers'] = self.separate_layers.isChecked() 59 | return data 60 | 61 | if __name__ == '__main__': 62 | import sys 63 | app = qg.QApplication(sys.argv) 64 | win = DxfExportWidget() 65 | win.exec_() 66 | sys.exit(app.exec_()) 67 | -------------------------------------------------------------------------------- /popupcad/widgets/listeditor.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt.QtCore as qc 9 | import qt.QtGui as qg 10 | from popupcad.filetypes.listwidgetitem import ListWidgetItem 11 | 12 | 13 | class ListBase(qg.QListWidget): 14 | 15 | def __init__(self, *args, **kwargs): 16 | super(ListBase, self).__init__(*args, **kwargs) 17 | self.setMinimumWidth(200) 18 | self.list = [] 19 | self.setSelectionBehavior(self.SelectRows) 20 | 21 | def linklist(self, listin): 22 | self.list = listin 23 | self.refresh() 24 | 25 | def add_item(self, item): 26 | self.list.append(item) 27 | self.refresh() 28 | 29 | def refresh(self): 30 | self.clear() 31 | widgetitems = [] 32 | for item in self.list: 33 | widgetitem = ListWidgetItem(item, self) 34 | widgetitems.append(widgetitem) 35 | return widgetitems 36 | 37 | def removeitem(self, index): 38 | self.list.pop(index) 39 | items = self.refresh() 40 | if len(items) > 0: 41 | if index == len(items): 42 | self.setCurrentItem(items[index - 1]) 43 | else: 44 | self.setCurrentItem(items[index]) 45 | 46 | def itemDoubleClicked_method(self, item): 47 | self.signal_edit.emit(item.customdata) 48 | 49 | def selectItems(self, items): 50 | for item in items: 51 | ii = self.list.index(item) 52 | self.item(ii).setSelected(True) 53 | 54 | def selectedData(self): 55 | return [item.customdata for item in self.selectedItems()] 56 | 57 | def customadditems(self, items): 58 | itemlist = [] 59 | heights = [] 60 | for ii, item in enumerate(items): 61 | listwidgetitem = ListWidgetItem(item, self) 62 | h = self.sizeHintForRow(ii) 63 | heights.append(h) 64 | itemlist.append(listwidgetitem) 65 | return itemlist 66 | 67 | 68 | class ListEditor(ListBase): 69 | signal_edit = qc.Signal(object) 70 | itemdeleted = qc.Signal(object) 71 | 72 | def __init__(self, *args, **kwargs): 73 | super(ListEditor, self).__init__(*args, **kwargs) 74 | self.setSelectionMode(qg.QAbstractItemView.SingleSelection) 75 | self.itemDoubleClicked.connect(self.itemDoubleClicked_method) 76 | 77 | def keyPressEvent(self, event): 78 | if event.key() == qc.Qt.Key_Delete: 79 | for item in self.selectedItems(): 80 | self.removeitem(self.row(item)) 81 | self.itemdeleted.emit(item.customdata) 82 | 83 | 84 | class ListSelector(ListBase): 85 | 86 | def __init__(self, *args, **kwargs): 87 | super(ListSelector, self).__init__(*args, **kwargs) 88 | self.setSelectionMode(self.MultiSelection) 89 | 90 | if __name__ == "__main__": 91 | import sys 92 | app = qg.QApplication(sys.argv) 93 | a = ListEditor() 94 | b = a.model() 95 | -------------------------------------------------------------------------------- /popupcad/widgets/materialselection.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | #import popupcad.materials.materials as materials 8 | from popupcad.filetypes.layerdef import LayerDef 9 | 10 | import qt.QtCore as qc 11 | import qt.QtGui as qg 12 | 13 | class ClassItem(qg.QListWidgetItem): 14 | 15 | def __init__(self, *args, **kwargs): 16 | super(ClassItem, self).__init__(*args, **kwargs) 17 | 18 | def setClass(self, class1): 19 | self.class1 = class1 20 | 21 | def getClass(self): 22 | return self.class1 23 | 24 | 25 | class MaterialSelection(qg.QDialog): 26 | 27 | def __init__(self, initialleft, initialright, *args, **kwargs): 28 | super(MaterialSelection, self).__init__(*args, **kwargs) 29 | 30 | self.layerdef = LayerDef(*initialleft) 31 | self.lw = qg.QListWidget(self) 32 | self.lw.itemDoubleClicked.connect(self.remove_item) 33 | 34 | self.rw = qg.QListWidget(self) 35 | self.rw.itemDoubleClicked.connect(self.add_item) 36 | 37 | self.ok_button = qg.QPushButton('&Ok', self) 38 | self.cancel_button = qg.QPushButton('&Cancel', self) 39 | self.ok_button.clicked.connect(self.accept) 40 | self.cancel_button.clicked.connect(self.reject) 41 | 42 | l1 = qg.QHBoxLayout() 43 | l1.addWidget(self.lw) 44 | l1.addWidget(self.rw) 45 | 46 | l3 = qg.QHBoxLayout() 47 | l3.addStretch(1) 48 | l3.addWidget(self.ok_button) 49 | l3.addWidget(self.cancel_button) 50 | l3.addStretch(1) 51 | 52 | l2 = qg.QVBoxLayout() 53 | l2.addLayout(l1) 54 | l2.addLayout(l3) 55 | 56 | self.setLayout(l2) 57 | self.setWindowTitle('Material Selection') 58 | self.initialize_right(initialright) 59 | self.update_left() 60 | 61 | def add_item(self, item): 62 | self.layerdef.addlayer(item.class1.copy(identical = False)) 63 | self.update_left() 64 | 65 | def update_left(self): 66 | self.lw.clear() 67 | for item in self.layerdef.layers: 68 | ci = ClassItem(item.name) 69 | ci.setClass(item) 70 | self.lw.addItem(ci) 71 | 72 | def remove_item(self, item): 73 | ii = self.lw.row(item) 74 | self.layerdef.layers.pop(ii) 75 | self.update_left() 76 | 77 | def initialize_right(self, items): 78 | self.lw.clear() 79 | for item in items: 80 | ci = ClassItem(item.name) 81 | ci.setClass(item) 82 | self.rw.addItem(ci) 83 | 84 | def initialize_left(self, items): 85 | self.lw.clear() 86 | for item in items: 87 | ci = ClassItem(item.name) 88 | ci.setClass(item) 89 | self.lw.addItem(ci) 90 | 91 | if __name__ == '__main__': 92 | import sys 93 | 94 | app = qg.QApplication(sys.argv) 95 | 96 | window = MaterialSelection([], []) 97 | a = window.exec_() 98 | -------------------------------------------------------------------------------- /popupcad/widgets/materialselection2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt.QtCore as qc 9 | import qt.QtGui as qg 10 | 11 | from popupcad.widgets.dragndroplist import DraggableListWidget, UserData 12 | 13 | 14 | class CompositeMakeup(DraggableListWidget): 15 | 16 | def __init__(self): 17 | super(CompositeMakeup, self).__init__() 18 | self.setDragDropMode(self.DropOnly) 19 | 20 | 21 | class AvailableMaterials(DraggableListWidget): 22 | 23 | def __init__(self): 24 | super(AvailableMaterials, self).__init__() 25 | self.setDragDropMode(self.DragOnly) 26 | 27 | def get_item_names(widget): 28 | for ii in range(widget.model().rowCount()): 29 | print(widget.item(ii)) 30 | 31 | 32 | if __name__ == '__main__': 33 | import sys 34 | app = qg.QApplication(sys.argv) 35 | 36 | list1 = range(10) 37 | list1 = [UserData(str(item)) for item in list1] 38 | 39 | widget1 = AvailableMaterials() 40 | widget2 = CompositeMakeup() 41 | mw = qg.QWidget() 42 | layout = qg.QVBoxLayout() 43 | layout.addWidget(widget1) 44 | layout.addWidget(widget2) 45 | mw.setLayout(layout) 46 | 47 | widget1.linklist(list1) 48 | mw.show() 49 | -------------------------------------------------------------------------------- /popupcad/widgets/operationlist.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | 12 | class OperationList(qg.QWidget): 13 | # opchange = qc.Signal() 14 | unary_selected = qc.Signal() 15 | binary_selected = qc.Signal() 16 | 17 | def __init__(self, unaryops, binaryops, text_list): 18 | super(OperationList, self).__init__() 19 | 20 | self.unaryops = unaryops 21 | self.binaryops = binaryops 22 | 23 | # self.addItems(text_list) 24 | self.combobox = qg.QComboBox() 25 | self.combobox.addItems(text_list) 26 | layout = qg.QVBoxLayout() 27 | layout.addWidget(qg.QLabel('Operation Type')) 28 | layout.addWidget(self.combobox) 29 | layout.setContentsMargins(0, 0, 0, 0) 30 | self.setLayout(layout) 31 | self.combobox.currentIndexChanged.connect(self.testchange) 32 | 33 | def is_unary(self): 34 | return self.combobox.currentText() in self.unaryops 35 | 36 | def is_binary(self): 37 | return self.combobox.currentText() in self.binaryops 38 | 39 | def setCurrentIndex(self, ii): 40 | self.combobox.setCurrentIndex(ii) 41 | if self.is_unary(): 42 | self.unary_selected.emit() 43 | if self.is_binary(): 44 | self.binary_selected.emit() 45 | 46 | def testchange(self): 47 | # self.opchange.emit() 48 | if self.is_unary(): 49 | self.unary_selected.emit() 50 | if self.is_binary(): 51 | self.binary_selected.emit() 52 | 53 | def currentText(self): 54 | return self.combobox.currentText() 55 | 56 | def currentIndex(self): 57 | return self.combobox.currentIndex() 58 | -------------------------------------------------------------------------------- /popupcad/widgets/render_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import os 9 | import popupcad 10 | 11 | import qt 12 | import qt.QtCore as qc 13 | import qt.QtGui as qg 14 | from popupcad.graphics2d.graphicsscene import SimpleGraphicsScene 15 | from popupcad.graphics2d.graphicsview import SimpleGraphicsView 16 | 17 | 18 | class RenderWidget(qg.QWidget): 19 | 20 | def __init__(self, rect_size): 21 | super(RenderWidget, self).__init__() 22 | 23 | # gs = popupcad.graphics2d.graphicsscene.GraphicsScene() 24 | # gs = qg.QGraphicsScene() 25 | # gs.setBackgroundBrush(qg.QBrush(qg.QColor.fromRgbF(1, 1, 1, 1))) 26 | # self.gv = popupcad.graphics2d.graphicsview.GraphicsView(gs) 27 | self.gv = SimpleGraphicsView() 28 | gs = SimpleGraphicsScene(self.gv) 29 | self.gv.setScene(gs) 30 | self.gv.finish_init() 31 | 32 | self.gv.setRenderHint(qg.QPainter.Antialiasing) 33 | # self.gv.setRenderHint(qg.QPainter.HighQualityAntialiasing,True) 34 | # self.gv.setRenderHint(qg.QPainter.SmoothPixmapTransform,True) 35 | # self.gs.setBackgroundBrush(qg.QBrush(qg.QColor.fromRgbF(1,1,1,0.1))) 36 | # self.gs.setBackgroundBrush(qg.QBrush()) 37 | 38 | self.directory_name = qg.QLineEdit() 39 | self.directory_button = qg.QPushButton('...') 40 | self.render_button = qg.QPushButton('render') 41 | 42 | layout = qg.QVBoxLayout() 43 | # layout.addWidget(self.gv) 44 | layout.addWidget(self.directory_name) 45 | layout.addWidget(self.directory_button) 46 | layout.addWidget(self.render_button) 47 | 48 | self.setLayout(layout) 49 | self.gv.setMinimumSize(*rect_size) 50 | self.gv.setMaximumSize(*rect_size) 51 | 52 | self.directory_button.clicked.connect(self.select_directory) 53 | self.render_button.clicked.connect(self.render) 54 | 55 | def render(self): 56 | path = self.directory_name.text() 57 | d = popupcad.filetypes.design.Design.load_yaml(path) 58 | d.reprocessoperations() 59 | directory, file = os.path.split(path) 60 | self.raster_design(d, directory) 61 | 62 | def select_directory(self): 63 | if qt.loaded == 'PySide': 64 | filename, selectedfilter = qg.QFileDialog.getOpenFileName(self, '', dir=self.directory_name.text(), filter='*.cad') 65 | elif qt.loaded == 'PyQt5': 66 | filename, selectedfilter = qg.QFileDialog.getOpenFileName(self, '', dir=self.directory_name.text(), filter='*.cad') 67 | else: 68 | filename = qg.QFileDialog.getOpenFileName(self, '', dir=self.directory_name.text(), filter='*.cad') 69 | 70 | print(filename) 71 | if filename != '': 72 | self.load_directory(filename) 73 | 74 | def load_directory(self, path): 75 | self.directory_name.setText(path) 76 | 77 | def clear(self): 78 | for item in self.gv.scene().items(): 79 | self.gv.scene().removeItem(item) 80 | 81 | def raster_design(self, d, dest, filetype='png'): 82 | d.raster(destination=dest, filetype=filetype, gv=self.gv) 83 | 84 | if __name__ == "__main__": 85 | import sys 86 | 87 | filter1 = '*.cad' 88 | # source = 'C:/Users/danaukes/popupCAD_files/designs' 89 | # source= os.path.normpath('C:/Users/danaukes/Desktop/source') 90 | destination = os.path.normpath('C:/Users/danaukes/Desktop') 91 | rect_size = 400, 300 92 | app = qg.QApplication(sys.argv) 93 | widget = RenderWidget(rect_size) 94 | widget.show() 95 | -------------------------------------------------------------------------------- /popupcad/widgets/textwindow.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | 12 | class TextWindow(qg.QWidget): 13 | 14 | def __init__(self): 15 | super(TextWindow, self).__init__() 16 | self.te = qg.QTextEdit() 17 | # self.te.setEnabled(False) 18 | 19 | layout = qg.QVBoxLayout() 20 | layout2 = qg.QHBoxLayout() 21 | self.close_button = qg.QPushButton('Close') 22 | layout.addWidget(self.te) 23 | layout2.addStretch() 24 | layout2.addWidget(self.close_button) 25 | layout2.addStretch() 26 | layout.addLayout(layout2) 27 | self.setLayout(layout) 28 | 29 | self.close_button.clicked.connect(self.close) 30 | 31 | def appendText(self, text): 32 | current = self.te.toPlainText() 33 | current += '\n' + text 34 | self.te.setText(current) 35 | def sizeHint(self): 36 | return qc.QSize(640,480) 37 | if __name__ == "__main__": 38 | import sys 39 | app = qg.QApplication(sys.argv) 40 | mw = TextWindow() 41 | mw.appendText('asdfasdfasdf\nasdfasdfasdfasdfasdfasdfasfd') 42 | mw.appendText('asdfasdfasdf') 43 | mw.appendText('asdfasdfasdf') 44 | mw.appendText('asdfasdfasdf') 45 | mw.show() 46 | mw.raise_() 47 | sys.exit(app.exec_()) 48 | -------------------------------------------------------------------------------- /popupcad/widgets/userinput.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | # -*- coding: utf-8 -*- 9 | """ 10 | Written by Aaron Gokaslan. 11 | Email: aaronGokaslangmail.com. 12 | Please see LICENSE.txt for full license. 13 | """ 14 | 15 | 16 | import qt.QtCore as qc 17 | import qt.QtGui as qg 18 | from popupcad.algorithms.python_syntax_formatter import PythonHighlighter 19 | 20 | 21 | class UserInputIDE(qg.QDialog): 22 | 23 | def __init__(self): 24 | super(UserInputIDE, self).__init__() 25 | self.te = qg.QTextEdit() 26 | # self.te.setEnabled(False) 27 | self.ok = qg.QPushButton('Compile and Run Simulation') 28 | self.loadbtn = qg.QPushButton('Load a script') 29 | self.loadbtn.pressed.connect(self.loadFile) 30 | self.savebtn = qg.QPushButton('Save current script') 31 | self.savebtn.pressed.connect(self.saveFile) 32 | self.ok.pressed.connect(self.accept) 33 | layout = qg.QVBoxLayout() 34 | top_bar = qg.QHBoxLayout() 35 | top_bar.addWidget(self.loadbtn) 36 | top_bar.addWidget(self.savebtn) 37 | layout.addLayout(top_bar) 38 | layout.addWidget(self.te) 39 | layout.addWidget(self.ok) 40 | self.setLayout(layout) 41 | PythonHighlighter(self.te.document()) 42 | 43 | def appendText(self, text): 44 | current = self.te.toPlainText() 45 | current += text + "\n" 46 | self.te.setText(current) 47 | 48 | def sizeHint(self): 49 | return qc.QSize(800,600) 50 | 51 | def loadFile(self): 52 | from os.path import expanduser 53 | home = expanduser("~") 54 | fname, _ = qg.QFileDialog.getOpenFileName(self, 'Open file',home) 55 | infile = open(fname, 'r') 56 | self.te.setPlainText(infile.read()) 57 | infile.close() 58 | 59 | def saveFile(self): 60 | from os.path import expanduser 61 | home = expanduser("~") 62 | fname, _ = qg.QFileDialog.getSaveFileName(self, 'Save file',home) 63 | infile = open(fname, 'w') 64 | infile.write(self.te.toPlainText()) 65 | infile.close() 66 | 67 | def acceptdata(self): 68 | return self.te.toPlainText(), 69 | 70 | if __name__ == "__main__": 71 | import sys 72 | app = qg.QApplication(sys.argv) 73 | 74 | mw = UserInputIDE() 75 | mw.appendText('asdfasdfasdf\nasdfasdfasdfasdfasdfasdfasfd') 76 | mw.appendText('asdfasdfasdf') 77 | mw.appendText('asdfasdfasdf') 78 | mw.appendText('asdfasdfasdf') 79 | mw.te.setReadOnly(False) 80 | mw.te.document() 81 | mw.exec_() 82 | sys.exit(app.exec_()) 83 | -------------------------------------------------------------------------------- /popupcad/widgets/widgetcommon.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | import qt.QtCore as qc 10 | import qt.QtGui as qg 11 | import popupcad 12 | 13 | class WidgetBasic(object): 14 | def sizeHint(self): 15 | buffer_x = 14 16 | buffer_y = 36 17 | return qc.QSize(popupcad.nominal_width - buffer_x, popupcad.nominal_height - buffer_y) 18 | 19 | def set_nominal_size(self): 20 | # buffer_x=14 21 | # buffer_y=36 22 | # self.resize(popupcad.nominal_width-buffer_x,popupcad.nominal_height-buffer_y) 23 | pass 24 | 25 | def move_center(self): 26 | screen_width = qg.QApplication.desktop().screen().width() 27 | screen_height = qg.QApplication.desktop().screen().height() 28 | 29 | new_pos_x = (screen_width - self.width())/2 30 | new_pos_y = (screen_height - self.height())/2 31 | 32 | self.move(new_pos_x,new_pos_y) 33 | 34 | @staticmethod 35 | def builddialog(widget): 36 | layout = qg.QVBoxLayout() 37 | layout.addWidget(widget) 38 | 39 | dialog = qg.QDialog() 40 | dialog.setLayout(layout) 41 | dialog.setModal(True) 42 | return dialog 43 | 44 | def action_uncheck(self, action_to_uncheck): 45 | action_to_uncheck.setChecked(False) 46 | 47 | class MainGui(WidgetBasic): 48 | def create_menu_system(self,filename): 49 | import yaml 50 | with open(filename) as f: 51 | self.menu_system = yaml.load(f,Loader=yaml.FullLoader) 52 | self.setMenuBar(qg.QMenuBar()) 53 | self.loaded_menu_systems=[] 54 | self.load_menu_system(self.menu_system) 55 | 56 | def load_menu_system(self,menu_system): 57 | self.loaded_menu_systems.append(menu_system) 58 | menu_system.build(self) 59 | menu_bar = self.menuBar() 60 | [menu_bar.addMenu(item) for item in menu_system.main_menu] 61 | [self.addToolBar(qc.Qt.TopToolBarArea, toolbar) for toolbar in menu_system.toolbars] 62 | 63 | 64 | -------------------------------------------------------------------------------- /popupcad_deprecated/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Jul 13 14:39:55 2016 4 | 5 | @author: daukes 6 | """ 7 | 8 | -------------------------------------------------------------------------------- /popupcad_deprecated/locateoperation3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt.QtCore as qc 9 | import qt.QtGui as qg 10 | from popupcad.filetypes.laminate import Laminate 11 | from popupcad.filetypes.operation2 import Operation2 12 | from popupcad.widgets.listmanager import SketchListManager 13 | import popupcad 14 | 15 | class Dialog(qg.QDialog): 16 | 17 | def __init__(self, cls, design, sketch=None): 18 | super(Dialog, self).__init__() 19 | self.design = design 20 | self.cls = cls 21 | 22 | self.sketchwidget = SketchListManager(self.design) 23 | for ii in range(self.sketchwidget.itemlist.count()): 24 | item = self.sketchwidget.itemlist.item(ii) 25 | if item.value == sketch: 26 | item.setSelected(True) 27 | 28 | button1 = qg.QPushButton('Ok') 29 | button2 = qg.QPushButton('Cancel') 30 | buttonlayout = qg.QHBoxLayout() 31 | buttonlayout.addWidget(button1) 32 | buttonlayout.addWidget(button2) 33 | 34 | layout = qg.QVBoxLayout() 35 | layout.addWidget(self.sketchwidget) 36 | layout.addLayout(buttonlayout) 37 | self.setLayout(layout) 38 | 39 | button1.clicked.connect(self.accept) 40 | button2.clicked.connect(self.reject) 41 | 42 | def sketch(self): 43 | try: 44 | return self.sketchwidget.itemlist.selectedItems()[0].value 45 | except IndexError: 46 | return None 47 | 48 | def acceptdata(self): 49 | sketch_links = {'sketch': [self.sketch().id]} 50 | return sketch_links, 51 | 52 | 53 | class LocateOperation3(Operation2): 54 | name = 'LocateOp' 55 | 56 | def copy(self): 57 | new = type(self)(self.sketch_links.copy()) 58 | new.id = self.id 59 | return new 60 | 61 | def __init__(self, *args): 62 | super(LocateOperation3, self).__init__() 63 | self.editdata(*args) 64 | self.id = id(self) 65 | 66 | def editdata(self, sketch_links): 67 | super(LocateOperation3, self).editdata({}, sketch_links, {}) 68 | 69 | @classmethod 70 | def buildnewdialog(cls, design, currentop): 71 | dialog = Dialog(cls, design) 72 | return dialog 73 | 74 | def buildeditdialog(self, design): 75 | sketchid = self.sketch_links['sketch'][0] 76 | sketch = design.sketches[sketchid] 77 | dialog = Dialog(self, design, sketch) 78 | return dialog 79 | 80 | def operate(self, design): 81 | sketchid = self.sketch_links['sketch'][0] 82 | sketch = design.sketches[sketchid] 83 | operationgeom = popupcad.algorithms.csg_shapely.unary_union_safe( 84 | [item.to_shapely() for item in sketch.operationgeometry]) 85 | lsout = Laminate(design.return_layer_definition()) 86 | for layer in design.return_layer_definition().layers: 87 | lsout.replacelayergeoms( 88 | layer, 89 | popupcad.algorithms.csg_shapely.condition_shapely_entities(operationgeom)) 90 | return lsout 91 | 92 | def locationgeometry(self): 93 | sketchid = self.sketch_links['sketch'][0] 94 | return sketchid 95 | -------------------------------------------------------------------------------- /popupcad_gazebo/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Written by Daniel M. Aukes and CONTRIBUTORS 5 | Email: danaukesasu.edu. 6 | Please see LICENSE for full license. 7 | """ 8 | 9 | from . import gazebo_controller 10 | 11 | #import external modules 12 | import PIL 13 | 14 | import array 15 | import lxml 16 | import multiprocessing 17 | import pygazebo 18 | import trollius 19 | import collada 20 | import stl 21 | 22 | from . import enhanced_grid 23 | from . import gradient 24 | from . import image 25 | from . import perlin_noise 26 | 27 | def initialize(program): 28 | projectactions =[] 29 | projectactions.append({'text': 'Run Simulation', 'kwargs': {'triggered': lambda:gazebo_controller.export(program)}}) 30 | projectactions.append({'text': 'Export DAE', 'kwargs': {'triggered': lambda:export_dae(program)}}) 31 | projectactions.append({'text': 'Export STL', 'kwargs': {'triggered': lambda:export_stl(program)}}) 32 | program.editor.addMenu(projectactions, name='Gazebo') 33 | 34 | def export_dae(program): 35 | editor = program.editor 36 | ii, jj = editor.operationeditor.currentIndeces2()[0] 37 | output = editor.design.operations[ii].output[jj] 38 | output.generic_laminate().toDAE() 39 | 40 | def export_stl(program): 41 | editor = program.editor 42 | ii, jj = editor.operationeditor.currentIndeces2()[0] 43 | output = editor.design.operations[ii].output[jj] 44 | output.generic_laminate().toSTL() 45 | -------------------------------------------------------------------------------- /popupcad_gazebo/gazebo_plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 2 | 3 | FIND_PACKAGE( Boost 1.40 COMPONENTS system REQUIRED ) 4 | set (CMAKE_CXX_FLAGS "-g -Wall") 5 | 6 | include (FindPkgConfig) 7 | if (PKG_CONFIG_FOUND) 8 | pkg_check_modules(GAZEBO gazebo) 9 | endif() 10 | include_directories( 11 | ${GAZEBO_INCLUDE_DIRS} 12 | ${CMAKE_CURRENT_BINARY_DIR}/msgs 13 | ) 14 | link_directories(${GAZEBO_LIBRARY_DIRS} ${SDF_LIBRARY_DIRS} msgs) 15 | add_subdirectory(msgs) 16 | 17 | add_library(model_vel SHARED model_vel.cc) 18 | target_link_libraries(model_vel velocity_msgs ${Boost_LIBRARIES} ${GAZEBO_LIBRARIES} ${SDF_LIBRARIES}) 19 | add_dependencies(model_vel velocity_msgs) 20 | -------------------------------------------------------------------------------- /popupcad_gazebo/gazebo_plugins/libmodel_vel.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad_gazebo/gazebo_plugins/libmodel_vel.so -------------------------------------------------------------------------------- /popupcad_gazebo/gazebo_plugins/model_vel.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include "velocity_message.pb.h" 9 | 10 | namespace gazebo 11 | { 12 | 13 | class ModelVel : public ModelPlugin 14 | { 15 | transport::NodePtr node; 16 | transport::PublisherPtr velPublisher; 17 | physics::WorldPtr world; 18 | 19 | 20 | public: void Load(physics::ModelPtr _parent, sdf::ElementPtr /*_sdf*/) 21 | { 22 | // Store the pointer to the model 23 | this->model = _parent; 24 | this->world = this->model->GetWorld(); 25 | node = transport::NodePtr(new transport::Node()); 26 | // Initialize the node with the world name 27 | node->Init(world->GetName()); 28 | velPublisher = node->Advertise("~/default_bot/velocity"); 29 | 30 | 31 | // Listen to the update event. This event is broadcast every 32 | // simulation iteration. 33 | this->updateConnection = event::Events::ConnectWorldUpdateBegin( 34 | boost::bind(&ModelVel::OnUpdate, this, _1)); 35 | } 36 | 37 | // Called by the world update start event 38 | public: void OnUpdate(const common::UpdateInfo & /*_info*/) 39 | { 40 | // Apply a small linear velocity to the model. 41 | //this->model->SetLinearVel(math::Vector3(.03, 0, 0)); 42 | //std::cout << this->model->GetWorldLinearVel(); 43 | model_velocity::msgs::ModelVel_V res_v; 44 | *res_v.mutable_time() = msgs::Convert(world->GetSimTime()); 45 | std::cout << world->GetSimTime() << " "; 46 | for (physics::Link_V::const_iterator iter = this->model->GetLinks().begin(); 47 | iter != this->model->GetLinks().end(); ++iter){ 48 | model_velocity::msgs::ModelVelResponse* res = res_v.add_linkage(); 49 | std::string name = (&*(*iter))->GetName(); 50 | std::cout << name << " "; 51 | *res->mutable_name() = name; 52 | msgs::Vector3d angv = msgs::Convert((&*(*iter))->GetWorldAngularVel()); 53 | std::cout << (&*(*iter))->GetWorldAngularVel() << " "; 54 | *res->mutable_angularvel() = angv; 55 | msgs::Vector3d angl = msgs::Convert((&*(*iter))->GetWorldLinearVel()); 56 | std::cout << (&*(*iter))->GetWorldLinearVel() << " "; 57 | *res->mutable_linearvel() = angl; 58 | } 59 | velPublisher->Publish(res_v); 60 | } 61 | 62 | // Pointer to the model 63 | private: physics::ModelPtr model; 64 | 65 | // Pointer to the update event connection 66 | private: event::ConnectionPtr updateConnection; 67 | }; 68 | 69 | // Register this plugin with the simulator 70 | GZ_REGISTER_MODEL_PLUGIN(ModelVel); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /popupcad_gazebo/gazebo_plugins/msgs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Protobuf REQUIRED) 2 | 3 | 4 | set(PROTOBUF_IMPORT_DIRS) 5 | foreach(ITR ${GAZEBO_INCLUDE_DIRS}) 6 | if(ITR MATCHES ".*gazebo-[0-9.]+$") 7 | set(PROTOBUF_IMPORT_DIRS "${ITR}/gazebo/msgs/proto") 8 | endif() 9 | endforeach() 10 | 11 | set (msgs 12 | velocity_message.proto 13 | ${PROTOBUF_IMPORT_DIRS}/vector3d.proto 14 | ${PROTOBUF_IMPORT_DIRS}/header.proto 15 | ${PROTOBUF_IMPORT_DIRS}/time.proto 16 | ) 17 | 18 | PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${msgs}) 19 | 20 | add_library(velocity_msgs SHARED ${PROTO_SRCS}) 21 | target_link_libraries(velocity_msgs ${PROTOBUF_LIBRARY}) 22 | -------------------------------------------------------------------------------- /popupcad_gazebo/gazebo_plugins/msgs/libvelocity_msgs.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/popupcad/code_popupcad/d3da448260cd5cb9e05417b0a723d7f73ae4e06e/popupcad_gazebo/gazebo_plugins/msgs/libvelocity_msgs.so -------------------------------------------------------------------------------- /popupcad_gazebo/gazebo_plugins/msgs/velocity_message.proto: -------------------------------------------------------------------------------- 1 | package model_velocity.msgs; 2 | import "vector3d.proto"; 3 | import "time.proto"; 4 | 5 | message ModelVel_V{ 6 | required gazebo.msgs.Time time = 1; 7 | repeated model_velocity.msgs.ModelVelResponse linkage = 2; 8 | } 9 | 10 | 11 | message ModelVelResponse 12 | { 13 | required string name = 1; 14 | required gazebo.msgs.Vector3d angularVel = 2; 15 | required gazebo.msgs.Vector3d linearVel = 3; 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /popupcad_gazebo/gradient.py: -------------------------------------------------------------------------------- 1 | ## @package gradient 2 | 3 | """ 4 | Written by Daniel M. Aukes and CONTRIBUTORS 5 | Email: danaukesasu.edu. 6 | Please see LICENSE for full license. 7 | """ 8 | 9 | # Functions for handling colour gradients. 10 | 11 | from math import floor 12 | from .enhanced_grid import Grid2D 13 | from .image import mix_color 14 | 15 | ## A gradient without any interpolation. 16 | class DiscreteGradient: 17 | def __init__(self, colors): 18 | self.colors = [] 19 | 20 | for color in colors: 21 | self.colors.append(color) 22 | 23 | self.color_count = len(colors) 24 | 25 | def get_color(self, t): #assumes 0 <= t < 1 26 | col_index = int(floor(t * self.color_count)) 27 | 28 | if (col_index >= self.color_count): 29 | col_index = self.color_count - 1 30 | 31 | return self.colors[col_index] 32 | 33 | ## A gradient between two colours with linear interpolation. 34 | class SimpleGradient: 35 | def __init__(self, color0, color1): 36 | self.color0 = color0 37 | self.color1 = color1 38 | 39 | def get_color(self, t): 40 | return mix_color(self.color0, self.color1, t) 41 | 42 | ## Maps a gradient to a grid, and returns the result as a new grid. 43 | # @grid A grid containing values in the range [0 1] 44 | def map_gradient(gradient, grid): 45 | color_grid = Grid2D(grid.dims) 46 | 47 | for index in grid.index_iter(): 48 | color_grid[index] = gradient.get_color(grid[index]) 49 | 50 | return color_grid 51 | -------------------------------------------------------------------------------- /popupcad_gazebo/terrain_generation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | ## @package perlin_demo 8 | # Illustrates some functions in the perlin_noise module. 9 | 10 | from __future__ import division 11 | from __future__ import with_statement 12 | 13 | from .perlin_noise import SmoothNoise, perlin_noise_from_smoothnoise 14 | from .gradient import SimpleGradient, map_gradient 15 | from .image import grid_to_greyscale_image 16 | from lxml import etree 17 | 18 | def generate_heightmap(filename, size = 129, octaves = 9, persistence = 0.5): 19 | w = h = size 20 | 21 | print('Making smooth noise...') 22 | s_noise = SmoothNoise(w, h) 23 | 24 | print('Making Perlin noise...') 25 | p_noise = perlin_noise_from_smoothnoise(w, h, octaves, persistence, s_noise, True) 26 | 27 | gradient = SimpleGradient((0, 0, 0, 0), (1, 1, 1, 1)) 28 | color_grid = map_gradient(gradient, p_noise) 29 | grid_to_greyscale_image(color_grid, filename + ".png") 30 | 31 | print('Done Generating Geoms') 32 | 33 | def generate_terrain(output_loc): 34 | #Generate the actual heightmap geometry 35 | geometry = etree.Element("geometry") 36 | height_map = etree.SubElement(geometry, "heightmap") 37 | generate_heightmap("terrain") 38 | etree.SubElement(height_map, "uri").text = "file://" + output_loc + "terrain.png" 39 | etree.SubElement(height_map, "pos").text = '0 0 0' 40 | etree.SubElement(height_map, "size").text = '129 129 5' 41 | 42 | #Generate the rest of the stuff we need 43 | model_root = etree.SubElement(world_root, "model", name='terrain') 44 | etree.SubElement(model_root, "static").text = "true" 45 | #etree.SubElement(model_root, "pose").text = "0 0 0 0 0 0" 46 | link_root = etree.SubElement(model_root, "link", name='hills') 47 | visual_root = etree.SubElement(link_root, "visual", name='visual') 48 | visual_root.insert(0, geometry) 49 | material = etree.SubElement(visual_root, "material") 50 | etree.SubElement(material, "ambient").text = "1 0 0 1" 51 | etree.SubElement(material, "diffuse").text = "1 0 0 1" 52 | 53 | collision_root = etree.SubElement(link_root, 'collision', name ='collision') 54 | from copy import deepcopy 55 | copy = deepcopy(geometry) 56 | collision_root.insert(0, copy) 57 | return model_root 58 | 59 | #Main 60 | if __name__ == "__main__": 61 | import os 62 | sdf_root = etree.Element("sdf", version='1.5') 63 | world_root = etree.SubElement(sdf_root, "world", name='world') 64 | world_root.append(generate_terrain(os.getcwd() + "/")) 65 | file_output = os.getcwd() + os.path.sep + "terrain" + ".world" 66 | f = open(file_output,"w") 67 | f.write(etree.tostring(sdf_root, pretty_print=True)) 68 | f.close() 69 | print("File saved") -------------------------------------------------------------------------------- /popupcad_gazebo/userinput.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | # -*- coding: utf-8 -*- 9 | """ 10 | Written by Aaron Gokaslan. 11 | Email: aaronGokaslangmail.com. 12 | Please see LICENSE.txt for full license. 13 | """ 14 | 15 | 16 | import qt.QtCore as qc 17 | import qt.QtGui as qg 18 | from popupcad.algorithms.python_syntax_formatter import PythonHighlighter 19 | 20 | class UserInputIDE(qg.QDialog): 21 | 22 | def __init__(self): 23 | super(UserInputIDE, self).__init__() 24 | self.te = qg.QTextEdit() 25 | # self.te.setEnabled(False) 26 | self.ok = qg.QPushButton('Compile and Run Simulation') 27 | self.loadbtn = qg.QPushButton('Load a script') 28 | self.loadbtn.pressed.connect(self.loadFile) 29 | self.savebtn = qg.QPushButton('Save current script') 30 | self.savebtn.pressed.connect(self.saveFile) 31 | self.ok.pressed.connect(self.accept) 32 | layout = qg.QVBoxLayout() 33 | top_bar = qg.QHBoxLayout() 34 | top_bar.addWidget(self.loadbtn) 35 | top_bar.addWidget(self.savebtn) 36 | layout.addLayout(top_bar) 37 | layout.addWidget(self.te) 38 | layout.addWidget(self.ok) 39 | self.setLayout(layout) 40 | PythonHighlighter(self.te.document()) 41 | 42 | def appendText(self, text): 43 | current = self.te.toPlainText() 44 | current += text + "\n" 45 | self.te.setText(current) 46 | 47 | def sizeHint(self): 48 | return qc.QSize(800,600) 49 | 50 | def loadFile(self): 51 | from os.path import expanduser 52 | home = expanduser("~") 53 | fname, _ = qg.QFileDialog.getOpenFileName(self, 'Open file', 54 | home) 55 | infile = open(fname, 'r') 56 | self.te.setPlainText(infile.read()) 57 | infile.close() 58 | 59 | def saveFile(self): 60 | from os.path import expanduser 61 | home = expanduser("~") 62 | fname, _ = qg.QFileDialog.getSaveFileName(self, 'Save file', 63 | home) 64 | infile = open(fname, 'w') 65 | infile.write(self.te.toPlainText()) 66 | infile.close() 67 | 68 | if __name__ == "__main__": 69 | import sys 70 | app = qg.QApplication(sys.argv) 71 | 72 | mw = UserInputIDE() 73 | mw.appendText('asdfasdfasdf\nasdfasdfasdfasdfasdfasdfasfd') 74 | mw.appendText('asdfasdfasdf') 75 | mw.appendText('asdfasdfasdf') 76 | mw.appendText('asdfasdfasdf') 77 | mw.te.setReadOnly(False) 78 | mw.te.document() 79 | mw.exec_() 80 | sys.exit(app.exec_()) 81 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from . import manufacturing 8 | 9 | #import external modules 10 | import numpy 11 | import shapely 12 | 13 | def build_menu_system(program): 14 | def new_sheet(): 15 | program.editor.newoperation(manufacturing.outersheet3.OuterSheet3) 16 | def new_web(): 17 | program.editor.newoperation(manufacturing.autoweb4.AutoWeb4) 18 | def new_scrap(): 19 | program.editor.newoperation(manufacturing.scrapoperation2.ScrapOperation2) 20 | def new_support(): 21 | program.editor.newoperation(manufacturing.supportcandidate4.SupportCandidate4) 22 | def new_custom_support(): 23 | program.editor.newoperation(manufacturing.customsupport4.CustomSupport4) 24 | def new_keepout(): 25 | program.editor.newoperation(manufacturing.keepout3.KeepOut3) 26 | def new_removability(): 27 | program.editor.newoperation(manufacturing.removability2.Removability2) 28 | def new_identify_bodies(): 29 | program.editor.newoperation(manufacturing.identifybodies2.IdentifyBodies2) 30 | def new_identify_rigid_bodies(): 31 | program.editor.newoperation(manufacturing.identifyrigidbodies2.IdentifyRigidBodies2) 32 | 33 | action_definitions = {} 34 | 35 | action_definitions['sheet']={'text': 'Sheet','icon': 'outersheet'} 36 | action_definitions['web']={'text': '&Web','icon': 'outerweb' } 37 | action_definitions['scrap']={'text': 'Scrap','icon': 'scrap'} 38 | 39 | action_definitions['support_action']={'text': 'S&upport','icon': 'autosupport'} 40 | action_definitions['custom_support']={'text': 'Custom Support','icon': 'customsupport'} 41 | 42 | action_definitions['keepout']={'text': 'Keep-out','icon': 'firstpass'} 43 | action_definitions['identify_rigid_bodies']={'text': 'Identify Rigid Bodies'} 44 | 45 | action_definitions['removability']={'text': 'Removability','icon': 'removability'} 46 | action_definitions['identify_bodies']={'text': 'Identify Bodies','icon': 'identifybodies'} 47 | 48 | 49 | toolbar_definitions={} 50 | toolbar_definitions['Scrap']={'text': 'Scrap', 'icon': 'scrap'} 51 | toolbar_definitions['Support']={'text': 'Support','icon': 'outerweb'} 52 | toolbar_definitions['Misc']={'text': 'Misc...','icon': 'dotdotdot'} 53 | 54 | menu_structure = {} 55 | menu_structure['manufacturing'] = ['Scrap','Support','identify_bodies','Misc'] 56 | menu_structure['top'] = ['manufacturing'] 57 | menu_structure['Scrap'] = ['sheet','web','scrap'] 58 | menu_structure['Support'] = ['support_action','custom_support'] 59 | menu_structure['Misc'] = ['keepout','identify_rigid_bodies','removability'] 60 | 61 | toolbar_structure = menu_structure.copy() 62 | shortcuts = {} 63 | 64 | triggered = {} 65 | triggered['sheet'] = new_sheet 66 | triggered['web'] = new_web 67 | triggered['scrap'] = new_scrap 68 | triggered['support_action'] = new_support 69 | triggered['custom_support'] = new_custom_support 70 | triggered['keepout'] = new_keepout 71 | triggered['identify_rigid_bodies'] = new_identify_rigid_bodies 72 | triggered['removability'] = new_removability 73 | triggered['identify_bodies'] = new_identify_bodies 74 | 75 | for key,value in triggered.items(): 76 | action_definitions[key]['triggered'] = value 77 | 78 | from popupcad.guis.actions import MenuSystem 79 | menu_system = MenuSystem(action_definitions,toolbar_definitions,menu_structure,toolbar_structure,shortcuts,'top') 80 | return menu_system 81 | 82 | def initialize(program): 83 | menu_system = build_menu_system(program) 84 | program.editor.load_menu_system(menu_system) 85 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | #import popupcad 8 | #import types 9 | #import sys 10 | 11 | #from . import manufacturingplugin 12 | from . import autoweb4 13 | from . import customsupport4 14 | #from . import cutop2 15 | #from . import autoweb3 16 | from . import identifybodies2 17 | #from . import identifybodies 18 | from . import identifyrigidbodies2 19 | from . import keepout3 20 | from . import outersheet3 21 | from . import removability2 22 | from . import scrapoperation2 23 | from . import supportcandidate4 24 | #from . import generatealignmentlayup 25 | #from . import tilepart 26 | #from . import identifyrigidbodies 27 | #from . import supportcandidate3 28 | #from . import toolclearance2 29 | #from . import toolclearance3 30 | #from . import keepout2 31 | #from . import outersheet2 32 | #from . import removability 33 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/autoweb4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 9 | from popupcad.filetypes.operationoutput import OperationOutput 10 | 11 | class AutoWeb4(MultiValueOperation3): 12 | name = 'Web' 13 | valuenames = ['Outer Buffer', 'Support Gap'] 14 | defaults = [0., 0.] 15 | 16 | def generate(self, design): 17 | operation_ref, output_index = self.operation_links['parent'][0] 18 | 19 | import popupcad 20 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 21 | 22 | if self.keepout_type == self.keepout_types.laser_keepout: 23 | keepout = popupcad.algorithms.keepout.laserkeepout(ls1) 24 | elif self.keepout_type == self.keepout_types.mill_keepout: 25 | keepout = popupcad.algorithms.keepout.millkeepout(ls1) 26 | elif self.keepout_type == self.keepout_types.mill_flip_keepout: 27 | keepout = popupcad.algorithms.keepout.millflipkeepout(ls1) 28 | 29 | sheet, outer_web, inner_elements, buffered_keepout = popupcad.algorithms.web.generate_web(ls1, keepout, design.return_layer_definition( 30 | ), (self.values[0] + self.values[1]) *popupcad.csg_processing_scaling, self.values[1] *popupcad.csg_processing_scaling) 31 | 32 | a = OperationOutput(outer_web, 'Web', self) 33 | b = OperationOutput(sheet, 'Sheet', self) 34 | c = OperationOutput(inner_elements, 'Inner Scrap', self) 35 | d = OperationOutput(buffered_keepout, 'Removed Material', self) 36 | self.output = [a, b, c, d] 37 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/identifybodies2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 9 | from popupcad.filetypes.operationoutput import OperationOutput 10 | import popupcad 11 | 12 | 13 | class IdentifyBodies2(MultiValueOperation3): 14 | name = 'Identify Bodies' 15 | show = [] 16 | valuenames = [] 17 | defaults = [] 18 | 19 | def generate(self, design): 20 | operation_ref, output_index = self.operation_links['parent'][0] 21 | operation_output = design.op_from_ref(operation_ref).output[output_index] 22 | generic = operation_output.generic_laminate() 23 | laminates = popupcad.algorithms.body_detection.find(generic) 24 | self.output = [] 25 | for ii, item in enumerate(laminates): 26 | self.output.append(OperationOutput(item,'Body {0:d}'.format(ii),self)) 27 | self.output.insert(0, self.output[0]) 28 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/identifyrigidbodies2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 9 | from popupcad.filetypes.operationoutput import OperationOutput 10 | import popupcad 11 | 12 | class IdentifyRigidBodies2(MultiValueOperation3): 13 | name = 'Identify Rigid Bodies' 14 | show = [] 15 | valuenames = [] 16 | defaults = [] 17 | 18 | def generate(self, design): 19 | operation_ref, output_index = self.operation_links['parent'][0] 20 | generic = design.op_from_ref( 21 | operation_ref).output[output_index].generic_laminate() 22 | layerdef = design.return_layer_definition() 23 | new_csg = popupcad.algorithms.manufacturing_functions.find_rigid(generic,layerdef) 24 | new_generic = new_csg.to_generic_laminate() 25 | laminates = popupcad.algorithms.body_detection.find(new_generic) 26 | self.output = [] 27 | for ii, item in enumerate([new_csg]+laminates): 28 | self.output.append(OperationOutput(item,'Rigid Body {0:d}'.format(ii),self)) 29 | 30 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/keepout3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 9 | #from popupcad.filetypes.operation import Operation 10 | 11 | 12 | class KeepOut3(MultiValueOperation3): 13 | name = 'Keep-out' 14 | valuenames = [] 15 | defaults = [] 16 | 17 | def operate(self, design): 18 | operation_ref, output_index = self.operation_links['parent'][0] 19 | import popupcad 20 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 21 | 22 | if self.keepout_type == self.keepout_types.laser_keepout: 23 | keepout = popupcad.algorithms.keepout.laserkeepout(ls1) 24 | elif self.keepout_type == self.keepout_types.mill_keepout: 25 | keepout = popupcad.algorithms.keepout.millkeepout(ls1) 26 | elif self.keepout_type == self.keepout_types.mill_flip_keepout: 27 | keepout = popupcad.algorithms.keepout.millflipkeepout(ls1) 28 | else: 29 | raise Exception 30 | return keepout 31 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/outersheet3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import popupcad 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | 11 | 12 | class OuterSheet3(MultiValueOperation3): 13 | name = 'Sheet' 14 | show = [] 15 | valuenames = ['Buffer'] 16 | defaults = [0.] 17 | 18 | def operate(self, design): 19 | operation_ref, output_index = self.operation_links['parent'][0] 20 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 21 | ls, dummy = popupcad.algorithms.web.supportsheet(design.return_layer_definition(), ls1, self.values[0] *popupcad.csg_processing_scaling) 22 | return ls 23 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/removability2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 9 | import dev_tools.enum as enum 10 | import popupcad 11 | 12 | class Removability2(MultiValueOperation3): 13 | name = 'Removability' 14 | valuenames = [] 15 | defaults = [] 16 | keepout_types = enum.enum( 17 | one_way_up='one_way_up', 18 | one_way_down='one_way_down', 19 | two_way='two_way') 20 | keepout_type_default = keepout_types.one_way_up 21 | 22 | def operate(self, design): 23 | operation_ref, output_index = self.operation_links['parent'][0] 24 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 25 | 26 | if self.keepout_type == self.keepout_types.one_way_up: 27 | keepout = popupcad.algorithms.removability.one_way_up(ls1) 28 | elif self.keepout_type == self.keepout_types.one_way_down: 29 | keepout = popupcad.algorithms.removability.one_way_down(ls1) 30 | elif self.keepout_type == self.keepout_types.two_way: 31 | keepout = popupcad.algorithms.removability.two_way(ls1) 32 | else: 33 | raise Exception 34 | return keepout 35 | -------------------------------------------------------------------------------- /popupcad_manufacturing_plugins/manufacturing/supportcandidate4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | 9 | from popupcad.manufacturing.multivalueoperation3 import MultiValueOperation3 10 | from popupcad.filetypes.operationoutput import OperationOutput 11 | 12 | class SupportCandidate4(MultiValueOperation3): 13 | name = 'Support' 14 | valuenames = ['Support Gap', 'Keep-out Distance'] 15 | defaults = [0., 0.] 16 | 17 | def generate(self, design): 18 | operation_ref, output_index = self.operation_links['parent'][0] 19 | import popupcad 20 | ls1 = design.op_from_ref(operation_ref).output[output_index].csg 21 | 22 | if self.keepout_type == self.keepout_types.laser_keepout: 23 | keepout = popupcad.algorithms.keepout.laserkeepout(ls1) 24 | elif self.keepout_type == self.keepout_types.mill_keepout: 25 | keepout = popupcad.algorithms.keepout.millkeepout(ls1) 26 | elif self.keepout_type == self.keepout_types.mill_flip_keepout: 27 | keepout = popupcad.algorithms.keepout.millflipkeepout(ls1) 28 | else: 29 | raise Exception 30 | 31 | support, k3 = popupcad.algorithms.web.autosupport(ls1, keepout, design.return_layer_definition(), self.values[ 32 | 0] *popupcad.csg_processing_scaling, self.values[1] *popupcad.csg_processing_scaling, 1e-5 *popupcad.csg_processing_scaling) 33 | a = OperationOutput(support, 'support', self) 34 | b = OperationOutput(keepout, 'cut line', self) 35 | c = OperationOutput(k3, 'cut area', self) 36 | self.output = [a, a, b, c] 37 | -------------------------------------------------------------------------------- /popupcad_microrobotics/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | from . import generatealignmentlayup 8 | from . import tilepart 9 | 10 | #import external modules 11 | import numpy 12 | import shapely 13 | 14 | def build_menu_system(program): 15 | def new_alignment_layup(): 16 | program.editor.newoperation(generatealignmentlayup.AlignmentLayup) 17 | def new_tile_part(): 18 | program.editor.newoperation(tilepart.TilePart) 19 | 20 | action_definitions = {} 21 | action_definitions['alignment_layup']={'text': 'Alignment layup','icon': 'identifybodies'} 22 | action_definitions['tile_part']={'text': 'Tile parts','icon': 'identifybodies'} 23 | 24 | toolbar_definitions={} 25 | toolbar_definitions['Microrobotics']={'text': 'Microrobotics','icon': 'dotdotdot'} 26 | 27 | menu_structure = {} 28 | menu_structure['top'] = ['Microrobotics'] 29 | menu_structure['Microrobotics'] = ['alignment_layup', 'tile_part'] 30 | 31 | toolbar_structure = menu_structure.copy() 32 | shortcuts = {} 33 | 34 | triggered = {} 35 | triggered['alignment_layup'] = new_alignment_layup 36 | triggered['tile_part'] = new_tile_part 37 | 38 | for key,value in triggered.items(): 39 | action_definitions[key]['triggered'] = value 40 | 41 | from popupcad.guis.actions import MenuSystem 42 | menu_system = MenuSystem(action_definitions,toolbar_definitions,menu_structure,toolbar_structure,shortcuts,'top') 43 | return menu_system 44 | 45 | def initialize(program): 46 | menu_system = build_menu_system(program) 47 | program.editor.load_menu_system(menu_system) 48 | -------------------------------------------------------------------------------- /popupcad_tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | -------------------------------------------------------------------------------- /popupcad_tests/load_test_files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | import sys 8 | import os 9 | import popupcad 10 | import time 11 | import glob 12 | import time 13 | #import qt.QtCore as qc 14 | #import qt.QtGui as qg 15 | 16 | 17 | if __name__=='__main__': 18 | # app = qg.QApplication([sys.argv[0]]) 19 | t_0 = time.time() 20 | top_directory = popupcad.test_file_dir 21 | filenames = [] 22 | for directory,subdirectory,files in os.walk(top_directory): 23 | filenames.extend(glob.glob(directory+'/*.cad')) 24 | print(filenames) 25 | 26 | failed = [] 27 | passed = [] 28 | 29 | for filename in filenames: 30 | # print(filename) 31 | full_filename = os.path.normpath(os.path.join(directory,filename)) 32 | try: 33 | print(full_filename) 34 | d = popupcad.filetypes.design.Design.load_yaml(full_filename) 35 | d.reprocessoperations() 36 | passed.append(full_filename) 37 | except: 38 | failed.append(full_filename) 39 | 40 | t_final = time.time() 41 | t_total = t_final - t_0 42 | 43 | print('passed: '+str(passed)) 44 | print('failed: '+str(failed)) 45 | 46 | if len(failed)>0: 47 | raise(Exception('some files failed to load.')) 48 | -------------------------------------------------------------------------------- /popupcad_tests/test_gui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sys 9 | import os 10 | packages_path = ['.'] 11 | packages_path = [os.path.normpath(os.path.abspath(item)) for item in packages_path] 12 | sys.path.extend(packages_path) 13 | print(packages_path) 14 | [print(os.listdir(item)) for item in packages_path] 15 | 16 | import qt.QtCore as qc 17 | import qt.QtGui as qg 18 | 19 | #must import sympy before pyqtgraph 20 | import sympy 21 | #must import pyqtgraph before creating app 22 | import pyqtgraph 23 | 24 | app = qg.QApplication([sys.argv[0]]) 25 | import popupcad 26 | program = popupcad.filetypes.program.Program(app, *sys.argv) 27 | program.editor.destroy() 28 | #app.quit() 29 | #sys.exit() -------------------------------------------------------------------------------- /qt/QtCore.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt 9 | 10 | if qt.loaded == 'PyQt4': 11 | from PyQt4.QtCore import * 12 | from PyQt4.QtCore import Qt 13 | from PyQt4.QtCore import pyqtSignal as Signal 14 | 15 | elif qt.loaded == 'PyQt5': 16 | from PyQt5.QtCore import * 17 | from PyQt5.QtCore import Qt 18 | from PyQt5.QtCore import pyqtSignal as Signal 19 | 20 | elif qt.loaded == 'PySide': 21 | import PySide.QtCore 22 | from PySide.QtCore import * -------------------------------------------------------------------------------- /qt/QtGui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt 9 | 10 | if qt.loaded == 'PyQt4': 11 | from PyQt4.QtGui import * 12 | 13 | elif qt.loaded == 'PyQt5': 14 | from PyQt5.QtGui import * 15 | from PyQt5.QtWidgets import * 16 | 17 | elif qt.loaded == 'PySide': 18 | from PySide.QtGui import * 19 | -------------------------------------------------------------------------------- /qt/QtSvg.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import qt 9 | 10 | if qt.loaded == 'PyQt4': 11 | from PyQt4.QtSvg import * 12 | 13 | elif qt.loaded == 'PyQt5': 14 | from PyQt5.QtSvg import * 15 | 16 | elif qt.loaded == 'PySide': 17 | from PySide.QtSvg import * 18 | -------------------------------------------------------------------------------- /qt/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | import sys 9 | argv = [item.lower() for item in sys.argv] 10 | 11 | if 'qt4' in argv: 12 | loaded = 'PyQt4' 13 | 14 | elif 'qt5' in argv: 15 | loaded = 'PyQt5' 16 | 17 | elif 'pyside' in argv: 18 | loaded = 'PySide' 19 | 20 | else: 21 | loaded = 'PyQt5' 22 | -------------------------------------------------------------------------------- /qt/qt_hacks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | def to_tuple(item): 9 | return (item.x(),item.y()) 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Written by Daniel M. Aukes and CONTRIBUTORS 4 | Email: danaukesasu.edu. 5 | Please see LICENSE for full license. 6 | """ 7 | 8 | from distutils.core import setup 9 | import popupcad 10 | 11 | packages = [] 12 | 13 | packages.append('dev_tools') 14 | 15 | packages.append('api_examples') 16 | 17 | packages.append('popupcad') 18 | packages.append('popupcad.algorithms') 19 | packages.append('popupcad.constraints') 20 | packages.append('popupcad.filetypes') 21 | packages.append('popupcad.geometry') 22 | packages.append('popupcad.graphics2d') 23 | packages.append('popupcad.graphics3d') 24 | packages.append('popupcad.guis') 25 | packages.append('popupcad.manufacturing') 26 | packages.append('popupcad.materials') 27 | packages.append('popupcad.widgets') 28 | 29 | packages.append('popupcad_deprecated') 30 | 31 | packages.append('popupcad_manufacturing_plugins') 32 | packages.append('popupcad_manufacturing_plugins.manufacturing') 33 | 34 | packages.append('popupcad_microrobotics') 35 | 36 | packages.append('popupcad_tests') 37 | 38 | packages.append('qt') 39 | 40 | #packages.append('popupcad_manufacturing_plugins.manufacturing') 41 | #packages.append('pypoly2tri') 42 | 43 | package_data = {} 44 | package_data['popupcad'] = ['supportfiles/*','supportfiles/icons/*','supportfiles/test_files/*'] 45 | 46 | setup(name=popupcad.program_name, 47 | version=popupcad.version, 48 | classifiers=popupcad.classifiers, 49 | description=popupcad.description, 50 | author=popupcad.author, 51 | author_email=popupcad.author_email, 52 | url=popupcad.url, 53 | packages=packages, 54 | package_data=package_data 55 | ) 56 | --------------------------------------------------------------------------------