From 3a5045a49b7c385e7bc5bc3af241695fbb88bfec Mon Sep 17 00:00:00 2001 From: Daniel Weschke Date: Sat, 20 Jul 2024 15:29:58 +0200 Subject: [PATCH] update structure and readme and add area --- README.md | 25 +++++- setup.py | 22 ++--- src/engineering/area.py | 125 +++++++++++++++++++++++++++ src/{ => engineering}/awg.py | 3 +- src/{ => engineering}/beam.py | 1 - src/engineering/helper/color.py | 144 ++++++++++++++++++++++++++++++++ src/{ => engineering}/plate.py | 1 - src/{ => engineering}/tube.py | 1 - 8 files changed, 301 insertions(+), 21 deletions(-) create mode 100755 src/engineering/area.py rename src/{ => engineering}/awg.py (91%) rename src/{ => engineering}/beam.py (97%) create mode 100644 src/engineering/helper/color.py rename src/{ => engineering}/plate.py (97%) rename src/{ => engineering}/tube.py (93%) diff --git a/README.md b/README.md index 23910d1..5bea62f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,29 @@ -Install, in "development mode", so any change in the local repo is effective: +# Features + +commands +- `eng-area`: area of a simple polygon +- `eng-awg`: diameter/area from AWG wire size +- `eng-beam`: calculate mechanical beam eigen-frequencies +- `eng-plate`: central deflection and min. thickness of a circular plate +- `eng-tube`: bubkling stress of a tube + +libs +- `engineering.area.area(vertices)` +- `engineering.awg.diameter(number)` +- `engineering.awg.area(number)` +- `engineering.beam.eigen_frequency_fixed_free(n, E, I, rho, A, L)` +- `engineering.plate.deflection_pinned(p, r, nu, E, t)` +- `engineering.plate.deflection_clamped(p, r, nu, E, t)` +- `engineering.plate.thickness_min(p, d, Rp02, S)` +- `engineering.plate.allowable_stress(sigma, S)` + + +# Install +In "development mode", so any change in the local repo is effective: python -m pip install --editable git+#egg=engineering --src=$HOME/repos --prefix=$HOME/.local --break-system-packages -Uninstall: +# Uninstall python -m pip uninstall engineering --break-system-packages diff --git a/setup.py b/setup.py index 1f781c4..fe94c88 100644 --- a/setup.py +++ b/setup.py @@ -2,35 +2,29 @@ # -*- coding: utf-8 -*- from os import path from setuptools import setup, find_packages +from pkg_resources import parse_version with open(path.join(path.abspath(path.dirname(__file__)), 'README.md'), encoding='utf-8') as f: long_description = f.read() setup( name="engineering", - version="2024.07.20", + version=str(parse_version("2024.07.20")), description="engineering tools", long_description=long_description, author="Daniel Weschke", author_email="daniel.weschke@directbox.de", package_dir={'': 'src'}, - packages=find_packages("src"), - py_scripts = [ - # mech - 'beam.py', - 'plate.py', - 'tube.py', - # et - 'awg.py', - ], + packages=find_packages(where="src"), entry_points={ 'console_scripts': [ # mech - 'eng-beam=beam:main', - 'eng-plate=plate:main', - 'eng-tube=tube:main', + 'eng-area = engineering.area:main', + 'eng-beam = engineering.beam:main', + 'eng-plate = engineering.plate:main', + 'eng-tube = engineering.tube:main', # et - 'eng-awg=awg:main', + 'eng-awg = engineering.awg:main', ], }, keywords = 'mechanical electrical engineering mechanics plate tube stress', diff --git a/src/engineering/area.py b/src/engineering/area.py new file mode 100755 index 0000000..b4f41a1 --- /dev/null +++ b/src/engineering/area.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""\ +Determine the area of a simple polygon +""" +from builtins import input +import sys +import re + +__author__ = "Daniel Weschke" +__copyright__ = "Copyright 2019 Daniel Weschke" +__credits__ = ["Daniel Weschke"] +__license__ = "MIT" +__version__ = "2019.01.16" +__maintainer__ = "Daniel Weschke" +__email__ = "daniel.weschke@directbox.de" +__status__ = "Production" # "Prototype", "Development", "Production" + +VERSION = """\ +%(prog)s version {version} {copyright}""".format( + version=__version__, copyright=__copyright__) + +EPILOG = """\ +""" + +def area(vertices): + r""" + shoelace formula, shoelace algorithm, Gauss's area formula, surveyor's formula + http://stackoverflow.com/questions/24467972/calculate-area-of-polygon-given-x-y-coordinates + """ + count = len(vertices) # of corners + result = 0.0 + for i in range(count): + j = (i + 1) % count + result += vertices[i][0] * vertices[j][1] - vertices[j][0] * vertices[i][1] + result = abs(result) / 2.0 + return result + +def main(): + """\ + Main function + """ + import argparse + from .helper.color import primary as command, info, error, reset, csi, Style, FGColor + + parser = argparse.ArgumentParser( + description=__doc__, prefix_chars='-', epilog=EPILOG, + #usage="%(prog)s [OPTION]... NAME", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument('POINTS', nargs='?', + help='List of points, pair of x and y: "[[x1, y1], [x2, y2], ...]"') + parser.add_argument('-v', '--verbose', action="store_true", help="Verbose output") + parser.add_argument('-V', '--version', action='version', version=VERSION) + parser.add_argument('-D', '--debug', dest='debug', action='store_true', help=argparse.SUPPRESS) + args = parser.parse_args() + + # initialise variables + choice = args.POINTS if args.POINTS else '1' + points = [] + a = 0. + + if args.debug: + print("args", args) + print("choice", choice) + + if args.POINTS is None: + print("You may type '" + command('help') + + "' for information on how to use this program") + else: + rechoice = re.match(r'\[.*\]', ''.join(choice)) + if rechoice and rechoice.group(): + points = eval(rechoice.group()) + if args.debug: + print('list given: %s' % points) + a = area(points) + print('area: %s' % a) + choice = 'q' + try: + while choice not in ('q', 'quit', 'exit'): + choice = input(" %i Points, area: " % len(points) + + info("%.2f ") % a + "> " + csi(Style.NOBOLD, FGColor.COMMAND)) + sys.stdout.write(reset()) + choice = " ".join(choice.split()) # replace multiple spaces with single one + if choice[:1] == 'a': + choicesplit = choice.split(' ') + if len(choicesplit) == 3: + points.append([float(choicesplit[1]), float(choicesplit[2])]) + a = area(points) + else: + print(' ' + error('insert exact two coordinates, like:') + + ' ' + command('a ')) + elif choice == 'list': + if args.debug: + print("points", points) + for index, point in enumerate(points): + print('%2i' % (index+1), point) + + elif choice == 'help': + print('\n' + 'Determine the area of a simple polygon\n' + '\n' + 'Commands:\n' + ' ' + command('a ') + ' ' + + 'enter new absolute data point\n' + ' ' + command('r ') + ' ' + + 'enter new relative data point\n' + ' ' + command('list') + ' ' + + 'list all points entered\n' + ' ' + command('q')+', '+command('quit')+', '+command('exit') + ' '+ + 'exit the program\n' + '') + except KeyboardInterrupt: + sys.stdout.write(reset()) + print("Shutdown requested...exiting") + return 2 + except Exception: + sys.stdout.write(reset()) + import traceback + traceback.print_exc(file=sys.stdout) + return 2 + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/awg.py b/src/engineering/awg.py similarity index 91% rename from src/awg.py rename to src/engineering/awg.py index 1f37f05..5c86014 100755 --- a/src/awg.py +++ b/src/engineering/awg.py @@ -3,7 +3,6 @@ """\ Python script to determine the diameter for a given AWG wire size. """ -from __future__ import absolute_import, division, print_function, unicode_literals import sys from math import pi @@ -14,7 +13,7 @@ __license__ = "MIT" __version__ = "2019.01.16" __maintainer__ = "Daniel Weschke" __email__ = "daniel.weschke@directbox.de" -__status__ = "Production" # "Prototype", "Development", "Production" +__status__ = "Development" VERSION = """\ %(prog)s version {version} {copyright}""".format( diff --git a/src/beam.py b/src/engineering/beam.py similarity index 97% rename from src/beam.py rename to src/engineering/beam.py index c02e9c0..ae74ceb 100755 --- a/src/beam.py +++ b/src/engineering/beam.py @@ -3,7 +3,6 @@ """\ Beam """ -from __future__ import absolute_import, division, print_function, unicode_literals from math import sqrt, pi __author__ = "Daniel Weschke" diff --git a/src/engineering/helper/color.py b/src/engineering/helper/color.py new file mode 100644 index 0000000..1bd8aa5 --- /dev/null +++ b/src/engineering/helper/color.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Created on Mon Dec 21 19:39:44 2015 + +@author: Daniel +""" +import sys + +systeminfo = '' +colorfont = False +try: + import colorama + colorama.init() + colorfont = True +except: + try: + import tendo.ansiterm + colorfont = True + except: + + def in_ipy(): + """ + Check if in IPython + """ + try: + get_ipython().config + return True + except NameError: + return False + + def in_ipynb(): + """ + Check if in IPython Notebook + http://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook + """ + try: + cfg = get_ipython().config + return true if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook' else False + except NameError: + return False + + if hasattr(sys.stderr, "isatty") and sys.stderr.isatty(): + """ + http://stackoverflow.com/questions/7445658/how-to-detect-if-the-console-does-support-ansi-escape-codes-in-python + """ + try: + import platform + systeminfo = platform.system() + if platform.system()=='Windows': + colorfont = True + else: + colorfont = True + except: + colorfont = False + elif in_ipy(): + colorfont = True + else: + pass + +class Style: + """\ + Styling + """ + END = '0' # reset all (colors and brightness) + BRIGHT = '1' # bright (this might be the standard on some terminals) + DIM = '2' # dim (looks same as normal brightness on some terminals) + ITALIC = '3' # (not supported on some terminals) + UNDERLINE = '4' + NOBOLD = '22' # normal brightness + +class FGColor: + """\ + Foreground colors + """ + BLACK = '30' + RED = '31' + GREEN = '32' + YELLOW = '33' + BLUE = '34' + MAGENTA = '35' + CYAN = '36' + WHITE = '37' + RESET = '39' # (not supported on some terminals) + COMMAND = GREEN + INFO = YELLOW + ERROR = RED + +class BGColor: + """\ + Background colors + """ + BLACK = '40' + RED = '41' + GREEN = '42' + YELLOW = '43' + BLUE = '44' + MAGENTA = '45' + CYAN = '46' + WHITE = '47' + RESET = '49' # (not supported on some terminals) + +def csi(*v): + """ + ANSI escape codes + CSI for Control Sequence Introducer (or Control Sequence Initiator) + style, color, background color + http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python + https://en.wikipedia.org/wiki/ANSI_escape_code#Colors + """ + return '\x1B['+';'.join(map(str, v))+'m' + +def color(string, *styleColorBgcolor): + """\ + Color string if posible + """ + if colorfont: + return csi(*styleColorBgcolor) + string + csi(Style.END) + else: + return string + +def primary(string): + """\ + Styling for command string + """ + return color(string, Style.NOBOLD, FGColor.COMMAND) + +def info(string): + """\ + Styling for info string + """ + return color(string, FGColor.INFO) + +def error(string): + """\ + Styling for error string + """ + return color(string, FGColor.ERROR) + +def reset(): + """\ + Reset styling + """ + return csi(Style.END) diff --git a/src/plate.py b/src/engineering/plate.py similarity index 97% rename from src/plate.py rename to src/engineering/plate.py index 66936c3..a6c0f46 100755 --- a/src/plate.py +++ b/src/engineering/plate.py @@ -3,7 +3,6 @@ """\ Circular plate """ -from __future__ import absolute_import, division, print_function, unicode_literals from math import sqrt __author__ = "Daniel Weschke" diff --git a/src/tube.py b/src/engineering/tube.py similarity index 93% rename from src/tube.py rename to src/engineering/tube.py index 8fe20a1..fcb3275 100755 --- a/src/tube.py +++ b/src/engineering/tube.py @@ -3,7 +3,6 @@ """\ Tube """ -from __future__ import absolute_import, division, print_function, unicode_literals from math import sqrt __author__ = "Daniel Weschke"