├── .gitignore ├── LICENSE ├── npw ├── __init__.py ├── base.py ├── db │ ├── __init__.py │ ├── element.py │ ├── property.py │ └── propertygroup.py ├── exceptions.py ├── nvswks.py ├── ui │ ├── __init__.py │ └── selection.py └── utils │ ├── __init__.py │ ├── dotnet.py │ └── logger.py └── winterops ├── __init__.py ├── bbx.py ├── bin ├── Ifc.NET.XmlSerializers.dll ├── Ifc.NET.dll ├── IxMilia.Dxf.dll ├── Rhino3dmIO.dll ├── YamlDotNet.dll ├── YamlDotNet.xml ├── de │ └── Ifc.NET.resources.dll ├── en │ └── Ifc.NET.resources.dll └── rhino3dmio_native.dll ├── dxf.py ├── ifc.py ├── pts.py ├── rhino.py ├── stl.py ├── tests ├── __init__.py ├── dxftest.py └── rhinotest.py ├── xl.py └── yaml.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ehsan Iran-Nejad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /npw/__init__.py: -------------------------------------------------------------------------------- 1 | """Navisworks Python Wrapper.""" 2 | 3 | from npw.exceptions import * 4 | from npw.utils import logger, dotnet 5 | 6 | from npw.nvswks import API, COMAPI, ICOMAPI, doc 7 | from npw import db 8 | from npw.ui.selection import selection 9 | -------------------------------------------------------------------------------- /npw/base.py: -------------------------------------------------------------------------------- 1 | import npw 2 | from npw.exceptions import NpwTypeError, NpwException 3 | from npw.utils.logger import logger 4 | 5 | 6 | class BaseObject(object): 7 | def __init__(self, *args, **kwargs): 8 | pass 9 | 10 | def __repr__(self, data=None): 11 | return ''.format(self.__class__.__name__, data) 12 | 13 | 14 | class BaseWrapperObject(object): 15 | def __init__(self, navisworks_object): 16 | self._wrapped = navisworks_object 17 | 18 | def __repr__(self, data=None): 19 | return ''.format(self.__class__.__name__, 20 | self._wrapped.ToString(), 21 | data) 22 | 23 | def unwrap(self): 24 | return self._wrapped 25 | -------------------------------------------------------------------------------- /npw/db/__init__.py: -------------------------------------------------------------------------------- 1 | """Wrappers for Navisworks API classes.""" 2 | 3 | from npw.db import element 4 | 5 | 6 | def wrap(nvswrks_mi): 7 | return element.Element(nvswrks_mi) 8 | -------------------------------------------------------------------------------- /npw/db/element.py: -------------------------------------------------------------------------------- 1 | """Wrapper for Navisworks.Api.ModelItem.""" 2 | 3 | from npw import base 4 | from npw.db.propertygroup import PropertyCategory 5 | 6 | 7 | class Element(base.BaseWrapperObject): 8 | def __init__(self, nw_modelitem): 9 | base.BaseWrapperObject.__init__(self, nw_modelitem) 10 | 11 | @property 12 | def property_categories(self): 13 | return self._wrapped.PropertyCategories 14 | 15 | def _lookup_propcat(self, param_name): 16 | for pc in self.property_categories: 17 | if pc.DisplayName == param_name \ 18 | or pc.Name == param_name: 19 | return pc 20 | 21 | def __getitem__(self, param_name): 22 | pcat = self._lookup_propcat(param_name) 23 | if pcat: 24 | return PropertyCategory(pcat) 25 | 26 | raise AttributeError('Property category does not exist: {}' 27 | .format(param_name)) 28 | 29 | def __contains__(self, key): 30 | return key in [x.DisplayName for x in self.property_categories] 31 | -------------------------------------------------------------------------------- /npw/db/property.py: -------------------------------------------------------------------------------- 1 | """Wrapper for Navisworks.Api.DataProperty.""" 2 | 3 | from npw import base 4 | from npw import API 5 | 6 | 7 | class Property(base.BaseWrapperObject): 8 | def __init__(self, nw_dataprop): 9 | base.BaseWrapperObject.__init__(self, nw_dataprop) 10 | 11 | @property 12 | def value(self): 13 | val = self._wrapped.Value 14 | if val.IsAnyDouble: 15 | return val.ToAnyDouble() 16 | elif val.IsBoolean: 17 | return val.ToBoolean() 18 | elif val.IsDateTime: 19 | return val.ToDateTime() 20 | elif val.IsDisplayString: 21 | return val.ToDisplayString() 22 | elif val.IsDouble: 23 | return val.ToDouble() 24 | elif val.IsDoubleAngle: 25 | return val.ToDoubleAngle() 26 | elif val.IsDoubleArea: 27 | return val.ToDoubleArea() 28 | elif val.IsDoubleLength: 29 | return val.ToDoubleLength() 30 | elif val.IsDoubleVolume: 31 | return val.ToDoubleVolume() 32 | elif val.IsIdentifierString: 33 | return val.ToIdentifierString() 34 | elif val.IsInt32: 35 | return val.ToInt32() 36 | elif val.IsNamedConstant: 37 | return val.ToNamedConstant() 38 | elif val.IsPoint2D: 39 | return val.ToPoint2D() 40 | elif val.IsPoint3D: 41 | return val.ToPoint3D() 42 | elif val.IsDisposed or val.IsNone: 43 | return None 44 | -------------------------------------------------------------------------------- /npw/db/propertygroup.py: -------------------------------------------------------------------------------- 1 | """Wrapper for Navisworks.Api.ModelItem.""" 2 | 3 | from npw import base 4 | from npw.db.property import Property 5 | 6 | 7 | class PropertyCategory(base.BaseWrapperObject): 8 | def __init__(self, nw_propgroup): 9 | base.BaseWrapperObject.__init__(self, nw_propgroup) 10 | 11 | @property 12 | def properties(self): 13 | return self._wrapped.Properties 14 | 15 | def _lookup_prop(self, param_name): 16 | for dp in self.properties: 17 | if dp.DisplayName == param_name \ 18 | or dp.Name == param_name: 19 | return dp 20 | 21 | def __getitem__(self, param_name): 22 | dprop = self._lookup_prop(param_name) 23 | if dprop: 24 | return Property(dprop) 25 | 26 | raise AttributeError('Property does not exist: {}' 27 | .format(param_name)) 28 | 29 | def __contains__(self, key): 30 | return key in [x.DisplayName for x in self.properties] 31 | -------------------------------------------------------------------------------- /npw/exceptions.py: -------------------------------------------------------------------------------- 1 | """ Custom NPW exceptions.""" # 2 | 3 | 4 | class NpwException(Exception): 5 | """Navis Python Wrapper Base Exception.""" 6 | 7 | 8 | class NpwTypeError(TypeError): 9 | """Navis Python Wrapper Base Exception.""" 10 | 11 | def __init__(self, type_expected, type_received=None): 12 | type_received = type_received or 'not reported' 13 | msg = 'expected [{}], got [{}]'.format(type_expected, type_received) 14 | super(NpwTypeError, self).__init__(msg) 15 | 16 | 17 | class NpwParameterNotFound(NpwException, KeyError): 18 | """Navis Python Wrapper Parameter Error.""" 19 | 20 | def __init__(self, mi_guid, param_name): 21 | msg = 'parameter not found [element:{}]:[param_name:{}]'\ 22 | .format(mi_guid, param_name) 23 | 24 | super(NpwParameterNotFound, self).__init__(msg) 25 | -------------------------------------------------------------------------------- /npw/nvswks.py: -------------------------------------------------------------------------------- 1 | import clr 2 | 3 | clr.AddReference('Autodesk.Navisworks.Api') 4 | clr.AddReference('Autodesk.Navisworks.ComApi') 5 | clr.AddReference('Autodesk.Navisworks.Interop.ComApi') 6 | import Autodesk.Navisworks.Api as API 7 | import Autodesk.Navisworks.Api.ComApi as COMAPI 8 | import Autodesk.Navisworks.Api.Interop.ComApi as ICOMAPI 9 | 10 | doc = API.Application.ActiveDocument 11 | -------------------------------------------------------------------------------- /npw/ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/npw/ui/__init__.py -------------------------------------------------------------------------------- /npw/ui/selection.py: -------------------------------------------------------------------------------- 1 | from npw import db 2 | from npw import doc, API 3 | 4 | from System.Collections.Generic import List 5 | 6 | 7 | selection = [db.wrap(x) for x in doc.CurrentSelection.SelectedItems] 8 | 9 | 10 | def select_items(modelitems): 11 | doc.CurrentSelection.Clear() 12 | doc.CurrentSelection.AddRange(List[API.ModelItem](modelitems)) 13 | -------------------------------------------------------------------------------- /npw/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/npw/utils/__init__.py -------------------------------------------------------------------------------- /npw/utils/dotnet.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from npw.utils.logger import logger 4 | 5 | import clr 6 | 7 | clr.AddReference('System') # Enum, Diagnostics 8 | clr.AddReference('System.Collections') # List 9 | 10 | # Core Imports 11 | from System import Enum 12 | from System.Collections.Generic import List 13 | from System.Diagnostics import Process 14 | -------------------------------------------------------------------------------- /npw/utils/logger.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import logging 3 | 4 | 5 | class LoggerWrapper(): 6 | """ Logger Wrapper to extend loggers functionality. 7 | Usage: 8 | from logger import LoggerWrapper 9 | 10 | logger = LoggerWrapper() # Initialized loger 11 | 12 | Same calls as regular logger: 13 | logger.info('Message') 14 | >> [INFO] Message 15 | 16 | logger.debug('Message') 17 | >> [DEBUG] Message 18 | 19 | Set Logging Level/Debug: 20 | logger.verbose(True) # Set to Info or higher as default 21 | 22 | Additional Features: 23 | logger.title('Message'): Outputs lines above and below, uses clean format 24 | >> ========= 25 | >> Message 26 | >> ========= 27 | 28 | logger.error('Message'): appends errmsg to self.errors. 29 | This allows you to check if an error occured, 30 | and if it did not, close console window. 31 | >> [ERROR] Message 32 | print(logger.errors) 33 | >> ['Message'] 34 | 35 | # Hides windows if not errors have occured. 36 | if not logger.errors: 37 | __window__.Close() 38 | 39 | """ 40 | 41 | def __init__(self): 42 | 43 | handler = logging.StreamHandler(sys.stdout) 44 | formatter = logging.Formatter("[%(levelname)s] %(message)s") 45 | # TODO: Show Module 46 | # formatter = logging.Formatter("[%(levelname)s] %(message)s [%(module)s:%(lineno)s]") 47 | handler.setFormatter(formatter) 48 | 49 | logger = logging.getLogger('rpw_logger') 50 | logger.addHandler(handler) 51 | logger.setLevel(logging.INFO) 52 | 53 | handler_title = logging.StreamHandler(sys.stdout) 54 | formatter_title = logging.Formatter("%(message)s") 55 | handler_title.setFormatter(formatter_title) 56 | 57 | logger_title = logging.getLogger('rpw_logger_title') 58 | logger_title.addHandler(handler_title) 59 | logger_title.setLevel(logging.INFO) 60 | 61 | self._logger = logger 62 | self._logger_title = logger_title 63 | self.errors = [] 64 | 65 | def disable(self): 66 | self._logger.setLevel(logging.CRITICAL) 67 | 68 | def verbose(self, verbose): 69 | if verbose: 70 | self._logger.setLevel(logging.DEBUG) 71 | else: 72 | self._logger.setLevel(logging.INFO) 73 | 74 | def title(self, msg): 75 | print('=' * 100) 76 | self._logger_title.info(msg) 77 | print('=' * 100) 78 | 79 | def info(self, msg): 80 | self._logger.info(msg) 81 | 82 | def debug(self, msg): 83 | self._logger.debug(msg) 84 | 85 | def warning(self, msg): 86 | self._logger.warning(msg) 87 | 88 | def error(self, msg): 89 | self._logger.error(msg) 90 | self.errors.append(msg) 91 | 92 | def critical(self, msg): 93 | self._logger.critical(msg) 94 | 95 | def setLevel(self, level): 96 | self._logger.setLevel(level) 97 | 98 | 99 | logger = LoggerWrapper() 100 | -------------------------------------------------------------------------------- /winterops/__init__.py: -------------------------------------------------------------------------------- 1 | """Interoperability with other applications.""" 2 | 3 | import sys 4 | import os 5 | 6 | binary_path = os.path.join(os.path.dirname(__file__), 'bin') 7 | sys.path.append(binary_path) 8 | 9 | # pylama:ignore=E402,W0611 10 | import clr 11 | clr.AddReference('System') 12 | 13 | import System 14 | 15 | import winterops.bbx 16 | import winterops.dxf 17 | import winterops.ifc 18 | import winterops.pts 19 | import winterops.rhino 20 | import winterops.stl 21 | import winterops.xl 22 | import winterops.yaml 23 | 24 | 25 | __version__ = '0.2' 26 | -------------------------------------------------------------------------------- /winterops/bbx.py: -------------------------------------------------------------------------------- 1 | """Read and Write Bounding Box Files.""" 2 | 3 | 4 | def load(inputfile): 5 | bboxes = [] 6 | with open(inputfile, 'r') as bbxfile: 7 | bbox_count = int(bbxfile.readline()) #noqa 8 | for line in bbxfile: 9 | data = line.split(' ') 10 | bboxes.append( 11 | ((float(data[0]), float(data[1]), float(data[2])), 12 | (float(data[3]), float(data[4]), float(data[5]))) 13 | ) 14 | return bboxes 15 | 16 | 17 | def dump(outputfile, bbox_list): 18 | bbox_count = len(bbox_list) 19 | with open(outputfile, 'w') as bbxfile: 20 | bbxfile.write(str(bbox_count) + '\n') 21 | for bbox in bbox_list: 22 | minx, miny, minz = bbox[0] 23 | maxx, maxy, maxz = bbox[1] 24 | bbxfile.write( 25 | '{:.02f} {:.02f} {:.02f} {:.02f} {:.02f} {:.02f}\n' 26 | .format(minx, miny, minz, maxx, maxy, maxz) 27 | ) 28 | -------------------------------------------------------------------------------- /winterops/bin/Ifc.NET.XmlSerializers.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/Ifc.NET.XmlSerializers.dll -------------------------------------------------------------------------------- /winterops/bin/Ifc.NET.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/Ifc.NET.dll -------------------------------------------------------------------------------- /winterops/bin/IxMilia.Dxf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/IxMilia.Dxf.dll -------------------------------------------------------------------------------- /winterops/bin/Rhino3dmIO.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/Rhino3dmIO.dll -------------------------------------------------------------------------------- /winterops/bin/YamlDotNet.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/YamlDotNet.dll -------------------------------------------------------------------------------- /winterops/bin/de/Ifc.NET.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/de/Ifc.NET.resources.dll -------------------------------------------------------------------------------- /winterops/bin/en/Ifc.NET.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/en/Ifc.NET.resources.dll -------------------------------------------------------------------------------- /winterops/bin/rhino3dmio_native.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyrevitlabs/NavisPythonWrapper/9eb22b2dfe7934dc06bb30d92e4cb3afd8a74843/winterops/bin/rhino3dmio_native.dll -------------------------------------------------------------------------------- /winterops/dxf.py: -------------------------------------------------------------------------------- 1 | # pylama:ignore=E402,W0611 2 | from winterops import clr, System 3 | 4 | clr.AddReference('IxMilia.Dxf') 5 | 6 | from IxMilia import Dxf 7 | -------------------------------------------------------------------------------- /winterops/ifc.py: -------------------------------------------------------------------------------- 1 | # pylama:ignore=E402,W0611 2 | from winterops import clr, System 3 | 4 | clr.AddReference('Ifc.Net') 5 | 6 | import Ifc4 7 | -------------------------------------------------------------------------------- /winterops/pts.py: -------------------------------------------------------------------------------- 1 | """Read and Write PTS PointCloud Files.""" 2 | 3 | 4 | def load(inputfile): 5 | """Read list of point tuple from PTS file.""" 6 | points = [] 7 | with open(inputfile, 'r') as ptsfile: 8 | point_count = int(ptsfile.readline()) #noqa 9 | for line in ptsfile: 10 | data = line.split(' ') 11 | points.append(((float(data[0]), float(data[1]), float(data[2])), 12 | int(data[3]), 13 | (int(data[4]), int(data[5]), int(data[6]))) 14 | ) 15 | return points 16 | 17 | 18 | def dump(outputfile, points): 19 | """Write list of point tuple to PTS file.""" 20 | point_count = len(points) 21 | with open(outputfile, 'w') as ptsfile: 22 | ptsfile.write(str(point_count) + '\n') 23 | for coord, intensity, color in points: 24 | x, y, z = coord 25 | r, g, b = color 26 | ptsfile.write('{:.02f} {:.02f} {:.02f} ' 27 | '{} ' 28 | '{:03} {:03} {:03}\n'.format(x, y, z, 29 | intensity, 30 | r, g, b)) 31 | -------------------------------------------------------------------------------- /winterops/rhino.py: -------------------------------------------------------------------------------- 1 | # pylama:ignore=E402,W0611 2 | from winterops import clr, System 3 | 4 | clr.AddReference('System.Core') 5 | clr.ImportExtensions(System.Linq) 6 | clr.AddReferenceByName('Rhino3dmIO') 7 | 8 | import Rhino 9 | -------------------------------------------------------------------------------- /winterops/stl.py: -------------------------------------------------------------------------------- 1 | """Read and Write STL Binary and ASCII Files.""" 2 | # 3 | # import struct 4 | # 5 | # 6 | # def load(inputfile): 7 | # pass 8 | # 9 | # 10 | # def dump(outputfile): 11 | # struct.pack('= 1: 14 | return yamlstr.Documents[0].RootNode 15 | --------------------------------------------------------------------------------