├── .gitattributes ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── C ├── COPYING ├── Generic ├── Kernel │ ├── Command │ │ ├── __init__.py │ │ ├── arccommand.py │ │ ├── basecommand.py │ │ ├── bisectorcommand.py │ │ ├── ccirclecommand.py │ │ ├── chamfercommand.py │ │ ├── clinecommand.py │ │ ├── copycommand.py │ │ ├── deletecommand.py │ │ ├── ellipsecommand.py │ │ ├── filletcommand.py │ │ ├── mirrorcommand.py │ │ ├── movecommand.py │ │ ├── pointcommand.py │ │ ├── polygoncommand.py │ │ ├── polylinecommand.py │ │ ├── rectanglecommand.py │ │ ├── rotatecommand.py │ │ ├── segmentcommand.py │ │ ├── textcommand.py │ │ └── trimcommand.py │ ├── Db │ │ ├── __init__.py │ │ ├── basedb.py │ │ ├── entitydb.py │ │ ├── pycadobject.py │ │ ├── relationdb.py │ │ └── undodb.py │ ├── ExternalFormat │ │ ├── Dxf │ │ │ ├── __init__.py │ │ │ └── dxf.py │ │ ├── __init__.py │ │ └── externalformat.py │ ├── GeoComposedEntity │ │ ├── __init__.py │ │ ├── bisector.py │ │ ├── chamfer.py │ │ ├── fillet.py │ │ └── objoint.py │ ├── GeoEntity │ │ ├── __init__.py │ │ ├── arc.py │ │ ├── ccircle.py │ │ ├── cline.py │ │ ├── dimension.py │ │ ├── ellipse.py │ │ ├── entityutil.py │ │ ├── geometricalentity.py │ │ ├── hatch.py │ │ ├── nurbs.py │ │ ├── point.py │ │ ├── polyline.py │ │ ├── segment.py │ │ ├── style.py │ │ └── text.py │ ├── GeoUtil │ │ ├── __init__.py │ │ ├── geolib.py │ │ ├── intersection.py │ │ ├── rotate.py │ │ ├── tangent.py │ │ ├── tolerance.py │ │ └── util.py │ ├── __init__.py │ ├── binarytree.py │ ├── composedentity.py │ ├── document.py │ ├── entity.py │ ├── exception.py │ ├── initsetting.py │ ├── layer.py │ ├── layertree.py │ ├── pycadevent.py │ ├── pycadtransaction.py │ ├── settings.py │ └── unitparser.py ├── __init__.py └── application.py ├── INSTALL ├── INSTALL.md ├── Interface ├── .gitignore ├── CmdIntf │ ├── __init__.py │ ├── cmdaction.py │ ├── cmdcategory.py │ ├── cmdintf.py │ ├── cmdlinedock.py │ └── functionhandler.py ├── Command │ ├── __init__.py │ ├── distance2point.py │ └── icommand.py ├── Entity │ ├── __init__.py │ ├── actionhandler.py │ ├── arc.py │ ├── arrowitem.py │ ├── base.py │ ├── ellipse.py │ ├── point.py │ ├── polyline.py │ ├── segment.py │ └── text.py ├── LayerIntf │ ├── __init__.py │ ├── layerdock.py │ ├── layeritem.py │ └── layermodel.py ├── Preview │ ├── __init__.py │ ├── arc.py │ ├── base.py │ ├── ellipse.py │ ├── factory.py │ ├── polygon.py │ ├── polyline.py │ ├── rectangle.py │ └── segment.py ├── __init__.py ├── caddialogs.py ├── cadinitsetting.py ├── cadscene.py ├── cadview.py ├── cadwindow.py ├── cadwindow.qrc ├── cadwindow_rc.py ├── dinamicentryobject.py ├── evaluator.py ├── idocument.py └── pycadapp.py ├── MANIFEST.in ├── NEWS ├── NEWS.md ├── README ├── README.md ├── __init__.py ├── customevent.py ├── icons ├── ICONS_PythonCAD_version_15_06_2010.svg ├── PythonCAD_logo.png ├── PythoncadLogo.png ├── SForceDir.png ├── SGrid.png ├── SSnap.png ├── arc.png ├── bisect.png ├── centersnap.png ├── chamfer.png ├── clipboardCopy.png ├── clipboardPaste.png ├── clipboardcut.png ├── copy.png ├── delete.png ├── ellipse.png ├── endsnap.png ├── fillet.png ├── gtkpycad.png ├── gtkpycadnew.png ├── middlesnap.png ├── mirror.png ├── move.png ├── new.png ├── nurbs.png ├── open.png ├── ortosnap.png ├── polygon.png ├── polyline.png ├── print.png ├── pythoncad-logo-inkscape.svg ├── pythoncad.ico ├── pythoncad.png ├── quadrantsnap.png ├── rectangle.png ├── redo.png ├── rotate.png ├── save.png ├── segment.png ├── splashScreen1.png ├── splashScreen2.png ├── tangentsnap.png ├── trim.png └── undo.png ├── pythoncad_qt.py ├── test_application.py ├── test_kernel.py └── test_sympy.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | name: "CodeQL" 7 | 8 | on: 9 | push: 10 | branches: [master] 11 | pull_request: 12 | # The branches below must be a subset of the branches above 13 | branches: [master] 14 | schedule: 15 | - cron: '0 12 * * 3' 16 | 17 | jobs: 18 | analyze: 19 | name: Analyze 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | # Override automatic language detection by changing the below list 26 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 27 | language: ['python'] 28 | # Learn more... 29 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v2 34 | with: 35 | # We must fetch at least the immediate parents so that if this is 36 | # a pull request then we can checkout the head. 37 | fetch-depth: 2 38 | 39 | # If this run was triggered by a pull request event, then checkout 40 | # the head of the pull request instead of the merge commit. 41 | - run: git checkout HEAD^2 42 | if: ${{ github.event_name == 'pull_request' }} 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # Binary file with the database(?) 6 | C 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | 45 | # Translations 46 | *.mo 47 | *.pot 48 | 49 | # Django stuff: 50 | *.log 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | # PyBuilder 56 | target/ 57 | 58 | # ========================= 59 | # Operating System Files 60 | # ========================= 61 | 62 | # OSX 63 | # ========================= 64 | 65 | .DS_Store 66 | .AppleDouble 67 | .LSOverride 68 | 69 | # Icon must end with two \r 70 | Icon 71 | 72 | 73 | # Thumbnails 74 | ._* 75 | 76 | # Files that might appear on external disk 77 | .Spotlight-V100 78 | .Trashes 79 | 80 | # Directories potentially created on remote AFP share 81 | .AppleDB 82 | .AppleDesktop 83 | Network Trash Folder 84 | Temporary Items 85 | .apdisk 86 | 87 | # Windows 88 | # ========================= 89 | 90 | # Windows image file caches 91 | Thumbs.db 92 | ehthumbs.db 93 | 94 | # Folder config file 95 | Desktop.ini 96 | 97 | # Recycle Bin used on file shares 98 | $RECYCLE.BIN/ 99 | 100 | # Windows Installer files 101 | *.cab 102 | *.msi 103 | *.msm 104 | *.msp 105 | -------------------------------------------------------------------------------- /C: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/C -------------------------------------------------------------------------------- /Generic/Kernel/Command/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | 5 | # 6 | # this file is needed for Python's import mechanism 7 | # 8 | from GeoEntity.arc import Arc 9 | from GeoEntity.cline import CLine 10 | from GeoEntity.ellipse import Ellipse 11 | from GeoEntity.ccircle import CCircle 12 | from GeoEntity.polyline import Polyline 13 | from GeoEntity.segment import Segment 14 | from GeoEntity.text import Text 15 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/arccommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the arc command 22 | # 23 | import math 24 | 25 | from exception import * 26 | from Command.basecommand import * 27 | from GeoEntity.arc import Arc 28 | 29 | class ArcCommand(BaseCommand): 30 | """ 31 | this class rappresent the arc command 32 | """ 33 | def __init__(self, document): 34 | BaseCommand.__init__(self, document) 35 | self.exception = [ExcPoint, ExcLenght, ExcAngle, ExcAngle] 36 | self.defaultValue =[None, 10, 0, math.pi * 2] 37 | self.message = ["Give Me the center Point", 38 | "Give Me the radius", 39 | "Give Me the start Angle (Could Be None)", 40 | "Give Me the span Angle (Could Be None)"] 41 | 42 | def applyCommand(self): 43 | if len(self.value) < 2: 44 | raise PyCadWrongImputData("Wrong number of imput parameter") 45 | self.applyDefault() 46 | arg = {"ARC_0": self.value[0], 47 | "ARC_1": self.value[1], 48 | "ARC_2": self.value[2], 49 | "ARC_3": self.value[3] 50 | } 51 | arc = Arc(arg) 52 | self.document.saveEntity(arc) 53 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/bisectorcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the bisector command 22 | # 23 | from exception import * 24 | from composedentity import ComposedEntity 25 | from Command.basecommand import * 26 | from GeoComposedEntity.bisector import Bisector 27 | from GeoEntity.segment import Segment 28 | from GeoUtil.util import getIdPoint 29 | 30 | class BisectorCommand(BaseCommand): 31 | """ 32 | this class rappresent the champfer command 33 | """ 34 | def __init__(self, document): 35 | BaseCommand.__init__(self, document) 36 | self.exception = [ExcEntityPoint, 37 | ExcEntityPoint, 38 | ExcLenght, 39 | ] 40 | self.defaultValue = [None, None, 100] 41 | self.message = ["Select the First entity or give me a the keyword Text As: (4@10,20)", 42 | "Select the Second entity or give me a the keyword Text As: (4@10,20)", 43 | "Give me the bisector lengh"] 44 | 45 | def getEntsToSave(self): 46 | """ 47 | get the chamfer segments 48 | """ 49 | id0, p0 = self.value[0] 50 | id1, p1 = self.value[1] 51 | objEnt = [] 52 | ent1 = self.document.getEntity(id0) 53 | ent2 = self.document.getEntity(id1) 54 | 55 | cel1 = ent1.getConstructionElements() 56 | seg1 = Segment(cel1) 57 | 58 | cel2 = ent2.getConstructionElements() 59 | seg2 = Segment(cel2) 60 | arg = { 61 | "OBJECTJOINT_0": seg1, 62 | "OBJECTJOINT_1": seg2, 63 | "OBJECTJOINT_2": p0, 64 | "OBJECTJOINT_3": p1, 65 | "OBJECTJOINT_5": self.value[2], 66 | } 67 | 68 | cmf = Bisector(arg) 69 | bisectorSegment = cmf.getReletedComponent() 70 | objEnt.append(bisectorSegment) 71 | return objEnt 72 | 73 | def applyCommand(self): 74 | """ 75 | apply the champfer command 76 | """ 77 | if len(self.value) != 3: 78 | raise PyCadWrongImputData("Wrong number of imput parameter") 79 | for _ent in self.getEntsToSave(): 80 | self.document.saveEntity(_ent) 81 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/ccirclecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the arc command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.ccircle import CCircle 26 | 27 | class CCircleCommand(BaseCommand): 28 | """ 29 | this class rappresent the arc command 30 | """ 31 | def __init__(self, document): 32 | BaseCommand.__init__(self, document) 33 | self.exception = [ExcPoint, ExcLenght] 34 | self.defaultValue = [None, 10] 35 | self.message = ["Give Me the center Point", "Give Me the radius"] 36 | 37 | def applyCommand(self): 38 | if len(self.value) < 2: 39 | raise PyCadWrongImputData("Wrong number of imput parameter") 40 | arg = { 41 | "CCIRCLE_0": self.value[0], 42 | "CCIRCLE_1": self.value[1] 43 | } 44 | ccircle = CCircle(arg) 45 | self.document.saveEntity(ccircle) 46 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/chamfercommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the champfer command 22 | # 23 | from exception import * 24 | from composedentity import ComposedEntity 25 | from Command.basecommand import * 26 | from GeoComposedEntity.chamfer import Chamfer 27 | from GeoEntity.segment import Segment 28 | from GeoUtil.util import getIdPoint 29 | 30 | class ChamferCommand(BaseCommand): 31 | """ 32 | this class rappresent the champfer command 33 | """ 34 | def __init__(self, document): 35 | BaseCommand.__init__(self, document) 36 | self.exception = [ExcEntityPoint, 37 | ExcEntityPoint, 38 | ExcText , 39 | ExcLenght, 40 | ExcLenght 41 | ] 42 | self.defaultValue = [None, None, "BOTH", 10, 10] 43 | self.message = [ "Select the First entity or give me a the keyword Text As: (4@10,20)", 44 | "Select the Second entity or give me a the keyword Text As: (4@10,20)", 45 | "Give me trim Mode (FIRST,SECOND,BOTH,NO_TRIM)", 46 | "Give me the first Lenght", 47 | "Give me the second Lenght", 48 | ] 49 | 50 | def getEntsToSave(self): 51 | """ 52 | get the chamfer segments 53 | """ 54 | id0, p0 = self.value[0] 55 | id1, p1 = self.value[1] 56 | 57 | objEnt = [] 58 | ent1 = self.document.getEntity(id0) 59 | ent2 = self.document.getEntity(id1) 60 | 61 | cel1 = ent1.getConstructionElements() 62 | seg1 = Segment(cel1) 63 | 64 | cel2 = ent2.getConstructionElements() 65 | seg2 = Segment(cel2) 66 | arg = { 67 | "OBJECTJOINT_0": seg1, 68 | "OBJECTJOINT_1": seg2, 69 | "OBJECTJOINT_2": p0, 70 | "OBJECTJOINT_3": p1, 71 | "OBJECTJOINT_4": self.value[2], 72 | "OBJECTJOINT_5": self.value[3], 73 | "OBJECTJOINT_6": self.value[4] 74 | } 75 | 76 | cmf = Chamfer(arg) 77 | seg1Mod, seg2Mod, chamferSegment = cmf.getReletedComponent() 78 | 79 | _cElements1, entityType = self.document._getCelements(seg1Mod) 80 | _cElements2, entityType = self.document._getCelements(seg2Mod) 81 | 82 | ent1.setConstructionElements(_cElements1) 83 | ent2.setConstructionElements(_cElements2) 84 | 85 | objEnt.append(ent1) 86 | objEnt.append(ent2) 87 | objEnt.append(chamferSegment) 88 | return objEnt 89 | 90 | def applyCommand(self): 91 | """ 92 | apply the champfer command 93 | """ 94 | if len(self.value) != 5: 95 | raise PyCadWrongImputData("Wrong number of imput parameter") 96 | 97 | try: 98 | self.document.startMassiveCreation() 99 | for _ent in self.getEntsToSave(): 100 | self.document.saveEntity(_ent) 101 | finally: 102 | self.document.stopMassiveCreation() 103 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/clinecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the segment command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.cline import CLine 26 | 27 | class CLineCommand(BaseCommand): 28 | """ 29 | this class rappresent the segment command 30 | """ 31 | def __init__(self, document): 32 | BaseCommand.__init__(self, document) 33 | self.exception = [ExcPoint, ExcPoint] 34 | self.message = ["Give Me the first Point", "Give Me the first Point"] 35 | 36 | def applyCommand(self): 37 | if len(self.value) != 2: 38 | raise PyCadWrongImputData("Wrong number of imput parameter") 39 | arg = {"CLINE_0": self.value[0], "CLINE_0": self.value[1]} 40 | cline = CLine(arg) 41 | self.document.saveEntity(cline) 42 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/copycommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the move command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.arc import Arc 26 | 27 | class CopyCommand(BaseCommand): 28 | """ 29 | this class rappresent the Move command 30 | """ 31 | def __init__(self, document): 32 | BaseCommand.__init__(self, document) 33 | self.exception = [ExcMultiEntity, 34 | ExcPoint, 35 | ExcPoint] 36 | self.defaultValue = [None, None, None] 37 | self.message = ["Select the entity to copy [or give me a the keyword Text As: (10,20,30,...)]", 38 | "Give me the base point", 39 | "Give me the destination point"] 40 | 41 | def getEntsToSave(self): 42 | """ 43 | get entity to save 44 | """ 45 | updEnts = [] 46 | for id in str(self.value[0]).split(','): 47 | dbEnt = self.document.getEntity(id) 48 | geoEnt = self.document.convertToGeometricalEntity(dbEnt) 49 | geoEnt.move(self.value[1], self.value[2]) 50 | updEnts.append(geoEnt) 51 | return updEnts 52 | 53 | def applyCommand(self): 54 | """ 55 | apply the champfer command 56 | """ 57 | if len(self.value) != 3: 58 | raise PyCadWrongImputData("Wrong number of imput parameter") 59 | try: 60 | self.document.startMassiveCreation() 61 | for _ent in self.getEntsToSave(): 62 | self.document.saveEntity(_ent) 63 | finally: 64 | self.document.stopMassiveCreation() 65 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/deletecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the Trim command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity import * 26 | from GeoUtil.intersection import * 27 | from GeoUtil.util import * 28 | 29 | class DeleteCommand(BaseCommand): 30 | """ 31 | this class rappresent the Trim command 32 | """ 33 | def __init__(self, document): 34 | BaseCommand.__init__(self, document) 35 | self.exception = [ExcMultiEntity] 36 | self.message = ["Select the entity to delete or give me a the keyword Text As: (10,20,30,..)"] 37 | 38 | def applyDefault(self): 39 | """ 40 | aver written to avoid apply default in this command 41 | """ 42 | return 43 | 44 | def applyCommand(self): 45 | """ 46 | apply the champfer command 47 | """ 48 | if len(self.value) != 1: 49 | raise PyCadWrongImputData("Wrong number of imput parameter") 50 | try: 51 | self.document.startMassiveCreation() 52 | for id in str(self.value[0]).split(','): 53 | self.document.deleteEntity(id) 54 | finally: 55 | self.document.stopMassiveCreation() 56 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/ellipsecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the ellipse command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.ellipse import Ellipse 26 | 27 | class EllipseCommand(BaseCommand): 28 | """ 29 | this class rappresent the ellips command 30 | """ 31 | def __init__(self, document): 32 | BaseCommand.__init__(self, document) 33 | self.exception = [ExcPoint, ExcLenght, ExcLenght] 34 | self.defaultValue = [None, 100, 50] 35 | self.message = ["Give Me the center Point", "Give Me the horizontal radius", "Give Me the vertical radius"] 36 | 37 | def applyCommand(self): 38 | if len(self.value) > 3: 39 | raise PyCadWrongImputData("Wrong number of imput parameter") 40 | arg = {"ELLIPSE_0": self.value[0], "ELLIPSE_1": self.value[1], "ELLIPSE_2": self.value[2]} 41 | ellipse = Ellipse(arg) 42 | self.document.saveEntity(ellipse) 43 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/filletcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the fillet command 22 | # 23 | from exception import * 24 | from composedentity import ComposedEntity 25 | from Command.basecommand import * 26 | from GeoComposedEntity.fillet import Fillet 27 | from GeoEntity.segment import Segment 28 | from GeoUtil.util import getIdPoint 29 | 30 | class FilletCommand(BaseCommand): 31 | """ 32 | this class rappresent the champfer command 33 | """ 34 | def __init__(self, document): 35 | BaseCommand.__init__(self, document) 36 | self.exception = [ExcEntityPoint, 37 | ExcEntityPoint, 38 | ExcText, 39 | ExcLenght] 40 | self.defaultValue = [None, None, "BOTH", 10] 41 | self.message = [ "Select the First entity or give me a the keyword Text As: (4@10,20)", 42 | "Select the Second entity or give me a the keyword Text As: (4@10,20)", 43 | "Give me trim Mode (FIRST,SECOND,BOTH,NO_TRIM)", 44 | "Give me the radius " 45 | ] 46 | 47 | def getEntsToSave(self): 48 | """ 49 | get the fillet segments 50 | """ 51 | id0, p0 = self.value[0] 52 | id1, p1 = self.value[1] 53 | 54 | objEnt = [] 55 | ent1 = self.document.getEntity(id0) 56 | ent2 = self.document.getEntity(id1) 57 | 58 | cel1 = ent1.getConstructionElements() 59 | seg1 = Segment(cel1) 60 | 61 | cel2 = ent2.getConstructionElements() 62 | seg2 = Segment(cel2) 63 | arg = { 64 | "OBJECTJOINT_0": seg1, 65 | "OBJECTJOINT_1": seg2, 66 | "OBJECTJOINT_2": p0, 67 | "OBJECTJOINT_3": p1, 68 | "OBJECTJOINT_4": self.value[2], 69 | "OBJECTJOINT_5": self.value[3] 70 | } 71 | 72 | fillet = Fillet(arg) 73 | seg1Mod, seg2Mod, filletArc = fillet.getReletedComponent() 74 | 75 | _cElements1, entityType = self.document._getCelements(seg1Mod) 76 | _cElements2, entityType = self.document._getCelements(seg2Mod) 77 | 78 | ent1.setConstructionElements(_cElements1) 79 | ent2.setConstructionElements(_cElements2) 80 | 81 | objEnt.append(ent1) 82 | objEnt.append(ent2) 83 | 84 | objEnt.append(filletArc) 85 | return objEnt 86 | 87 | def applyCommand(self): 88 | """ 89 | apply the champfer command 90 | """ 91 | if len(self.value) != 4: 92 | raise PyCadWrongImputData("Wrong number of imput parameter") 93 | try: 94 | self.document.startMassiveCreation() 95 | for _ent in self.getEntsToSave(): 96 | self.document.saveEntity(_ent) 97 | finally: 98 | self.document.stopMassiveCreation() 99 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/mirrorcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the polyline command 22 | # 23 | 24 | from exception import * 25 | from Command.basecommand import * 26 | from GeoEntity.point import Point 27 | 28 | class MirrorCommand(BaseCommand): 29 | """ 30 | This class rappresent the mirror command 31 | """ 32 | def __init__(self, document): 33 | BaseCommand.__init__(self, document) 34 | self.exception = [ExcMultiEntity, 35 | ExcEntity, 36 | ExcText] 37 | self.defaultValue = [None, None, "C"] 38 | self.message = ["Select the entity to mirror or give me a the keyword Text As: (10,20,30,...)", 39 | "Select the reference line ", 40 | "Give me the Mode (M or None ->Move,C ->Copy)"] 41 | 42 | def performMirror(self): 43 | """ 44 | perform the mirror of all the entity selected 45 | """ 46 | move = True 47 | if self.value[2]: 48 | if self.value[2] == 'C': 49 | move = False 50 | mirrorRef = self.document.getEntity(self.value[1]) 51 | geoMirrorRef = self.document.convertToGeometricalEntity(mirrorRef) 52 | updEnts = [] 53 | for id in str(self.value[0]).split(','): 54 | dbEnt = self.document.getEntity(id) 55 | geoEnt = self.document.convertToGeometricalEntity(dbEnt) 56 | geoEnt.mirror(geoMirrorRef) 57 | if move: 58 | dbEnt.setConstructionElements(geoEnt.getConstructionElements()) 59 | updEnts.append(dbEnt) 60 | else: 61 | updEnts.append(geoEnt) 62 | return updEnts 63 | 64 | def applyCommand(self): 65 | """ 66 | perform the write of the entity 67 | """ 68 | if len(self.value) != 3: 69 | raise PyCadWrongImputData("Wrong number of imput parameter") 70 | try: 71 | self.document.startMassiveCreation() 72 | for _ent in self.performMirror(): 73 | self.document.saveEntity(_ent) 74 | finally: 75 | self.document.stopMassiveCreation() 76 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/movecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the move command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.arc import Arc 26 | 27 | class MoveCommand(BaseCommand): 28 | """ 29 | this class rappresent the Move command 30 | """ 31 | def __init__(self, document): 32 | BaseCommand.__init__(self, document) 33 | self.exception = [ExcMultiEntity, 34 | ExcPoint, 35 | ExcPoint] 36 | self.defaultValue = [None, None, None] 37 | self.message = ["Select the entity to move [or give me a the keyword Text As: (10,20,30,...)]", 38 | "Give me the base point", 39 | "Give me the destination point"] 40 | 41 | def getEntsToSave(self): 42 | """ 43 | get entity to save 44 | """ 45 | updEnts = [] 46 | for id in str(self.value[0]).split(','): 47 | dbEnt = self.document.getEntity(id) 48 | geoEnt = self.document.convertToGeometricalEntity(dbEnt) 49 | geoEnt.move(self.value[1], self.value[2]) 50 | dbEnt.setConstructionElements(geoEnt.getConstructionElements()) 51 | updEnts.append(dbEnt) 52 | return updEnts 53 | 54 | def applyCommand(self): 55 | """ 56 | apply the champfer command 57 | """ 58 | if len(self.value) != 3: 59 | raise PyCadWrongImputData("Wrong number of imput parameter") 60 | try: 61 | self.document.startMassiveCreation() 62 | for _ent in self.getEntsToSave(): 63 | self.document.saveEntity(_ent) 64 | finally: 65 | self.document.stopMassiveCreation() 66 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/pointcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the point command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.point import Point 26 | 27 | class PointCommand(BaseCommand): 28 | """ 29 | this class represents the point command 30 | """ 31 | def __init__(self, kernel): 32 | BaseCommand.__init__(self, kernel) 33 | self.exception = [ExcPoint] 34 | self.defaultValue = [None] 35 | self.message = ["Give Me the Point"] 36 | 37 | def applyCommand(self): 38 | if len(self.value) != 1: 39 | raise PyCadWrongImputData("Wrong number of input parameters") 40 | point = Point(self.value[0]) 41 | self.document.saveEntity(point) 42 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/polylinecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the polyline command 22 | # 23 | 24 | from exception import * 25 | from Command.basecommand import * 26 | from GeoEntity.polyline import Polyline 27 | from GeoEntity.point import Point 28 | 29 | class PolylineCommand(BaseCommand): 30 | """ 31 | this class rappresent the ellips command 32 | """ 33 | def __init__(self, document): 34 | BaseCommand.__init__(self, document) 35 | self.exception = [ExcPoint] 36 | self.defaultValue = [None] 37 | self.message = ["Give Me A Point"] 38 | self.raiseStop = False 39 | self.automaticApply = False #In case of polyline we need to stop the automatic apply 40 | 41 | def __setitem__(self, key, value): 42 | """ 43 | overwrite the command to perform the stop operation 44 | """ 45 | value = self.translateCmdValue(value) 46 | if isinstance(value, Point): 47 | self.value.append(value) 48 | self.exception.append(ExcPoint) 49 | self.message.append("Give Me A Point") 50 | self.defaultValue.append(None) 51 | else: 52 | self.raiseStop = True 53 | 54 | def applyCommand(self): 55 | """ 56 | perform the write of the entity 57 | """ 58 | i = 0 59 | args = {} 60 | for k in self.value: 61 | args["POLYLINE_%s" % str(i)] = k 62 | i += 1 63 | pline = Polyline(args) 64 | self.document.saveEntity(pline) 65 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/rectanglecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the Rectangle command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.point import Point 26 | from GeoEntity.segment import Segment 27 | 28 | class RectangleCommand(BaseCommand): 29 | """ 30 | this class rappresent the segment command 31 | """ 32 | def __init__(self, document): 33 | BaseCommand.__init__(self, document) 34 | self.exception = [ExcPoint, ExcPoint] 35 | self.defaultValue = [None, None] 36 | self.message = ["Give Me the first Point","Give Me The second Point"] 37 | 38 | def getEntsToSave(self): 39 | """ 40 | get all the segment of the rectangle 41 | """ 42 | objEnt = [] 43 | p1 = self.value[0] 44 | p2 = self.value[1] 45 | x1, y1 = p1.getCoords() 46 | x2, y2=p2.getCoords() 47 | p3 = Point(x1, y2) 48 | p4 = Point(x2, y1) 49 | segArg = {"SEGMENT_0": p1, "SEGMENT_1": p4} 50 | objEnt.append(Segment(segArg)) 51 | segArg = {"SEGMENT_0": p4, "SEGMENT_1": p2} 52 | objEnt.append(Segment(segArg)) 53 | segArg = {"SEGMENT_0": p2, "SEGMENT_1": p3} 54 | objEnt.append(Segment(segArg)) 55 | segArg = {"SEGMENT_0": p3, "SEGMENT_1": p1} 56 | objEnt.append(Segment(segArg)) 57 | return objEnt 58 | 59 | def applyCommand(self): 60 | if len(self.value) != 2: 61 | raise PyCadWrongImputData("Wrong number of imput parameter") 62 | try: 63 | self.document.startMassiveCreation() 64 | for _ent in self.getEntsToSave(): 65 | self.document.saveEntity(_ent) 66 | finally: 67 | self.document.stopMassiveCreation() 68 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/rotatecommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the rotate command 22 | # 23 | import math 24 | 25 | from exception import * 26 | from Command.basecommand import * 27 | from GeoEntity.point import Point 28 | 29 | class RotateCommand(BaseCommand): 30 | """ 31 | this class rappresent the rotate command 32 | """ 33 | def __init__(self, document): 34 | BaseCommand.__init__(self, document) 35 | self.exception = [ExcMultiEntity, 36 | ExcPoint, 37 | ExcAngle, 38 | ExcText] 39 | self.defaultValue = [None, None, math.pi / 2, "C"] 40 | self.message = ["Select the entity to rotate or give me a the keyword Text As: (10,20,30,...)", 41 | "Give me the reference rotation point", 42 | "Give me the rotation angle[rad]", 43 | "Give me the Mode (M or None ->Move,C ->Copy)"] 44 | 45 | def performRotation(self): 46 | """ 47 | perform the mirror of all the entity selected 48 | """ 49 | copy = True 50 | if self.value[3]: 51 | if self.value[3] == 'C': 52 | copy = False 53 | updEnts = [] 54 | for id in str(self.value[0]).split(','): 55 | dbEnt = self.document.getEntity(id) 56 | geoEnt = self.document.convertToGeometricalEntity(dbEnt) 57 | geoEnt.rotate(self.value[1], self.value[2]) 58 | if not copy: 59 | dbEnt.setConstructionElements(geoEnt.getConstructionElements()) 60 | updEnts.append(dbEnt) 61 | else: 62 | updEnts.append(geoEnt) 63 | return updEnts 64 | 65 | def applyCommand(self): 66 | """ 67 | perform the write of the entity 68 | """ 69 | if len(self.value) != 4: 70 | raise PyCadWrongImputData("Wrong number of imput parameter") 71 | try: 72 | self.document.startMassiveCreation() 73 | for _ent in self.performRotation(): 74 | self.document.saveEntity(_ent) 75 | finally: 76 | self.document.stopMassiveCreation() 77 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/segmentcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the segment command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.segment import Segment 26 | from GeoEntity.point import Point 27 | 28 | class SegmentCommand(BaseCommand): 29 | """ 30 | this class rappresent the segment command 31 | """ 32 | def __init__(self, document): 33 | BaseCommand.__init__(self, document) 34 | self.exception = [ExcPoint, ExcPoint] 35 | self.message = ["Give Me the first Point", "Give Me The Second Point"] 36 | self.defaultValue = [None, None] 37 | 38 | def applyCommand(self): 39 | if len(self.value) != 2: 40 | raise PyCadWrongImputData("Wrong number of imput parameter") 41 | segArg = {"SEGMENT_0": self.value[0], "SEGMENT_1": self.value[1]} 42 | seg = Segment(segArg) 43 | self.document.saveEntity(seg) 44 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/textcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the segment command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity.text import Text 26 | 27 | class TextCommand(BaseCommand): 28 | """ 29 | This class rappresent the segment command 30 | """ 31 | def __init__(self, document): 32 | BaseCommand.__init__(self, document) 33 | self.exception = [ExcPoint, ExcText, ExcAngle,ExcText ] 34 | self.defaultValue = [None, "Dummy Text", 0, "sw"] 35 | self.message = ["Give Me the first Point", 36 | "Give Me The Text string", 37 | "Give Me The angle", 38 | "Give me the position of the text referred to the point"] 39 | 40 | def applyCommand(self): 41 | if len(self.value) != 4: 42 | raise PyCadWrongImputData("Wrong number of imput parameter") 43 | textArgs = {"TEXT_0": self.value[0], "TEXT_1": self.value[1], "TEXT_2": self.value[2], "TEXT_3": self.value[3]} 44 | text = Text(textArgs) 45 | self.document.saveEntity(text) 46 | -------------------------------------------------------------------------------- /Generic/Kernel/Command/trimcommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the Trim command 22 | # 23 | from exception import * 24 | from Command.basecommand import * 25 | from GeoEntity import * 26 | from GeoUtil.intersection import * 27 | from GeoUtil.util import * 28 | 29 | class TrimCommand(BaseCommand): 30 | """ 31 | this class rappresent the Trim command 32 | """ 33 | def __init__(self, document): 34 | BaseCommand.__init__(self, document) 35 | self.exception = [ExcText, 36 | ExcText, 37 | ExcText] 38 | self.defaultValue = [None, None, "BOTH"] 39 | self.message = ["Give me the First entity", 40 | "Give me the Second entity", 41 | "Give me a point near the First entity", 42 | "Give me a point near the Second entity", 43 | "Give me The Trim Mode ((FIRST,SECOND,BOTH)"] 44 | 45 | def performTrim(self): 46 | """ 47 | get the chamfer segments 48 | """ 49 | updEnts = [] 50 | dbEnt1 = self.document.getEntity(self.value[0]) 51 | geoEnt1 = self.document.convertToGeometricalEntity(dbEnt1) 52 | dbEnt2 = self.document.getEntity(self.value[1]) 53 | geoEnt2 = self.document.convertToGeometricalEntity(dbEnt2) 54 | intPoint = findSegmentExtendedIntersectionPoint(geoEnt1, geoEnt2) 55 | if len(intPoint) <= 0: 56 | raise PythopnCadWarning("No intersection Found") 57 | 58 | if dbEnt1.eType == "SEGMENT": 59 | geoEntTrim1 = updateSegment(geoEnt1, self.value[2], intPoint[0]) 60 | 61 | if dbEnt2.eType == "SEGMENT": 62 | geoEntTrim2 = updateSegment(geoEnt2, self.value[3], intPoint[0]) 63 | 64 | if self.value[4] == 'FIRST': 65 | dbEnt1.setConstructionElements(geoEntTrim1.getConstructionElements()) 66 | updEnts.append(dbEnt1) 67 | elif self.value[4] == 'SECOND': 68 | dbEnt2.setConstructionElements(geoEntTrim2.getConstructionElements()) 69 | updEnts.append(dbEnt2) 70 | else: 71 | dbEnt1.setConstructionElements(geoEntTrim1.getConstructionElements()) 72 | updEnts.append(dbEnt1) 73 | dbEnt2.setConstructionElements(geoEntTrim2.getConstructionElements()) 74 | updEnts.append(dbEnt2) 75 | return updEnts 76 | 77 | def applyCommand(self): 78 | """ 79 | apply the trim command 80 | """ 81 | if len(self.value) != 5: 82 | raise PyCadWrongImputData("Wrong number of imput parameter") 83 | try: 84 | self.document.startMassiveCreation() 85 | for _ent in self.performTrim(): 86 | self.document.saveEntity(_ent) 87 | finally: 88 | self.document.stopMassiveCreation() 89 | -------------------------------------------------------------------------------- /Generic/Kernel/Db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/Kernel/Db/__init__.py -------------------------------------------------------------------------------- /Generic/Kernel/Db/basedb.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module provide access to the basic operation on pythoncad database 22 | # 23 | 24 | import os 25 | import sys 26 | import tempfile 27 | import sqlite3 as sql 28 | 29 | from exception import * 30 | 31 | 32 | class BaseDb(object): 33 | """ 34 | this class provide base db operation 35 | """ 36 | commit = True 37 | 38 | def __init__(self): 39 | self.__dbConnection = None 40 | self.dbPath = None 41 | 42 | def createConnection(self, dbPath=None): 43 | """ 44 | create the connection with the database 45 | """ 46 | if dbPath is None: 47 | f = tempfile.NamedTemporaryFile(prefix='PyCad_', suffix='.pdr') 48 | dbPath = f.name 49 | f.close() 50 | 51 | if type(dbPath) == tuple: 52 | dbPath = dbPath[0] 53 | 54 | self.__dbConnection = sql.connect(dbPath) 55 | self.dbPath = dbPath 56 | 57 | def setConnection(self, dbConnection): 58 | """ 59 | set the connection with the database 60 | """ 61 | if not self.__dbConnection is None: 62 | # Todo fire a warning 63 | self.__dbConnection.close() 64 | self.__dbConnection = dbConnection 65 | 66 | def getConnection(self): 67 | """ 68 | Get The active connection 69 | """ 70 | return self.__dbConnection 71 | 72 | def makeSelect(self, statment): 73 | """ 74 | perform a select operation 75 | """ 76 | try: 77 | _cursor = self.__dbConnection.cursor() 78 | _rows = _cursor.execute(statment) 79 | except sql.Error as _e: 80 | msg = "Sql Phrase: %s" % str( 81 | statment) + "\nSql Error: %s" % str(_e.args[0]) 82 | raise StructuralError(msg) 83 | except: 84 | for s in sys.exc_info(): 85 | print("Generic Error: %s" % str(s)) 86 | raise StructuralError 87 | # _cursor.close() 88 | return _rows 89 | 90 | def fetchOneRow(self, sqlSelect, tupleArgs=None): 91 | """ 92 | get the first row of the select 93 | """ 94 | try: 95 | _cursor = self.__dbConnection.cursor() 96 | if tupleArgs: 97 | _rows = _cursor.execute(sqlSelect, tupleArgs) 98 | else: 99 | _rows = _cursor.execute(sqlSelect) 100 | except sql.Error as _e: 101 | msg = "Sql Phrase: %s" % str( 102 | sqlSelect) + "\nSql Error: %s" % str(_e.args[0]) 103 | raise StructuralError(msg) 104 | except: 105 | for s in sys.exc_info(): 106 | print("Generic Error: %s" % str(s)) 107 | raise StructuralError 108 | _row = _rows.fetchone() 109 | _cursor.close() 110 | if _row is None or _row[0] is None: 111 | return None 112 | return _row[0] 113 | 114 | def makeUpdateInsert(self, statment, tupleArgs=None): 115 | """ 116 | make an update Inster operation 117 | """ 118 | # print "qui1 : sql ",statment 119 | try: 120 | _cursor = self.__dbConnection.cursor() 121 | if tupleArgs: 122 | _rows = _cursor.execute(statment, tupleArgs) 123 | else: 124 | _rows = _cursor.execute(statment) 125 | # if self.__commit: 126 | if BaseDb.commit: 127 | self.performCommit() 128 | _cursor.close() 129 | except sql.Error as _e: 130 | msg = "Sql Phrase: %s" % str( 131 | statment) + "\nSql Error: %s" % str(_e.args[0]) 132 | raise sql.Error(msg) 133 | except: 134 | for s in sys.exc_info(): 135 | print("Generic Error: %s" % str(s)) 136 | raise KeyError 137 | 138 | def close(self): 139 | """ 140 | close the database connection 141 | """ 142 | self.__dbConnection.close() 143 | 144 | def suspendCommit(self): 145 | """ 146 | suspend the commit in the update\insert 147 | """ 148 | # self.__commit=False 149 | BaseDb.commit = False 150 | 151 | def reactiveCommit(self): 152 | """ 153 | reactive the commit in the update\insert 154 | """ 155 | # self.__commit=True 156 | BaseDb.commit = True 157 | 158 | def performCommit(self): 159 | """ 160 | perform a commit 161 | """ 162 | try: 163 | self.__dbConnection.commit() 164 | except: 165 | print("Error on commit") 166 | -------------------------------------------------------------------------------- /Generic/Kernel/Db/pycadobject.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module provide basic pythoncadObject 22 | # 23 | from GeoEntity.style import Style 24 | 25 | class PyCadObject(object): 26 | """ 27 | This class provide basic information usefoul for the 28 | db like id for exsample 29 | """ 30 | def __init__(self, objId, style, eType): 31 | from Generic.Kernel.initsetting import OBJECT_STATE 32 | self.OBJECT_STATE = OBJECT_STATE 33 | self.__entityId = objId 34 | self.__state = "MODIFIE" 35 | self.__index = 0 36 | self.__visible = 1 37 | self.__style = style 38 | self.__entType = eType 39 | 40 | def setVisible(self, visible): 41 | """ 42 | set the visible value 43 | """ 44 | self.__visible = visible 45 | 46 | def getVisible(self): 47 | """ 48 | get the visible value 49 | """ 50 | return self.__visible 51 | visible = property(getVisible, setVisible, None, "Set/Get the entity visibiolity") 52 | 53 | def getId(self): 54 | """ 55 | get the entity id 56 | """ 57 | return self.__entityId 58 | 59 | def getState(self): 60 | """ 61 | get the active entity state 62 | """ 63 | return self.__state 64 | 65 | def setState(self, state): 66 | """ 67 | set the active state 68 | """ 69 | if state in self.OBJECT_STATE: 70 | self.__state = state 71 | else: 72 | print("Wrong argunent") 73 | raise 74 | 75 | state = property(getState, setState, None, "Get/Set the state of the entity") 76 | 77 | def getIndex(self): 78 | """ 79 | get the index of the revision index of the current object 80 | """ 81 | return self.__index 82 | 83 | def getNewIndex(self): 84 | """ 85 | Get the new index of the current entity 86 | """ 87 | if index : 88 | self.__index += self.__index 89 | self.__state = self.OBJECT_STATE[0] 90 | else: 91 | self.__index = 0 92 | self.__state = self.OBJECT_STATE[0] 93 | 94 | def setIndex(self, index): 95 | """ 96 | Set The index of the entity 97 | """ 98 | if index: 99 | self.__index = index 100 | index = property(getIndex, setIndex, "Get The new index of the current entity") 101 | 102 | def delete(self): 103 | """ 104 | mark the entity to delete 105 | """ 106 | self.__state = 'DELETE' 107 | 108 | def relese(self): 109 | """ 110 | mark the entity as released 111 | """ 112 | self.__state = 'RELEASED' 113 | 114 | def getStyle(self): 115 | """ 116 | get the object EntityStyle 117 | """ 118 | return self.__style 119 | 120 | def setStyle(self,style): 121 | """ 122 | set/update the entitystyle 123 | """ 124 | if not isinstance(style, Style): 125 | raise TypeError('Type error in style') 126 | self.__style = style 127 | 128 | style = property(getStyle, setStyle, None, "Get/Set the entity style") 129 | 130 | def getInnerStyle(self): 131 | """ 132 | return the inner style of type Style 133 | """ 134 | if self.getStyle(): 135 | styleEnt = self.getStyle().getConstructionElements() 136 | return styleEnt[list(styleEnt.keys())[0]] 137 | else: 138 | return None 139 | 140 | def setEntType(self, type): 141 | """ 142 | Set the entity type 143 | """ 144 | self.__entType = type 145 | 146 | def getEntityType(self): 147 | """ 148 | Get the entity type 149 | """ 150 | return self.__entType 151 | 152 | eType = property(getEntityType, setEntType, None, "Get/Set the etity type ") 153 | -------------------------------------------------------------------------------- /Generic/Kernel/ExternalFormat/Dxf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/Kernel/ExternalFormat/Dxf/__init__.py -------------------------------------------------------------------------------- /Generic/Kernel/ExternalFormat/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/Kernel/ExternalFormat/__init__.py -------------------------------------------------------------------------------- /Generic/Kernel/ExternalFormat/externalformat.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2009,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the termscl_bo of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | import os.path 22 | 23 | from ExternalFormat.Dxf.dxf import Dxf 24 | 25 | class ExtFormat(object): 26 | """ 27 | This class provide base class for hendly different drawing format in pythoncad 28 | """ 29 | def __init__(self, kernel): 30 | """ 31 | Default Constructor 32 | """ 33 | self.__kernel = kernel 34 | self.__errorList = [] 35 | 36 | def openFile(self, fileName): 37 | """ 38 | Open a generic file 39 | """ 40 | path, exte = os.path.splitext(fileName[0]) 41 | if(exte.upper() == ".dxf".upper()): 42 | dxf = Dxf(self.__kernel, fileName) 43 | dxf.importEntitis() 44 | if not dxf.getError() is None: 45 | self.__errorList = dxf.getError() 46 | raise DxfReport("Dxf report have to be shown some error/warning in import dxf") 47 | else: 48 | raise DxfUnsupportedFormat("Format %s not supported" % str(exte)) 49 | 50 | def saveFile(self, fileName): 51 | """ 52 | save the current file in a non pythoncad Format 53 | """ 54 | path,exte = os.path.splitext( fileName ) 55 | if exte.upper() == ".dxf".upper(): 56 | dxf = Dxf(self.__kernel, fileName) 57 | dxf.exportEntitis() 58 | 59 | def getErrorList(self): 60 | """ 61 | get the error warning generated 62 | """ 63 | return self.__errorList 64 | -------------------------------------------------------------------------------- /Generic/Kernel/GeoComposedEntity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/Kernel/GeoComposedEntity/__init__.py -------------------------------------------------------------------------------- /Generic/Kernel/GeoComposedEntity/bisector.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # code for base for Bisector 22 | # 23 | 24 | from GeoComposedEntity.objoint import * 25 | from GeoUtil.geolib import Vector 26 | import math 27 | 28 | class Bisector(ObjectJoint): 29 | """ 30 | A Bisector class 31 | """ 32 | def __init__(self, kw): 33 | """ 34 | "OBJECTJOINT_0" obj1 :(Segment ,ACLine,Arc,CCircle) 35 | "OBJECTJOINT_1" obj2 :(Segment ,ACLine,Arc,CCircle) 36 | "OBJECTJOINT_2" pointClick1 :Clicked point from the u.i near the obj1 37 | "OBJECTJOINT_3" pointClick2 :Clicked point from the u.i near the obj2 38 | "OBJECTJOINT_4" str :Fixed Value "NO_TRIM" not needed 39 | "OBJECTJOINT_5" lengh :Bisector lengh from intersection point 40 | """ 41 | kw["OBJECTJOINT_4"] = "NO_TRIM" 42 | argDes = {"OBJECTJOINT_5": (float, int, None)} 43 | ObjectJoint.__init__(self, kw, argDes) 44 | if not kw["OBJECTJOINT_5"]: 45 | self["OBJECTJOINT_5"] = self.getDefaultLeng() 46 | self._UpdateBisector() 47 | 48 | def _UpdateBisector(self): 49 | """ 50 | Update the segment base on the imput value 51 | """ 52 | v1 = self.getAngledVector(self.obj1, self.pointClick1) 53 | v2 = self.getAngledVector(self.obj2, self.pointClick2) 54 | ang= v1.ang(v2) / 2.0 55 | if v1.absAng == 0 or v2.absAng == 0: 56 | if v2.point.y < 0: 57 | bisecVector = v2.mag() 58 | elif v1.point.y < 0: 59 | bisecVector = v1.mag() 60 | else: 61 | if v1.absAng > v2.absAng: 62 | bisecVector = v2.mag() 63 | else: 64 | bisecVector = v1.mag() 65 | else: 66 | v1v2Ang = abs(v1.absAng - v2.absAng) 67 | if v1.absAng > v2.absAng: 68 | if v1v2Ang > math.pi: 69 | bisecVector = v1.mag() 70 | else: 71 | bisecVector = v2.mag() 72 | else: 73 | if v1v2Ang > math.pi: 74 | bisecVector = v2.mag() 75 | else: 76 | bisecVector = v1.mag() 77 | bisecVector.mult(self.lengh) 78 | bisecVector.rotate(ang) 79 | newPoint = self.intersection[0] + bisecVector.point 80 | arg = {"SEGMENT_0": self.intersection[0], "SEGMENT_1": newPoint} 81 | self.bisector = Segment(arg) 82 | 83 | @property 84 | def lengh(self): 85 | """ 86 | Second object of the bisector 87 | """ 88 | return self['OBJECTJOINT_5'] 89 | 90 | @lengh.setter 91 | def lengh(self, value): 92 | if value: 93 | self['OBJECTJOINT_5'] = value 94 | else: 95 | self.getDefaultLeng() 96 | 97 | @property 98 | def bisector(self): 99 | """ 100 | Bisector segment object 101 | """ 102 | return self.__bisector 103 | 104 | @bisector.setter 105 | def bisector(self, value): 106 | self.__bisector = value 107 | 108 | def getDefaultLeng(self): 109 | """ 110 | get the default bisector lengh 111 | """ 112 | pp1 = obj1.projection(pointClick1.getSympy()) 113 | pp2 = obj2.projection(pointClick2.getSympy()) 114 | ppi.self.intersection[0].getSympy() 115 | 116 | import sympy.geometry as geoSympy 117 | 118 | t = geoSympy.Triangle(pp1,pp1,ppi) 119 | return float(t.bisectors[ppi].length) 120 | 121 | def clone(self): 122 | """ 123 | Clone the Chamfer .. 124 | I do not why somone whant to clone a chamfer .. 125 | But Tis is the functionality .. :-) 126 | """ 127 | newChamfer = Chamfer(self._obj1, 128 | self._obj2, 129 | self.pointClick1, 130 | self.pointClick2) 131 | return newChamfer 132 | 133 | def getReletedComponent(self): 134 | """ 135 | return the element to be written in the db and used for renderin 136 | """ 137 | return self.bisector 138 | -------------------------------------------------------------------------------- /Generic/Kernel/GeoEntity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/Kernel/GeoEntity/__init__.py -------------------------------------------------------------------------------- /Generic/Kernel/GeoEntity/entityutil.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module provide some utility for the entity 22 | # 23 | import math 24 | 25 | import sympy as mainSympy 26 | import sympy.geometry as geoSympy 27 | 28 | from GeoEntity.point import Point 29 | from GeoEntity.segment import Segment 30 | from GeoEntity.arc import Arc 31 | from GeoEntity.ellipse import Ellipse 32 | 33 | 34 | # "Ray", 35 | # "Line", 36 | # "Triangle", 37 | # "RegularPolygon", 38 | # "Polygon", 39 | # "Curve" 40 | 41 | def getEntityEntity(sympyEntity): 42 | """ 43 | convert sympy object into PyCAD object 44 | """ 45 | if isinstance(sympyEntity, geoSympy.Circle): 46 | arg = {"ARC_0": Point(0.0, 0.0), 47 | "ARC_1": 1, 48 | "ARC_2": None, 49 | "ARC_3": None 50 | } 51 | arc = Arc(arg) 52 | arc.setFromSympy(sympyEntity) 53 | return arc 54 | elif isinstance(sympyEntity, geoSympy.Point): 55 | p = Point(0.0, 0.0) 56 | p.setFromSympy(sympyEntity) 57 | return p 58 | elif isinstance(sympyEntity, geoSympy.Segment): 59 | segArg = {"SEGMENT_0": Point(0.0, 0.0), "SEGMENT_1": Point(1.0, 1.0)} 60 | seg = Segment(segArg) 61 | seg.setFromSympy(sympyEntity) 62 | return seg 63 | elif isinstance(sympyEntity, geoSympy.Ellipse): 64 | arg = {"ELLIPSE_0": Point(0.0, 0.0), "ELLIPSE_1": 1.0, "ELLIPSE_2": 2.0} 65 | e = Ellipse(arg) 66 | e.setFromSympy(sympyEntity) 67 | return e 68 | else: 69 | raise "not supported entity" 70 | -------------------------------------------------------------------------------- /Generic/Kernel/GeoEntity/geometricalentity.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This is the base class for all the geometrical entitys 22 | # 23 | import math 24 | 25 | import sympy as mainSympy 26 | import sympy.geometry as geoSympy 27 | 28 | class GeometricalEntity(dict): 29 | """ 30 | This class provide the basic interface for all the geometrical entitys 31 | """ 32 | def __init__(self, kw, argNameType): 33 | """ 34 | argv name must be created befor init the base class 35 | """ 36 | if kw is None and argNameType is None: 37 | return 38 | if len(kw) != len(argNameType): 39 | raise TypeError("Wrong number of items ") 40 | for k in kw: 41 | if k in argNameType: 42 | if isinstance(kw[k], argNameType[k]): 43 | self[k] = kw[k] 44 | else: 45 | raise TypeError("Wrong Type for argument %s" % str(k)) 46 | else: 47 | raise TypeError("Wrong argument %s " % str(k)) 48 | self.arguments = argNameType 49 | self._snapPoints = [] 50 | 51 | def updateSnapPoint(self, force = None, fromPoint = None, fromEnt = None): 52 | pass 53 | 54 | def getUpdatedSnapPoints(self, force, fromPoint = None, fromEnt = None): 55 | """ 56 | update the snappoint with force argument and return an array of geopoint 57 | """ 58 | self.updateSnapPoint(force, fromPoint, fromEnt) 59 | return self.snapPoints 60 | 61 | @property 62 | def snapPoints(self): 63 | """ 64 | return the snap points 65 | """ 66 | return self._snapPoints 67 | 68 | @snapPoints.setter 69 | def snapPoints(self, value): 70 | self._snapPoints = value 71 | 72 | def getArgumentsName(self): 73 | """ 74 | get the construction arguments Name 75 | """ 76 | return self.arguments 77 | 78 | def getConstructionElements(self): 79 | """ 80 | Get the construction element of entity.. 81 | """ 82 | return self 83 | 84 | def setConstructionElements(self, **kw): 85 | """ 86 | set the construction elemtnts 87 | """ 88 | self = kw 89 | 90 | def move(self, fromPoint, toPoint): 91 | """ 92 | this method must be defined for moving operation 93 | """ 94 | from Kernel.GeoUtil.geolib import Vector 95 | from Kernel.GeoEntity.point import Point 96 | v = Vector(fromPoint, toPoint) 97 | for key in self: 98 | if isinstance(self[key], Point): 99 | self[key] += v.point 100 | return v.point 101 | 102 | def rotate(self, rotationPoint, angle): 103 | """ 104 | this method must be defined for rotation 105 | """ 106 | from Kernel.GeoUtil.geolib import Vector 107 | from Kernel.GeoEntity.point import Point 108 | 109 | for key in self: 110 | if isinstance(self[key], Point): 111 | v = Vector(rotationPoint, self[key]) 112 | v.rotate(angle) 113 | self[key] = rotationPoint + v.point 114 | 115 | 116 | def getSympy(self): 117 | """ 118 | get the sympy object 119 | """ 120 | pass 121 | 122 | def setFromSympy(self, sympyPoint): 123 | """ 124 | update the points cord from a sympyobject 125 | """ 126 | pass 127 | 128 | class GeometricalEntityComposed(dict): 129 | """ 130 | this class provide the basic object for composed entity 131 | like dimension labels ... 132 | """ 133 | def __init__(self, kw, argNameType): 134 | if kw is None and argNameType is none: 135 | return 136 | if len(kw) != len(argNameType): 137 | raise TypeError("Wrong number of items ") 138 | for k in kw: 139 | if k in argNameType: 140 | newTest = argNameType[k] 141 | if isinstance(argNameType[k], tuple): 142 | if None in argNameType[k]: 143 | if kw[k] == None: 144 | self[k] = kw[k] 145 | continue 146 | else: 147 | newTest = tuple([x for x in argNameType[k] if x != None]) 148 | if isinstance(kw[k],newTest): 149 | self[k] = kw[k] 150 | else: 151 | raise TypeError("Wrong Type for argument %s"%str(k)) 152 | else: 153 | raise TypeError("Wrong argument %s "%str(k)) 154 | self.arguments = argNameType 155 | 156 | def getArgumentsName(self): 157 | """ 158 | get the construction arguments Name 159 | """ 160 | return self.arguments 161 | def getConstructionElements(self): 162 | """ 163 | Get the construction element of .. 164 | This must return a tuple of object better if there are point 165 | """ 166 | pass 167 | def getReletedComponent(self): 168 | """ 169 | Get The releted object to be updated 170 | """ 171 | pass 172 | 173 | -------------------------------------------------------------------------------- /Generic/Kernel/GeoEntity/style.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This class provide all the style operation for the pythoncadDB 22 | # 23 | 24 | from GeoEntity.geometricalentity import GeometricalEntity 25 | from GeoUtil.util import getRandomString 26 | 27 | class Style(GeometricalEntity): 28 | """ 29 | This class rappresent the style in pythoncad 30 | objID is the object that rappresent the id in the db 31 | """ 32 | def __init__(self, kw): 33 | """ 34 | Initialize a Arc/Circle. 35 | kw['STYLE_0'] 36 | kw['STYLE_1'] 37 | """ 38 | argDescription = dict([(key, str) for key in kw]) 39 | GeometricalEntity.__init__(self, kw, argDescription) 40 | 41 | if 'STYLE_1' in self: 42 | if self['STYLE_1'] == None: 43 | from Kernel.initsetting import getDefaultStyle 44 | self.__styleProperty = getDefaultStyle() 45 | else: 46 | from Generic.Kernel.initsetting import getDefaultStyle 47 | self['STYLE_1'] = getDefaultStyle() 48 | #if self.has_key('STYLE_0'): # old Python 2 syntax 49 | if 'STYLE_0' in self: 50 | if self['STYLE_0'] == None: 51 | self.name = getRandomString() 52 | else: 53 | self['STYLE_0'] = getRandomString() 54 | 55 | def setName(self, name): 56 | """ 57 | set the name of the style 58 | """ 59 | self['STYLE_0'] = name 60 | 61 | def getName(self): 62 | """ 63 | get the style name 64 | """ 65 | return self['STYLE_0'] 66 | 67 | name = property(setName, getName, None, "Style Name") 68 | 69 | def getStyleProp(self, name): 70 | """ 71 | get the style property 72 | """ 73 | if name in self['STYLE_1']: 74 | return self['STYLE_1'][name] 75 | else: 76 | return None 77 | 78 | def setStyleProp(self, name, value): 79 | """ 80 | set the style property 81 | """ 82 | from Kernel.initsetting import PYTHONCAD_STYLE_ATTRIBUTES 83 | from Kernel.exception import EntityMissing 84 | if name in PYTHONCAD_STYLE_ATTRIBUTES: 85 | self['STYLE_1'][name] = value 86 | else: 87 | raise EntityMissing("Unable to find the property %s" % str(name)) 88 | -------------------------------------------------------------------------------- /Generic/Kernel/GeoUtil/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/Kernel/GeoUtil/__init__.py -------------------------------------------------------------------------------- /Generic/Kernel/GeoUtil/geolib.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2009 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # This module provide class to manage geometrical vector operation 21 | # 22 | 23 | import math 24 | 25 | from Generic.Kernel.GeoEntity.point import Point 26 | 27 | class Vector: 28 | """ 29 | Provide a full 2d vector operation and definition 30 | """ 31 | def __init__(self, p1, p2): 32 | """ 33 | Default Constructor 34 | """ 35 | if(not isinstance(p1, Point)): 36 | raise TypeError("Invalid Argument p1: Point Required") 37 | if(not isinstance(p2, Point)): 38 | raise TypeError("Invalid Argument p2: Point Required") 39 | x, y = p1.getCoords() 40 | x1, y1 = p2.getCoords() 41 | self.X = x1 - x 42 | self.Y = y1 - y 43 | 44 | def mag(self): 45 | """ 46 | Get the versor 47 | """ 48 | _a = self.absAng 49 | p1 = Point(0, 0) 50 | p2 = Point(math.cos(_a), math.sin(_a)) 51 | return Vector(p1, p2) 52 | 53 | @property 54 | def norm(self): 55 | """ 56 | Get The Norm Of the vector 57 | """ 58 | return math.sqrt(pow(self.X, 2) + pow(self.Y, 2)) 59 | 60 | def __eq__(self, vector): 61 | """ 62 | the 2 vector are equal 63 | """ 64 | if(not isinstance(vector, Vector)): 65 | raise TypeError("Invalid Argument vector: Vector Required") 66 | if(self.point == vector.point): 67 | return True 68 | else: 69 | return False 70 | 71 | @property 72 | def point(self): 73 | """ 74 | Return The Point 75 | """ 76 | return Point(self.X, self.Y) 77 | 78 | @property 79 | def x(self): 80 | """ 81 | return the x value of the vector 82 | """ 83 | return self.X 84 | 85 | @property 86 | def y(self): 87 | """ 88 | return the y value of the vector 89 | """ 90 | return self.Y 91 | 92 | def dot(self, vector): 93 | """ 94 | Compute The Dot Product 95 | """ 96 | if(not isinstance(vector, Vector)): 97 | raise TypeError("Invalid Argument vector: Vector Required") 98 | v0 = self.point.getCoords() 99 | v1 = vector.point.getCoords() 100 | som = 0 101 | for a, b in zip(v0, v1): 102 | som += a * b 103 | return som 104 | 105 | def cross(self, vector): 106 | """ 107 | Compute The Cross Product 108 | """ 109 | if(not isinstance(vector, Vector)): 110 | raise TypeError("Invalid Argument vector: Vector Required") 111 | x1, y1 = self.point.getCoords() 112 | x2, y2 = vector.point.getCoords() 113 | cros = x1 * y2 - y1 * x2 114 | return cros 115 | 116 | def ang(self, vector): 117 | """ 118 | Calculate the angle Between the two vector 119 | """ 120 | if(not isinstance(vector, Vector)): 121 | raise TypeError("Invalid Argument vector: Vector Required") 122 | vself = self.mag() 123 | vvector = vector.mag() 124 | dot = vself.dot(vvector) 125 | if(dot < -1): 126 | dot = -1 127 | if(dot > 1): 128 | dot = 1 129 | ang = math.acos(dot) 130 | return ang 131 | 132 | @property 133 | def absAng(self): 134 | """ 135 | return the angle from the cartesian reference 136 | """ 137 | _y = self.point.y 138 | ang = math.atan2(float(_y), float(self.point.x)) 139 | if _y < 0: 140 | ang = ang + 2 * math.pi 141 | return ang 142 | 143 | def mult(self, scalar): 144 | """ 145 | Multiplae the vector for a scalar value 146 | """ 147 | self.X = scalar * self.norm * math.cos(self.absAng) 148 | self.Y = scalar * self.norm * math.sin(self.absAng) 149 | 150 | 151 | def map(self, pPro): 152 | """ 153 | Get a vector for the mapping point 154 | """ 155 | p0 = Point(0, 0) 156 | vProj = Vector(p0, pPro) 157 | ang = self.ang(vProj) 158 | vProjNorm = vProj.norm 159 | projectionUnitDistance = vProjNorm * math.cos(ang) 160 | vSelfMag = self.mag() 161 | vSelfMag.mult(projectionUnitDistance) 162 | return vSelfMag 163 | 164 | def rotate(self, angle): 165 | """ 166 | rotate the vector of a given angle 167 | """ 168 | _a = self.absAng + angle 169 | _norm = self.norm 170 | self.X = _norm * math.cos(_a) 171 | self.Y = _norm * math.sin(_a) 172 | 173 | def invert(self): 174 | """ 175 | Invert the vector 176 | """ 177 | self.rotate(math.pi) 178 | 179 | def __str__(self): 180 | """ 181 | print the vector 182 | """ 183 | msg = "Vector :(%s,%s),Norm: %s"%(self.point.x, self.point.y, self.norm) 184 | return msg 185 | -------------------------------------------------------------------------------- /Generic/Kernel/GeoUtil/tolerance.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2002, 2003 Art Haas 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # this is a class that keeps a tolerance value. It should 22 | # be used as a class (static) variable for classes that 23 | # will compare instances with a tolerance 24 | # 25 | # a valid tolerance is a float value 0 or greater 26 | # 27 | 28 | TOL = 1e-10 29 | 30 | class TolObject(object): 31 | """A class for maintaining a tolerance value. 32 | 33 | The tolerance value is a float that must be 0.0 or 34 | greater. Any class using this class as a base class 35 | will have a tolerance value unique to that class. 36 | 37 | There are two member functions: 38 | 39 | getTolerance(): return the current tolerance 40 | setTolerance(t): set the new tolerance 41 | 42 | """ 43 | def __init__(self, t=None): 44 | """Initialize a TolObject. 45 | 46 | TolObject(t) 47 | 48 | Optional argument t must be a float, and it 49 | must be greater than 0. A default tolerance is set 50 | if the function is called without arguments. 51 | """ 52 | if t is None: 53 | t = TOL 54 | tol = t 55 | if not isinstance(tol, float): 56 | tol = float(t) 57 | if tol < 0.0: 58 | raise ValueError("Tolerance must be greater than 0: " + str(tol)) 59 | self.__tolerance = tol 60 | 61 | def setTolerance(self, t=None): 62 | """Set the tolerance value. 63 | 64 | setTolerance(t) 65 | 66 | Optional argument t must be a float, and it 67 | must be greater than 0. The default tolerance is 68 | reset if the function is called without arguments. 69 | This function returns the old tolerance value. 70 | """ 71 | old_tol = self.__tolerance 72 | if t is None: 73 | t = TOL 74 | tol = t 75 | if not isinstance(tol, float): 76 | tol = float(t) 77 | if tol < 0.0: 78 | raise ValueError("Tolerance must be greater than 0: " + str(tol)) 79 | self.__tolerance = tol 80 | return old_tol 81 | 82 | def getTolerance(self): 83 | """Get the tolerance value. 84 | 85 | getTolerance() 86 | 87 | Return the current tolerance. 88 | """ 89 | return self.__tolerance 90 | 91 | tolerance = property(getTolerance, setTolerance, None, "Tolerance value") 92 | 93 | class StaticTolObject(object): 94 | """A class for maintaining a tolerance value. 95 | 96 | This class is meant to be a base-class for classes 97 | that wish to use a tolerance value for comparing 98 | one instance to another. 99 | 100 | There are two class methods: 101 | 102 | getTolerance(): return the current tolerance 103 | setTolerance(tol): set the new tolerance 104 | 105 | This class stores the tolerance value as a static class 106 | variable, so any classes using this class as a base class 107 | will share the same tolerance value. 108 | """ 109 | 110 | __tolerance = TOL 111 | 112 | def setTolerance(cls, t = None): 113 | """Set the tolerance value. 114 | 115 | Optional argument t must be a float, and itmust be 116 | greater than 0. The default tolerance is reset if 117 | the function is called without arguments. 118 | 119 | This function returns the old tolerance value. 120 | """ 121 | old_tol = cls.__tolerance 122 | if t is None: 123 | t = TOL 124 | _t = t 125 | if not isinstance(_t, float): 126 | _t = float(t) 127 | if _t < 0.0: 128 | raise ValueError("Tolerance must be greater than 0: " + str(_t)) 129 | cls.__tolerance = _t 130 | return old_tol 131 | 132 | setTolerance = classmethod(setTolerance) 133 | 134 | def getTolerance(cls): 135 | """Get the tolerance value. 136 | 137 | Return the current tolerance. 138 | """ 139 | return cls.__tolerance 140 | 141 | getTolerance = classmethod(getTolerance) 142 | 143 | def toltest(tol): 144 | """Test that a tolerance value is valid. 145 | 146 | toltest(tol) 147 | 148 | The argument "tol" should be a float. 149 | """ 150 | _t = tol 151 | if not isinstance(_t, float): 152 | _t = float(tol) 153 | if _t < TOL: 154 | raise ValueError("Invalid tolerance: %g" % _t) 155 | return _t 156 | -------------------------------------------------------------------------------- /Generic/Kernel/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2004 Art Haas 3 | # 4 | 5 | # 6 | # this file is needed for Python's import mechanism 7 | # 8 | 9 | -------------------------------------------------------------------------------- /Generic/Kernel/binarytree.py: -------------------------------------------------------------------------------- 1 | class BinaryTree(object): 2 | """ 3 | generic tree binary structure object 4 | """ 5 | def __init__(self): 6 | self.__tree = EmptyNode() 7 | 8 | def __repr__(self): 9 | return str(self.__tree) 10 | 11 | def lookUp(self, key): 12 | return self.__tree.lookUp(key) 13 | 14 | def insert(self, key, value): 15 | self.__tree = self.__tree.insert(key, value) 16 | 17 | class EmptyNode(object): 18 | """ 19 | empty Node 20 | """ 21 | def __repr__(self): 22 | return '*' 23 | 24 | def lookUp(self, key): 25 | return None 26 | 27 | def insert(self, key, value): 28 | return BinaryNode(self, key, value, self) 29 | 30 | class BinaryNode(object): 31 | """ 32 | this class rappresent a binary node 33 | """ 34 | def __init__(self, left, key, value, right): 35 | self.key, self.data = key, value 36 | self.left, self.right = left, right 37 | 38 | def lookUp(self, key): 39 | """ 40 | look up at the value 41 | """ 42 | if self.key == key: 43 | return self.data 44 | elif self.key > key: 45 | return self.left.lookUp(key) 46 | else: 47 | return self.right.lookUp(key) 48 | 49 | def insert(self, key, value): 50 | """ 51 | insert a new value at the node 52 | """ 53 | if self.key == key: 54 | self.data = value 55 | elif self.key > key: 56 | self.left = self.left.insert(key, value) 57 | elif self.key < key: 58 | self.right = self.right.insert(key, value) 59 | return self 60 | 61 | def __repr__(self): 62 | return '(%s,%s,%s,%s)' % (str(self.left), str(self.key), str(self.data), str(self.right) 63 | 64 | 65 | def testBinaryTree(): 66 | x = BinaryTree() 67 | x.insert('root', "1") 68 | x.insert('layer_1', "3") 69 | x.insert('layer_2', "2") 70 | print("-->", x.lookUp('layer_1')) 71 | print("-->%s" % str(x)) 72 | 73 | if __name__ == '__main__': 74 | testBinaryTree() 75 | -------------------------------------------------------------------------------- /Generic/Kernel/composedentity.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module provide basic DB class for storing entity with relation in pythoncad 22 | # entity such as Chamfer Fillet Blocks 23 | # 24 | 25 | from Db.pycadobject import * 26 | from GeoEntity.style import Style 27 | from GeoEntity.point import Point 28 | 29 | class ComposedEntity(PyCadObject): 30 | """ 31 | this class provide the besic functionality for storing entity that need a 32 | sort of relation such Chamfer Fillet Blocks 33 | """ 34 | def __init__(self, objId, constructionElements, eType, style, childEnt = []): 35 | """ 36 | Inizialize a composed entity 37 | """ 38 | from Kernel.initsetting import PY_CAD_COMPOSED_ENT 39 | if not eType in PY_CAD_COMPOSED_ENT: 40 | raise TypeError('entType not supported') 41 | PyCadObject.__init__(self, eType = eType, objId = objId,style = style) 42 | self.setChildEnt(childEnt) 43 | self.setConstructionElement(constructionElements) 44 | 45 | def getChildEnt(self): 46 | """ 47 | return an array of cildren ents 48 | """ 49 | return self.__childEnt 50 | 51 | def setChildEnt(self, childEnt): 52 | """ 53 | set all the child entitys 54 | """ 55 | from Kernel.initsetting import PY_CAD_ENT 56 | for ent in childEnt: 57 | if not ent.eType in PY_CAD_ENT: 58 | raise TypeError('entType with id: %s not supported as child ent' % (str(ent.getId()))) 59 | self.__childEnt = childEnt 60 | 61 | def getConstructionElements(self): 62 | """ 63 | Return the base entity 64 | """ 65 | return self._constructionElements 66 | 67 | def setConstructionElement(self, constructionElements): 68 | """ 69 | set the construction elements for the object 70 | """ 71 | if not isinstance(constructionElements,dict): 72 | raise TypeError('type error in dictionary') 73 | self._constructionElements = constructionElements 74 | -------------------------------------------------------------------------------- /Generic/Kernel/entity.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module provide basic DB class for storing entity in pythoncad 22 | # 23 | 24 | from Db.pycadobject import * 25 | from GeoEntity.point import Point 26 | 27 | class Entity(PyCadObject): 28 | """ 29 | basic PythonCad entity structure 30 | """ 31 | def __init__(self, entType, constructionElements, style, objId): 32 | from Generic.Kernel.initsetting import PY_CAD_ENT 33 | if not entType in PY_CAD_ENT: 34 | raise TypeError('entType not supported') 35 | if not isinstance(constructionElements,dict): 36 | raise TypeError('type error in dictionary') 37 | PyCadObject.__init__(self, eType=entType, objId=objId, style=style) 38 | self.setConstructionElements(constructionElements) 39 | 40 | def __str__(self): 41 | return ('Entity : %s' % self.eType) 42 | 43 | def getBBox(self): 44 | """ 45 | get the bounding Box Of the entity 46 | """ 47 | return self.__bBox 48 | 49 | def updateBBox(self): 50 | """ 51 | update the bounding box from the construction elements 52 | """ 53 | # Todo : Find a better way to create the bounding box for all 54 | # the geometrical entity may be is better that all the geometrical 55 | # entity have an implementatio of the bounding box 56 | self.__bBox = (0, 0, 0, 0) 57 | return 58 | _xList = [] 59 | _yList = [] 60 | for key in self._constructionElements: 61 | if isinstance(self._constructionElements[key], Point): 62 | x,y = self._constructionElements[key].getCoords() 63 | _xList.append(x) 64 | _yList.append(y) 65 | _xList.sort() 66 | _yList.sort() 67 | if len(_xList) > 0: 68 | if len(_xList) == 1: 69 | _yList = _xList 70 | self.__bBox = (_xList[0], _yList[0], _xList[-1], _yList[-1]) 71 | else: 72 | self.__bBox = (0, 0, 0, 0) 73 | 74 | def getConstructionElements(self): 75 | """ 76 | return the base entity array 77 | """ 78 | return self._constructionElements 79 | 80 | def setConstructionElements(self, constructionElements): 81 | """ 82 | set the construction elements for the object 83 | """ 84 | self._constructionElements = constructionElements 85 | self.updateBBox() 86 | 87 | def toGeometricalEntity(self): 88 | """ 89 | Convert an entity into a geometrical entity 90 | """ 91 | from Kernel.initsetting import DRAWIN_ENTITY 92 | geoEnt = None 93 | cObjecs = self.getConstructionElements() 94 | cType = self.getEntityType() 95 | for key in DRAWIN_ENTITY: 96 | if DRAWIN_ENTITY[key] == cType: 97 | if cType == "POINT": 98 | geoEnt = Point(cObjecs["POINT_0"], cObjecs["POINT_1"]) 99 | else: 100 | geoEnt = key(cObjecs) 101 | break 102 | return geoEnt 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /Generic/Kernel/layer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2002, 2003, 2004, 2005, 2006 Art Haas 2009 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # classes that describe the layer 22 | # 23 | 24 | class Layer(object): 25 | """ 26 | this class manage a single layer 27 | """ 28 | def __init__(self, layerName = None): 29 | """ 30 | name = name of the layer 31 | parentLayerObj = parent layer object 32 | styleObj = styleObject 33 | """ 34 | self.name = layerName 35 | 36 | def getName(self): 37 | """ 38 | get the layer name 39 | """ 40 | return self.__name 41 | 42 | def setName(self, layerName): 43 | """ 44 | set the layer name 45 | """ 46 | if len(layerName) == 0: 47 | raise ValueError("You mast provide a name for the layer") 48 | 49 | self.__name = layerName 50 | 51 | name = property(getName, setName, None, "Get/Set The layer name") 52 | -------------------------------------------------------------------------------- /Generic/Kernel/pycadevent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # 22 | # This module define a custom event class 23 | # 24 | class PyCadEvent(object): 25 | """ 26 | this class fire the envent from the python kernel 27 | """ 28 | def __init__(self): 29 | self.handlers = set() 30 | 31 | def handle(self, handler): 32 | self.handlers.add(handler) 33 | return self 34 | 35 | def unhandle(self, handler): 36 | try: 37 | self.handlers.remove(handler) 38 | except: 39 | raise ValueError("PythonCad Handler is not handling this event.") 40 | return self 41 | 42 | def fire(self, *args, **kargs): 43 | for handler in self.handlers: 44 | handler(*args, **kargs) 45 | 46 | def getHandlerCount(self): 47 | return len(self.handlers) 48 | 49 | __iadd__ = handle 50 | __isub__ = unhandle 51 | __call__ = fire 52 | __len__ = getHandlerCount 53 | -------------------------------------------------------------------------------- /Generic/Kernel/pycadtransaction.py: -------------------------------------------------------------------------------- 1 | class Transaction(object): 2 | 3 | def __init__(self, connection): 4 | 5 | self._connection = connection 6 | self._cursor = self._connection.cursor() 7 | 8 | 9 | def _GetCursor(self): 10 | return self._cursor 11 | 12 | Cursor = property(_GetCursor, None, None, "gets the cursor") 13 | 14 | 15 | def Close(self, commit): 16 | 17 | if commit == True: 18 | # commit transaction 19 | self._connection.commit() 20 | else: 21 | # abort transaction 22 | self._connection.abort() 23 | # close cursor 24 | self._cursor.close() 25 | -------------------------------------------------------------------------------- /Generic/Kernel/settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # 22 | # This module provide all the basic operation for the pythoncad settings 23 | # 24 | 25 | class Settings(object): 26 | """ 27 | this class provide access at all the pythoncad settings 28 | """ 29 | def __init__(self, name): 30 | """ 31 | the name of the settings schema 32 | """ 33 | self.__name = name 34 | self.__activeLayer = "ROOT" 35 | self.__property = {} 36 | 37 | @property 38 | def name(self): 39 | """ 40 | get the settings Name 41 | """ 42 | return self.__name 43 | 44 | @name.setter 45 | def name(self, name): 46 | """ 47 | set the settings name 48 | """ 49 | self.__name = name 50 | 51 | @property 52 | def layerName(self): 53 | """ 54 | get the anctive layer of the settings 55 | """ 56 | return self.__activeLayer 57 | 58 | @layerName.setter 59 | def layerName(self, lName): 60 | """ 61 | set the active layer id 62 | """ 63 | self.__activeLayer = lName 64 | 65 | def getVariable(self, name): 66 | """ 67 | Get The variable in the settings object 68 | """ 69 | # if self.__property and self.__property.has_key(name): 70 | if self.__property and (name in self.__property): 71 | return self.__property[name] 72 | return None 73 | 74 | def setVariable(self, name, value): 75 | """ 76 | Set The variable in the settings object 77 | """ 78 | self.__property[name] = value 79 | -------------------------------------------------------------------------------- /Generic/Kernel/unitparser.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module provide a parser for the imput interface 22 | # 23 | from sympy.physics import units as u 24 | 25 | def decodePoint(value, previusPoint=None): 26 | """ 27 | this static method decode an imput and return a point(mm,mm) 28 | """ 29 | value = str(value).lower() 30 | from Kernel.GeoEntity.point import Point 31 | x, y = str(value).split(',') 32 | return Point(convertLengh(x), convertLengh(y)) 33 | 34 | def convertAngle(value): 35 | """ 36 | convert a angle in simpy units syntax into a rad float 37 | """ 38 | value = str(value).lower() 39 | retVal = None 40 | try: 41 | retVal = float(value) 42 | except: 43 | try: 44 | retVal = sympyConvertAngle(value) 45 | except: 46 | print("Wrong formatting string") 47 | finally: 48 | return retVal 49 | 50 | def sympyConvertAngle(value): 51 | retVal = None 52 | value = 'retVal=' + value 53 | exec(value) 54 | retVal = retVal / u.rad 55 | return float(retVal) 56 | 57 | def convertLengh(value): 58 | """ 59 | convert a lengh in simpy units syntax into a mm float 60 | return : Float 61 | """ 62 | value = str(value).lower() 63 | retVal = None 64 | try: 65 | retVal = float(value) 66 | except: 67 | try: 68 | retVal = sympyConvertLeng(value) 69 | except: 70 | print("Wrong formatting string") 71 | finally: 72 | return retVal 73 | 74 | def sympyConvertLeng(value): 75 | retVal = None 76 | value = 'retVal=' + value 77 | exec(value) 78 | retVal = retVal / u.mm 79 | return float(retVal.n()) 80 | 81 | if __name__ == '__main__': 82 | print(convertLengh('10*u.m+3.5*u.cm+10*u.ft')) 83 | print(convertAngle('10')) 84 | print(convertAngle('90*u.deg')) 85 | print(sympyConvertAngle('10*u.rad+10*u.deg')) 86 | -------------------------------------------------------------------------------- /Generic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Generic/__init__.py -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | Windows from binary: Just use the installer provided 5 | 6 | From Source (All Platform) 7 | Install Python 3.3 or later 8 | Install Sympy 9 | Install PyQt5 10 | 11 | execute python pythoncad_qt.py (under the pythoncad Folder) 12 | 13 | 14 | Problems 15 | ======== 16 | 17 | If something doesn't work plese call me at matteo.boscolo@boscolini.eu or go to the official web site http://sourceforge.net/projects/pythoncad/ 18 | 19 | 20 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Windows from binary 4 | 5 | Just use the installer provided 6 | 7 | # From source (all Platforms) 8 | 9 | 1. Install Python 3.3 or later 10 | 2. Install sympy 11 | 3. Install PyQt5 12 | 4. Execute python/python3 pythoncad_qt.py (when in the pythoncad folder) 13 | 14 | # Problems 15 | 16 | If something doesn't work plese call me at matteo.boscolo@boscolini.eu or 17 | go to the official web site http://sourceforge.net/projects/pythoncad/. 18 | Alternatively you can create an issue on the GitHub page of the PythonCAD3 19 | project: https://github.com/Csega/PythonCAD3. 20 | -------------------------------------------------------------------------------- /Interface/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | -------------------------------------------------------------------------------- /Interface/CmdIntf/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010, PythonCad team 3 | # 4 | # Cui = custom user interface 5 | # The custom user interface defines menu's, toolbars and palettes 6 | # which are used to interact with the user. 7 | 8 | 9 | -------------------------------------------------------------------------------- /Interface/CmdIntf/cmdaction.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 12, 2010 3 | 4 | @author: gertwin 5 | ''' 6 | 7 | # This is only needed for Python v2 but is harmless for Python v3. 8 | import sip 9 | sip.setapi('QString', 2) 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | 15 | class CmdAction(QtWidgets.QAction): 16 | ''' 17 | Derived action class to hold a command name. 18 | The FunctionHandler class handles signals emitted by this class. 19 | ''' 20 | 21 | def __init__(self, command, icon, text, parent, function_handler): 22 | ''' 23 | Parameters: 24 | command: name of the command. 25 | function_handler: reference to the function_handler object. 26 | ''' 27 | if not icon is None: 28 | super(CmdAction, self).__init__(icon, text, parent, triggered=self._actionHandler) 29 | else: 30 | super(CmdAction, self).__init__(text, parent, triggered=self._actionHandler) 31 | # command name 32 | self.__command = command 33 | # function handler 34 | self.__function_handler = function_handler 35 | # visible 36 | self.__visible = True 37 | return 38 | 39 | def show(self): 40 | """ 41 | show the command 42 | """ 43 | self.setEnabled(True) 44 | 45 | def hide(self): 46 | """ 47 | hide the command 48 | """ 49 | self.setEnabled(False) 50 | 51 | @property 52 | def command(self): 53 | """ 54 | get the command name 55 | """ 56 | return self.__command 57 | 58 | def _actionHandler(self): 59 | ''' 60 | All actions are handled by the function handler. 61 | From the function handler the command call-back is called. 62 | ''' 63 | self.__function_handler.evaluate(self.__command) 64 | return 65 | 66 | 67 | -------------------------------------------------------------------------------- /Interface/CmdIntf/cmdcategory.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Art Haas 3 | # Copyright (c) 2009, 2010 Matteo Boscolo, Gertwin Groen 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the termscl_bo of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # 22 | 23 | 24 | class CmdCategory(object): 25 | ''' 26 | Defines all possible categories for the user input interface 27 | A category represents a menu or a tool-bar. 28 | ''' 29 | 30 | def __init__(self, main_window): 31 | ''' 32 | Create category attributes from a string. 33 | Adding a category is adding it to the string categories. 34 | ''' 35 | # list with menus 36 | self.__menus = {} 37 | # list with tool-bars 38 | self.__toolbars = {} 39 | # categories defines all possible categories 40 | self.__categories = 'File Edit Draw Modify View Snap Tools Windows Help' 41 | # create attributes from the categories string 42 | for number, category in enumerate(self.__categories.split()): 43 | # create menu 44 | menu_name = '&' + category 45 | menu = main_window.menuBar().addMenu(menu_name) 46 | self.__menus[number] = menu 47 | # create tool-bar 48 | toolbar = main_window.addToolBar(category) 49 | toolbar.setObjectName(category) #this is needed for remember toolbar position in cadwindow.writesettings(savestate) 50 | self.__toolbars[number] = toolbar 51 | # set attribute for category 52 | setattr(self, category, number) 53 | return 54 | 55 | 56 | def getMenu(self, number): 57 | ''' 58 | Gets an menu from the list. 59 | The number is the enumerated number from the categories string 60 | ''' 61 | # if self.__menus.has_key(number): 62 | if number in self.__menus: 63 | return self.__menus[number] 64 | return None 65 | 66 | @property 67 | def getToolbarList(self): 68 | return self.__toolbars 69 | 70 | def getToolbar(self, number): 71 | ''' 72 | Gets an tool-bar from the list. 73 | The number is the enumerated number from the categories string 74 | ''' 75 | #if self.__toolbars.has_key(number): 76 | if number in self.__toolbars: 77 | return self.__toolbars[number] 78 | return None 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Interface/Command/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Interface/Command/__init__.py -------------------------------------------------------------------------------- /Interface/Command/distance2point.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # This module provide a command to calculate the distance from 2 point 22 | # 23 | 24 | import math 25 | 26 | from Kernel.exception import * 27 | from Kernel.Command.basecommand import * 28 | 29 | class Distance2Point(BaseCommand): 30 | """ 31 | This class rappresent the distance 2 point command 32 | """ 33 | def __init__(self, document, iDocument): 34 | BaseCommand.__init__(self, document) 35 | self.iDocuemnt=iDocument 36 | self.exception=[ExcPoint, ExcPoint] 37 | self.defaultValue=[None, None] 38 | self.message=["Give Me the first Point", 39 | "Give Me the second Point"] 40 | 41 | def applyCommand(self): 42 | if len(self.value)<1: 43 | raise PyCadWrongImputData("Wrong number of imput parameter") 44 | leng=self.value[0].dist(self.value[1]) 45 | msg="Lenght, "+ str(leng) 46 | self.iDocuemnt.popUpInfo(msg) 47 | -------------------------------------------------------------------------------- /Interface/Entity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Interface/Entity/__init__.py -------------------------------------------------------------------------------- /Interface/Entity/arc.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) ,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # qt arc class 22 | # 23 | 24 | from Interface.Entity.base import * 25 | 26 | class Arc(BaseEntity): 27 | """ 28 | this class define the arcQT object 29 | """ 30 | def __init__(self, entity): 31 | super(Arc, self).__init__(entity) 32 | geoEnt=self.geoItem # get the geometry from kernel 33 | self.startPoint, p2=geoEnt.getEndpoints() 34 | self.xc, self.yc=geoEnt.center.getCoords() 35 | startAngle=geoEnt.startAngle 36 | self.sa=startAngle 37 | spanAngle=geoEnt.endAngle 38 | self.yc=(-1.0*self.yc)- geoEnt.radius 39 | self.xc=self.xc-geoEnt.radius 40 | self.h=geoEnt.radius*2 41 | # By default, the span angle is 5760 (360 * 16, a full circle). 42 | # From pythoncad the angle are in radiant .. 43 | startAngle=(startAngle*180/math.pi)*16 44 | spanAngle=(spanAngle*180/math.pi)*16 45 | spanAngle=spanAngle 46 | self.startAngle=startAngle 47 | self.spanAngle=spanAngle 48 | return 49 | 50 | def arcRect(self): 51 | return QtCore.QRectF(self.xc, 52 | self.yc, 53 | self.h, 54 | self.h) 55 | 56 | 57 | def drawShape(self, painterPath): 58 | """ 59 | extending of the shape method 60 | """ 61 | x, y=self.startPoint.getCoords() 62 | painterPath.moveTo(x, y*-1.0) 63 | painterPath.arcTo(self.arcRect(),self.startAngle/16.0,self.spanAngle/16.0) 64 | return 65 | 66 | def drawGeometry(self, painter, option, widget): 67 | """ 68 | extending of the paint method 69 | """ 70 | #Create Arc/Circle 71 | 72 | painter.drawArc(self.arcRect(),self.startAngle, self.spanAngle) 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Interface/Entity/arrowitem.py: -------------------------------------------------------------------------------- 1 | #QLinearGradient myGradient; 2 | #QPen myPen; 3 | #QPolygonF myPolygon; 4 | 5 | #QPainterPath myPath; 6 | #myPath.addPolygon(myPolygon); 7 | 8 | #QPainter painter(this); 9 | #painter.setBrush(myGradient); 10 | #painter.setPen(myPen); 11 | #painter.drawPath(myPath); 12 | 13 | import math 14 | from PyQt5 import QtCore, QtGui, QtWidgets 15 | 16 | class ArrowItem(QtWidgets.QGraphicsItem): 17 | 18 | def definePath(self): 19 | poligonArrow = QtGui.QPolygonF() 20 | poligonArrow.append(QtCore.QPointF(0.0, 5.0)) 21 | poligonArrow.append(QtCore.QPointF(60.0, 5.0)) 22 | poligonArrow.append(QtCore.QPointF(60.0, 10.0)) 23 | poligonArrow.append(QtCore.QPointF(80.0, 0.0)) 24 | poligonArrow.append(QtCore.QPointF(60.0, -10.0)) 25 | poligonArrow.append(QtCore.QPointF(60.0, -5.0)) 26 | poligonArrow.append(QtCore.QPointF(0.0, -5.0)) 27 | poligonArrow.append(QtCore.QPointF(0.0, 5.0)) 28 | 29 | arrowPath = QtGui.QPainterPath() 30 | arrowPath.addPolygon(poligonArrow) 31 | return arrowPath 32 | 33 | def boundingRect(self): 34 | """ 35 | overloading of the qt bounding rectangle 36 | """ 37 | return QtCore.QRectF(-1, -250, 80, 50) 38 | 39 | def paint(self, painter, option, widget): 40 | """ 41 | overloading of the paint method 42 | """ 43 | painter.setPen(QtGui.QPen(QtGui.QColor(79, 106, 25))) 44 | painter.setBrush(QtGui.QColor(122, 163, 39)) 45 | painter.drawPath(self.definePath()) 46 | -------------------------------------------------------------------------------- /Interface/Entity/ellipse.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) ,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # qt ellipse class 22 | # 23 | from Interface.Entity.base import * 24 | 25 | class Ellipse(BaseEntity): 26 | 27 | def __init__(self, entity): 28 | super(Ellipse, self).__init__(entity) 29 | geoEnt=self.geoItem 30 | self.xc,self.yc=geoEnt.center.getCoords() 31 | self.yc=self.yc*-1.0 32 | self.h=geoEnt.verticalRadius 33 | self.w=geoEnt.horizontalRadius 34 | self.setPos(QtCore.QPointF(self.xc, self.yc)) 35 | self.rotate(0.0) 36 | return 37 | 38 | def drawShape(self, painterPath): 39 | """ 40 | called from the shape method 41 | """ 42 | w2=self.w/2.0 43 | h2=self.h/2.0 44 | painterPath.addEllipse(-w2,-h2,self.w,self.h ) 45 | 46 | def drawGeometry(self, painter, option, widget): 47 | """ 48 | called from the paint method 49 | """ 50 | # Create Ellipse 51 | painter.drawEllipse(self.boundingRect()) 52 | 53 | -------------------------------------------------------------------------------- /Interface/Entity/point.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) ,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # qt pythoncad Point class 22 | # 23 | 24 | from Interface.Entity.base import * 25 | 26 | class Point(BaseEntity): 27 | """ 28 | this class define the arcQT object 29 | """ 30 | def __init__(self, entity): 31 | super(Point, self).__init__(entity) 32 | self.xc,self.yc = self.geoItem.getCoords() 33 | self.yc = (-1.0 * self.yc) 34 | return 35 | 36 | def drawShape(self, painterPath): 37 | """ 38 | overloading of the shape method 39 | """ 40 | painterPath.addRect (QtCore.QRectF(self.xc - 2,self.yc - 2 , 4, 4)) 41 | 42 | def drawGeometry(self, painter, option, widget): 43 | """ 44 | overloading of the paint method 45 | """ 46 | # Create Arc/Circle 47 | p = QtCore.QPoint(self.xc, self.yc) 48 | painter.drawRect(self.boundingRect()) # self.xc-2,self.yc-2 ,4 ,4) with coordinates seems better 49 | painter.drawPoint(p) 50 | -------------------------------------------------------------------------------- /Interface/Entity/polyline.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) ,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # qt arc class 22 | # 23 | 24 | from Interface.Entity.base import * 25 | 26 | class Polyline(BaseEntity): 27 | """ 28 | this class define the polyline object 29 | """ 30 | def __init__(self, entity): 31 | super(Polyline, self).__init__(entity) 32 | self.qtPoints=self.getQtPointF() 33 | return 34 | 35 | def getQtPointF(self): 36 | qtPoints=[] 37 | geoPolyline=self.geoItem 38 | for p in geoPolyline.points(): 39 | x, y=p.getCoords() 40 | qtPointf=QtCore.QPointF(x, y*-1.0 ) 41 | qtPoints.append(qtPointf) 42 | return qtPoints 43 | 44 | def drawShape(self, painterPath): 45 | """ 46 | overloading of the shape method 47 | """ 48 | painterPath.moveTo(self.qtPoints[0]) 49 | for i in range(1,len(self.qtPoints)): 50 | painterPath.lineTo(self.qtPoints[i]) 51 | 52 | def drawGeometry(self, painter, option, widget): 53 | """ 54 | overloading of the paint method 55 | """ 56 | #Create poliline Object 57 | pol=QtGui.QPolygonF(self.qtPoints) 58 | painter.drawPolyline(pol) 59 | #painter.drawRect(self.boundingRect()) 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Interface/Entity/segment.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2009,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # classes for interface segment 22 | # 23 | from Interface.Entity.base import * 24 | 25 | class Segment(BaseEntity): 26 | 27 | def __init__(self, entity): 28 | super(Segment, self).__init__(entity) 29 | p1, p2=self.geoItem.getEndpoints() 30 | self.x, self.y=p1.getCoords() 31 | self.x1, self.y1=p2.getCoords() 32 | self.y=self.y*-1.0 33 | self.y1=self.y1*-1.0 34 | return 35 | 36 | def drawShape(self, painterPath): 37 | """ 38 | overloading of the shape method 39 | """ 40 | painterPath.moveTo(self.x, self.y) 41 | painterPath.lineTo(self.x1, self.y1) 42 | 43 | def drawGeometry(self, painter, option, widget): 44 | #Create Segment 45 | p1=QtCore.QPointF(self.x, self.y) 46 | p2=QtCore.QPointF(self.x1, self.y1) 47 | painter.drawLine(p1,p2) 48 | -------------------------------------------------------------------------------- /Interface/Entity/text.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) ,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # qt text class 22 | # 23 | 24 | from Interface.Entity.base import * 25 | from math import degrees 26 | class Text(BaseEntity): 27 | def __init__(self, entity): 28 | super(Text, self).__init__(entity) 29 | geoEnt=self.geoItem 30 | self.text=geoEnt.text #QtCore.QString(geoEnt.text) 31 | x, y=geoEnt.location.getCoords() 32 | self.angle=degrees(geoEnt.angle) 33 | self.location=QtCore.QPointF(float(x), -1.0*y) 34 | self.pointPosition=geoEnt.pointPosition 35 | self.font=QtGui.QFont() #This have to be derived from the geoent as son is implemented 36 | self.setPos(self.location) 37 | self.rotate(self.angle) 38 | return 39 | 40 | def drawShape(self, painterPath): 41 | """ 42 | overloading of the shape method 43 | """ 44 | painterPath.addText(QtCore.QPointF(0.0, 0.0), self.font, self.text) 45 | return 46 | 47 | 48 | def drawGeometry(self, painter, option, widget): 49 | #Create Text 50 | painter.drawText(self.boundingRect(),QtCore.Qt.AlignCenter, self.text) 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Interface/LayerIntf/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010, PythonCad team 3 | # 4 | # Cui = custom user interface 5 | # The custom user interface defines menu's, toolbars and palettes 6 | # which are used to interact with the user. 7 | 8 | 9 | -------------------------------------------------------------------------------- /Interface/LayerIntf/layerdock.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # This is only needed for Python v2 but is harmless for Python v3. 4 | import sip 5 | sip.setapi('QString', 2) 6 | 7 | from PyQt5 import QtCore, QtGui, QtWidgets 8 | from Interface.pycadapp import PyCadApp 9 | 10 | 11 | class LayerDock(QtWidgets.QDockWidget): 12 | ''' 13 | A dockable window containing a layer list object. 14 | The layer list contains all visible layers. 15 | ''' 16 | 17 | def __init__(self, parent): 18 | ''' 19 | Creates an edit line in which commands or expressions are evaluated. 20 | Evaluation of expressions is done by the FunctionHandler object. 21 | ''' 22 | super(LayerDock, self).__init__('Layers', parent) 23 | # only dock at the bottom or top 24 | self.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) 25 | self.__layer_ctrl = QtWidgets.QTreeWidget(self, itemDoubleClicked=self._itemActivated, itemActivated=self._itemActivated, itemSelectionChanged=self._itemSelectionChanged) 26 | self.setWidget(self.__layer_ctrl) 27 | 28 | 29 | def ShowAllLayers(self): 30 | ''' 31 | Show all layers from the kernel in the control 32 | ''' 33 | # application object from the kernel 34 | appl = getApplication() 35 | if appl: 36 | doc = appl.getActiveDocument() 37 | if doc: 38 | layer_tree = doc.LayerTree 39 | if layer_tree: 40 | self._populateLayerCtrl(self.__layer_ctrl.invisibleRootItem(), layer_tree) 41 | return 42 | 43 | 44 | def _populateLayerCtrl(self, item, layers): 45 | ''' 46 | Show layers from the kernel in the layer list/tree/ctrl 47 | ''' 48 | if layers: 49 | for layer in layers: 50 | parent, children = layers[layer] 51 | # add parent to the tree 52 | 53 | 54 | # add child layers to the tree 55 | self._populateLayerCtrl(item, children) 56 | return 57 | 58 | 59 | def _itemActivated(self, item): 60 | ''' 61 | Make the selected layer in the list the active layer 62 | ''' 63 | 64 | return 65 | 66 | 67 | def _itemSelectionChanged(self, item): 68 | ''' 69 | The user selects an layer from the list 70 | ''' 71 | 72 | return 73 | 74 | 75 | def addLayer(self, layer): 76 | ''' 77 | Add a new layer to the drawing 78 | ''' 79 | 80 | return 81 | -------------------------------------------------------------------------------- /Interface/LayerIntf/layeritem.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo, Gertwin Groen 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module contain a layer item used in the layer tree 22 | # 23 | 24 | from PyQt4 import QtCore, QtGui 25 | 26 | 27 | class LayerItem(object): 28 | 29 | def __init__(self, data, parent=None): 30 | self.parent_item = parent 31 | self.item_data = data 32 | self.children = [] 33 | 34 | 35 | def appendChild(self, item): 36 | self.children.append(item) 37 | 38 | 39 | def child(self, row): 40 | return self.children[row] 41 | 42 | 43 | def childCount(self): 44 | return len(self.children) 45 | 46 | 47 | def columnCount(self): 48 | return len(self.item_data) 49 | 50 | 51 | def data(self, column): 52 | try: 53 | return self.item_data[column] 54 | except IndexError: 55 | return None 56 | 57 | 58 | def parent(self): 59 | return self.parent_item 60 | 61 | 62 | def row(self): 63 | if self.parent_item: 64 | return self.parent_item.children.index(self) 65 | return 0 66 | 67 | -------------------------------------------------------------------------------- /Interface/LayerIntf/layermodel.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo, Gertwin Groen 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module contain a layer model used in the layer tree 22 | # 23 | 24 | from PyQt4 import QtCore, QtGui 25 | from Interface.LayerIntf.layeritem import LayerItem 26 | 27 | 28 | class LayerModel(QtCore.QAbstractItemModel): 29 | 30 | def __init__(self, data, parent=None): 31 | super(LayerModel, self).__init__(parent) 32 | 33 | self.rootItem = LayerItem(("Title", "Summary")) 34 | self.setupModelData(data.split('\n'), self.rootItem) 35 | 36 | 37 | def columnCount(self, parent): 38 | if parent.isValid(): 39 | return parent.internalPointer().columnCount() 40 | else: 41 | return self.rootItem.columnCount() 42 | 43 | 44 | def data(self, index, role): 45 | if not index.isValid(): 46 | return None 47 | 48 | if role != QtCore.Qt.DisplayRole: 49 | return None 50 | 51 | item = index.internalPointer() 52 | 53 | return item.data(index.column()) 54 | 55 | 56 | def flags(self, index): 57 | if not index.isValid(): 58 | return QtCore.Qt.NoItemFlags 59 | 60 | return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable 61 | 62 | 63 | def headerData(self, section, orientation, role): 64 | if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: 65 | return self.rootItem.data(section) 66 | 67 | return None 68 | 69 | 70 | def index(self, row, column, parent): 71 | if not self.hasIndex(row, column, parent): 72 | return QtCore.QModelIndex() 73 | 74 | if not parent.isValid(): 75 | parentItem = self.rootItem 76 | else: 77 | parentItem = parent.internalPointer() 78 | 79 | childItem = parentItem.child(row) 80 | if childItem: 81 | return self.createIndex(row, column, childItem) 82 | else: 83 | return QtCore.QModelIndex() 84 | 85 | 86 | def parent(self, index): 87 | if not index.isValid(): 88 | return QtCore.QModelIndex() 89 | 90 | childItem = index.internalPointer() 91 | parentItem = childItem.parent() 92 | 93 | if parentItem == self.rootItem: 94 | return QtCore.QModelIndex() 95 | 96 | return self.createIndex(parentItem.row(), 0, parentItem) 97 | 98 | 99 | def rowCount(self, parent): 100 | if parent.column() > 0: 101 | return 0 102 | 103 | if not parent.isValid(): 104 | parentItem = self.rootItem 105 | else: 106 | parentItem = parent.internalPointer() 107 | 108 | return parentItem.childCount() 109 | 110 | 111 | def setupModelData(self, lines, parent): 112 | parents = [parent] 113 | indentations = [0] 114 | 115 | number = 0 116 | 117 | while number < len(lines): 118 | position = 0 119 | while position < len(lines[number]): 120 | if lines[number][position] != ' ': 121 | break 122 | position += 1 123 | 124 | lineData = lines[number][position:].trimmed() 125 | 126 | if lineData: 127 | # Read the column data from the rest of the line. 128 | columnData = [s for s in lineData.split('\t') if s] 129 | 130 | if position > indentations[-1]: 131 | # The last child of the current parent is now the new 132 | # parent unless the current parent has no children. 133 | 134 | if parents[-1].childCount() > 0: 135 | parents.append(parents[-1].child(parents[-1].childCount() - 1)) 136 | indentations.append(position) 137 | 138 | else: 139 | while position < indentations[-1] and len(parents) > 0: 140 | parents.pop() 141 | indentations.pop() 142 | 143 | # Append a new item to the current parent's list of children. 144 | parents[-1].appendChild(LayerItem(columnData, parents[-1])) 145 | 146 | number += 1 147 | 148 | -------------------------------------------------------------------------------- /Interface/Preview/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/Interface/Preview/__init__.py -------------------------------------------------------------------------------- /Interface/Preview/arc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # SegmentPreview object 22 | # 23 | import math 24 | 25 | from Interface.Preview.base import * 26 | 27 | class QtArcItem(BaseQtPreviewItem): 28 | def __init__(self, command): 29 | super(QtArcItem, self).__init__(command) 30 | # get the geometry 31 | 32 | def drawGeometry(self, painter,option,widget): 33 | """ 34 | overloading of the paint method 35 | """ 36 | if self.center and self.radius: 37 | # By default, the span angle is 5760 (360 * 16, a full circle). 38 | # From pythoncad the angle are in radiant .. 39 | startAngle=(self.startAngle*180.0/math.pi)*16.0 40 | spanAngle=(self.spanAngle*180.0/math.pi)*16.0 41 | xc=self.center.x()-self.radius 42 | yc=self.center.y()-self.radius 43 | h=self.radius*2.0 44 | painter.drawArc(xc,yc ,h ,h ,startAngle, spanAngle) 45 | #first angle segment 46 | x=self.center.x() 47 | y=self.center.y() 48 | xsP=self.radius*math.cos(self.startAngle) 49 | ysP=self.radius*math.sin(self.startAngle)*-1.0 50 | painter.drawLine(self.center, QtCore.QPointF(xsP+x, ysP+y)) 51 | #second angle segment 52 | secondAngle=self.startAngle+self.spanAngle 53 | xsP=self.radius*math.cos(secondAngle) 54 | ysP=self.radius*math.sin(secondAngle)*-1.0 55 | painter.drawLine(self.center, QtCore.QPointF(xsP+x, ysP+y)) 56 | 57 | def drawShape(self, painterPath): 58 | """ 59 | overloading of the shape method 60 | """ 61 | 62 | painterPath.arcTo(self.boundingRect(),self.startAngle,self.spanAngle) 63 | 64 | def boundingRect(self): 65 | """ 66 | overloading of the qt bounding rectangle 67 | """ 68 | if self.center and self.radius: 69 | _s=self.radius 70 | xc=self.center.x()-_s 71 | yc=self.center.y()-_s 72 | _h=(_s*2.0) 73 | #print "boundingRect ", xc,yc,_h ,_h 74 | return QtCore.QRectF(xc,yc,_h ,_h) 75 | return QtCore.QRectF(0,0 ,0.1,0.1) 76 | 77 | @property 78 | def center(self): 79 | return self.value[0] 80 | @center.setter 81 | def center(self, value): 82 | self.value[0]=value 83 | self.update(self.boundingRect()) 84 | @property 85 | def radius(self): 86 | return self.value[1] 87 | @radius.setter 88 | def radius(self, value): 89 | self.value[1]=value 90 | self.update(self.boundingRect()) 91 | @property 92 | def startAngle(self): 93 | return self.value[2] 94 | @startAngle.setter 95 | def startAngle(self, value): 96 | self.value[2] =value 97 | self.update(self.boundingRect()) 98 | @property 99 | def spanAngle(self): 100 | return self.value[3] 101 | @spanAngle.setter 102 | def spanAngle(self, value): 103 | self.value[3]=value 104 | self.update(self.boundingRect()) 105 | -------------------------------------------------------------------------------- /Interface/Preview/base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | #This module provide a class for the segment command 22 | # 23 | from PyQt5 import QtCore, QtGui, QtWidgets 24 | 25 | from Kernel.exception import * 26 | from Kernel.GeoEntity.point import Point as GeoPoint 27 | from Kernel.GeoUtil.geolib import Vector 28 | from Kernel.initsetting import PYTHONCAD_PREVIEW_COLOR 29 | 30 | class Base(object): 31 | def __init__(self, command): 32 | """ 33 | inizialize base preview items 34 | """ 35 | self._command = command 36 | self._items = command.lenght 37 | 38 | def getPreviewObject(self): 39 | return None 40 | 41 | 42 | class BaseQtPreviewItem(QtWidgets.QGraphicsItem): 43 | def __init__(self, command): 44 | super(BaseQtPreviewItem, self).__init__() 45 | self.updateColor() 46 | self.value = [] 47 | for dValue in command.defaultValue: 48 | val = self.convertToQTObject(dValue) 49 | self.value.append(val) 50 | 51 | def updateColor(self): 52 | """ 53 | update the preview color 54 | """ 55 | r, g, b = PYTHONCAD_PREVIEW_COLOR 56 | self.color = QtGui.QColor.fromRgb(r, g, b) 57 | 58 | def updatePreview(self, position, distance, kernelCommand): 59 | """ 60 | update the data at the preview item 61 | """ 62 | # Assing default values 63 | for i in range(0, len(kernelCommand.exception)): 64 | if len(self.value) > i: 65 | self.value[i] = self.convertToQTObject(kernelCommand.defaultValue[i]) 66 | else: 67 | self.value.append(self.convertToQTObject(kernelCommand.defaultValue[i])) 68 | # Assing Command Values 69 | for i in range(0, len(kernelCommand.exception)): 70 | if(i < len(kernelCommand.value)): 71 | self.value[i] = self.convertToQTObject(kernelCommand.value[i]) 72 | # Assing mouse keyboard values 73 | index = kernelCommand.valueIndex 74 | try: 75 | raise kernelCommand.exception[index](None) 76 | except(ExcPoint): 77 | self.value[index] = position 78 | except(ExcLenght, ExcInt): 79 | self.value[index] = distance 80 | except(ExcAngle): 81 | p1 = GeoPoint(0.0, 0.0) 82 | p2 = GeoPoint(position.x(), position.y() * -1.0) 83 | self.value[index] = Vector(p1, p2).absAng 84 | except: 85 | return 86 | self.update(self.boundingRect()) 87 | 88 | def paint(self, painter, option, widget): 89 | """ 90 | overloading of the paint method 91 | """ 92 | #painter.setPen(QtGui.QPen(self.color, self.lineWith)) 93 | painter.setPen(QtGui.QPen(self.color)) 94 | #draw geometry 95 | #painter.drawPath(self.shape()) 96 | self.drawGeometry(painter,option,widget) 97 | 98 | def convertToQTObject(self, value): 99 | """ 100 | convert the imput value in a proper value 101 | """ 102 | if isinstance(value, (float, int)): 103 | return value 104 | elif isinstance(value, tuple): 105 | return QtCore.QPointF(value[0], value[1]) 106 | elif isinstance(value, GeoPoint): 107 | return QtCore.QPointF(value.x, value.y * -1.0) 108 | else: 109 | return value 110 | -------------------------------------------------------------------------------- /Interface/Preview/ellipse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # EllipsePreview object 22 | # 23 | import math 24 | 25 | from Interface.Preview.base import * 26 | 27 | class QtEllipseItem(BaseQtPreviewItem): 28 | def __init__(self, command): 29 | super(QtEllipseItem, self).__init__(command) 30 | # get the geometry 31 | 32 | def drawGeometry(self, painter,option,widget): 33 | """ 34 | overloading of the paint method 35 | """ 36 | if self.center: 37 | xc=self.center.x() 38 | yc=self.center.y() 39 | painter.drawEllipse(xc-(self.major/2.0),yc-(self.minor/2.0),self.major ,self.minor) 40 | 41 | def drawShape(self, painterPath): 42 | """ 43 | overloading of the shape method 44 | """ 45 | if self.center: 46 | xc=self.center.x() 47 | yc=self.center.y() 48 | painterPath.drawEllipse(xc-(self.major/2.0),yc-(self.minor/2.0),self.major ,self.minor) 49 | 50 | def boundingRect(self): 51 | """ 52 | overloading of the qt bounding rectangle 53 | """ 54 | if self.center: 55 | xc=self.center.x() 56 | yc=self.center.y() 57 | return QtCore.QRectF(xc-(self.major/2.0),yc- (self.minor/2.0) ,self.major ,self.minor ) 58 | return QtCore.QRectF(0,0 ,0.1,0.1) 59 | 60 | @property 61 | def center(self): 62 | return self.value[0] 63 | @center.setter 64 | def center(self, value): 65 | self.value[0]=value 66 | self.update(self.boundingRect()) 67 | @property 68 | def major(self): 69 | return self.value[1] 70 | @major.setter 71 | def major(self, value): 72 | self.value[1] =value 73 | self.update(self.boundingRect()) 74 | @property 75 | def minor(self): 76 | return self.value[2] 77 | @minor.setter 78 | def minor(self, value): 79 | self.value[2]=value 80 | self.update(self.boundingRect()) 81 | -------------------------------------------------------------------------------- /Interface/Preview/factory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # This module provide a factory for the preview objects 22 | # 23 | from Kernel.Command.segmentcommand import SegmentCommand 24 | from Kernel.Command.arccommand import ArcCommand 25 | from Kernel.Command.rectanglecommand import RectangleCommand 26 | from Kernel.Command.ellipsecommand import EllipseCommand 27 | from Kernel.Command.polylinecommand import PolylineCommand 28 | from Kernel.Command.polygoncommand import PolygonCommand 29 | 30 | from Interface.Preview.segment import QtSegmentItem 31 | from Interface.Preview.arc import QtArcItem 32 | from Interface.Preview.rectangle import QtRectangleItem 33 | from Interface.Preview.ellipse import QtEllipseItem 34 | from Interface.Preview.polyline import QtPolylineItem 35 | from Interface.Preview.polygon import QtPolygonItem 36 | 37 | def getPreviewObject(command): 38 | if isinstance(command , SegmentCommand): 39 | return QtSegmentItem(command) 40 | elif isinstance(command , ArcCommand): 41 | return QtArcItem(command) 42 | elif isinstance(command , RectangleCommand): 43 | return QtRectangleItem(command) 44 | elif isinstance(command , EllipseCommand): 45 | return QtEllipseItem(command) 46 | elif isinstance(command , PolylineCommand): 47 | return QtPolylineItem(command) 48 | elif isinstance(command , PolygonCommand): 49 | return QtPolygonItem(command) 50 | else: 51 | return None 52 | -------------------------------------------------------------------------------- /Interface/Preview/polygon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # SegmentPreview object 22 | # 23 | import math 24 | 25 | from Interface.Preview.base import * 26 | from Kernel.GeoUtil.geolib import Vector 27 | from Kernel.GeoEntity.point import Point 28 | 29 | 30 | class QtPolygonItem(BaseQtPreviewItem): 31 | def __init__(self, command): 32 | super(QtPolygonItem, self).__init__(command) 33 | self.command=command 34 | # get the geometry 35 | @property 36 | def polygonPoint(self): 37 | """ 38 | get the poligon points 39 | """ 40 | if self.side<=0: 41 | self.side=6 42 | deltaAngle=(math.pi*2)/self.side 43 | cPoint=Point(self.center.x(), self.center.y()) 44 | vPoint=Point(self.vertex.x(), self.vertex.y()) 45 | vertexVector=Vector(cPoint, vPoint) 46 | radius=vertexVector.norm 47 | angle=vertexVector.absAng 48 | pol=QtGui.QPolygonF() 49 | pFirst=None 50 | for i in range(0, int(self.side)): 51 | angle=deltaAngle+angle 52 | xsP=cPoint.x+radius*math.cos(angle)*-1.0 53 | ysP=cPoint.y+radius*math.sin(angle)*-1.0 54 | p=QtCore.QPointF(xsP,ysP) 55 | pol.append(p) 56 | if not pFirst: 57 | pFirst=p 58 | if pFirst: 59 | pol.append(pFirst) 60 | return pol 61 | 62 | def drawGeometry(self, painter,option,widget): 63 | """ 64 | overloading of the paint method 65 | """ 66 | if self.center and self.vertex: 67 | painter.drawPolyline(self.polygonPoint) 68 | 69 | def drawShape(self, painterPath): 70 | """ 71 | overloading of the shape method 72 | """ 73 | if self.center and self.vertex: 74 | painter.drawPolyline(self.polygonPoint) 75 | 76 | def boundingRect(self): 77 | """ 78 | overloading of the qt bounding rectangle 79 | """ 80 | if self.center and self.vertex: 81 | return self.polygonPoint.boundingRect() 82 | return QtCore.QRectF(0,0 ,0.1,0.1) 83 | 84 | @property 85 | def center(self): 86 | return self.value[0] 87 | @center.setter 88 | def center(self, value): 89 | self.value[0]=value 90 | self.update(self.boundingRect()) 91 | @property 92 | def vertex(self): 93 | return self.value[1] 94 | @vertex.setter 95 | def vertex(self, value): 96 | self.value[1]=value 97 | self.update(self.boundingRect()) 98 | @property 99 | def side(self): 100 | return self.value[2] 101 | 102 | -------------------------------------------------------------------------------- /Interface/Preview/polyline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # SegmentPreview object 22 | # 23 | import math 24 | 25 | from Interface.Preview.base import * 26 | 27 | class QtPolylineItem(BaseQtPreviewItem): 28 | def __init__(self, command): 29 | super(QtPolylineItem, self).__init__(command) 30 | 31 | 32 | def drawShape(self, painterPath): 33 | """ 34 | overloading of the shape method 35 | """ 36 | first=True 37 | for p in self.value: 38 | if p and first: 39 | painterPath.moveTo(p) 40 | first=false 41 | elif p: 42 | painterPath.lineTo(p) 43 | 44 | def boundingRect(self): 45 | """ 46 | overloading of the qt bounding rectangle 47 | """ 48 | X=[p.x() for p in self.value if p] 49 | Y=[p.y() for p in self.value if p] 50 | if X and Y: 51 | xmax=max(X) 52 | ymax=max(Y) 53 | xmin=min(X) 54 | ymin=min(Y) 55 | h=abs(xmin-xmax) 56 | w=abs(ymin-ymax) 57 | return QtCore.QRectF(xmin,ymin,h ,w) 58 | return QtCore.QRectF(0,0 ,0.1,0.1) 59 | 60 | def drawGeometry(self, painter, option, widget): 61 | """ 62 | overloading of the paint method 63 | """ 64 | #Create polyline Object 65 | pol=QtGui.QPolygonF() 66 | points=[p for p in self.value if p] 67 | #points.reverse() 68 | for p in points: 69 | pol.append(p) 70 | if len(points)>1: 71 | painter.drawPolyline(pol) 72 | 73 | #painter.drawRect(self.boundingRect()) 74 | -------------------------------------------------------------------------------- /Interface/Preview/rectangle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # SegmentPreview object 22 | # 23 | import math 24 | 25 | from Interface.Preview.base import * 26 | from Kernel.GeoEntity.segment import Segment as geoSegment 27 | 28 | class QtRectangleItem(BaseQtPreviewItem): 29 | def __init__(self,command): 30 | super(QtRectangleItem, self).__init__(command) 31 | 32 | def drawGeometry(self, painter,option,widget): 33 | """ 34 | Overloading of the paint method 35 | """ 36 | if self.value[0]!=None and self.value[1]!=None: 37 | painter.drawRect(self.getRectangle()) 38 | 39 | def boundingRect(self): 40 | """ 41 | Overloading of the qt bounding rectangle 42 | """ 43 | if self.value[0]!=None and self.value[1]!=None : 44 | return self.getRectangle() 45 | return QtCore.QRectF(0.0,0.0 ,0.1,0.1) 46 | 47 | def getRectangle(self): 48 | """ 49 | Create the rectangle 50 | """ 51 | x=min(self.value[0].x(), self.value[1].x()) 52 | y=min(self.value[0].y(), self.value[1].y()) 53 | d1=abs(self.value[0].x()-self.value[1].x()) 54 | d2=abs(self.value[0].y()-self.value[1].y()) 55 | return QtCore.QRectF(x,y ,d1,d2) 56 | -------------------------------------------------------------------------------- /Interface/Preview/segment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public Licensesegmentcmd.py 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # SegmentPreview object 22 | # 23 | import math 24 | # 25 | from Interface.Preview.base import * 26 | from Kernel.GeoEntity.segment import Segment as geoSegment 27 | from Kernel.initsetting import PYTHONCAD_PREVIEW_COLOR 28 | # 29 | class QtSegmentItem(BaseQtPreviewItem): 30 | def __init__(self,command): 31 | super(QtSegmentItem, self).__init__(command) 32 | 33 | def drawGeometry(self, painter,option,widget): 34 | """ 35 | Overloading of the paint method 36 | """ 37 | if self.value[0]!=None and self.value[1]!=None: 38 | #print "drawLine", self.value[0],self.value[1] 39 | painter.drawLine(self.value[0],self.value[1]) 40 | 41 | def boundingRect(self): 42 | """ 43 | Overloading of the qt bounding rectangle 44 | """ 45 | if self.value[0]!=None and self.value[1]!=None: 46 | x=min(self.value[0].x(), self.value[1].x()) 47 | y=min(self.value[0].y(), self.value[1].y()) 48 | d1=abs(self.value[0].x()-self.value[1].x()) 49 | d2=abs(self.value[0].y()-self.value[1].y()) 50 | #print "boundingRect", x, y, d1, d2 51 | return QtCore.QRectF(x,y ,d1,d2) 52 | #print "not updated" 53 | return QtCore.QRectF(0.0,0.0 ,0.1,0.1) 54 | -------------------------------------------------------------------------------- /Interface/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2002, Art Haas 3 | # 4 | 5 | # 6 | # don't define an __all__ variable - the value of importing 7 | # different front-end interfaces into a module seems very 8 | # low right now ... 9 | # 10 | 11 | -------------------------------------------------------------------------------- /Interface/caddialogs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo, Carlo Pavan 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # 22 | # This module PROVIDE ALL GLOBAL VARIABLE NEEDE TO THE SCENE 23 | # 24 | 25 | from PyQt5 import QtCore, QtGui, QtWidgets 26 | from Kernel.initsetting import * 27 | 28 | class ConfigDialog(QtWidgets.QDialog): 29 | def __init__(self): 30 | super(ConfigDialog, self).__init__() 31 | self.setWindowTitle("Preferences") 32 | 33 | self.exec_() 34 | 35 | -------------------------------------------------------------------------------- /Interface/cadinitsetting.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010 Matteo Boscolo 4 | # 5 | # This file is part of PythonCAD. 6 | # 7 | # PythonCAD is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # PythonCAD is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with PythonCAD; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | # 22 | # This module PROVIDE ALL GLOBAL VARIABLE NEEDE TO THE SCENE 23 | # 24 | from Interface.Entity.point import Point 25 | from Interface.Entity.segment import Segment 26 | from Interface.Entity.arc import Arc 27 | from Interface.Entity.text import Text 28 | from Interface.Entity.ellipse import Ellipse 29 | from Interface.Entity.polyline import Polyline 30 | 31 | from PyQt5 import QtCore 32 | 33 | from Interface.Command.distance2point import Distance2Point 34 | 35 | SCENE_SUPPORTED_TYPE = ["SEGMENT", 36 | "POINT", 37 | "ARC", 38 | "TEXT", 39 | "ELLIPSE", 40 | "POLYLINE"] 41 | 42 | SCANE_OBJECT_TYPE = dict(zip(SCENE_SUPPORTED_TYPE, 43 | ( 44 | Segment, 45 | Point, 46 | Arc, 47 | Text, 48 | Ellipse, 49 | Polyline 50 | ))) 51 | 52 | INTERFACE_COMMAND = {'DISTANCE2POINT': Distance2Point} 53 | 54 | RESTART_COMMAND_OPTION = True 55 | 56 | BACKGROUND_COLOR = (255, 255, 255) 57 | 58 | KEY_MAP = { 59 | QtCore.Qt.Key_Delete: 'DELETE', 60 | QtCore.Qt.Key_L: 'SEGMENT', 61 | QtCore.Qt.Key_P: 'POLYLINE', 62 | QtCore.Qt.Key_G: 'MOVE', 63 | QtCore.Qt.Key_C: 'COPY', 64 | QtCore.Qt.Key_D: 'DELETE', 65 | QtCore.Qt.Key_R: 'ROTATE', 66 | QtCore.Qt.Key_M: 'MIRROR' 67 | } 68 | -------------------------------------------------------------------------------- /Interface/cadview.py: -------------------------------------------------------------------------------- 1 | 2 | import math 3 | from PyQt5 import QtCore, QtGui, QtWidgets 4 | 5 | from Interface.Entity.base import * 6 | 7 | class CadView(QtWidgets.QGraphicsView): 8 | def __init__(self, scene, parent=None): 9 | super(CadView, self).__init__(scene, parent) 10 | self.scaleFactor = 1 11 | self.controlPress = False 12 | self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag) 13 | self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse) 14 | 15 | #handle mouse midbutton pan and zoom 16 | scene.fireZoomFit += self.fit 17 | scene.firePan += self.Pan 18 | self.firstPanPoint = QtCore.QPointF() 19 | 20 | def Pan(self, panActive, eventPoint): 21 | 22 | if panActive == True: 23 | self.setDragMode(QtWidgets.QGraphicsView.NoDrag) 24 | self.firstPanPoint = eventPoint 25 | elif panActive == False: 26 | self.firstPanPoint = None 27 | self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag) 28 | else: 29 | if self.controlPress == False: 30 | c = QtCore.QPoint((self.width() / 2 - 10), (self.height() / 2 - 10)) 31 | cOnScene = self.mapToScene(c) 32 | vector = self.firstPanPoint-eventPoint 33 | newC = cOnScene + vector 34 | self.centerOn(newC) 35 | 36 | def wheelEvent(self, event): 37 | # get the center of the view in scene coordinates 38 | c = QtCore.QPoint((self.width() / 2.0) - 10, (self.height() / 2.0) - 10) 39 | cOnScene = self.mapToScene(c) 40 | # get the mouse position in scene coordinates 41 | pOnView = event.pos() 42 | pOnScene = self.mapToScene(pOnView) 43 | # old command 44 | self.scaleFactor = math.pow(2.0, event.angleDelta().y() / 240.0) 45 | self.scaleView(self.scaleFactor) 46 | # self.updateShape() << 2 | 3 | images/new.png 4 | images/print.png 5 | images/save.png 6 | images/undo.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /Interface/dinamicentryobject.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo, Gertwin Groen 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module the graphics scene class 22 | # 23 | # 24 | 25 | import math 26 | 27 | from PyQt5 import QtCore, QtGui, QtWidgets 28 | from Kernel.pycadevent import PyCadEvent 29 | 30 | class DinamicEntryLine(QtWidgets.QLineEdit): 31 | def __init__(self): 32 | super(DinamicEntryLine, self).__init__() 33 | self.hide() 34 | self.h = 20 35 | self.w = 60 36 | self.onEnter = PyCadEvent() 37 | 38 | def setPos(self, x, y): 39 | self.setGeometry(x, y, self.w, self.h) 40 | 41 | @property 42 | def text(self): 43 | return super(DinamicEntryLine, self).text() 44 | 45 | @text.setter 46 | def text(self, value): 47 | super(DinamicEntryLine, self).settext(value) 48 | 49 | def show(self): 50 | self.setFocus(7) 51 | super(DinamicEntryLine, self).show() 52 | 53 | def keyPressEvent(self, event): 54 | if event.key() == QtCore.Qt.Key_Return: 55 | self.onEnter() 56 | super(DinamicEntryLine, self).hide() 57 | super(DinamicEntryLine, self).keyPressEvent(event) 58 | -------------------------------------------------------------------------------- /Interface/evaluator.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) ,2010 Matteo Boscolo 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # evaluator Class to manage command computation 22 | # 23 | from math import * 24 | from Interface.pycadapp import PyCadApp 25 | from sympy.physics import units as u 26 | 27 | RESERVED_WORK=['self._print', 'self._error', 'self._ok','self._cadApplication','self.evaluate', 'self._eval', 'self._exec' ] 28 | 29 | class Evaluator(object): 30 | def __init__(self, printFunction): 31 | self._print=printFunction 32 | self._error='*error*' 33 | self._ok='*Ok*' 34 | self._cadApplication=PyCadApp 35 | 36 | def evaluate(self, value): 37 | """ 38 | evaluate the string 39 | """ 40 | if len(value)<=0: 41 | return None 42 | for cmd in RESERVED_WORK: 43 | if value.count(cmd): 44 | return self._error + "->Reserved word" 45 | 46 | 47 | if value[0]=='>': # eval 48 | return self._eval(value[1:]) 49 | if value[0]=='@': 50 | return self._exec(value[1:]) 51 | else: 52 | return value 53 | 54 | def _eval(self, value): 55 | """ 56 | evaluate the evaluated value 57 | """ 58 | try: 59 | return eval(value) 60 | except: 61 | return self._error 62 | 63 | def _exec(self, value): 64 | """ 65 | exec value 66 | """ 67 | try: 68 | value=str(value).replace('print', 'self._print') 69 | value=str(value).replace('pyCad', 'self._cadApplication') 70 | exec(value) 71 | return self._ok 72 | except: 73 | return self._error 74 | 75 | -------------------------------------------------------------------------------- /Interface/idocument.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | from Generic.Kernel.document import * 3 | from Interface.LayerIntf.layerdock import LayerDock 4 | from Interface.cadscene import CadScene 5 | from Interface.cadview import CadView 6 | 7 | class IDocument(QtWidgets.QMdiSubWindow): 8 | sequenceNumber = 1 9 | def __init__(self, document, cmdInf, parent): 10 | super(IDocument, self).__init__(parent) 11 | IDocument.sequenceNumber += 1 12 | self.__document = document 13 | self.__cmdInf = cmdInf 14 | self.__cadwindow = parent 15 | self.setWindowTitle(document.dbPath[0] + '[*]') 16 | self.setAttribute(QtCore.Qt.WA_DeleteOnClose) 17 | self.isUntitled = True 18 | # layer list 19 | self.__layer_dock = LayerDock(self) 20 | self.__scene = CadScene(document) 21 | self.__cmdInf.commandLine.evaluatePressed += self.scene.textInput 22 | self.__view = CadView(self.__scene, self) 23 | # the graphics view is the main/central component 24 | innerWindows = QtWidgets.QMainWindow() 25 | innerWindows.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.__layer_dock) 26 | innerWindows.setCentralWidget(self.__view) 27 | self.setWidget(innerWindows) 28 | #Inizialize scene 29 | self.__scene.initDocumentEvents() 30 | self.__scene.populateScene(document) 31 | self.__scene.zoomWindows += self.__view.zoomWindows 32 | self.__scene.fireCommandlineFocus += self.__cmdInf.commandLine.setFocus 33 | self.__scene.fireKeyShortcut += self.keyShortcut 34 | self.__scene.fireKeyEvent += self.keyEvent 35 | self.__scene.fireWarning += self.popUpWarning 36 | self.__scene.fireCoords += self.setStatusbarCoords 37 | 38 | @property 39 | def document(self): 40 | return self.__document 41 | 42 | @property 43 | def cmdInf(self): 44 | return self.__cmdInf 45 | 46 | @property 47 | def view(self): 48 | return self.__view 49 | 50 | @property 51 | def scene(self): 52 | return self.__scene 53 | 54 | @property 55 | def application(self): 56 | """ 57 | get the kernel application object 58 | """ 59 | return self.__application 60 | 61 | @property 62 | def layerDock(self): 63 | """ 64 | get the layer tree dockable window 65 | """ 66 | return self.__layer_dock 67 | 68 | @property 69 | def fileName(self): 70 | """ 71 | get the current file name 72 | """ 73 | return self.document.dbPath 74 | 75 | def unDo(self): 76 | """ 77 | perform undo on the active document 78 | """ 79 | self.document.unDo() 80 | 81 | def reDo(self): 82 | """ 83 | perform redo on the active document 84 | """ 85 | self.document.reDo() 86 | 87 | def importExternalFormat(self, file): 88 | """ 89 | import an external document 90 | """ 91 | self.document.importExternalFormat(file) 92 | 93 | def renderCurrentScene(self, painter): 94 | """ 95 | render the current scene for the printer 96 | """ 97 | self.view.render(painter) 98 | 99 | 100 | def wWellEWvent(self, event): 101 | self.__view.scaleFactor = math.pow(2.0, -event.delta() / 240.0) 102 | self.__view.scaleView(self.__view.scaleFactor) 103 | 104 | def popUpWarning(self, msg): 105 | """ 106 | popUp a warning mesage 107 | """ 108 | ret = QtGui.QMessageBox.warning(self, "Warning", msg) 109 | return 110 | 111 | def popUpInfo(self, msg): 112 | """ 113 | popUp a Info mesage 114 | """ 115 | ret = QtGui.QMessageBox.information(self, "Information", msg) 116 | return 117 | 118 | #--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 119 | #---------------------------------------------------------------------------------------------------------------------------------------MANAGE SCENE EVENTS 120 | #--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 121 | 122 | def setStatusbarCoords(self, x, y, status): 123 | #set statusbar coordinates when mouse move on the scene 124 | if status == "abs": 125 | self.__cadwindow.coordLabel.setText("X=" + str("%.3f" % x) + "\n"+"Y=" + str("%.3f" % y)) # "%.3f" % sets the precision decimals to 3 126 | elif status == "rel": 127 | self.__cadwindow.coordLabel.setText("dx=" + str("%.3f" % x) + "\n" + "dy=" + str("%.3f" % y)) # "%.3f" % sets the precision decimals to 3 128 | 129 | def keyEvent(self, event): # fire the key event in the scene to the commandline 130 | self.__cmdInf.commandLine._keyPress(event) 131 | pass 132 | 133 | def keyShortcut(self, command): 134 | self.__cadwindow.statusBar().showMessage(str(command)) 135 | self.__cadwindow.callCommand(command) 136 | -------------------------------------------------------------------------------- /Interface/pycadapp.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2010 Matteo Boscolo, Gertwin Groen 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | # 21 | # This module contain global functions 22 | # 23 | 24 | # This is only needed for Python v2 but is harmless for Python v3. 25 | import sip 26 | sip.setapi('QString', 2) 27 | 28 | from PyQt5 import QtGui 29 | 30 | 31 | class PyCadApp(object): 32 | ''' 33 | PyCadApp contain static interface functions to the kernel application object. 34 | ''' 35 | 36 | # kernel application object 37 | __application = None 38 | # main application window 39 | __cad_window = None 40 | 41 | 42 | @staticmethod 43 | def CadWindow(): 44 | ''' 45 | Gets the main window. 46 | The main window is an instance of the CadWindow object. 47 | ''' 48 | return PyCadApp.__cad_window 49 | 50 | 51 | @staticmethod 52 | def SetCadWindow(cad_window): 53 | ''' 54 | Sets the main window. 55 | The main window is an instance of the CadWindow object. 56 | ''' 57 | PyCadApp.__cad_window = cad_window 58 | 59 | 60 | @staticmethod 61 | def Application(): 62 | ''' 63 | Gets the application object from the kernel. 64 | ''' 65 | return PyCadApp.__application 66 | 67 | 68 | @staticmethod 69 | def SetApplication(application): 70 | ''' 71 | Sets the application object from the kernel. 72 | ''' 73 | PyCadApp.__application = application 74 | 75 | 76 | @staticmethod 77 | def ActiveDocument(): 78 | ''' 79 | Gets the current active document in the editor. 80 | ''' 81 | if not PyCadApp.__application is None: 82 | return PyCadApp.__application.getActiveDocument() 83 | return None 84 | 85 | 86 | @staticmethod 87 | def CreateNewDocument(): 88 | ''' 89 | Create a new document. 90 | ''' 91 | if not PyCadApp.__application is None: 92 | PyCadApp.__application.newDocument() 93 | return PyCadApp.__application.getActiveDocument() 94 | return None 95 | 96 | 97 | @staticmethod 98 | def OpenDocument(filename): 99 | ''' 100 | Open an existing document. 101 | ''' 102 | if not PyCadApp.__application is None: 103 | PyCadApp.__application.openDocument(filename) 104 | # return the opened, current active document 105 | return PyCadApp.ActiveDocument() 106 | return None 107 | 108 | 109 | @staticmethod 110 | def critical(text): 111 | ''' 112 | Shows an critical message dialog 113 | ''' 114 | dlg = QtGui.QMessageBox() 115 | dlg.setText(text) 116 | dlg.setIcon(QtGui.QMessageBox.Critical) 117 | dlg.exec_() 118 | return 119 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2002, 2003, 2004, 2005, 2006 Art Haas 3 | # 4 | # This file is part of PythonCAD. 5 | # 6 | # PythonCAD is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # PythonCAD is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with PythonCAD; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | 21 | include NEWS.md 22 | include INSTALL.md 23 | include COPYING 24 | include TODO 25 | include gtkpycad.py 26 | include pythoncad.xsd 27 | include prefs.py 28 | include PythonCad.py 29 | include buildapp.py 30 | include Mac_OS_X_Read_Me.txt 31 | include PythonCAD/Interface/Cocoa/ImageDocument.nib/*.nib 32 | include PythonCAD/Interface/Cocoa/MainMenu.nib/*.nib 33 | include pythoncad.spec 34 | include pythoncad.desktop 35 | include gtkpycad.png 36 | include po/PythonCAD.pot 37 | include po/*.po 38 | 39 | # 40 | 41 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | PythonCAD is an open-source CAD package built designed 5 | around Python. As such, it aims to be a fully scriptable 6 | and customizable CAD program. It is initially designed 7 | to run under Linux, one of the BSD flavors, or Unix. 8 | 9 | Using an established, powerful, and expressive language 10 | like Python as the core of the program saves an enormous 11 | amount of work for developers and, for users who are 12 | already familiar with Python, you don't have to try and 13 | learn a new language if you want to extend or customize 14 | the code. If you've never written Python code before, 15 | there are extensive resources available for you. A good 16 | place to start is at the Python home page ... 17 | 18 | http://www.python.org 19 | 20 | Goals 21 | ===== 22 | 23 | The primary design goal is to provide a good CAD package. 24 | The open-source world has been moving steadily from providing 25 | superior tools for proprietary systems (i.e. GCC), to 26 | world-class operating systems (i.e. Linux), and has advanced 27 | remarkably in providing complete desktop environments (GNOME 28 | and KDE). It is hoped that PythonCAD will grow to be an 29 | excellent addition to the desktop programs now available 30 | for users of open-source software. 31 | 32 | A design goal with the program code is to keep the user 33 | interface completely separated from the back end or generic 34 | code. In doing so, it should be possible for developers to 35 | write code porting PythonCAD to their chosen interface with 36 | less work. The initial release is written using GTK-2.0 as the 37 | interface (utilizing the PyGTK library). The addition of 38 | a front end utilizing the Py-Objc bindings on Mac OS X and 39 | Cocoa demonstrates that this approach of separating the 40 | interface from the core program is a viable approach of 41 | application design. It is hoped that interfaces for GNOME, 42 | QT, KDE, and other packages will eventually be added to 43 | PythonCAD. 44 | Now PythonCAD is developer using the pyQT toolkit 45 | 46 | A second code design goal is to write a powerful graphical 47 | program without writing much, if any, C or C++ code. The Python 48 | language frees the programmer from many of the difficulties 49 | that are associated with C (memory allocation, buffer handling, 50 | etc.) or C++ code (i.e. compiler and platform issues). No 51 | language is perfect, but it is hoped that PythonCAD can 52 | demonstrate that choosing Python as the primary language 53 | for development provides good performance, ease of maintenance, 54 | and a fun language to work with. 55 | 56 | Requirements 57 | ============ 58 | 59 | Python: Version 2.6 at a minimum. 60 | Sympy: last git version 61 | PyQt: 62 | 63 | 64 | License 65 | ======= 66 | 67 | PythonCAD is distributed under the terms of the 68 | GNU General Public License (GPL). 69 | 70 | Modifications 71 | ============= 72 | 73 | Csega is intended to modify the original module, which was written 74 | for Python 2 and has not been maintained since two years at least, 75 | to convert the whole source to Python 3 compatible with the additional 76 | goal to convert from PyQt4 to PyQt5 dependency. 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | PythonCAD is an open-source CAD package built and designed around Python. 4 | As such, it aims to be a fully scriptable and customizable CAD program. 5 | It is initially designed to run under Linux, one of the BSD flavors, or Unix, 6 | however, running it on Windows is now also possible. 7 | 8 | Using an established, powerful, and expressive language like Python as the core 9 | of the program saves an enormous amount of work for developers and, for users 10 | who are already familiar with Python, you don't have to try and learn a new 11 | language if you want to extend or customize the code. If you've never written 12 | Python code before, there are extensive resources available for you. A good 13 | place to start is at the Python home page ... 14 | 15 | http://www.python.org 16 | 17 | # Goals 18 | 19 | The primary design goal is to provide a good CAD package. The open-source world 20 | has been moving steadily from providing superior tools for proprietary systems 21 | (i.e. GCC), to world-class operating systems (i.e. Linux), and has advanced 22 | remarkably in providing complete desktop environments (GNOME and KDE). It is 23 | hoped that PythonCAD will grow to be an excellent addition to the desktop 24 | programs now available for users of open-source software. 25 | 26 | A design goal with the program code is to keep the user interface completely 27 | separated from the backend or the generic code. In doing so, it should be 28 | possible for developers to write code porting PythonCAD to their chosen 29 | interface with less work. The initial release is written using GTK-2.0 as the 30 | interface (utilizing the PyGTK library). The addition of a front end utilizing 31 | the PyObjC bindings on Mac OS X and Cocoa demonstrates that this approach of 32 | separating the interface from the core program is a viable approach of 33 | application design. It is hoped that interfaces for GNOME, QT, KDE, and other 34 | packages will eventually be added to PythonCAD. Now PythonCAD is developed 35 | using the PyQt toolkit. 36 | 37 | A second code design goal is to write a powerful graphical program without 38 | writing much, if any, C or C++ code. The Python language frees the programmer 39 | from many of the difficulties that are associated with C (memory allocation, 40 | buffer handling, etc.) or C++ code (i.e. compiler and platform issues). 41 | No language is perfect, but it is hoped that PythonCAD can demonstrate that 42 | choosing Python as the primary language for development provides good 43 | performance, ease of maintenance, and a fun language to work with. 44 | 45 | # Requirements 46 | 47 | * Python: version 3.3+ 48 | * Sympy: version 1.4 49 | * PyQt: known to work with PyQt5, version 5.12.2 50 | 51 | 52 | # License 53 | 54 | PythonCAD is distributed under the terms of the 55 | GNU General Public License (GPL). 56 | 57 | # Modifications 58 | 59 | Csega is intended to modify the original module, which was written for 60 | Python 2 and has not been maintained since two years at least, to convert 61 | the whole source to Python 3 compatible with the additional goal to convert 62 | from PyQt4 to PyQt5 dependency. 63 | 64 | However, since the package is still not fully functional as of (25th October 2019), Csega is intended to do a deep revision of the whole code base using [Porting Python 2 Code to Python 3](https://docs.python.org/3/howto/pyporting.html) official guide. 65 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/__init__.py -------------------------------------------------------------------------------- /icons/PythonCAD_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/PythonCAD_logo.png -------------------------------------------------------------------------------- /icons/PythoncadLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/PythoncadLogo.png -------------------------------------------------------------------------------- /icons/SForceDir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/SForceDir.png -------------------------------------------------------------------------------- /icons/SGrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/SGrid.png -------------------------------------------------------------------------------- /icons/SSnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/SSnap.png -------------------------------------------------------------------------------- /icons/arc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/arc.png -------------------------------------------------------------------------------- /icons/bisect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/bisect.png -------------------------------------------------------------------------------- /icons/centersnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/centersnap.png -------------------------------------------------------------------------------- /icons/chamfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/chamfer.png -------------------------------------------------------------------------------- /icons/clipboardCopy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/clipboardCopy.png -------------------------------------------------------------------------------- /icons/clipboardPaste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/clipboardPaste.png -------------------------------------------------------------------------------- /icons/clipboardcut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/clipboardcut.png -------------------------------------------------------------------------------- /icons/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/copy.png -------------------------------------------------------------------------------- /icons/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/delete.png -------------------------------------------------------------------------------- /icons/ellipse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/ellipse.png -------------------------------------------------------------------------------- /icons/endsnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/endsnap.png -------------------------------------------------------------------------------- /icons/fillet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/fillet.png -------------------------------------------------------------------------------- /icons/gtkpycad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/gtkpycad.png -------------------------------------------------------------------------------- /icons/gtkpycadnew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/gtkpycadnew.png -------------------------------------------------------------------------------- /icons/middlesnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/middlesnap.png -------------------------------------------------------------------------------- /icons/mirror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/mirror.png -------------------------------------------------------------------------------- /icons/move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/move.png -------------------------------------------------------------------------------- /icons/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/new.png -------------------------------------------------------------------------------- /icons/nurbs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/nurbs.png -------------------------------------------------------------------------------- /icons/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/open.png -------------------------------------------------------------------------------- /icons/ortosnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/ortosnap.png -------------------------------------------------------------------------------- /icons/polygon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/polygon.png -------------------------------------------------------------------------------- /icons/polyline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/polyline.png -------------------------------------------------------------------------------- /icons/print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/print.png -------------------------------------------------------------------------------- /icons/pythoncad.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/pythoncad.ico -------------------------------------------------------------------------------- /icons/pythoncad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/pythoncad.png -------------------------------------------------------------------------------- /icons/quadrantsnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/quadrantsnap.png -------------------------------------------------------------------------------- /icons/rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/rectangle.png -------------------------------------------------------------------------------- /icons/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/redo.png -------------------------------------------------------------------------------- /icons/rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/rotate.png -------------------------------------------------------------------------------- /icons/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/save.png -------------------------------------------------------------------------------- /icons/segment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/segment.png -------------------------------------------------------------------------------- /icons/splashScreen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/splashScreen1.png -------------------------------------------------------------------------------- /icons/splashScreen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/splashScreen2.png -------------------------------------------------------------------------------- /icons/tangentsnap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/tangentsnap.png -------------------------------------------------------------------------------- /icons/trim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/trim.png -------------------------------------------------------------------------------- /icons/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Csega/PythonCAD3/74dcd3acee5ed53fa5e0eafc379e925d5d1feccd/icons/undo.png -------------------------------------------------------------------------------- /pythoncad_qt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is only needed for Python v2 but is harmless for Python v3. 4 | # 5 | import PyQt5.sip as sip 6 | sip.setapi('QString', 2) 7 | # 8 | from PyQt5 import QtCore, QtGui, QtWidgets 9 | # 10 | import sys 11 | import os 12 | import sqlite3 as sqlite 13 | # 14 | # this is needed for me to use unpickle objects 15 | # 16 | sys.path.append(os.path.join(os.getcwd(), 'Generic')) 17 | genericPath = sys.path[len(sys.path) - 1] 18 | sys.path.append(os.path.join(genericPath, 'Kernel')) 19 | sys.path.append(os.path.join(genericPath, 'Interface')) 20 | # 21 | from Interface.cadwindow import CadWindowMdi 22 | 23 | 24 | def getPythonCAD(): 25 | app = QtWidgets.QApplication(sys.argv) 26 | 27 | # Splash screen 28 | splashPath = os.path.join(os.getcwd(), 'icons', 'splashScreen1.png') 29 | splash_pix = QtGui.QPixmap(splashPath) 30 | splash = QtWidgets.QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint) 31 | splash.setMask(splash_pix.mask()) 32 | splash.show() 33 | 34 | w = CadWindowMdi() 35 | w.show() 36 | 37 | # End of splash screen 38 | splash.finish(w) 39 | 40 | return w, app 41 | 42 | 43 | if __name__ == '__main__': 44 | w, app = getPythonCAD() 45 | sys.exit(app.exec_()) 46 | -------------------------------------------------------------------------------- /test_application.py: -------------------------------------------------------------------------------- 1 | import sympy.geometry as geoSympy 2 | 3 | from Generic.Kernel.GeoEntity.point import Point 4 | from Generic.Kernel.GeoEntity.segment import Segment 5 | from Generic.Kernel.GeoEntity.arc import Arc 6 | from Generic.Kernel.GeoEntity.ellipse import Ellipse 7 | from Generic.Kernel.GeoEntity.cline import CLine 8 | 9 | from Generic.Kernel.GeoUtil.intersection import find_intersections 10 | 11 | 12 | def testSympySegment(): 13 | print("++ Sympy Segment ++") 14 | p1 = Point(0, 1) 15 | p2 = Point(10, 20) 16 | arg = {"SEGMENT_0": p1, "SEGMENT_1": p2} 17 | seg = Segment(arg) 18 | symSeg = seg.getSympy() 19 | print(symSeg) 20 | p3 = Point(30, 40) 21 | arg1 = {"SEGMENT_0": p1, "SEGMENT_1": p3} 22 | seg1 = Segment(arg1) 23 | seg1.setFromSympy(symSeg) 24 | print("Segment ", seg1) 25 | print("-- Sympy Segment --") 26 | 27 | 28 | def testSympyCline(): 29 | print("++ Sympy CLine ++") 30 | p1 = Point(0, 1) 31 | p2 = Point(10, 20) 32 | arg = {"CLINE_0": p1, "CLINE_1": p2} 33 | seg = CLine(arg) 34 | symSeg = seg.getSympy() 35 | print(symSeg) 36 | p3 = Point(30, 40) 37 | arg1 = {"CLINE_0": p1, "CLINE_1": p3} 38 | seg1 = CLine(arg1) 39 | seg1.setFromSympy(symSeg) 40 | print("CLine ", seg1) 41 | print("-- Sympy CLine --") 42 | 43 | 44 | def testSympyCircle(): 45 | print("++ Sympy Arc ++") 46 | p1 = Point(0, 1) 47 | arg = {"ARC_0": p1, "ARC_1": 5, "ARC_2": 0, "ARC_3": 6.2831} 48 | arc = Arc(arg) 49 | sympCircle = arc.getSympy() 50 | print("sympCircle", sympCircle) 51 | sympCircel = geoSympy.Circle(geoSympy.Point(10, 10), 10) 52 | arc.setFromSympy(sympCircel) 53 | print("Pythonca Arc ", arc) 54 | print("-- Sympy Arc --") 55 | 56 | 57 | def testSympyEllipse(): 58 | print("++ Sympy Ellipse ++") 59 | p1 = Point(0, 1) 60 | arg = {"ELLIPSE_0": p1, "ELLIPSE_1": 100, "ELLIPSE_2": 50} 61 | eli = Ellipse(arg) 62 | sympEli = eli.getSympy() 63 | print("sympEllipse", sympEli) 64 | sympEli1 = geoSympy.Ellipse(geoSympy.Point(10, 10), 300, 200) 65 | eli.setFromSympy(sympEli1) 66 | print("Pythonca Ellipse ", eli) 67 | print("-- Sympy Ellipse --") 68 | 69 | 70 | def TestSympy(): 71 | testSympySegment() 72 | testSympyCline() 73 | testSympyCircle() 74 | testSympyEllipse() 75 | 76 | 77 | # ***************************************************************** 78 | # Test Intersection 79 | # ***************************************************************** 80 | 81 | 82 | def segment_segmet(): 83 | print("++ segment_segmet ++") 84 | p1 = Point(0, 0) 85 | p2 = Point(0, 1) 86 | arg = {"SEGMENT_0": p1, "SEGMENT_1": p2} 87 | seg1 = Segment(arg) 88 | p3 = Point(0, 0) 89 | p4 = Point(-1, 0) 90 | arg = {"SEGMENT_0": p3, "SEGMENT_1": p4} 91 | seg2 = Segment(arg) 92 | 93 | print(find_intersections(seg1, seg2)) 94 | print("-- segment_segmet --") 95 | 96 | 97 | def segment_cline(): 98 | print("++ segment_cline ++") 99 | p1 = Point(0, 0) 100 | p2 = Point(0, 1) 101 | arg = {"CLINE_0": p1, "CLINE_1": p2} 102 | seg1 = CLine(arg) 103 | p3 = Point(0, 0) 104 | p4 = Point(-1, 0) 105 | arg = {"SEGMENT_0": p3, "SEGMENT_1": p4} 106 | seg2 = Segment(arg) 107 | 108 | print(find_intersections(seg1, seg2)) 109 | print("-- segment_cline --") 110 | 111 | 112 | def segment_circle(): 113 | print("++ segment_circle ++") 114 | p1 = Point(0, 0) 115 | arg = {"ARC_0": p1, "ARC_1": 5, "ARC_2": 0, "ARC_3": 6.2831} 116 | arc = Arc(arg) 117 | p2 = Point(0, 0) 118 | p3 = Point(-1, 0) 119 | arg = {"CLINE_0": p2, "CLINE_1": p3} 120 | seg1 = CLine(arg) 121 | print(find_intersections(arc, seg1)) 122 | print("-- segment_circle --") 123 | 124 | 125 | def segment_ellipse(): 126 | print("++ segment_ellipse ++") 127 | p1 = Point(0, 0) 128 | arg = {"ELLIPSE_0": p1, "ELLIPSE_1": 300, "ELLIPSE_2": 100} 129 | eli = Ellipse(arg) 130 | p2 = Point(0, 0) 131 | p3 = Point(-1, 0) 132 | arg = {"CLINE_0": p2, "CLINE_1": p3} 133 | seg1 = CLine(arg) 134 | print(find_intersections(eli, seg1)) 135 | print("-- segment_ellipse --") 136 | 137 | 138 | def TestIntersection(): 139 | segment_segmet() 140 | segment_cline() 141 | segment_circle() 142 | segment_ellipse() 143 | 144 | 145 | if __name__ == "__main__": 146 | TestSympy() 147 | TestIntersection() 148 | -------------------------------------------------------------------------------- /test_sympy.py: -------------------------------------------------------------------------------- 1 | from pythoncad_qt import * 2 | from sympy import * 3 | 4 | w,app = getPythonCAD() 5 | w.createSympyDocument() 6 | 7 | p = Point(10, 10) 8 | w.plotFromSympy([p]) 9 | 10 | w.getSympyObject() 11 | --------------------------------------------------------------------------------