#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  screw_maker2_2.py
#  


"""
Macro to generate screws with FreeCAD.
Version 1.4 from 1st of September 2013
Version 1.5 from 23rd of December 2013
Corrected hex-heads above M12 not done.
Version 1.6 from 15th of March 2014
Added PySide support

Version 1.7 from April 2014
fixed bool type error. (int is not anymore accepted at linux)
fixed starting point of real thread at some screw types.

Version 1.8 from July 2014
first approch for a faster real thread

Version 1.9 / 2.0 July 2015
new calculation of starting point of thread
shell-based approach for screw generation
added:
ISO 14582 Hexalobular socket countersunk head screws, high head
ISO 14584 Hexalobular socket raised countersunk head screws
ISO 7380-2 Hexagon socket button head screws with collar
DIN 967 Cross recessed pan head screws with collar
ISO 4032 Hexagon nuts, Style 1
ISO 4033 Hexagon nuts, Style 2
ISO 4035 Hexagon thin nuts, chamfered
EN 1661 Hexagon nuts with flange
ISO 7094 definitions  Plain washers - Extra large series
ISO 7092 definitions  Plain washers - Small series
ISO 7093-1 Plain washer - Large series
Screw-tap to drill inner threads in parts with user defined length

ScrewMaker can now also used as a python module.
The following shows how to generate a screw from a python script:
  import screw_maker2_0

  threadDef = 'M3.5'
  o = screw_maker2_0.Screw()
  t = screw_maker2_0.Screw.setThreadType(o,'real')
  # Creates a Document-Object with label describing the screw
  d = screw_maker2_0.Screw.createScrew(o, 'ISO1207', threadDef, '20', 'real')

  # creates a shape in memory
  t = screw_maker2_0.Screw.setThreadType(o,'real')
  s = screw_maker1_9d.Screw.makeIso7046(o, 'ISO14582', threadDef, 40.0)
  Part.show(s)

Version 2.1 August 2015
added:
ISO 8676 Hexagon head screw with metric fine pitch thread

Version 2.2 May 2018
- Extend function "moveScrew" to check for Body and Part.
- Add Screw to Part if Body is in Part.
- Search for plane support face to get correct orientation
- fix failed hex-head

Version 2.3 Oct 2018
- fix missing function equal_vertex

Version 2.4 Feb. 2019
- fix nuts < M6: use cut method (slower but works here)

Fixes June 2020
- new version of makeInnerThread_2, fixes some issues with nuts.

to do: check ISO7380 usage of rs and rt, actual only rs is used 
check chamfer angle on hexogon heads and nuts
***************************************************************************
*   Copyright (c) 2013, 2014, 2015 2018, 2020                                   *
*   Ulrich Brammer <ulrich1a[at]users.sourceforge.net>                    *
*                                                                         *
*   This file is a supplement to the FreeCAD CAx development system.      *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU Lesser General Public License (LGPL)    *
*   as published by the Free Software Foundation; either version 2 of     *
*   the License, or (at your option) any later version.                   *
*   for detail see the LICENCE text file.                                 *
*                                                                         *
*   This software is distributed in the hope that it will be useful,      *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU Library General Public License for more details.                  *
*                                                                         *
*   You should have received a copy of the GNU Library General Public     *
*   License along with this macro; if not, write to the Free Software     *
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
*   USA                                                                   *
*                                                                         *
***************************************************************************
"""

__author__ = "Ulrich Brammer <ulrich1a@users.sourceforge.net>"



import FreeCAD, FreeCADGui, Part, math
from FreeCAD import Base
import DraftVecUtils

try:
  from PySide import QtCore, QtGui
  #FreeCAD.Console.PrintMessage("PySide is used" + "\n")
except:
  #FreeCAD.Console.PrintMessage("PyQt4 is needed" + "\n")
  from PyQt4 import QtCore, QtGui


DEBUG = False # set to True to show debug messages; does not work, still todo.

debObject = None

# Diameters included in this library/macro
# some ISO-standards may include more diameters!
# Dictionary used for user messages
standard_diameters = {
  'ISO4017': ('M1.6', 'M64'), # ISO 4017 Hex-head-screw
  'ISO4014': ('M1.6', 'M64'), # ISO 4014 Hex-head-bolt
  'EN1662':  ('M5',   'M16'), # EN 1662 Hexagon bolts with flange, small series
  'EN1665':  ('M5',   'M20'), # EN 1665 Hexagon bolts with flange, heavy series
  'ISO8676': ('M8x1', 'M64x4'), # ISO 8676 Hexagon head screw with metric fine pitch thread
  'ISO4762': ('M1.6', 'M64'), # ISO 4762 Hexagon socket head cap screws
  'ISO2009': ('M1.6', 'M10'), # ISO 2009 Slotted countersunk flat head screws
  'ISO2010': ('M1.6', 'M10'), # ISO 2010 Slotted raised countersunk head screws
  'ISO1580': ('M1.6', 'M10'), # ISO 1580 Slotted pan head screws
  'ISO7045': ('M1.6', 'M10'), # ISO 7045 Pan head screws type H cross recess
  'ISO7046': ('M1.6', 'M10'),
  'ISO7047': ('M1.6', 'M10'),
  'ISO1207': ('M3',   'M10'), # ISO 1207 Slotted cheese head screws
  'ISO7048': ('M2.5', 'M8'),  # ISO 7048 Cross-recessed cheese head screws with type H cross recess
  'ISO7380-1':('M3',  'M16'), # ISO 7380 Hexagon socket button head screws
  'ISO7380-2':('M3',  'M16'), # ISO 7380 Hexagon socket button head screws with collar
  'DIN967'  :('M3',   'M8'),  # DIN 967 Cross recessed pan head screws with collar
  'ISO10642':('M3',   'M20'), # ISO 10642 Hexagon socket countersunk head screws
  'ISO14579':('M2',   'M20'), # ISO 14579 Hexalobular socket head cap screws
  'ISO14580':('M2',   'M10'), # ISO 14580 Hexalobular socket cheese head screws
  'ISO14581':('M2',   'M10'), # ISO 14581 Hexalobular socket countersunk flat head screws (to do!!)
  'ISO14582':('M3',   'M10'), # ISO 14582 Hexalobular socket countersunk head screws, high head
  'ISO14583':('M2',   'M10'), # ISO 14583 Hexalobular socket pan head screws
  'ISO14584':('M2',   'M10'), # ISO 14584 Hexalobular socket raised countersunk head screws
  'ISO7089': ('M1.6', 'M64'), # Washer
  'ISO7090': ('M5',   'M64'), # ISO 7090 definitions Plain washers, chamfered - Normal series
  'ISO7091': ('M1.6', 'M64'), # ISO 7091 definitions  Plain washer - Normal series Product Grade C
  'ISO7092': ('M1.6', 'M36'), # ISO 7092 definitions  Plain washers - Small series
  'ISO7093-1': ('M3', 'M36'), # ISO 7093-1 Plain washer - Large series
  'ISO7094': ('M5',   'M36'), # ISO 7094 definitions  Plain washers - Extra large series
  'ISO4032': ('M1.6', 'M64'), # ISO 4032 Hexagon nuts, Style 1
  'ISO4033': ('M5',   'M36'), # ISO 4033 Hexagon nuts, Style 2
  'ISO4035': ('M1.6', 'M64'), # ISO 4035 Hexagon thin nuts, chamfered
  'ISO4036': ('M1.6', 'M10'), # ISO 4035 Hexagon thin nuts, unchamfered, todo no function coded
  'EN1661':  ('M5',   'M20')} # EN 1661 Hexagon nuts with flange

# ISO 4017 Hex-head-screw
#           P,    c,  dw,    e,     k,   r,   s
iso4017head={
  'M1.6':  (0.35, 0.2, 2.9,  3.4,   1.1, 0.1,  3.2),
  'M2':    (0.40, 0.2, 3.7,  4.4,   1.4, 0.1,  4.0),
  'M2.5':  (0.45, 0.2, 4.6,  5.5,   1.7, 0.1,  5.0),
  'M3':    (0.5,  0.2, 5.2,  6.1,   2.0, 0.1,  5.5),
  '(M3.5)':(0.6,  0.2, 5.2,  6.6,   2.4, 0.1,  5.5),
  'M4':    (0.7,  0.2, 6.6,  7.7,   2.8, 0.2,  7.0), 
  'M5':    (0.8,  0.2, 7.5,  8.9,   3.5, 0.2,  8.0),
  'M6':    (1.0,  0.2, 9.5,  11.05, 4.0, 0.25, 10.0),
  'M8':    (1.25, 0.3, 11.7, 14.5,  5.3, 0.25, 13.0),
  'M10':   (1.50, 0.3, 14.7, 17.9,  6.4, 0.4,  16.0),
  'M12':   (1.75, 0.3, 16.7, 20.1,  7.5, 0.6,  18.0),
  '(M14)': (2.00, 0.3, 20.5, 24.5,  8.8, 0.6,  22.0),
  'M16':   (2.00, 0.4, 22.4, 26.9, 10.0, 0.6,  24.0),
  '(M18)': (2.50, 0.4, 25.4, 30.2, 11.5, 0.6,  27.0),
  'M20':   (2.50, 0.4, 28.2, 33.7, 12.5, 0.8,  30.0),
  '(M22)': (2.50, 0.4, 31.8, 37.7, 14.0, 0.8,  34.0),
  'M24':   (3.00, 0.4, 33.7, 40.1, 15.0, 0.8,  36.0),
  '(M27)': (3.00, 0.4, 38.0, 45.2, 17.0, 1.0,  41.0),
  'M30':   (3.50, 0.4, 42.8, 50.9, 18.7, 1.0,  46.0), #dw not in class A, e not in class A
  '(M33)': (3.50, 0.4, 46.6, 55.4, 21.0, 1.0,  50.0), 
  'M36':   (4.00, 0.4, 51.2, 61.0, 22.5, 1.0,  55.0), #dw not in class A, e not in class A
  '(M39)': (4.00, 0.5, 55.9, 66.5, 25.0, 1.0,  60.0),
  'M42':   (4.50, 0.7, 60.0, 71.3, 26.0, 1.2,  65.0),
  '(M45)': (4.50, 0.7, 64.7, 77.0, 28.0, 1.2,  70.0),
  'M48':   (5.00, 0.7, 69.5, 82.6, 30.0, 1.6,  75.0),
  '(M52)': (5.00, 0.7, 74.5, 88.3, 33.0, 1.6,  80.0),
  'M56':   (5.50, 0.7, 78.7, 93.6, 35.0, 2.0,  85.0),
  '(M60)': (5.50, 0.7, 82.7, 99.2, 38.0, 2.0,  90.0),
  'M64':   (6.00, 0.7, 88.2,104.9, 40.0, 2.0,  95.0)
  } 



iso4017length = {
  '2': ( 1.8,  2.2),
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8),
  '180':(179.2, 180.8),
  '200':(199.1, 200.9)
  }

# range of typical srew lengths
#    min_length,  max_length
iso4017range = {
  'M1.6':  ('2', '16'),
  'M2':    ('4', '20'),
  'M2.5':  ('5', '25'),
  'M3':    ('5', '30'),
  '(M3.5)':('8', '35'),
  'M4':    ('6', '40'),
  'M5':    ('8', '50'),
  'M6':   ('12', '60'),
  'M8':   ('16', '80'),
  'M10':  ('20','100'),
  'M12':  ('25','120'),
  '(M14)':('25','140'),
  'M16':  ('30','150'),
  '(M18)':('35','200'),
  'M20':  ('40','160'),
  '(M22)':('45','200'),
  'M24':  ('50','180'),
  '(M27)':('50','100'),
  'M30':  ('60','200'), 
  '(M33)':('65','200'),
  'M36':  ('70','200'),
  '(M39)':('80','200'),
  'M42':  ('70','200'),
  '(M45)':('90','200'),
  'M48': ('100','200'),
  '(M52)':('100','200'),
  'M56':  ('110','200'),
  '(M60)':('120','200'),
  'M64':  ('120','200')
  } 

# ISO 8676 Hexagon head screw with metric fine pitch thread
#                P,    c,  dw,    e,     k,   r,   s
iso8676def={
  'M8x1':      (1.00, 0.3, 11.7, 14.5,  5.3, 0.25, 13.0),
  'M10x1':     (1.00, 0.3, 14.7, 17.9,  6.4, 0.4,  16.0),
  '(M10x1.25)':(1.25, 0.3, 14.7, 17.9,  6.4, 0.4,  16.0),
  'M12x1.5':   (1.50, 0.3, 16.7, 20.1,  7.5, 0.6,  18.0),
  '(M12x1.25)':(1.75, 0.3, 16.7, 20.1,  7.5, 0.6,  18.0),
  '(M14x1.5)': (1.50, 0.3, 20.5, 24.5,  8.8, 0.6,  22.0),
  'M16x1.5':   (1.50, 0.4, 22.4, 26.9, 10.0, 0.6,  24.0),
  '(M18x1.5)': (1.50, 0.4, 25.4, 30.2, 11.5, 0.6,  27.0),
  'M20x1.5':   (1.50, 0.4, 28.2, 33.7, 12.5, 0.8,  30.0),
  '(M20x2)':   (2.00, 0.4, 28.2, 33.7, 12.5, 0.8,  30.0),
  '(M22x1.5)': (1.50, 0.4, 31.8, 37.7, 14.0, 0.8,  34.0),
  'M24x2':     (2.00, 0.4, 33.7, 40.1, 15.0, 0.8,  36.0),
  '(M27x2)':   (2.00, 0.4, 38.0, 45.2, 17.0, 1.0,  41.0),
  'M30x2':     (2.00, 0.4, 42.8, 50.9, 18.7, 1.0,  46.0), #dw not in class A, e not in class A
  '(M33x2)':   (2.00, 0.4, 46.6, 55.4, 21.0, 1.0,  50.0), 
  'M36x3':     (3.00, 0.4, 51.2, 61.0, 22.5, 1.0,  55.0), #dw not in class A, e not in class A
  '(M39x3)':   (3.00, 0.5, 55.9, 66.5, 25.0, 1.0,  60.0),
  'M42x3':     (3.00, 0.7, 60.0, 71.3, 26.0, 1.2,  65.0),
  '(M45x3)':   (3.00, 0.7, 64.7, 77.0, 28.0, 1.2,  70.0),
  'M48x3':     (3.00, 0.7, 69.5, 82.6, 30.0, 1.6,  75.0),
  '(M52x4)':   (4.00, 0.7, 74.5, 88.3, 33.0, 1.6,  80.0),
  'M56x4':     (4.00, 0.7, 78.7, 93.6, 35.0, 2.0,  85.0),
  '(M60x4)':   (4.00, 0.7, 82.7, 99.2, 38.0, 2.0,  90.0),
  'M64x4':     (4.00, 0.7, 88.2,104.9, 40.0, 2.0,  95.0)
  } 

iso8676length = {
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8),
  '180':(179.2, 180.8),
  '200':(199.1, 200.9),
  '220':(217.7, 222.3),
  '240':(237.7, 242.3),
  '260':(219.1, 220.9),
  '280':(219.1, 220.9),
  '300':(219.1, 220.9),
  '320':(219.1, 220.9),
  '340':(219.1, 220.9),
  '360':(219.1, 220.9),
  '380':(219.1, 220.9),
  '400':(219.1, 220.9),
  '420':(219.1, 220.9),
  '440':(219.1, 220.9),
  '460':(219.1, 220.9),
  '480':(219.1, 220.9),
  '500':(496.85, 503.15)   
  }

# range of typical srew lengths
#    min_length,  max_length
iso8676range = {
  'M8x1':      ('16', '80'),
  'M10x1':     ('20','100'),
  '(M10x1.25)':('20','100'),
  'M12x1.5':   ('25','120'),
  '(M12x1.25)':('25','120'),
  '(M14x1.5)': ('30','140'),
  'M16x1.5':   ('35','160'),
  '(M18x1.5)': ('35','180'),
  'M20x1.5':   ('40','200'),
  '(M20x2)':   ('40','200'),
  '(M22x1.5)': ('45','220'),
  'M24x2':     ('40','200'),
  '(M27x2)':   ('55','260'),
  'M30x2':     ('40','200'), 
  '(M33x2)':   ('65','360'),
  'M36x3':     ('40','200'),
  '(M39x3)':   ('80','380'),
  'M42x3':     ('90','420'),
  '(M45x3)':   ('90','440'),
  'M48x3':     ('100','480'),
  '(M52x4)':   ('100','500'),
  'M56x4':     ('120','500'),
  '(M60x4)':   ('120','500'),
  'M64x4':     ('130','500')
  } 






# ISO 4014 Hex-head-bolt
#          P,      b1,    b2,    b3,  c,   dw,    e,    k,   r,   s
iso4014head={
  'M1.6':  (0.35,   9.0,  15.0,  28.0, 0.2,  2.3,  3.4,  1.1, 0.1,  3.2),
  'M2':    (0.40,  10.0,  16.0,  29.0, 0.2,  3.0,  4.4,  1.4, 0.1,  4.0),
  'M2.5':  (0.45,  11.0,  17.0,  30.0, 0.2,  4.0,  5.5,  1.7, 0.1,  5.0),
  'M3':    (0.50,  12.0,  18.0,  31.0, 0.2,  4.6,  6.1,  2.0, 0.1,  5.5),
  '(M3.5)':(0.60,  13.0,  19.0,  32.0, 0.2,  5.1,  6.6,  2.4, 0.1,  6.0),
  'M4':    (0.70,  14.0,  20.0,  33.0, 0.2,  5.9,  7.7,  2.8, 0.2,  7.0),
  'M5':    (0.80,  16.0,  22.0,  35.0, 0.2,  6.9,  8.9,  3.5, 0.2,  8.0), 
  'M6':    (1.00,  18.0,  24.0,  37.0, 0.2,  8.9, 11.05, 4.0, 0.25,10.0),
  'M8':    (1.25,  22.0,  28.0,  41.0, 0.3, 11.7, 14.5,  5.3, 0.4, 13.0),
  'M10':   (1.50,  26.0,  32.0,  45.0, 0.3, 14.7, 17.9,  6.4, 0.4, 16.0),
  'M12':   (1.75,  30.0,  36.0,  49.0, 0.3, 16.7, 20.1,  7.5, 0.6, 18.0),
  '(M14)': (2.00,  34.0,  40.0,  53.0, 0.3, 20.5, 24.5,  8.8, 0.6, 22.0),
  'M16':   (2.00,  38.0,  44.0,  57.0, 0.4, 22.4, 26.9, 10.0, 0.6, 24.0),
  '(M18)': (2.50,  42.0,  48.0,  61.0, 0.4, 25.4, 30.2, 11.5, 0.6, 27.0),
  'M20':   (2.50,  46.0,  52.0,  65.0, 0.4, 28.2, 33.7, 12.5, 0.8, 30.0),
  '(M22)': (2.50,  50.0,  56.0,  69.0, 0.4, 31.8, 37.7, 14.0, 0.8, 34.0),
  'M24':   (3.00,  54.0,  60.0,  73.0, 0.4, 33.7, 40.1, 15.0, 0.8, 36.0),
  '(M27)': (3.00,  60.0,  66.0,  79.0, 0.4, 38.0, 45.2, 17.0, 1.0, 41.0),
  'M30':   (3.50,  66.0,  72.0,  85.0, 0.4, 42.8, 50.9, 18.7, 1.0, 46.0), #dw not in class A, e not in class A
  '(M33)': (3.50,  78.0,  78.0,  91.0, 0.4, 46.6, 55.4, 21.0, 1.0, 50.0), 
  'M36':   (4.00,  84.0,  84.0,  97.0, 0.4, 51.2, 60.8, 22.5, 1.0, 55.0),
  '(M39)': (4.00,  90.0,  90.0, 103.0, 0.5, 55.9, 66.5, 25.0, 1.0, 60.0),
  'M42':   (4.50,  96.0,  96.0, 109.0, 0.6, 60.0, 71.3, 26.0, 1.2, 65.0),
  '(M45)': (4.50, 102.0, 102.0, 115.0, 0.7, 64.7, 77.0, 28.0, 1.2, 70.0),
  'M48':   (5.00, 108.0, 108.0, 121.0, 0.6, 69.5, 82.6, 30.0, 1.6, 75.0),
  '(M52)': (5.00, 116.0, 116.0, 129.0, 0.7, 74.5, 88.3, 33.0, 1.6, 80.0),
  'M56':   (5.50, 137.0, 137.0, 137.0, 0.6, 78.7, 93.6, 35.0, 2.0, 85.0),
  '(M60)': (5.50, 145.0, 145.0, 145.0, 0.7, 82.7, 99.2, 38.0, 2.0, 90.0),
  'M64':   (6.00, 153.0, 153.0, 153.0, 0.6, 88.2,104.9, 40.0, 2.0, 55.0)
  }


iso4014length = {
  '12':(11.65, 12.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8),
  '180':(179.2, 180.8),
  '200':(199.1, 200.9),
  '220':(219.1, 220.9),   
  '240':(237.7, 242.3),
  '260':(219.1, 220.9),
  '280':(219.1, 220.9),
  '300':(219.1, 220.9),
  '320':(219.1, 220.9),
  '340':(219.1, 220.9),
  '360':(219.1, 220.9),
  '380':(219.1, 220.9),
  '400':(219.1, 220.9),
  '420':(219.1, 220.9),
  '440':(219.1, 220.9),
  '460':(219.1, 220.9),
  '480':(219.1, 220.9),
  '500':(496.85, 503.15)   
  }

# range of typical srew lengths
#    min_length,  max_length
iso4014range = {
  'M1.6':('12', '16'),
  'M2':  ('16', '20'),
  'M2.5':('16', '25'),
  'M3':  ('20', '30'),
  '(M3.5)':('20', '35'),
  'M4':  ('25', '50'),
  'M5':  ('25', '50'),
  'M6':  ('30', '130'),
  'M8':  ('30', '180'),
  'M10': ('35', '150'),
  'M12': ('50', '150'),
  '(M14)': ('50', '160'),
  'M16': ('55', '200'),
  '(M18)':('70','180'),
  'M20': ('60', '300'),
  '(M22)':('70','220'),
  'M24': ('80', '220'),
  '(M27)':('90', '220'),
  'M30': ('110','300'),
  '(M33)':('130','320'),
  'M36': ('140','360'),
  '(M39)':('150','380'),
  'M42': ('160','440'),
  '(M45)':('180','440'),
  'M48': ('180','480'),
  '(M52)':('200','480'),
  'M56': ('220','500'),
  '(M60)':('220','500'),
  'M64': ('260','500')
  }


# EN 1662 Hexagon bolts with flange, small series
#          P,   b0,    b1,   b2,   b3,   c,  dc,    dw,    e,     k,   kw,  lf,  r1,   s
en1662def={
  'M5': (0.80, 25.0, 16.0,  0.0,  0.0, 1.0, 11.4,  9.4,  7.59,  5.6, 2.3, 1.4, 0.2, 7.0), 
  'M6': (1.00, 30.0, 18.0,  0.0,  0.0, 1.1, 13.6, 11.6,  8.71,  6.9, 2.9, 1.6, 0.25, 8.0),
  'M8': (1.25, 35.0, 22.0, 28.0,  0.0, 1.2, 17.0, 14.9, 10.95,  8.5, 3.8, 2.1, 0.4, 10.0),
  'M10':(1.50, 40.0, 26.0, 32.0,  0.0, 1.5, 20.8, 18.7, 14.26,  9.7, 4.3, 2.1, 0.4, 13.0),
  'M12':(1.75, 45.0, 30.0, 36.0,  0.0, 1.8, 24.7, 22.5, 17.62, 12.1, 5.4, 2.1, 0.6, 16.0),
  '(M14)':(2.00, 50.0, 34.0, 40.0,  0.0, 2.1, 28.6, 26.4, 19.86, 12.9, 5.6, 2.1, 0.6, 18.0),
  'M16':(2.00, 55.0, 38.0, 44.0, 57.0, 2.4, 32.8, 30.6, 23.15, 15.2, 6.8, 3.2, 0.6, 21.0)}


# range of typical srew lengths
#    min_length,  max_length
en1662range = {
  'M5': ('10', '50'),
  'M6': ('12', '60'),
  'M8': ('16', '80'),
  'M10':('20','100'),
  'M12':('25','120'),
  '(M14)':('30','140'), 
  'M16':('35','160')
  } 

en1662length = {
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '90':(89.3, 90.7),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8)
  }


# EN 1665 Hexagon bolts with flange, heavy series
#          P,    b0,  b1,   b2,   b3,   c,  dc,    dw,    e,     k,   kw,  lf,  r1,   s
en1665def={
  'M5': (0.80, 25.0, 16.0,  0.0,  0.0, 1.0, 11.8,  9.8,  8.71,  5.8, 2.6, 1.4, 0.2,  8.0), 
  'M6': (1.00, 30.0, 18.0,  0.0,  0.0, 1.1, 14.2, 12.2, 10.95,  6.6, 3.0, 1.6, 0.25,10.0),
  'M8': (1.25, 35.0, 22.0, 28.0,  0.0, 1.2, 18.0, 15.8, 14.26,  8.1, 3.9, 2.1, 0.4, 13.0),
  'M10':(1.50, 40.0, 26.0, 32.0,  0.0, 1.5, 22.3, 19.6, 17.62, 10.4, 4.1, 2.1, 0.4, 16.0),
  'M12':(1.75, 45.0, 30.0, 36.0,  0.0, 1.8, 26.6, 23.8, 19.86, 11.8, 5.6, 2.1, 0.6, 18.0),
  '(M14)':(2.00, 50.0, 34.0, 40.0,  0.0, 2.1, 30.5, 27.6, 23.15, 13.7, 6.5, 2.1, 0.6, 21.0),
  'M16':(2.00, 55.0, 38.0, 44.0, 57.0, 2.4, 35.0, 31.9, 26.51, 15.4, 7.3, 3.2, 0.6, 24.0),
  'M20':(2.50, 65.0, 46.0, 52.0, 65.0, 3.0, 43.0, 39.9, 33.23, 18.9, 8.9, 4.2, 0.8, 30.0)}


# range of typical srew lengths
#    min_length,  max_length
en1665range = {
  'M5': ('10', '50'),
  'M6': ('12', '60'),
  'M8': ('16', '80'),
  'M10':('20','100'),
  'M12':('25','120'),
  '(M14)':('30','140'), 
  'M16':('35','160'),
  'M20':('65','200')
  } 

en1665length = {
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '90':(89.3, 90.7),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8),
  '180':(179.2, 180.8),
  '200':(199.1, 200.9)
  }



# ISO 1207 definitions Class A, Slotted cheese head screws
#          P,     a,   b,   dk,  dk_mean, da,  k,  n_min, r, t_min, x
iso1207def={
  'M1.6':(0.35, 0.7, 25.0,  3.0,  2.9,  2.0, 1.1, 0.46, 0.1, 0.45, 0.9),
  'M2':  (0.40, 0.8, 25.0,  3.8,  3.7,  2.6, 1.4, 0.56, 0.1, 0.6, 1.0),
  'M2.5':(0.45, 0.9, 25.0,  4.5,  4.4,  3.1, 1.8, 0.66, 0.1, 0.7, 1.1),
  'M3':  (0.50, 1.0, 25.0,  5.5,  5.4,  3.6, 2.0, 0.86, 0.1, 0.85, 1.25),
  '(M3.5)':(0.60, 1.2, 38.0,  6.0,  5.9,  4.1, 2.4, 1.06, 0.1, 1.0, 1.5),
  'M4':  (0.70, 1.4, 38.0,  7.0,  6.9,  4.7, 2.6, 1.26, 0.2, 1.1, 1.75),
  'M5':  (0.80, 1.6, 38.0,  8.5,  8.4,  5.7, 3.3, 1.26, 0.2, 1.3, 2.0),
  'M6':  (1.00, 2.0, 38.0, 10.0,  9.9,  6.8, 3.9, 1.66, 0.25,1.6, 2.5),
  'M8':  (1.25, 2.5, 38.0, 13.0, 12.85, 9.2, 5.0, 2.06, 0.4, 2.0, 3.2),
  'M10': (1.50, 3.0, 38.0, 16.0, 15.85, 11.2,6.0, 2.56, 0.4, 2.4, 3.8)}

# range of typical srew lengths
#    min_length,  max_length
iso1207range = {
  'M1.6':('2', '16'),
  'M2':  ('3', '20'),
  'M2.5':('3', '25'),
  'M3':  ('4', '30'),
  '(M3.5)':('5', '35'),
  'M4':  ('5', '40'),
  'M5':  ('6', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '80'),
  'M10':('12', '80')}

# slotted cheese head screws
# nom length: l_min, l_max       
iso1207length = {
  '2': (1.8,  2.2),
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.05, 55.95),
  '60':(59.05, 60.95),
  '65':(64.05, 65.95),
  '70':(69.05, 70.95),
  '75':(74.05, 75.95),
  '80':(79.05, 80.95)
  }


# ISO 14580 definitions , Hexalobular socket cheese head screws
#          P,     a,   b,   dk,  dk_mean, da,  k,  n_min, r, t_min, x
#           tt,    k,    A,  t_mean
iso14580def={
  'M2':  ('T6',  1.55, 1.75, 0.8),
  'M2.5':('T8',  1.85, 2.40, 0.9),
  'M3':  ('T10', 2.40, 2.80, 1.2),
  '(M3.5)':('T15', 2.60, 3.35, 1.3),
  'M4':  ('T20', 3.10, 3.95, 1.5),
  'M5':  ('T25', 3.65, 4.50, 1.7),
  'M6':  ('T30', 4.40, 5.60, 2.1),
  'M8':  ('T45', 5.80, 7.95, 2.9),
  'M10': ('T50', 6.90, 8.95, 3.3)}
  
# range of typical srew lengths
#    min_length,  max_length
# iso14580range = iso1207range

# nom length: l_min, l_max       
iso14580length = {
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.05, 55.95),
  '60':(59.05, 60.95),
  '65':(64.05, 65.95),
  '70':(69.05, 70.95),
  '75':(74.05, 75.95),
  '80':(79.05, 80.95)
  }



# ISO 7048 definitions Class A, 
# Cross-recessed cheese head screws with type H or Z cross recess
#          P,     a,   b,   dk,  dk_mean, da,  k,   r,   x, cT,   mH,   mZ 
iso7048def={
  'M2.5':(0.45, 0.9, 25.0,  4.5,  4.4,  3.1, 1.8, 0.1, 1.1, '1', 2.7, 2.4),
  'M3':  (0.50, 1.0, 25.0,  5.5,  5.4,  3.6, 2.0, 0.1, 1.25,'2', 3.5, 3.5),
  '(M3.5)':(0.60, 1.2, 38.0,  6.0,  5.9,  4.1, 2.4, 0.1, 1.5, '2', 3.8, 3.7),
  'M4':  (0.70, 1.4, 38.0,  7.0,  6.9,  4.7, 2.6, 0.2, 1.75,'2', 4.1, 4.0),
  'M5':  (0.80, 1.6, 38.0,  8.5,  8.4,  5.7, 3.3, 0.2, 2.0, '2', 4.8, 4.6),
  'M6':  (1.00, 2.0, 38.0, 10.0,  9.9,  6.8, 3.9, 0.25,2.5, '3', 6.2, 6.1),
  'M8':  (1.25, 2.5, 38.0, 13.0, 12.85, 9.2, 5.0, 0.4, 3.2, '3', 7.7, 7.5)
  }

# range of typical srew lengths
#    min_length,  max_length
iso7048range = {
  'M2.5':('3', '25'),
  'M3':  ('4', '30'),
  '(M3.5)':('5', '35'),
  'M4':  ('5', '40'),
  'M5':  ('6', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '80')}

# nom length: l_min, l_max       
iso7048length = {
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '60':(59.05, 60.95),
  '70':(69.05, 70.95),
  '80':(79.05, 80.95)
  }


# Button Head Screw
# nom length: l_min, l_max       
iso7380length = {
  #'2.5':(2.3,  2.7),
  #'3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.05, 55.95),
  '60':(59.05, 60.95),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '90':(89.3, 90.7)
  }

# ISO 7380-1 definitions Class A 
# http://www.agrati.com/it/unificati/it/gamma/unificati/home02.htm
#          P,   b,     a,   da, dk,  dk_mean,s_mean,t_min, r, k,   e,    w,  
iso7380def={
  'M3':  (0.50, 18.0, 1.0,  3.6,  5.7,  5.5, 2.03, 1.04, 0.1, 1.65, 2.3,  0.2),
  'M4':  (0.70, 20.0, 1.4,  4.7,  7.6,  7.4, 2.54, 1.30, 0.2, 2.20, 2.87, 0.3),
  'M5':  (0.80, 22.0, 1.6,  5.7,  9.5,  9.3, 3.05, 1.56, 0.2, 2.75, 3.44, 0.38),
  'M6':  (1.00, 24.0, 2.0,  6.8, 10.5, 10.3, 4.05, 2.08, 0.25,3.3,  4.58, 0.74),
  'M8':  (1.25, 28.0, 2.5,  9.2, 14.0, 13.8, 5.05, 2.60, 0.4, 4.4,  5.72, 1.05),
  'M10': (1.50, 32.0, 3.0, 11.2, 17.5, 17.3, 6.05, 3.12, 0.4, 5.5,  6.86, 1.45),
  'M12': (1.75, 36.0, 3.5, 13.7, 21.0, 20.7, 8.06, 4.16, 0.6, 6.6,  9.15, 1.63),
  'M16': (2.00, 44.0, 3.5, 17.7, 28.0, 27.8, 10.06,5.20, 0.6, 8.8, 11.43, 2.25)
  }

# range of typical srew lengths
#    min_length,  max_length
iso7380range = {
  'M3':  ('6', '30'),
  'M4':  ('6', '40'),
  'M5':  ('8', '50'),
  'M6':  ('10', '60'),
  'M8': ('12', '80'),
  'M10':('16', '90'),
  'M12':('20', '90'),
  'M16':('25', '90')}

# ISO 7380-2 definitions 
#          P,   b,     c,   da, dk,    dk_c,s_mean,t_min, r,  k,   e,    w,  
iso7380_2def={
  'M3':  (0.50, 18.0, 0.7,  3.6,  5.2,  6.9, 2.03, 1.04, 0.1, 1.65, 2.3,  0.2),
  'M4':  (0.70, 20.0, 0.8,  4.7,  7.2,  9.4, 2.54, 1.30, 0.2, 2.20, 2.87, 0.3),
  'M5':  (0.80, 22.0, 1.0,  5.7,  8.8, 11.8, 3.05, 1.56, 0.2, 2.75, 3.44, 0.38),
  'M6':  (1.00, 24.0, 1.2,  6.8, 10.0, 13.6, 4.05, 2.08, 0.25,3.3,  4.58, 0.74),
  'M8':  (1.25, 28.0, 1.5,  9.2, 13.2, 17.8, 5.05, 2.60, 0.4, 4.4,  5.72, 1.05),
  'M10': (1.50, 32.0, 2.0, 11.2, 16.5, 21.9, 6.05, 3.12, 0.4, 5.5,  6.86, 1.45),
  'M12': (1.75, 36.0, 2.4, 13.7, 19.4, 26.0, 8.06, 4.16, 0.6, 6.6,  9.15, 1.63),
  'M16': (2.00, 44.0, 2.8, 17.7, 26.0, 34.0, 10.06,5.20, 0.6, 8.8, 11.43, 2.25)
  }


# DIN 967 definitions: Cross recessed pan head screw with collar
#          P,   b,     c,   da,   dk,   r,  k,    rf,  x,    cT,  mH,   mZ 
din967def={
  'M3':  (0.50, 25.0, 0.7,  3.6,  7.5, 0.1, 2.35,  3.8, 1.25, '1', 3.0, 2.9),
  '(M3.5)':(0.60, 38.0, 0.8,  4.1,  9.0, 0.1, 2.60,  4.6, 1.5,  '2', 4.2, 3.9),
  'M4':  (0.70, 38.0, 1.0,  4.7, 10.0, 0.2, 3.05,  5.8, 1.75, '2', 4.6, 4.3),
  'M5':  (0.80, 38.0, 1.2,  5.7, 11.5, 0.2, 3.55,  6.6, 2.0,  '2', 5.0, 4.7),
  'M6':  (1.00, 38.0, 1.6,  6.8, 14.5, 0.25,4.55,  8.2, 2.5,  '3', 7.1, 6.7),
  'M8':  (1.25, 38.0, 2.0,  9.2, 19.0, 0.4, 5.90, 11.0, 3.2,  '4', 9.0, 8.8)
  }

# range of typical srew lengths
#    min_length,  max_length
din967range = {
  'M3':  ('4', '30'),
  '(M3.5)':  ('5', '35'),
  'M4':  ('5', '40'),
  'M5':  ('6', '45'),
  'M6':  ('8', '60'),
  'M8': ('10', '60')
}
# Button Head Screw
# nom length: l_min, l_max       
din967length = {
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.05, 55.95),
  '60':(59.05, 60.95)
  }


L_iso2009length =['2.5','3','4','5','6','8','10','12','14','16','20', \
   '25','30','35','40','45','50','55','60','65','70','75','80'] 
# nom length: l_min, l_max       
iso2009length = {
  '2.5':(2.3,  2.7),
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.05, 55.95),
  '60':(59.05, 60.95),
  '65':(64.05, 65.95),
  '70':(69.05, 70.95),
  '75':(74.05, 75.95),
  '80':(79.05, 80.95)
  }


# ISO 2009 definitions Class A
#          P, a, b, dk_theo, dk_mean, k, n_min, r, t_mean, x
iso2009def={
   'M1.6':(0.35, 0.7, 25, 3.6, 2.8,  1.0,  0.46, 0.2, 0.4, 0.9),
   'M2':  (0.40, 0.8, 25, 4.4, 3.6,  1.2,  0.56, 0.3, 0.5, 1.0),
   'M2.5':(0.45, 0.9, 25, 5.5, 4.5,  1.5,  0.66, 0.3, 0.6, 1.1),
   'M3':  (0.50, 1.0, 25, 6.3, 5.3,  1.65, 0.86, 0.4, 0.7, 1.25),
   '(M3.5)':(0.60, 1.2, 38, 8.2, 7.1,  2.35, 1.06, 0.4, 1.0, 1.5),
   'M4':  (0.70, 1.4, 38, 9.4, 8.2,  2.7,  1.26, 0.5, 1.1, 1.75),
   'M5':  (0.80, 1.6, 38,10.4, 9.2,  2.7,  1.26, 0.6, 1.2, 2.0),
   'M6':  (1.00, 2.0, 38,12.6, 11.2, 3.3,  1.66, 0.7, 1.4, 2.5),
   'M8':  (1.25, 2.5, 38,17.3, 15.6, 4.65, 2.06, 1.0, 2.0, 3.2),
   'M10': (1.50, 3.0, 38,20.0, 18.1, 5.0,  2.56, 1.2, 2.3, 3.8)}
   
# range of typical srew lengths
#    min_length,  max_length
iso2009range = {
  'M1.6':('2.5', '16'),
  'M2':  ('3', '20'),
  'M2.5':('4', '25'),
  'M3':  ('5', '30'),
  '(M3.5)':('6', '35'),
  'M4':  ('6', '40'),
  'M5':  ('8', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '80'),
  'M10':('12', '80')}


# ISO 7046 definitions Class A
# ISO 7046 Countersunk flat head srews (common head style)
# with type H or type Z cross recess
# Parameters P, a, b, dk_theo, dk_mean, k, r, x to be read from iso2009def
# Length = iso7045length
#          cT,   mH,   mZ 
iso7046def={
  'M1.6':('0', 1.6, 1.6),
  'M2':  ('0', 1.9, 1.9),
  'M2.5':('1', 2.9, 2.8),
  'M3':  ('1', 3.2, 3.0),
  '(M3.5)':('2', 4.4, 4.1),
  'M4':  ('2', 4.6, 4.4),
  'M5':  ('2', 5.2, 4.0),
  'M6':  ('3', 6.8, 6.6),
  'M8':  ('4', 8.9, 8.8),
  'M10': ('4', 10.0,9.8)}

# range of typical srew lengths
#    min_length,  max_length
iso7046range = {
  'M1.6':('3', '16'),
  'M2':  ('3', '20'),
  'M2.5':('3', '25'),
  'M3':  ('4', '30'),
  '(M3.5)':('5', '35'),
  'M4':  ('5', '40'),
  'M5':  ('6', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '60'),
  'M10':('12', '60')}

# ISO 2010, ISO 7047 definitions Class A: Raised Countersunk head srews
# ISO 2010 slotted screws (common head style)   range = iso2009range
# ISO 7047  with type H or type Z cross recess  range = iso7046range
# Parameters P, a, b, dk_theo, dk_mean, k, r, x to be read from iso2009def
# Length = iso7045length
#          rf, t_mean, cT,   mH,   mZ 
Raised_countersunk_def={
  'M1.6':(3.0,  0.7, '0', 1.9,  1.9),
  'M2':  (4.0,  0.9, '0', 2.0,  2.2),
  'M2.5':(5.0,  1.1, '1', 3.0,  2.8),
  'M3':  (6.0,  1.3, '1', 3.4,  3.1),
  '(M3.5)':(8.5,  1.5, '2', 4.8,  4.6),
  'M4':  (9.5,  1.8, '2', 5.2,  5.0),
  'M5':  (9.5,  2.2, '2', 5.4,  5.3),
  'M6':  (12.0, 2.6, '3', 7.3,  7.1),
  'M8':  (16.5, 3.5, '4', 9.6,  9.5),
  'M10': (19.5, 4.1, '4', 10.4,10.3)}



# ISO 14582 definitions 
#          P,    a,    b, dk_theo, dk_mean,k,   r,  tt, A, t_mean
iso14582def={
  'M3':  (0.50, 1.0, 18.0,  7.40,  6.5, 2.20, 0.10, 'T10', 2.80, 1.1),
  'M4':  (0.70, 1.4, 20.0, 10.02,  9.0, 3.01, 0.20, 'T20', 3.95, 1.6),
  'M5':  (0.80, 1.6, 22.0, 12.00, 10.8, 3.50, 0.20, 'T25', 4.50, 1.8),
  'M6':  (1.00, 2.0, 24.0, 14.44, 13.1, 4.22, 0.25, 'T30', 5.60, 2.2),
  'M8':  (1.25, 2.5, 28.0, 19.38, 17.8, 5.69, 0.40, 'T45', 7.93, 2.8),
  'M10': (1.50, 3.0, 32.0, 23.00, 21.1, 6.50, 0.40, 'T50', 8.95, 3.3)}

# range of typical srew lengths
#    min_length,  max_length
iso14582range = {
  'M3':  ('8', '30'),
  'M4':  ('8', '40'),
  'M5':  ('8', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '80'),
  'M10':('12', '100')}

# nom length: l_min, l_max       
iso14582length = {
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '90':(89.3, 90.7),
  '100':(99.3, 100.7)
  }



# ISO 1580 definitions Class A, Slotted pan head screws
#           P,    a,   b, dk_max,da,  k, n_min,  r,  rf, t_mean, x
iso1580def={
  'M1.6':(0.35, 0.7, 25,  3.2, 2.0, 1.0, 0.46, 0.1, 0.5, 0.4, 0.9),
  'M2':  (0.4,  0.8, 25,  4.0, 2.6, 1.3, 0.56, 0.1, 0.6, 0.5, 1.0),
  'M2.5':(0.45, 0.9, 25,  5.0, 3.1, 1.5, 0.66, 0.1, 0.8, 0.6, 1.1),
  'M3':  (0.5,  1.0, 25,  5.6, 3.6, 1.8, 0.86, 0.1, 0.9, 0.7, 1.25),
  '(M3.5)':(0.6,  1.2, 38,  7.0, 4.1, 2.1, 1.06, 0.1, 1.0, 0.8, 1.5),
  'M4':  (0.7,  1.4, 38,  8.0, 4.7, 2.4, 1.26, 0.2, 1.2, 1.0, 1.75),
  'M5':  (0.8,  1.6, 38,  9.5, 5.7, 3.0, 1.26, 0.2, 1.5, 1.2, 2.0),
  'M6':  (1.0,  2.0, 38, 12.0, 6.8, 3.6, 1.66, 0.25,1.8, 1.4, 2.5),
  'M8':  (1.25, 2.5, 38, 16.0, 9.2, 4.8, 2.06, 0.4, 2.4, 1.9, 3.2),
  'M10': (1.50, 3.0, 38, 20.0,11.2, 6.0, 2.56, 0.4, 3.0, 2.4, 3.8)}



# ISO 7045 definitions Class A, Pan head screws with type H or type Z
# partly used also for ISO 14583 Hexalobular socket pan head screws
#   cross recess;    cT = size of cross recess
#           P,    a,   b, dk_max,da,  k,   r,   rf,  x,  cT,   mH,   mZ 
iso7045def={
  'M1.6':(0.35, 0.7, 25,  3.2, 2.0, 1.3, 0.1, 2.5, 0.9, '0', 1.7, 1.6),
  'M2':  (0.4,  0.8, 25,  4.0, 2.6, 1.6, 0.1, 3.2, 1.0, '0', 1.9, 2.1),
  'M2.5':(0.45, 0.9, 25,  5.0, 3.1, 2.1, 0.1, 4.0, 1.1, '1', 2.7, 2.6),
  'M3':  (0.5,  1.0, 25,  5.6, 3.6, 2.4, 0.1, 5.0, 1.25,'1', 3.0, 2.8),
  '(M3.5)':(0.6,  1.2, 38,  7.0, 4.1, 2.6, 0.1, 6.0, 1.5, '2', 3.9, 3.9),
  'M4':  (0.7,  1.4, 38,  8.0, 4.7, 3.1, 0.2, 6.5, 1.75,'2', 4.4, 4.3),
  'M5':  (0.8,  1.6, 38,  9.5, 5.7, 3.7, 0.2, 8.0, 2.0, '2', 4.9, 4.7),
  'M6':  (1.0,  2.0, 38, 12.0, 6.8, 4.6, 0.25,10., 2.5, '3', 6.9, 6.7),
  'M8':  (1.25, 2.5, 38, 16.0, 9.2, 6.0, 0.4, 13., 3.2, '4', 9.0, 8.8),
  'M10': (1.50, 3.0, 38, 20.0,11.2, 7.5, 0.4, 16., 3.8, '4', 10.1,9.9)}

# nom length: l_min, l_max       
iso7045length = {
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.05, 55.95),
  '60':(59.05, 60.95)
  }

# range of typical srew lengths
#    min_length,  max_length
iso7045range = {
  'M1.6':('3', '16'),
  'M2':  ('3', '20'),
  'M2.5':('3', '25'),
  'M3':  ('4', '30'),
  '(M3.5)':('5', '35'),
  'M4':  ('5', '40'),
  'M5':  ('6', '45'),
  'M6':  ('8', '60'),
  'M8': ('10', '60'),
  'M10':('12', '60')}


# ISO 14583 Hexalobular socket pan head screws
#   hexalobular recess;    tt = size of hexalobular recess

#           tt,    A,  t_mean
iso14583def={
  'M2':  ('T6',  1.75, 0.7),
  'M2.5':('T8',  2.40, 1.0),
  'M3':  ('T10', 2.80, 1.2),
  '(M3.5)':('T15', 3.35, 1.3),
  'M4':  ('T20', 3.95, 1.5),
  'M5':  ('T25', 4.50, 1.7),
  'M6':  ('T30', 5.60, 2.2),
  'M8':  ('T45', 7.95, 3.0),
  'M10': ('T50', 8.95, 3.8)}


#iso14583range = iso7046range
#iso14583length = iso7045length

# ISO 14584 Hexalobular socket raised countersunk head screws
#           P,   b, dk_theo, dk_mean, f,  k,   r,   rf,    x,    tt,    A,  t_mean
iso14584def={
  'M2':  (0.40, 25.0,  4.4,  3.8,  0.5, 1.20, 0.2,  4.0, 1.00, 'T6',  1.75, 0.7),
  'M2.5':(0.45, 25.0,  5.5,  4.7,  0.6, 1.50, 0.3,  5.0, 1.10, 'T8',  2.40, 1.0),
  'M3':  (0.50, 25.0,  6.3,  5.5,  0.7, 1.65, 0.4,  6.0, 1.25, 'T10', 2.80, 1.2),
  '(M3.5)':(0.60, 38.0,  8.2,  7.3,  0.8, 2.35, 0.4,  8.5, 1.50, 'T15', 3.35, 1.3),
  'M4':  (0.70, 38.0,  9.4,  8.4,  1.0, 2.70, 0.5,  9.5, 1.75, 'T20', 3.95, 1.5),
  'M5':  (0.80, 38.0, 10.4,  9.3,  1.2, 2.70, 0.6,  9.5, 2.00, 'T25', 4.50, 1.7),
  'M6':  (1.00, 38.0, 12.6, 11.3,  1.4, 3.30, 0.7, 12.0, 2.50, 'T30', 5.60, 2.2),
  'M8':  (1.25, 38.0, 17.3, 15.8,  2.0, 4.65, 1.0, 16.5, 3.20, 'T45', 7.95, 3.0),
  'M10': (1.50, 38.0, 20.0, 18.3,  2.3, 5.00, 1.2, 19.5, 3.80, 'T50', 8.95, 3.8)}


# range of typical srew lengths
#    min_length,  max_length
iso14584range = {
  'M2':  ('3', '20'),
  'M2.5':('3', '25'),
  'M3':  ('4', '30'),
  '(M3.5)':('5', '35'),
  'M4':  ('5', '40'),
  'M5':  ('6', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '60'),
  'M10':('12', '60')}

#iso14584length = iso7045length


# ISO 4762 Hexagon socket head cap screws ( Allan screw)
# ISO 4762 definitions
#           P,   b,  dk_max,  da,  ds_min,   e,    lf,   k,   r,   s_mean, t,    v,   dw,   w
iso4762def={
  'M1.6':(0.35,  15.0,  3.0,  2.0,  1.46,  1.73, 0.34,  1.6, 0.1,  1.56,  0.7, 0.16, 2.72, 0.55),
  'M2':  (0.40,  16.0,  3.8,  2.6,  1.86,  1.73, 0.51,  2.0, 0.1,  1.56,  1.0, 0.2,  3.48, 0.55),
  'M2.5':(0.45,  17.0,  4.5,  3.1,  2.36,  2.30, 0.51,  2.5, 0.1,  2.06,  1.1, 0.25, 4.18, 0.85),
  'M3':  (0.50,  18.0,  5.5,  3.6,  2.86,  2.87, 0.51,  3.0, 0.1,  2.56,  1.3, 0.3,  5.07, 1.15),
  'M4':  (0.70,  20.0,  7.0,  4.7,  3.82,  3.44, 0.60,  4.0, 0.2,  3.06,  2.0, 0.4,  6.53, 1.40),
  'M5':  (0.80,  22.0,  8.5,  5.7,  4.82,  4.58, 0.60,  5.0, 0.2,  4.06,  2.5, 0.5,  8.03, 1.9),
  'M6':  (1.00,  24.0, 10.0,  6.8,  5.82,  5.72, 0.68,  6.0, 0.25, 5.06,  3.0, 0.6,  9.38, 2.3),
  'M8':  (1.25,  28.0, 13.0,  9.2,  7.78,  6.86, 1.02,  8.0, 0.4,  6.06,  4.0, 0.8, 12.33, 3.3),
  'M10': (1.50,  32.0, 16.0, 11.2,  9.78,  9.15, 1.02, 10.0, 0.4,  8.07,  5.0, 1.0, 15.33, 4.0),
  'M12': (1.75,  36.0, 18.0, 13.7, 11.73, 11.43, 1.45, 12.0, 0.6, 10.07,  6.0, 1.2, 17.23, 4.8),
  '(M14)':(2.00,  40.0, 21.0, 15.7, 13.73, 13.72, 1.45, 14.0, 0.6, 12.07,  7.0, 1.4, 20.17, 5.8),
  'M16': (2.00,  44.0, 24.0, 17.7, 15.73, 16.00, 1.45, 16.0, 0.6, 14.08,  8.0, 1.6, 23.17, 6.8),
  'M20': (2.50,  52.0, 30.0, 22.4, 19.67, 19.44, 2.04, 20.0, 0.8, 17.10, 10.0, 2.0, 28.87, 8.6),
  'M24': (3.00,  60.0, 36.0, 26.4, 23.67, 21.73, 2.04, 24.0, 0.8, 19.15, 12.0, 2.0, 34.81, 10.4),
  'M30': (3.50,  72.0, 45.0, 33.4, 29.67, 25.15, 2.89, 30.0, 1.0, 22.15, 15.5, 2.4, 43.61, 13.1),
  'M36': (4.00,  84.0, 54.0, 39.4, 35.61, 30.85, 2.89, 36.0, 1.0, 27.15, 19.0, 3.0, 52.54, 15.3),
  'M42': (4.50,  96.0, 63.0, 45.6, 41.61, 36.58, 3.06, 42.0, 1.2, 32.15, 24.0, 4.2, 61.34, 16.3),
  'M48': (5.00, 108.0, 72.0, 52.6, 47.61, 41.14, 3.91, 48.0, 1.6, 36.15, 28.0, 4.8, 70.34, 17.5),
  'M56': (5.50, 124.0, 84.0, 63.0, 55.54, 46.84, 5.95, 56.0, 2.0, 41.15, 34.0, 5.6, 82.26, 19.0),
  'M64': (6.00, 140.0, 96.0, 71.0, 63.54, 52.54, 5.95, 64.0, 2.0, 46.15, 38.0, 6.4, 94.26, 22.0)
  }

# nom length: l_min, l_max       
iso4762length = {
  '2.5':(2.3,  2.7),
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '14':(13.65, 14.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '75':(74.4, 75.6),
  '80':(79.4, 80.6),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8),
  '180':(179.2, 180.8),
  '200':(199.1, 200.9),
  '220':(219.1, 220.9),   
  '240':(237.7, 242.3),
  '260':(219.1, 220.9),
  '280':(219.1, 220.9),
  '300':(219.1, 220.9)
  }

# range of typical srew lengths
#    min_length,  max_length
iso4762range = {
  'M1.6':('2.5', '16'),
  'M2':  ('3', '20'),
  'M2.5':('4', '25'),
  'M3':  ('5', '30'),
  '(M3.5)':('6', '35'),
  'M4':  ('6', '40'),
  'M5':  ('8', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '80'),
  'M10':('16', '100'),
  'M12':('20', '120'),
  '(M14)':('25', '140'),
  'M16':('25', '160'),
  'M20':('16', '100'),
  'M24':('40', '200'),
  'M30':('45', '200'),
  'M36':('55', '200'),   
  'M42':('60', '300'),
  'M48':('100','300'),
  'M56':('110','300'),
  'M64':('120','300')
  }


# ISO 14579 Hexalobular socket head cap screws
#   hexalobular recess;    tt = size of hexalobular recess

#           tt,    A,  t_mean
iso14579def={
  'M2':  ( 'T6',  1.75, 0.8),
  'M2.5':( 'T8',  2.40, 1.0),
  'M3':  ('T10',  2.80, 1.2),
  'M4':  ('T20',  3.95, 1.7),
  'M5':  ('T25',  4.50, 1.9),
  'M6':  ('T30',  5.60, 2.3),
  'M8':  ('T45',  7.95, 3.2),
  'M10': ('T50',  8.95, 3.8),
  'M12': ('T55', 11.35, 5.0),
  '(M14)': ('T60', 13.45, 5.8),
  'M16': ('T70', 15.70, 6.8),
  '(M18)': ('T80', 17.75, 7.8),
  'M20': ('T90', 20.20, 9.0),
  }

# range of typical srew lengths
#    min_length,  max_length
iso14579range = {
  'M2':  ('3', '20'),
  'M2.5':('4', '25'),
  'M3':  ('5', '30'),
  'M4':  ('6', '40'),
  'M5':  ('8', '50'),
  'M6': ('10', '60'),
  'M8': ('12', '80'),
  'M10':('16','100'),
  'M12':('20','120'),
  '(M14)':('25','140'), 
  'M16':('25','160'),
  '(M18)':('30','180'),
  'M20':('30','200'),
  } 

iso14579length = {
  '3': ( 2.8,  3.2),
  '4': ( 3.76, 4.24),
  '5': ( 4.76, 5.24),
  '6': ( 5.76, 6.24),
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '90':(89.3, 90.7),
  '100':(99.3, 100.7),
  '110':(109.3, 110.7),
  '120':(119.3, 120.7),
  '130':(129.2, 130.8),
  '140':(139.2, 130.8),
  '150':(149.2, 150.8),
  '160':(159.2, 160.8),
  '180':(179.2, 180.8),
  '200':(199.1, 200.9)
  }


# ISO 10642 Hexagon socket countersunk head screws ( Allan screw)
# ISO 10642 definitions
#           P,   b,  dk_theo, dk_mean,da,  ds_min,   e,  k,   r,   s_mean, t,    w
iso10642def={
  'M3':  (0.50, 18.0,  6.72,  6.0,  3.3,  2.86,  2.31, 1.86, 0.1,  2.06,  1.1, 0.25),
  'M4':  (0.70, 20.0,  8.96,  8.0,  4.4,  3.82,  2.88, 2.48, 0.2,  2.56,  1.5, 0.45),
  'M5':  (0.80, 22.0, 11.20, 10.0,  5.5,  4.82,  3.45, 3.10, 0.2,  3.06,  1.9, 0.66),
  'M6':  (1.00, 24.0, 13.44, 12.0,  6.6,  5.82,  4.59, 3.72, 0.25, 4.06,  2.2, 0.70),
  'M8':  (1.25, 28.0, 17.92, 16.0,  8.54, 7.78,  5.73, 4.96, 0.4,  5.06,  3.0, 1.16),
  'M10': (1.50, 32.0, 22.40, 20.5, 10.62, 9.78,  6.87, 6.20, 0.4,  6.06,  3.6, 1.62),
  'M12': (1.75, 36.0, 26.88, 25.0, 13.5, 11.73,  9.15, 7.44, 0.6,  8.07,  4.3, 1.80),
  '(M14)': (2.00, 40.0, 30.80, 28.4, 15.5, 13.73, 11.43, 8.40, 0.6, 10.07,  4.5, 1.62),
  'M16': (2.00, 44.0, 33.60, 31.0, 17.5, 15.73, 11.43, 8.80, 0.6, 10.07,  4.8, 2.20),
  'M20': (2.50, 52.0, 40.32, 38.0, 22.0, 19.67, 13.72, 10.16, 0.8, 12.10,  5.6, 2.20)}

# range of typical srew lengths
#    min_length,  max_length
iso10642range = {
  'M3':  ('8', '30'),
  'M4':  ('8', '40'),
  'M5':  ('8', '50'),
  'M6':  ('8', '60'),
  'M8': ('10', '80'),
  'M10':('12','100'),
  'M12':('20','100'),
  '(M14)':('25','100'), 
  'M16':('30','100'),
  'M20':('35','100'),
  } 

iso10642length = {
  '8': ( 7.71, 8.29),
  '10':( 9.71, 10.29),
  '12':(11.65, 12.35),
  '16':(15.65, 16.35),
  '20':(19.58, 20.42),
  '25':(24.58, 25.42),
  '30':(29.58, 30.42),
  '35':(34.5,  35.5),
  '40':(39.5,  40.5),
  '45':(44.5,  45.5),
  '50':(49.5,  50.5),
  '55':(54.4, 55.6),
  '60':(59.4, 60.6),
  '65':(64.4, 65.6),
  '70':(69.4, 70.6),
  '80':(79.4, 80.6),
  '90':(89.3, 90.7),
  '100':(99.3, 100.7),
  }


# ISO 7089 definitions  Washer
#           d1_min, d2_max, h, h_max
iso7089def={
  'M1.6':( 1.7,  4.0, 0.3, 0.35),
  'M2':  ( 2.2,  5.0, 0.3, 0.35),
  'M2.5':( 2.7,  6.0, 0.5, 0.55),
  'M3':  ( 3.2,  7.0, 0.5, 0.55),
  'M4':  ( 4.3,  9.0, 0.8, 0.90),
  'M5':  ( 5.3, 10.0, 1.0, 1.10),
  'M6':  ( 6.4, 12.0, 1.6, 1.80),
  'M8':  ( 8.4, 16.0, 1.6, 1.80),
  'M10': (10.5, 20.0, 2.0, 2.20),
  'M12': (13.0, 24.0, 2.5, 2.70),
  'M16': (17.0, 30.0, 3.0, 3.30),
  'M20': (21.0, 37.0, 3.0, 3.30),
  'M24': (25.0, 44.0, 4.0, 4.30),
  'M30': (31.0, 56.0, 4.0, 4.30),
  'M36': (37.0, 66.0, 5.0, 5.60),
  'M42': (45.0, 78.0, 8.0, 9.0),
  'M48': (52.0, 92.0, 8.0, 9.0),
  'M56': (62.0,105.0,10.0, 11.0),
  'M64': (70.0,115.0,10.0, 11.0)
  }       


# ISO 7090 definitions Plain washers, chamfered - Normal series
# chamfer angle 30° / 45°
# chamfer      h/4 / h/2
#           d1_min, d2_max, h, h_max
iso7090def={
  'M5':  ( 5.3, 10.0, 1.0, 1.10),
  'M6':  ( 6.4, 12.0, 1.6, 1.80),
  'M8':  ( 8.4, 16.0, 1.6, 1.80),
  'M10': (10.5, 20.0, 2.0, 2.20),
  'M12': (13.0, 24.0, 2.5, 2.70),
  'M16': (17.0, 30.0, 3.0, 3.30),
  'M20': (21.0, 37.0, 3.0, 3.30),
  'M24': (25.0, 44.0, 4.0, 4.30),
  'M30': (31.0, 56.0, 4.0, 4.30),
  'M36': (37.0, 66.0, 5.0, 5.60),
  'M42': (45.0, 78.0, 8.0, 9.0),
  'M48': (52.0, 92.0, 8.0, 9.0),
  'M56': (62.0,105.0,10.0, 11.0),
  'M64': (70.0,115.0,10.0, 11.0)
  }       


# ISO 7091 definitions  Plain washer - Normal series Product Grade C
#           d1_min, d2_max, h, h_max
iso7091def={
  'M1.6':( 1.8,  4.0, 0.3, 0.35),
  'M2':  ( 2.4,  5.0, 0.3, 0.35),
  'M2.5':( 2.9,  6.0, 0.5, 0.55),
  'M3':  ( 3.4,  7.0, 0.5, 0.55),
  'M4':  ( 4.5,  9.0, 0.8, 0.90),
  'M5':  ( 5.5, 10.0, 1.0, 1.10),
  'M6':  ( 6.6, 12.0, 1.6, 1.80),
  'M8':  ( 9.0, 16.0, 1.6, 1.80),
  'M10': (11.0, 20.0, 2.0, 2.20),
  'M12': (13.5, 24.0, 2.5, 2.70),
  'M16': (17.5, 30.0, 3.0, 3.30),
  'M20': (22.0, 37.0, 3.0, 3.30),
  'M24': (26.0, 44.0, 4.0, 4.30),
  'M30': (33.0, 56.0, 4.0, 4.30),
  'M36': (39.0, 66.0, 5.0, 5.60),
  'M42': (45.0, 78.0, 8.0, 9.0),
  'M48': (52.0, 92.0, 8.0, 9.0),
  'M56': (62.0,105.0,10.0, 11.0),
  'M64': (70.0,115.0,10.0, 11.0)
  }       


# ISO 7092 definitions  Plain washers - Small series
#           d1_min, d2_max, h, h_max
iso7092def={
  'M1.6':( 1.7,  3.5, 0.3, 0.35),
  'M2':  ( 2.2,  4.5, 0.3, 0.35),
  'M2.5':( 2.7,  5.0, 0.5, 0.55),
  'M3':  ( 3.2,  6.0, 0.5, 0.55),
  'M4':  ( 4.3,  8.0, 0.5, 0.55),
  'M5':  ( 5.3,  9.0, 1.0, 1.10),
  'M6':  ( 6.4, 11.0, 1.6, 1.80),
  'M8':  ( 8.4, 15.0, 1.6, 1.80),
  'M10': (10.5, 18.0, 1.6, 1.80),
  'M12': (13.0, 20.0, 2.0, 2.20),
  'M16': (17.0, 28.0, 2.5, 2.70),
  'M20': (21.0, 34.0, 3.0, 3.30),
  'M24': (25.0, 39.0, 4.0, 4.30),
  'M30': (31.0, 50.0, 4.0, 4.30),
  'M36': (37.0, 60.0, 5.0, 5.60)
  }       



# ISO 7093-1 definitions  Plain washers - Large series
#           d1_min, d2_max, h, h_max
iso7093def={
  'M3':    ( 3.2,  9.0, 0.8, 0.90),
  '(M3.5)':( 3.7, 11.0, 0.8, 0.90),
  'M4':    ( 4.3, 12.0, 1.0, 1.10),
  'M5':    ( 5.3, 15.0, 1.0, 1.10),
  'M6':    ( 6.4, 18.0, 1.6, 1.80),
  'M8':    ( 8.4, 24.0, 2.0, 2.20),
  'M10':   (10.5, 30.0, 2.5, 2.70),
  'M12':   (13.0, 37.0, 3.0, 3.30),
  '(M14)': (15.0, 44.0, 3.0, 3.30),
  'M16':   (17.0, 50.0, 3.0, 3.30),
  '(M18)': (19.0, 56.0, 4.0, 4.30),
  'M20':   (21.0, 60.0, 4.0, 4.30),
  '(M22)': (23.0, 66.0, 5.0, 5.60),
  'M24':   (25.0, 72.0, 5.0, 5.60),
  '(M27)': (30.0, 85.0, 6.0, 6.60),
  'M30':   (33.0, 92.0, 6.0, 6.60),
  '(M33)': (36.0,105.0, 6.0, 6.60),
  'M36':   (39.0,110.0, 8.0, 9.00)
  }       


# ISO 7094 definitions  Plain washers - Extra large series
#           d1_min, d2_max, h, h_max
iso7094def={
  'M5':    ( 5.5, 18.0, 2.0, 2.3),
  'M6':    ( 6.6, 22.0, 2.0, 2.3),
  'M8':    ( 9.0, 28.0, 3.0, 3.6),
  'M10':   (11.0, 34.0, 3.0, 3.6),
  'M12':   (13.5, 44.0, 4.0, 4.6),
  '(M14)': (15.5, 50.0, 4.0, 4.6),
  'M16':   (17.5, 56.0, 5.0, 6.0),
  '(M18)': (20.0, 60.0, 5.0, 6.0),
  'M20':   (22.0, 72.0, 6.0, 7.0),
  '(M22)': (24.0, 80.0, 6.0, 7.0),
  'M24':   (26.0, 85.0, 6.0, 7.0),
  '(M27)': (30.0, 98.0, 6.0, 7.0),
  'M30':   (33.0,105.0, 6.0, 7.0),
  '(M33)': (36.0,115.0, 8.0, 9.2),
  'M36':   (39.0,125.0, 8.0, 9.2)
  }       




# ISO 4757:1983 Definition of cross recess type H
#          b, e_min, g, f_mean, r, t1, alpha, beta
iso4757def = {
  '0': (0.61, 0.26, 0.81, 0.34, 0.3, 0.22, 138.0, 7.0 ),
  '1': (0.97, 0.41, 1.27, 0.54, 0.5, 0.34, 138.0, 7.0 ),
  '2': (1.47, 0.79, 2.29, 0.70, 0.6, 0.61, 140.0, 5.75),
  '3': (2.41, 1.98, 3.81, 0.83, 0.8, 1.01, 146.0, 5.75),
  '4': (3.48, 2.39, 5.08, 1.23, 1.0, 1.35, 153.0, 7.0 )
  }

# ISO 10664 Hexalobular internal driving feature for bolts and screws
#           A,     B,   Re
iso10664def = {
  'T6': ( 1.75,  1.205, 0.14),
  'T8': ( 2.40,  1.67, 0.20),
  'T10':( 2.80,  1.98, 0.24),
  'T15':( 3.35,  2.35, 0.28),
  'T20':( 3.95,  2.75, 0.32),
  'T25':( 4.50,  3.16, 0.39),
  'T30':( 5.60,  3.95, 0.46),
  'T40':( 6.75,  4.76, 0.56),
  'T45':( 7.93,  5.55, 0.59),
  'T50':( 8.95,  6.36, 0.78),
  'T55':(11.35,  7.92, 0.77),
  'T60':(13.45,  9.48, 1.07),
  'T70':(15.70, 11.08, 1.20),
  'T80':(17.75, 12.64, 1.53),
  'T90':(20.20, 14.22, 1.54),
  'T100':(22.40,15.81, 1.73)
  } 



# ISO 4032 Hex-head-nut
#           P,   c,  damax, dw,    e,     m,  mw,  s_nom
iso4032def={
  'M1.6':  (0.35, 0.2, 1.84, 2.9,  3.4,   1.3, 0.8,  3.2),
  'M2':    (0.40, 0.2, 2.3,  3.7,  4.4,   1.6, 1.1,  4.0),
  'M2.5':  (0.45, 0.2, 2.9,  4.6,  5.5,   2.0, 1.4,  5.0),
  'M3':    (0.5,  0.2, 3.45, 5.2,  6.1,   2.4, 1.7,  5.5),
  '(M3.5)':(0.6,  0.2, 4.00, 5.7,  6.6,   2.8, 2.0,  6.0),
  'M4':    (0.7,  0.2, 4.6,  6.6,  7.7,   3.2, 2.3,  7.0), 
  'M5':    (0.8,  0.2, 5.75, 7.5,  8.9,   3.5, 3.5,  8.0),
  'M6':    (1.0,  0.2, 6.75, 9.5,  11.05, 4.7, 3.9, 10.0),
  'M8':    (1.25, 0.3, 8.75, 11.7, 14.5,  6.8, 5.2, 13.0),
  'M10':   (1.50, 0.3, 10.8, 14.7, 17.9,  8.4, 6.4,  16.0),
  'M12':   (1.75, 0.3, 13.0, 16.7, 20.1, 10.8, 8.3,  18.0),
  '(M14)': (2.00, 0.3, 15.1, 20.5, 24.5, 12.8, 9.7,  22.0),
  'M16':   (2.00, 0.4, 17.3, 22.4, 26.9, 14.8, 11.3,  24.0),
  '(M18)': (2.50, 0.4, 19.5, 24.9, 29.6, 15.8, 12.3,  27.0),
  'M20':   (2.50, 0.4, 21.6, 28.2, 33.7, 18.0, 13.5,  30.0),
  '(M22)': (2.50, 0.4, 23.7, 31.4, 37.3, 19.4, 15.0,  34.0),
  'M24':   (3.00, 0.4, 25.9, 33.7, 40.1, 21.5, 16.2,  36.0),
  '(M27)': (3.00, 0.4, 29.1, 38.0, 45.2, 23.8, 18.0,  41.0),
  'M30':   (3.50, 0.4, 32.4, 42.8, 50.9, 25.6, 19.4,  46.0), 
  '(M33)': (3.50, 0.4, 35.6, 46.6, 55.4, 28.7, 21.4,  50.0), 
  'M36':   (4.00, 0.4, 38.9, 51.2, 61.0, 31.0, 23.5,  55.0),
  '(M39)': (4.00, 0.5, 42.1, 55.9, 66.5, 33.4, 24.5,  60.0),
  'M42':   (4.50, 0.7, 45.4, 60.0, 71.3, 34.0, 25.9,  65.0),
  '(M45)': (4.50, 0.7, 48.6, 64.7, 77.0, 36.0, 27.9,  70.0),
  'M48':   (5.00, 0.7, 51.8, 69.5, 82.6, 38.0, 29.1,  75.0),
  '(M52)': (5.00, 0.7, 56.2, 74.5, 88.3, 42.0, 32.1,  80.0),
  'M56':   (5.50, 0.7, 60.5, 78.7, 93.6, 45.0, 34.7,  85.0),
  '(M60)': (5.50, 0.7, 64.8, 82.7, 99.2, 48.0, 38.7,  90.0),
  'M64':   (6.00, 0.7, 69.1, 88.2,104.9, 51.0, 39.3,  95.0)
  } 



# ISO 4033 Hexagon nuts style 2
#           P,   c,  damax, dw,    e,     m,  mw,  s_nom
iso4033def={
  'M5':    (0.8,  0.2, 5.75, 7.5,  8.9,   5.1, 3.5,  8.0),
  'M6':    (1.0,  0.2, 6.75, 9.5,  11.05, 5.7, 3.9, 10.0),
  'M8':    (1.25, 0.3, 8.75, 11.7, 14.5,  7.5, 5.2, 13.0),
  'M10':   (1.50, 0.3, 10.8, 14.7, 17.9,  9.3, 6.4,  16.0),
  'M12':   (1.75, 0.3, 13.0, 16.7, 20.1, 12.0, 8.3,  18.0),
  '(M14)': (2.00, 0.3, 15.1, 20.5, 24.5, 14.1, 9.7,  22.0),
  'M16':   (2.00, 0.4, 17.3, 22.4, 26.9, 16.4, 11.3,  24.0),
  'M20':   (2.50, 0.4, 21.6, 28.2, 33.7, 20.3, 13.5,  30.0),
  'M24':   (3.00, 0.4, 25.9, 33.7, 40.1, 23.9, 16.2,  36.0),
  'M30':   (3.50, 0.4, 32.4, 42.8, 50.9, 28.6, 19.4,  46.0), 
  'M36':   (4.00, 0.4, 38.9, 51.2, 61.0, 33.1, 23.5,  55.0)
  }






# ISO 4035 Hexagon thin nuts, chamfered
#           P,   c,  damax, dw,    e,     m,  mw,  s_nom
iso4035def={
  'M1.6':  (0.35, 0.2, 1.84, 2.9,  3.4,   1.0,  0.8,  3.2),
  'M2':    (0.40, 0.2, 2.3,  3.7,  4.4,   1.2,  1.1,  4.0),
  'M2.5':  (0.45, 0.2, 2.9,  4.6,  5.5,   1.6,  1.4,  5.0),
  'M3':    (0.5,  0.2, 3.45, 5.2,  6.1,   1.8,  1.7,  5.5),
  '(M3.5)':(0.6,  0.2, 4.00, 5.7,  6.6,   2.0,  2.0,  6.0),
  'M4':    (0.7,  0.2, 4.6,  6.6,  7.7,   2.2,  2.3,  7.0), 
  'M5':    (0.8,  0.2, 5.75, 7.5,  8.9,   2.7,  3.5,  8.0),
  'M6':    (1.0,  0.2, 6.75, 9.5,  11.05, 3.2,  3.9, 10.0),
  'M8':    (1.25, 0.3, 8.75, 11.7, 14.5,  4.0,  5.2, 13.0),
  'M10':   (1.50, 0.3, 10.8, 14.7, 17.9,  5.0,  6.4, 16.0),
  'M12':   (1.75, 0.3, 13.0, 16.7, 20.1,  6.0,  8.3, 18.0),
  '(M14)': (2.00, 0.3, 15.1, 20.5, 24.5,  7.0,  9.7, 22.0),
  'M16':   (2.00, 0.4, 17.3, 22.4, 26.9,  8.0, 11.3, 24.0),
  '(M18)': (2.50, 0.4, 19.5, 24.9, 29.6,  9.0, 12.3, 27.0),
  'M20':   (2.50, 0.4, 21.6, 28.2, 33.7, 10.0, 13.5, 30.0),
  '(M22)': (2.50, 0.4, 23.7, 31.4, 37.3, 11.0, 15.0, 34.0),
  'M24':   (3.00, 0.4, 25.9, 33.7, 40.1, 12.0, 16.2, 36.0),
  '(M27)': (3.00, 0.4, 29.1, 38.0, 45.2, 13.5, 18.0, 41.0),
  'M30':   (3.50, 0.4, 32.4, 42.8, 50.9, 15.0, 19.4, 46.0), 
  '(M33)': (3.50, 0.4, 35.6, 46.6, 55.4, 16.5, 21.4, 50.0), 
  'M36':   (4.00, 0.4, 38.9, 51.2, 61.0, 18.0, 23.5, 55.0),
  '(M39)': (4.00, 0.5, 42.1, 55.9, 66.5, 19.5, 24.5, 60.0),
  'M42':   (4.50, 0.7, 45.4, 60.0, 71.3, 21.0, 25.9, 65.0),
  '(M45)': (4.50, 0.7, 48.6, 64.7, 77.0, 22.5, 27.9, 70.0),
  'M48':   (5.00, 0.7, 51.8, 69.5, 82.6, 24.0, 29.1, 75.0),
  '(M52)': (5.00, 0.7, 56.2, 74.5, 88.3, 26.0, 32.1, 80.0),
  'M56':   (5.50, 0.7, 60.5, 78.7, 93.6, 28.0, 34.7, 85.0),
  '(M60)': (5.50, 0.7, 64.8, 82.7, 99.2, 30.0, 38.7, 90.0),
  'M64':   (6.00, 0.7, 69.1, 88.2,104.9, 32.0, 39.3, 95.0)
  }






# ISO 4036 Hexagon thin nuts, unchamfered
#           P,      e,   m,  s_nom
iso4036def={
  'M1.6':  (0.35,  3.4, 1.0,  3.2),
  'M2':    (0.40,  4.4, 1.2,  4.0),
  'M2.5':  (0.45,  5.5, 1.6,  5.0),
  'M3':    (0.5,   6.1, 1.8,  5.5),
  '(M3.5)':(0.6,   6.6, 2.0,  6.0),
  'M4':    (0.7,   7.7, 2.2,  7.0), 
  'M5':    (0.8,   8.9, 2.7,  8.0),
  'M6':    (1.0,  10.9, 3.2, 10.0),
  'M8':    (1.25, 14.5, 4.0, 13.0),
  'M10':   (1.50, 17.9, 5.0, 16.0)}



# EN 1661 Hexagon nuts with flange
#          P,    damax,  c,  dc,    dw,    e,     m,   mw,   r,   s
en1661def={
  'M5'   :(0.80,  5.75, 1.0, 11.8,  9.8,  8.79,  5.0, 2.5,  0.30,  8.0), 
  'M6'   :(1.00,  6.75, 1.1, 14.2, 12.2, 11.05,  6.0, 3.1,  0.36, 10.0),
  'M8'   :(1.25,  8.75, 1.2, 17.9, 15.8, 14.38,  8.0, 4.6,  0.48, 13.0),
  'M10'  :(1.50, 10.80, 1.5, 21.8, 19.6, 17.77, 10.0, 5.9,  0.60, 16.0),
  'M12'  :(1.75, 13.00, 1.8, 26.0, 23.8, 20.03, 12.0, 6.8,  0.72, 18.0),
  '(M14)':(2.00, 15.10, 2.1, 29.9, 27.6, 23.36, 14.0, 7.7,  0.88, 21.0),
  'M16'  :(2.00, 17.30, 2.4, 34.5, 31.9, 26.75, 16.0, 8.9,  0.96, 24.0),
  'M20'  :(2.50, 21.60, 3.0, 42.8, 39.9, 33.23, 20.0,10.7,  1.20, 30.0)}


# Tuning table to get valid shapes
#         P, tunIn, tunEx   
tuningTable={
  'M1.6':(0.35, 516, 516),
  'M2':  (0.40, 515, 516),
  'M2.5':(0.45, 515, 515),
  'M3':  (0.5,  480, 502),
  '(M3.5)':(0.6,  480, 502),
  'M4':  (0.7,  510, 519), #last value needed for ISO7380
  'M5':  (0.8,  510, 510),
  'M6':  (1.0,  515, 515),
  'M8':  (1.25, 516, 516),
  'M10': (1.50, 515, 515),
  'M12': (1.75, 513, 513),
  '(M14)': (2.00, 513, 513),
  'M16': (2.00, 513, 513),
  'M20': (2.50, 513, 513),
  'M24': (3.00, 513, 513),
  '(M27)': (3.00, 513, 513),
  'M30': (3.50, 513, 513),
  '(M33)': (3.50, 513, 513),
  'M36': (4.00, 513, 513),
  'M42': (4.50, 515, 515),
  '(M45)': (4.50, 515, 515),
  'M48': (5.00, 515, 505), # ISO4014: 505, 502 or 488; ISO4017: above 505
  '(M52)': (5.00, 508, 508),
  'M56': (5.50, 508, 508),
  '(M60)': (5.50, 508, 508),
  'M64': (6.00, 489, 489) # Nut ISO4032: 489
  } 


def equal_vertex(vert1, vert2, p=5):
  # compares two vertices 
  return (round(vert1.X - vert2.X,p)==0 and round(vert1.Y - vert2.Y,p)==0 and round(vert1.Z - vert2.Z,p)==0)



try:
  _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
  _fromUtf8 = lambda s: s

class Ui_ScrewMaker(object):
  def setupUi(self, ScrewMaker):
    FCUi = FreeCADGui.UiLoader()

    ScrewMaker.setObjectName(_fromUtf8("ScrewMaker"))
    ScrewMaker.resize(450, 362)
    ScrewMaker.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
    self.layoutWidget = QtGui.QWidget(ScrewMaker)
    self.layoutWidget.setGeometry(QtCore.QRect(348, 35, 102, 161))
    self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
    self.verticalLayout_2 = QtGui.QVBoxLayout(self.layoutWidget)
    #self.verticalLayout_2.setMargin(0)
    self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
    self.ScrewTypeLabel = QtGui.QLabel(self.layoutWidget)
    self.ScrewTypeLabel.setObjectName(_fromUtf8("ScrewTypeLabel"))
    self.verticalLayout_2.addWidget(self.ScrewTypeLabel)
    self.NomDiaLabel = QtGui.QLabel(self.layoutWidget)
    self.NomDiaLabel.setObjectName(_fromUtf8("NomDiaLabel"))
    self.verticalLayout_2.addWidget(self.NomDiaLabel)
    self.NomLenLabel = QtGui.QLabel(self.layoutWidget)
    self.NomLenLabel.setObjectName(_fromUtf8("NomLenLabel"))
    self.verticalLayout_2.addWidget(self.NomLenLabel)
    self.UserLenLabel = QtGui.QLabel(self.layoutWidget)
    self.UserLenLabel.setObjectName(_fromUtf8("UserLenLabel"))
    self.verticalLayout_2.addWidget(self.UserLenLabel)

    self.layoutWidget1 = QtGui.QWidget(ScrewMaker)
    self.layoutWidget1.setGeometry(QtCore.QRect(3, 35, 350, 166))
    #self.layoutWidget1.setGeometry(QtCore.QRect(10, 5, 315, 200))
    self.layoutWidget1.setObjectName(_fromUtf8("layoutWidget1"))
    self.verticalLayout = QtGui.QVBoxLayout(self.layoutWidget1)
    #self.verticalLayout.setMargin(0)
    self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
    self.ScrewType = QtGui.QComboBox(self.layoutWidget1)
    self.ScrewType.setObjectName(_fromUtf8("ScrewType"))
    for i in range(33):
      self.ScrewType.addItem(_fromUtf8(""))  # 0

    self.verticalLayout.addWidget(self.ScrewType)
    self.NominalDiameter = QtGui.QComboBox(self.layoutWidget1)
    self.NominalDiameter.setObjectName(_fromUtf8("NominalDiameter"))
    for i in range(52):
      self.NominalDiameter.addItem(_fromUtf8("")) # 0

    self.verticalLayout.addWidget(self.NominalDiameter)
    self.NominalLength = QtGui.QComboBox(self.layoutWidget1)
    self.NominalLength.setObjectName(_fromUtf8("NominalLength"))
    for i in range(48):
      self.NominalLength.addItem(_fromUtf8("")) #0

    self.verticalLayout.addWidget(self.NominalLength)
    #self.UserLen = QtGui.QComboBox(self.layoutWidget1)
    self.UserLen = FCUi.createWidget("Gui::InputField")
    self.UserLen.setObjectName(_fromUtf8("UserLen"))
    #self.UserLen.addItem(_fromUtf8(""))
    self.UserLen.setProperty("text", "0 mm")
    self.verticalLayout.addWidget(self.UserLen)

    #self.CommentLabel = QtGui.QLabel(self.layoutWidget)
    self.CommentLabel = QtGui.QLabel(ScrewMaker)
    self.CommentLabel.setObjectName(_fromUtf8("CommentLabel"))
    self.CommentLabel.setGeometry(QtCore.QRect(10, 184, 411, 21))
    #self.verticalLayout.addWidget(self.CommentLabel)





    self.layoutWidget2 = QtGui.QWidget(ScrewMaker)
    #self.layoutWidget2.setGeometry(QtCore.QRect(10, 200, 321, 83))
    self.layoutWidget2.setGeometry(QtCore.QRect(3, 200, 321, 120))
    self.layoutWidget2.setObjectName(_fromUtf8("layoutWidget2"))
    self.verticalLayout_3 = QtGui.QVBoxLayout(self.layoutWidget2)
    #self.verticalLayout_3.setMargin(0)
    self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
    self.SimpleScrew = QtGui.QRadioButton(self.layoutWidget2)
    self.SimpleScrew.setChecked(True)
    self.SimpleScrew.setObjectName(_fromUtf8("SimpleScrew"))
    self.verticalLayout_3.addWidget(self.SimpleScrew)
    self.SymbolThread = QtGui.QRadioButton(self.layoutWidget2)
    self.SymbolThread.setObjectName(_fromUtf8("SymbolThread"))
    self.verticalLayout_3.addWidget(self.SymbolThread)
    self.RealThread = QtGui.QRadioButton(self.layoutWidget2)
    self.RealThread.setObjectName(_fromUtf8("RealThread"))
    self.verticalLayout_3.addWidget(self.RealThread)
    self.MessageLabel = QtGui.QLabel(ScrewMaker)
    self.MessageLabel.setGeometry(QtCore.QRect(10, 10, 411, 21))
    self.MessageLabel.setProperty("Empty_text", _fromUtf8(""))
    self.MessageLabel.setObjectName(_fromUtf8("MessageLabel"))
    self.CreateButton = QtGui.QToolButton(ScrewMaker)
    self.CreateButton.setGeometry(QtCore.QRect(180, 320, 111, 26))
    self.CreateButton.setObjectName(_fromUtf8("CreateButton"))
    self.ScrewAvailable = True
    
    self.simpThread = self.SimpleScrew.isChecked()
    self.symThread = self.SymbolThread.isChecked()
    self.rThread = self.RealThread.isChecked()
    
    self.theScrew = Screw()


    self.retranslateUi(ScrewMaker)
    self.NominalDiameter.setCurrentIndex(5)
    self.NominalLength.setCurrentIndex(9)
    QtCore.QObject.connect(self.ScrewType, QtCore.SIGNAL(_fromUtf8("currentIndexChanged(int)")), self.guiCheck_Data)
    QtCore.QObject.connect(self.CreateButton, QtCore.SIGNAL(_fromUtf8("pressed()")), self.guiCreateScrew)
    QtCore.QObject.connect(self.NominalDiameter, QtCore.SIGNAL(_fromUtf8("currentIndexChanged(int)")), self.guiCheck_Data)
    QtCore.QObject.connect(self.NominalLength, QtCore.SIGNAL(_fromUtf8("currentIndexChanged(int)")), self.guiCheck_Data)
    QtCore.QMetaObject.connectSlotsByName(ScrewMaker)

  def retranslateUi(self, ScrewMaker):
    ScrewMaker.setWindowTitle(QtGui.QApplication.translate("ScrewMaker", "Screw-Maker 2.4", None))
    self.ScrewTypeLabel.setText(QtGui.QApplication.translate("ScrewMaker", "Type of Screw", None))
    self.NomDiaLabel.setText(QtGui.QApplication.translate("ScrewMaker", "Nomimal\nDiameter", None))
    self.NomLenLabel.setText(QtGui.QApplication.translate("ScrewMaker", "Nominal\nLength", None))
    self.UserLenLabel.setText(QtGui.QApplication.translate("ScrewMaker", "User length \nfor screw-tap", None))
    self.CommentLabel.setText(QtGui.QApplication.translate("ScrewMaker", "Values in brackets are not recommended!", None))
    self.ScrewType.setItemText(0, QtGui.QApplication.translate("ScrewMaker", "ISO4017: Hexagon head screws", None))
    self.ScrewType.setItemText(1, QtGui.QApplication.translate("ScrewMaker", "ISO4014: Hexagon head bolts", None))
    self.ScrewType.setItemText(2, QtGui.QApplication.translate("ScrewMaker", "EN1662: Hexagon bolts with flange, small\n    series", None))
    self.ScrewType.setItemText(3, QtGui.QApplication.translate("ScrewMaker", "EN1665: Hexagon bolts with flange, heavy\n    series", None))
    self.ScrewType.setItemText(4, QtGui.QApplication.translate("ScrewMaker", "ISO8676: Hexagon head screw with\n    metric fine pitch thread", None))
    self.ScrewType.setItemText(5, QtGui.QApplication.translate("ScrewMaker", "ISO4762: Hexagon socket head cap screws", None))
    self.ScrewType.setItemText(6, QtGui.QApplication.translate("ScrewMaker", "ISO7380-1: Hexagon socket button head\n    screws", None))
    self.ScrewType.setItemText(7, QtGui.QApplication.translate("ScrewMaker", "ISO7380-2: Hexagon socket button head\n    screws with collar", None))
    self.ScrewType.setItemText(8, QtGui.QApplication.translate("ScrewMaker", "DIN967: Cross recessed pan head screws\n    with collar", None))
    self.ScrewType.setItemText(9, QtGui.QApplication.translate("ScrewMaker", "ISO10642: Hexagon socket countersunk \n    head screws", None))
    self.ScrewType.setItemText(10, QtGui.QApplication.translate("ScrewMaker", "ISO2009: Slotted countersunk flat head\n    screws", None))
    self.ScrewType.setItemText(11, QtGui.QApplication.translate("ScrewMaker", "ISO2010: Slotted raised countersunk head\n    screws", None))
    self.ScrewType.setItemText(12, QtGui.QApplication.translate("ScrewMaker", "ISO1207: Slotted cheese head screws", None))
    self.ScrewType.setItemText(13, QtGui.QApplication.translate("ScrewMaker", "ISO1580: Slotted pan head screws", None))
    self.ScrewType.setItemText(14, QtGui.QApplication.translate("ScrewMaker", "ISO7045: Pan head screws, type H cross recess", None))
    self.ScrewType.setItemText(15, QtGui.QApplication.translate("ScrewMaker", "ISO7046: Countersunk flat head screws\n    H cross recess", None))
    self.ScrewType.setItemText(16, QtGui.QApplication.translate("ScrewMaker", "ISO7047: Raised countersunk head screws\n    H cross recess", None))
    self.ScrewType.setItemText(17, QtGui.QApplication.translate("ScrewMaker", "ISO7048: Cheese head screws type H cross recess", None))
    self.ScrewType.setItemText(18, QtGui.QApplication.translate("ScrewMaker", "ISO14579: Hexalobular socket head cap screws", None))
    self.ScrewType.setItemText(19, QtGui.QApplication.translate("ScrewMaker", "ISO14580: Hexalobular socket cheese head\n    screws", None))
    self.ScrewType.setItemText(20, QtGui.QApplication.translate("ScrewMaker", "ISO14583: Hexalobular socket pan head screws", None))
    self.ScrewType.setItemText(21, QtGui.QApplication.translate("ScrewMaker", "ISO14582: Hexalobular socket countersunk\n    head screws, high head", None))
    self.ScrewType.setItemText(22, QtGui.QApplication.translate("ScrewMaker", "ISO14584: Hexalobular socket raised\n    countersunk head screws", None))
    self.ScrewType.setItemText(23, QtGui.QApplication.translate("ScrewMaker", "ISO7089: Plain washers - Normal series", None))
    self.ScrewType.setItemText(24, QtGui.QApplication.translate("ScrewMaker", "ISO7090: Plain washers, chamfered - Normal series", None))
    self.ScrewType.setItemText(25, QtGui.QApplication.translate("ScrewMaker", "ISO7092: Plain washers - Small series", None))
    self.ScrewType.setItemText(26, QtGui.QApplication.translate("ScrewMaker", "ISO7093-1: Plain washer - Large series", None))
    self.ScrewType.setItemText(27, QtGui.QApplication.translate("ScrewMaker", "ISO7094: Plain washers - Extra large series", None))
    self.ScrewType.setItemText(28, QtGui.QApplication.translate("ScrewMaker", "ISO4032: Hexagon nuts, Style 1", None))
    self.ScrewType.setItemText(29, QtGui.QApplication.translate("ScrewMaker", "ISO4033: Hexagon nuts, Style 2", None))
    self.ScrewType.setItemText(30, QtGui.QApplication.translate("ScrewMaker", "ISO4035: Hexagon thin nuts, chamfered", None))
    self.ScrewType.setItemText(31, QtGui.QApplication.translate("ScrewMaker", "EN1661: Hexagon nuts with flange", None))
    self.ScrewType.setItemText(32, QtGui.QApplication.translate("ScrewMaker", "ScrewTap: ISO Screw-Tap", None))
    
    self.NominalDiameter.setItemText(0, QtGui.QApplication.translate("ScrewMaker", "M1.6", None))
    self.NominalDiameter.setItemText(1, QtGui.QApplication.translate("ScrewMaker", "M2", None))
    self.NominalDiameter.setItemText(2, QtGui.QApplication.translate("ScrewMaker", "M2.5", None))
    self.NominalDiameter.setItemText(3, QtGui.QApplication.translate("ScrewMaker", "M3", None))
    self.NominalDiameter.setItemText(4, QtGui.QApplication.translate("ScrewMaker", "(M3.5)", None))
    self.NominalDiameter.setItemText(5, QtGui.QApplication.translate("ScrewMaker", "M4", None))
    self.NominalDiameter.setItemText(6, QtGui.QApplication.translate("ScrewMaker", "M5", None))
    self.NominalDiameter.setItemText(7, QtGui.QApplication.translate("ScrewMaker", "M6", None))
    self.NominalDiameter.setItemText(8, QtGui.QApplication.translate("ScrewMaker", "M8", None))
    self.NominalDiameter.setItemText(9, QtGui.QApplication.translate("ScrewMaker", "M10", None))
    self.NominalDiameter.setItemText(10, QtGui.QApplication.translate("ScrewMaker", "M12", None))
    self.NominalDiameter.setItemText(11, QtGui.QApplication.translate("ScrewMaker", "(M14)", None))
    self.NominalDiameter.setItemText(12, QtGui.QApplication.translate("ScrewMaker", "M16", None))
    self.NominalDiameter.setItemText(13, QtGui.QApplication.translate("ScrewMaker", "(M18)", None))
    self.NominalDiameter.setItemText(14, QtGui.QApplication.translate("ScrewMaker", "M20", None))
    self.NominalDiameter.setItemText(15, QtGui.QApplication.translate("ScrewMaker", "(M22)", None))
    self.NominalDiameter.setItemText(16, QtGui.QApplication.translate("ScrewMaker", "M24", None))
    self.NominalDiameter.setItemText(17, QtGui.QApplication.translate("ScrewMaker", "(M27)", None))
    self.NominalDiameter.setItemText(18, QtGui.QApplication.translate("ScrewMaker", "M30", None))
    self.NominalDiameter.setItemText(19, QtGui.QApplication.translate("ScrewMaker", "M36", None))
    self.NominalDiameter.setItemText(20, QtGui.QApplication.translate("ScrewMaker", "(M33)", None))
    self.NominalDiameter.setItemText(21, QtGui.QApplication.translate("ScrewMaker", "M42", None))
    self.NominalDiameter.setItemText(22, QtGui.QApplication.translate("ScrewMaker", "(M45)", None))
    self.NominalDiameter.setItemText(23, QtGui.QApplication.translate("ScrewMaker", "M48", None))
    self.NominalDiameter.setItemText(24, QtGui.QApplication.translate("ScrewMaker", "(M52)", None))
    self.NominalDiameter.setItemText(25, QtGui.QApplication.translate("ScrewMaker", "M54", None))
    self.NominalDiameter.setItemText(26, QtGui.QApplication.translate("ScrewMaker", "(M60)", None))
    self.NominalDiameter.setItemText(27, QtGui.QApplication.translate("ScrewMaker", "M64", None))

    self.NominalDiameter.setItemText(28, QtGui.QApplication.translate("ScrewMaker", 'M8x1', None))
    self.NominalDiameter.setItemText(29, QtGui.QApplication.translate("ScrewMaker", 'M10x1', None))
    self.NominalDiameter.setItemText(30, QtGui.QApplication.translate("ScrewMaker", '(M10x1.25)', None))
    self.NominalDiameter.setItemText(31, QtGui.QApplication.translate("ScrewMaker", 'M12x1.5', None))
    self.NominalDiameter.setItemText(32, QtGui.QApplication.translate("ScrewMaker", '(M12x1.25)', None))
    self.NominalDiameter.setItemText(33, QtGui.QApplication.translate("ScrewMaker", '(M14x1.5)', None))
    self.NominalDiameter.setItemText(34, QtGui.QApplication.translate("ScrewMaker", 'M16x1.5', None))
    self.NominalDiameter.setItemText(35, QtGui.QApplication.translate("ScrewMaker", '(M18x1.5)', None))
    self.NominalDiameter.setItemText(36, QtGui.QApplication.translate("ScrewMaker", 'M20x1.5', None))
    self.NominalDiameter.setItemText(37, QtGui.QApplication.translate("ScrewMaker", '(M20x2)', None))
    self.NominalDiameter.setItemText(38, QtGui.QApplication.translate("ScrewMaker", '(M22x1.5)', None))
    self.NominalDiameter.setItemText(39, QtGui.QApplication.translate("ScrewMaker", 'M24x2', None))
    self.NominalDiameter.setItemText(40, QtGui.QApplication.translate("ScrewMaker", '(M27x2)', None))
    self.NominalDiameter.setItemText(41, QtGui.QApplication.translate("ScrewMaker", 'M30x2', None))
    self.NominalDiameter.setItemText(42, QtGui.QApplication.translate("ScrewMaker", '(M33x2)', None))
    self.NominalDiameter.setItemText(43, QtGui.QApplication.translate("ScrewMaker", 'M36x3', None))
    self.NominalDiameter.setItemText(44, QtGui.QApplication.translate("ScrewMaker", '(M39x3)', None))
    self.NominalDiameter.setItemText(45, QtGui.QApplication.translate("ScrewMaker", 'M42x3', None))
    self.NominalDiameter.setItemText(46, QtGui.QApplication.translate("ScrewMaker", '(M45x3)', None))
    self.NominalDiameter.setItemText(47, QtGui.QApplication.translate("ScrewMaker", 'M48x3', None))
    self.NominalDiameter.setItemText(48, QtGui.QApplication.translate("ScrewMaker", '(M52x4)', None))
    self.NominalDiameter.setItemText(49, QtGui.QApplication.translate("ScrewMaker", 'M56x4', None))
    self.NominalDiameter.setItemText(50, QtGui.QApplication.translate("ScrewMaker", '(M60x4)', None))
    self.NominalDiameter.setItemText(51, QtGui.QApplication.translate("ScrewMaker", 'M64x4', None))



    self.NominalLength.setItemText(0, QtGui.QApplication.translate("ScrewMaker", "2", None))
    self.NominalLength.setItemText(1, QtGui.QApplication.translate("ScrewMaker", "2.5", None))
    self.NominalLength.setItemText(2, QtGui.QApplication.translate("ScrewMaker", "3", None))
    self.NominalLength.setItemText(3, QtGui.QApplication.translate("ScrewMaker", "4", None))
    self.NominalLength.setItemText(4, QtGui.QApplication.translate("ScrewMaker", "5", None))
    self.NominalLength.setItemText(5, QtGui.QApplication.translate("ScrewMaker", "6", None))
    self.NominalLength.setItemText(6, QtGui.QApplication.translate("ScrewMaker", "8", None))
    self.NominalLength.setItemText(7, QtGui.QApplication.translate("ScrewMaker", "10", None))
    self.NominalLength.setItemText(8, QtGui.QApplication.translate("ScrewMaker", "12", None))
    self.NominalLength.setItemText(9, QtGui.QApplication.translate("ScrewMaker", "16", None))
    self.NominalLength.setItemText(10, QtGui.QApplication.translate("ScrewMaker", "20", None))
    self.NominalLength.setItemText(11, QtGui.QApplication.translate("ScrewMaker", "25", None))
    self.NominalLength.setItemText(12, QtGui.QApplication.translate("ScrewMaker", "30", None))
    self.NominalLength.setItemText(13, QtGui.QApplication.translate("ScrewMaker", "35", None))
    self.NominalLength.setItemText(14, QtGui.QApplication.translate("ScrewMaker", "40", None))
    self.NominalLength.setItemText(15, QtGui.QApplication.translate("ScrewMaker", "45", None))
    self.NominalLength.setItemText(16, QtGui.QApplication.translate("ScrewMaker", "50", None))
    self.NominalLength.setItemText(17, QtGui.QApplication.translate("ScrewMaker", "55", None))
    self.NominalLength.setItemText(18, QtGui.QApplication.translate("ScrewMaker", "60", None))
    self.NominalLength.setItemText(19, QtGui.QApplication.translate("ScrewMaker", "65", None))
    self.NominalLength.setItemText(20, QtGui.QApplication.translate("ScrewMaker", "70", None))
    self.NominalLength.setItemText(21, QtGui.QApplication.translate("ScrewMaker", "80", None))
    self.NominalLength.setItemText(22, QtGui.QApplication.translate("ScrewMaker", "90", None))
    self.NominalLength.setItemText(23, QtGui.QApplication.translate("ScrewMaker", "100", None))
    self.NominalLength.setItemText(24, QtGui.QApplication.translate("ScrewMaker", "110", None))
    self.NominalLength.setItemText(25, QtGui.QApplication.translate("ScrewMaker", "120", None))
    self.NominalLength.setItemText(26, QtGui.QApplication.translate("ScrewMaker", "130", None))
    self.NominalLength.setItemText(27, QtGui.QApplication.translate("ScrewMaker", "140", None))
    self.NominalLength.setItemText(28, QtGui.QApplication.translate("ScrewMaker", "150", None))
    self.NominalLength.setItemText(29, QtGui.QApplication.translate("ScrewMaker", "160", None))
    self.NominalLength.setItemText(30, QtGui.QApplication.translate("ScrewMaker", "180", None))
    self.NominalLength.setItemText(31, QtGui.QApplication.translate("ScrewMaker", "200", None))
    self.NominalLength.setItemText(32, QtGui.QApplication.translate("ScrewMaker", "220", None))
    self.NominalLength.setItemText(33, QtGui.QApplication.translate("ScrewMaker", "240", None))
    self.NominalLength.setItemText(34, QtGui.QApplication.translate("ScrewMaker", "260", None))
    self.NominalLength.setItemText(35, QtGui.QApplication.translate("ScrewMaker", "280", None))
    self.NominalLength.setItemText(36, QtGui.QApplication.translate("ScrewMaker", "300", None))
    self.NominalLength.setItemText(37, QtGui.QApplication.translate("ScrewMaker", "320", None))
    self.NominalLength.setItemText(38, QtGui.QApplication.translate("ScrewMaker", "340", None))
    self.NominalLength.setItemText(39, QtGui.QApplication.translate("ScrewMaker", "360", None))
    self.NominalLength.setItemText(40, QtGui.QApplication.translate("ScrewMaker", "380", None))
    self.NominalLength.setItemText(41, QtGui.QApplication.translate("ScrewMaker", "400", None))
    self.NominalLength.setItemText(42, QtGui.QApplication.translate("ScrewMaker", "420", None))
    self.NominalLength.setItemText(43, QtGui.QApplication.translate("ScrewMaker", "440", None))
    self.NominalLength.setItemText(44, QtGui.QApplication.translate("ScrewMaker", "460", None))
    self.NominalLength.setItemText(45, QtGui.QApplication.translate("ScrewMaker", "480", None))
    self.NominalLength.setItemText(46, QtGui.QApplication.translate("ScrewMaker", "500", None))
    self.NominalLength.setItemText(47, QtGui.QApplication.translate("ScrewMaker", "User", None))
    #self.UserLen.setItemText(0, QtGui.QApplication.translate("ScrewMaker", "regular pitch", None))
    self.SimpleScrew.setText(QtGui.QApplication.translate("ScrewMaker", "Simple Screw (no thread at all!)", None))
    self.SymbolThread.setText(QtGui.QApplication.translate("ScrewMaker", "Symbol Thread (not implemented yet)", None))
    self.RealThread.setText(QtGui.QApplication.translate("ScrewMaker", "Real Thread (takes time, memory intensive)\nMay not work for all screws!", None))
    self.MessageLabel.setText(QtGui.QApplication.translate("ScrewMaker", "Select your screw type", None))
    self.MessageLabel.setProperty("Errortext", QtGui.QApplication.translate("ScrewMaker", "Combination not implemented", None))
    self.MessageLabel.setProperty("OK_text", QtGui.QApplication.translate("ScrewMaker", "Screw is made", None))
    self.CreateButton.setText(QtGui.QApplication.translate("ScrewMaker", "create", None))



  def guiCheck_Data(self):
    ST_text = str(self.ScrewType.currentText())
    ST_text = ST_text.split(':')[0]
    ND_text = str(self.NominalDiameter.currentText())
    NL_text = str(self.NominalLength.currentText())
    M_text, self.ScrewAvailable  = self.theScrew.check_Data(ST_text, ND_text, NL_text)
    self.MessageLabel.setText(QtGui.QApplication.translate("ScrewMaker", M_text, None))


  def guiCreateScrew(self):
    #self.simpThread = self.SimpleScrew.isChecked()
    #self.symThread = self.SymbolThread.isChecked()
    #self.rThread = self.RealThread.isChecked()
    if self.SimpleScrew.isChecked():
      threadType = 'simple'
    if self.SymbolThread.isChecked():
      threadType = 'symbol'
    if self.RealThread.isChecked():
      threadType = 'real'
      
    ND_text = str(self.NominalDiameter.currentText())
    NL_text = str(self.NominalLength.currentText())
    ST_text = str(self.ScrewType.currentText())
    ST_text = ST_text.split(':')[0]
    
    if (ST_text == 'ScrewTap') or (ST_text == 'ISO8676'):
      if NL_text == 'User':
        textValue = self.UserLen.property("text")
        stLength = FreeCAD.Units.parseQuantity(textValue).Value
        NL_text = str(stLength)

    myObj = self.theScrew.createScrew(ST_text, ND_text, NL_text, threadType)







class Screw(object):
  def __init__(self):
    self.objAvailable = True
    # The experience showed, that the helix diameter has a subtle
    # influence on the real thread produced with this helix.
    # It can be the difference between fast or slow creation of
    # the thread or a valid or invalid shape.
    # self.Tuner is an instrument to allow tests with different helix
    # diameters.
    self.Tuner = 510
    
    # OCCT seems to change the orientation of circles from time to time.
    # This is a test, in order to check this. self.circleAxis is used
    # where a circle and a hex are combined in one profile.
    # A combined profile is faster compared to cutting profiles.
    testCirc=Part.makeCircle(2.0,Base.Vector(0.0,0.0,-0.0),Base.Vector(0.0,0.0,-1.0))
    testDisk = Part.Face(Part.Wire(testCirc))
    z = testDisk.Surface.Axis.z
    if z > 0:
      self.circleAxis = Base.Vector(0.0,0.0,1.0)
    else:
      self.circleAxis = Base.Vector(0.0,0.0,-1.0)
  
  def check_Data(self, ST_text, ND_text, NL_text):
    #FreeCAD.Console.PrintMessage("Data checking" + NL_text + "\n")
    #set screw not ok
    self.objAvailable = False
    M_text = "Select your screw type"
    Type_text = ''
    if ST_text == 'ISO4017':
      table = iso4017head
      tab_len = iso4017length
      tab_range = iso4017range
      Type_text = 'Screw'

    if ST_text == 'EN1662':
      table = en1662def
      tab_len = en1662length
      tab_range = en1662range
      Type_text = 'Screw'
      
    if ST_text == 'EN1665':
      table = en1665def
      tab_len = en1665length
      tab_range = en1665range
      Type_text = 'Screw'
              
    if ST_text == 'ISO8676':
      table = iso8676def
      tab_len = iso8676length
      tab_range = iso8676range
      Type_text = 'Screw'
              
    if ST_text == 'ISO2009':
      table = iso2009def
      tab_len = iso2009length
      tab_range = iso2009range
      Type_text = 'Screw'
    if ST_text == 'ISO2010':
      table = iso2009def
      tab_len = iso2009length
      tab_range = iso2009range
      Type_text = 'Screw'
    if ST_text == 'ISO4762':
      table = iso4762def
      tab_len = iso4762length
      tab_range = iso4762range
      Type_text = 'Screw'

    if ST_text == 'ISO10642':
      table = iso10642def
      tab_len = iso10642length
      tab_range = iso10642range
      Type_text = 'Screw'

    if ST_text == 'ISO4014':
      table = iso4014head
      tab_len = iso4014length
      tab_range = iso4014range
      Type_text = 'Screw'
      
    if ST_text == 'ISO1207':
      table = iso1207def
      tab_len = iso1207length
      tab_range = iso1207range
      Type_text = 'Screw'
    if ST_text == 'ISO1580':
      table = iso1580def
      tab_len = iso2009length
      tab_range = iso2009range
      Type_text = 'Screw'

    if ST_text == 'ISO7045':
      table = iso7045def
      tab_len = iso7045length
      tab_range = iso7045range
      Type_text = 'Screw'

    if ST_text == 'ISO7046':
      table = iso7046def  # contains only cross recess data
      tab_len = iso7045length
      tab_range = iso7046range
      Type_text = 'Screw'

    if ST_text == 'ISO7047':
      table = iso2009def  
      tab_len = iso7045length
      tab_range = iso7046range
      Type_text = 'Screw'

    if ST_text == 'ISO7048':
      table = iso7048def
      tab_len = iso7048length
      tab_range = iso7048range
      Type_text = 'Screw'

    if ST_text == 'ISO7380-1':
      table = iso7380def
      tab_len = iso7380length
      tab_range = iso7380range
      Type_text = 'Screw'

    if ST_text == 'ISO7380-2':
      table = iso7380_2def
      tab_len = iso7380length
      tab_range = iso7380range
      Type_text = 'Screw'

    if ST_text == 'DIN967':
      table = din967def
      tab_len = din967length
      tab_range = din967range
      Type_text = 'Screw'

    if ST_text == 'ISO14579':
      table = iso14579def
      tab_len = iso14579length
      tab_range = iso14579range
      Type_text = 'Screw'

    if ST_text == 'ISO14580':
      table = iso14580def
      tab_len = iso14580length
      tab_range = iso1207range
      Type_text = 'Screw'

    if ST_text == 'ISO14583':
      table = iso14583def
      tab_len = iso7045length
      tab_range = iso7046range
      Type_text = 'Screw'

    if ST_text == 'ISO14584':
      table = iso14584def
      tab_len = iso7045length
      tab_range = iso14584range
      Type_text = 'Screw'

    if ST_text == 'ISO14582':
      table = iso14582def
      tab_len = iso14582length
      tab_range = iso14582range
      Type_text = 'Screw'

    if ST_text == 'ISO7089':
      table = iso7089def
      Type_text = 'Washer'

    if ST_text == 'ISO7090':
      table = iso7090def
      Type_text = 'Washer'

    if ST_text == 'ISO7091':
      table = iso7091def
      Type_text = 'Washer'

    if ST_text == 'ISO7092':
      table = iso7092def
      Type_text = 'Washer'

    if ST_text == 'ISO7093-1':
      table = iso7093def
      Type_text = 'Washer'
      
    if ST_text == 'ISO7094':
      table = iso7094def
      Type_text = 'Washer'

    if ST_text == 'ISO4032':
      table = iso4032def
      Type_text = 'Nut'

    if ST_text == 'ISO4033':
      table = iso4033def
      Type_text = 'Nut'

    if ST_text == 'ISO4035':
      table = iso4035def
      Type_text = 'Nut'

    if ST_text == 'ISO4036':
      table = iso4036def
      Type_text = 'Nut'

    if ST_text == 'EN1661':
      table = en1661def
      Type_text = 'Nut'

    if ST_text == 'ScrewTap':
      table = tuningTable
      Type_text = 'Screw-Tap'

    if ND_text not in table:
       ND_min, ND_max = standard_diameters[ST_text]
       M_text = ST_text+' has diameters from '+ ND_min +' to ' + ND_max + ' and not ' + ND_text +'!'
       self.objAvailable = False
       # set scew not ok
    else:
      if Type_text == 'Screw':
        #NL_text = str(self.NominalLength.currentText())
        NL_min, NL_max = tab_range[ND_text]
        NL_min_float = float(NL_min)
        NL_max_float = float(NL_max)
        if (NL_text == 'User') and (ST_text is not 'ISO8676'): 
          M_text = 'User length is only available for the screw-tab and ISO 8676!'
          self.objAvailable = False
        else:
          if NL_text == 'User':
            M_text = 'ISO 8676 with user length is ok!'
            self.objAvailable = True
          else:
            NL_text_float = float(NL_text)
            if (NL_text_float<NL_min_float)or(NL_text_float>NL_max_float)or(NL_text not in tab_len):            
              if '(' in ND_text:
                ND_text = ND_text.lstrip('(').rstrip(')')
              M_text = ST_text+'-'+ ND_text +' has lengths from '+ NL_min +' to ' + NL_max + ' and not ' + NL_text +'!'
              self.objAvailable = False
              # set screw not ok
            else:
              if '(' in ND_text:
                ND_text = ND_text.lstrip('(').rstrip(')')
              M_text = ST_text+'-'+ ND_text +'x'+ NL_text +' is in library available! '
              self.objAvailable = True
              #set screw ok
      else: # Washers and Nuts
        if not (Type_text == 'Screw-Tap'):
          if '(' in ND_text:
            ND_text = ND_text.lstrip('(').rstrip(')')
          M_text = ST_text+'-'+ ND_text +' is in library available! '
          self.objAvailable = True
          #set washer/nut ok
        else:
          if NL_text == 'User':
            M_text = 'Screw-tab with user length is ok!'
            self.objAvailable = True
          else:
            #NL_text = str(self.NominalLength.currentText())
            if '(' in ND_text:
              ND_text = ND_text.lstrip('(').rstrip(')')
            M_text = ST_text+'-'+ ND_text +' with '+ NL_text +'mm length is in library available! '
            self.objAvailable = True
            #set screwTap ok
    
    #print "Data checking: ", self.NominalLength.currentText(), "\n"
    #FreeCAD.Console.PrintMessage("Set Check_result into text " + str(self.objAvailable) + M_text + "\n")
    return M_text, self.objAvailable


  def createScrew(self, ST_text, ND_text, NL_text, threadType):
    #self.simpThread = self.SimpleScrew.isChecked()
    #self.symThread = self.SymbolThread.isChecked()
    #self.rThread = self.RealThread.isChecked()
    if threadType == 'real':
      self.rThread = True
    else:
      self.rThread = False
    
    if self.objAvailable:
      try:
        # first we check if valid numbers have been entered
        #FreeCAD.Console.PrintMessage("NominalLength: " + self.NominalLength.currentText() + "\n")
        #FreeCAD.Console.PrintMessage("NominalDiameter: " + self.NominalDiameter.currentText() + "\n")
        #FreeCAD.Console.PrintMessage("SimpleThread: " + str(self.SimpleScrew.isChecked()) + "\n")
        #FreeCAD.Console.PrintMessage("SymbolThread: " + str(self.SymbolThread.isChecked()) + "\n")
        #FreeCAD.Console.PrintMessage("RealThread: " + str(self.RealThread.isChecked()) + "\n")
                   
        #ND_text = str(self.NominalDiameter.currentText())
        #NL_text = str(self.NominalLength.currentText())
        #ST_text = str(self.ScrewType.currentText())
        #ST_text = ST_text.split(':')[0]
        #dia = float(ND_text.lstrip('M'))
        l = float(NL_text)
        if ST_text == 'ISO4017':
           table = iso4017head
        if ST_text == 'ISO4014':
           table = iso4014head
        if ST_text == 'EN1662':
           table = en1662def
        if ST_text == 'EN1665':
           table = en1665def
        if ST_text == 'ISO8676':
           table = iso8676def
        if ST_text == 'ISO2009':
           table = iso2009def
        if ST_text == 'ISO2010':
           table = iso2009def
        if ST_text == 'ISO4762':
           table = iso4762def
        if ST_text == 'ISO10642':
           table = iso10642def
        if ST_text == 'ISO1207':
           table = iso1207def
        if ST_text == 'ISO1580':
           table = iso1580def
        if ST_text == 'ISO7045':
           table = iso7045def
        if ST_text == 'ISO7046':
           table = iso7045def
        if ST_text == 'ISO7047':
           table = iso7045def
        if ST_text == 'ISO7048':
           table = iso7048def
        if ST_text == 'ISO7380-1':
           table = iso7380def
        if ST_text == 'ISO7380-2':
           table = iso7380_2def
        if ST_text == 'DIN967':
           table = din967def
        if ST_text == 'ISO14579':
           table = iso14579def
        if ST_text == 'ISO14580':
           table = iso14580def
        if ST_text == 'ISO14582':
           table = iso14582def
        if ST_text == 'ISO14583':
           table = iso14583def
        if ST_text == 'ISO14584':
           table = iso14584def
        if ST_text == 'ISO7089':
           table = iso7089def
        if ST_text == 'ISO7090':
           table = iso7090def
        if ST_text == 'ISO7091':
           table = iso7091def
        if ST_text == 'ISO7092':
           table = iso7092def
        if ST_text == 'ISO7093-1':
           table = iso7093def
        if ST_text == 'ISO7094':
           table = iso7094def
        if ST_text == 'ISO4032':
           table = iso4032def
        if ST_text == 'ISO4033':
           table = iso4033def
        if ST_text == 'ISO4035':
           table = iso4035def
        if ST_text == 'ISO4036':
           table = iso4036def
        if ST_text == 'EN1661':
           table = en1661def
        if ST_text == 'ScrewTap':
           table = tuningTable
        if ND_text not in table:
           FreeCAD.Console.PrintMessage("Combination of type "+ST_text \
              + " and diameter " + ND_text +" not available!" + "\n")
        #self.MessageLabel.setText(QtGui.QApplication.translate("ScrewMaker", "not implemented", None))
            
      except ValueError:
        #print "Error! nom_dia and length values must be valid numbers!"
        FreeCAD.Console.PrintMessage("Error! nom_dia and length values must be valid numbers!\n")
      else:
        doc=FreeCAD.activeDocument()
        done = False
        if (ST_text == 'ISO4014') or (ST_text == 'ISO4017') or (ST_text == 'ISO8676'):
          screw = self.makeIso4017_2(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'EN1662') or (ST_text == 'EN1665'):
          screw = self.makeEN1662_2(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO2009') or (ST_text == 'ISO2010') or (ST_text == 'ISO1580'):
          screw = self.makeSlottedScrew(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO4762') or (ST_text == 'ISO14579'):
          screw = self.makeIso4762(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO1207') or (ST_text == 'ISO14580') or (ST_text == 'ISO7048'):
          screw = self.makeIso1207(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO7045') or (ST_text == 'ISO14583'):
          screw = self.makeIso7045(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO7046') or (ST_text == 'ISO7047') or \
          (ST_text == 'ISO14582') or (ST_text == 'ISO14584') or (ST_text == 'ISO10642'):
          screw = self.makeIso7046(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO7380-1') or (ST_text == 'ISO7380-2') or (ST_text == 'DIN967'):
          screw = self.makeIso7380(ST_text, ND_text,l)
          Type_text = 'Screw'
          done = True
        if (ST_text == 'ISO7089') or (ST_text == 'ISO7090') or (ST_text == 'ISO7093-1') or \
          (ST_text == 'ISO7091') or (ST_text == 'ISO7092') or (ST_text == 'ISO7094'):
          screw = self.makeIso7089(ST_text, ND_text)
          Type_text = 'Washer'
          done = True
        if (ST_text == 'ISO4032') or (ST_text == 'ISO4033') or (ST_text == 'ISO4035'):
          screw = self.makeIso4032(ST_text, ND_text)
          Type_text = 'Nut'
          done = True
        if ST_text == 'EN1661':
          screw = self.makeEN1661(ND_text)
          Type_text = 'Nut'
          done = True
        if ST_text == 'ScrewTap':
          screw = self.makeScrewTap(ND_text,l)
          Type_text = 'Screw-Tap'
          done = True
        if not done:
          FreeCAD.Console.PrintMessage("No valid Screw Type!" +  "\n")
        if '(' in ND_text:
          ND_text = ND_text.lstrip('(').rstrip(')')
 
        if Type_text == 'Screw':
          label = ST_text + "-" + ND_text +"x"+ NL_text +"_"
        else:
          if (Type_text == 'Nut'):
            label = ST_text + '-' + ND_text +'_'
          else:
            if Type_text == 'Screw-Tap':
              label = ST_text + '-' + ND_text +'x'+ NL_text +'_'
            else: # washer
              label = ST_text + '-' + ND_text.lstrip('M') +'_'
        ScrewObj = doc.addObject("Part::Feature")
        ScrewObj.Label=label
        ScrewObj.Shape=screw
        #FreeCAD.Console.PrintMessage("Placement: "+ str(ScrewObj.Placement) +"\n")
        #FreeCAD.Console.PrintMessage("The label: "+ label +"\n")
        self.moveScrew(ScrewObj)
        #ScrewObj.Label = label
        if self.gotPart:
          self.thePart.addObject(ScrewObj)
        doc.recompute()
        # Part.show(screw)
        return ScrewObj


  def getFaceAxis(self, sp, c):
    fList = []
    fAxis = None
    if len(c.Vertexes) ==1:
      theVert = c.Vertexes[0]
      # search for faces which have a vertex equal to theVert.
      for f in sp.Faces:
        for v in f.Vertexes:
          if equal_vertex(v, theVert):
            fList.append(f)
    print (str(fList))
    # search for a plane face
    for f in fList:
      if hasattr(f,'Surface'):
        print ('type of surface: ', str(f.Surface))
        if f.Surface.isPlanar():
          fAxis = f.Surface.normal(0,0)
          print ('got planar Face with normal: ', str(f.Surface.normal(0,0)))
          print ('Orientation: ', str(f.Orientation))
          if f.Orientation == 'Reversed':
            fAxis = fAxis.multiply(-1.0)
    return fAxis

         
  def moveScrew(self, ScrewObj_m):
    #FreeCAD.Console.PrintMessage("In Move Screw: " + str(ScrewObj_m) + "\n")
    self.gotBody = False
    self.gotPart = False

    mylist = FreeCAD.Gui.Selection.getSelectionEx()
    if (mylist.__len__() == 1):
       # check selection
       #FreeCAD.Console.PrintMessage("Selektionen: " + str(mylist.__len__()) + "\n")
       Pnt1 = None
       Axis1 = None
       Axis2 = None
       theSelection = mylist[0]
       #FreeCAD.Console.PrintMessage( "ObjectName: " + str(theSelection.ObjectName) + "\n")
       if hasattr(theSelection, 'Object'):
         if hasattr(theSelection.Object, 'InList'):
           inLength = len(theSelection.Object.InList)
           #FreeCAD.Console.PrintMessage( "InList: " + str(theSelection.Object.InList) + "\n")
           for b in theSelection.Object.InList:
             #FreeCAD.Console.PrintMessage( "OType: " + str(b.TypeId) + "\n")
             if b.TypeId == 'PartDesign::Body':
               self.gotBody = True
               self.bPlacement = b.Placement
               for par in b.InList:
                 if par.TypeId == 'App::Part':
                   self.gotPart = True
                   self.thePart = par
                   
                   break
             
       for o in Gui.Selection.getSelectionEx():
          #FreeCAD.Console.PrintMessage( "name: " + str(o) + "\n")
          #FreeCAD.Console.PrintMessage( "Properties: " + str(o.PropertiesList) + "\n")
          
          #for s in o.SubElementNames:
             #FreeCAD.Console.PrintMessage( "name: " + str(s) + "\n")
          for s in o.SubObjects:
             #FreeCAD.Console.PrintMessage( "object: "+ str(s) + "\n")
             #FreeCAD.Console.PrintMessage( "Properties: " + str(s.PropertiesList) + "\n")
             if hasattr(s,"Curve"):
                #FreeCAD.Console.PrintMessage( "The Object is a Curve!\n")
                if hasattr(s.Curve,"Center"):
                   """
                   FreeCAD.Console.PrintMessage( "The object has a Center!\n")
                   FreeCAD.Console.PrintMessage( "Curve attribut. "+ str(s.__getattribute__('Curve')) + "\n")
                   FreeCAD.Console.PrintMessage( "Center: "+ str(s.Curve.Center) + "\n")
                   FreeCAD.Console.PrintMessage( "Axis: "+ str(s.Curve.Axis) + "\n")
                   """
                   Pnt1 = s.Curve.Center
                   Axis1 = s.Curve.Axis
                   fAxis = self.getFaceAxis(o.Object.Shape, s)
                   if fAxis:
                     Axis1 = fAxis
             if hasattr(s,'Surface'):
                #print 'the object is a face!'
                if hasattr(s.Surface,'Axis'):
                   Axis1 = s.Surface.Axis
       
             if hasattr(s,'Point'):
                #FreeCAD.Console.PrintMessage( "the object seems to be a vertex! "+ str(s.Point) + "\n")
                Pnt1 = s.Point
                   
       if (Axis1 != None):
          #FreeCAD.Console.PrintMessage( "Got Axis1: " + str(Axis1) + "\n")
          Axis2 = Base.Vector(0.0,0.0,1.0)
          Axis2_minus = Base.Vector(0.0,0.0,-1.0)
          
          # Calculate angle
          if Axis1 == Axis2:
             normvec = Base.Vector(1.0,0.0,0.0)
             result = 0.0
          else:
             if Axis1 == Axis2_minus:
                normvec = Base.Vector(1.0,0.0,0.0)
                result = math.pi
             else:
                normvec = Axis1.cross(Axis2) # Berechne Achse der Drehung = normvec
                normvec.normalize() # Normalisieren fuer Quaternionenrechnung
                #normvec_rot = normvec
                result = DraftVecUtils.angle(Axis1, Axis2, normvec) # Winkelberechnung
          sin_res = math.sin(result/2.0)
          cos_res = math.cos(result/2.0)
          normvec.multiply(-sin_res) # Berechnung der Quaternionen-Elemente
          #FreeCAD.Console.PrintMessage( "Winkel = "+ str(math.degrees(result)) + "\n")
          #FreeCAD.Console.PrintMessage("Normalvektor: "+ str(normvec) + "\n")
          
          pl = FreeCAD.Placement()
          pl.Rotation = (normvec.x,normvec.y,normvec.z,cos_res) #Drehungs-Quaternion
          
          #FreeCAD.Console.PrintMessage("pl mit Rot: "+ str(pl) + "\n")
          #neuPlatz = Part2.Object.Placement.multiply(pl)
          neuPlatz = ScrewObj_m.Placement
          FreeCAD.Console.PrintMessage("die Position     "+ str(neuPlatz) + "\n")
          neuPlatz.Rotation = pl.Rotation.multiply(ScrewObj_m.Placement.Rotation)
          # neuPlatz.move(Pnt1)
          FreeCAD.Console.PrintMessage("die Position in Body    "+ str(neuPlatz) + "\n")
          if self.gotBody:
            FreeCAD.Console.PrintMessage("got Placement: "+ str(self.bPlacement) + "\n")
            #neuPlatz.Rotation = neuPlatz.Rotation.multiply(self.bPlacement.Rotation)
            neuPlatz.Rotation = neuPlatz.Rotation.multiply(self.bPlacement.Rotation)
            Pnt1 = self.bPlacement.multVec(Pnt1)
          neuPlatz.move(Pnt1)
          #if self.gotBody:
            #neuPlatz.move(self.bPlacement.Base)
            
          # Python is not phytonic in FreeCAD 0.17, need to add allocation.
          ScrewObj_m.Placement = neuPlatz
          #FreeCAD.Console.PrintMessage("die rot. Position: "+ str(neuPlatz) + "\n")



  # make Washer
  def makeIso7089(self,SType ='ISO7089', ThreadType ='M6'):
    dia = self.getDia(ThreadType)
    #FreeCAD.Console.PrintMessage("die Scheibe mit dia: " + str(dia) + "\n")
    if SType == 'ISO7089':
      d1_min, d2_max, h, h_max = iso7089def[ThreadType]
    if SType == 'ISO7090':
      d1_min, d2_max, h, h_max = iso7090def[ThreadType]
    if SType == 'ISO7091':
      d1_min, d2_max, h, h_max = iso7091def[ThreadType]
    if SType == 'ISO7092':
      d1_min, d2_max, h, h_max = iso7092def[ThreadType]
    if SType == 'ISO7093-1':
      d1_min, d2_max, h, h_max = iso7093def[ThreadType]
    if SType == 'ISO7094':
      d1_min, d2_max, h, h_max = iso7094def[ThreadType]
      #FreeCAD.Console.PrintMessage("got: " + SType + "\n")

    #FreeCAD.Console.PrintMessage("die Scheibe mit d1_min: " + str(d1_min) + "\n")

    #Washer Points  
    Pnt0 = Base.Vector(d1_min/2.0,0.0,h_max)
    Pnt2 = Base.Vector(d2_max/2.0,0.0,h_max)
    Pnt3 = Base.Vector(d2_max/2.0,0.0,0.0)      
    Pnt4 = Base.Vector(d1_min/2.0,0.0,0.0)
    if SType == 'ISO7090':
      Pnt1 = Base.Vector(d2_max/2.0-h_max/4.0,0.0,h_max)
      Pnt2 = Base.Vector(d2_max/2.0,0.0,h_max*0.75)
      edge1 = Part.makeLine(Pnt0,Pnt1)
      edgeCham = Part.makeLine(Pnt1,Pnt2)
      edge1 = Part.Wire([edge1, edgeCham])
    else:
      edge1 = Part.makeLine(Pnt0,Pnt2)
    
    edge2 = Part.makeLine(Pnt2,Pnt3)
    edge3 = Part.makeLine(Pnt3,Pnt4)
    edge4 = Part.makeLine(Pnt4,Pnt0)
    #FreeCAD.Console.PrintMessage("Edges made Pnt2: " + str(Pnt2) + "\n")

    aWire=Part.Wire([edge1,edge2,edge3,edge4])
    #Part.show(aWire)
    aFace =Part.Face(aWire)
    head = aFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #FreeCAD.Console.PrintMessage("Washer revolved: " + str(dia) + "\n")

    return head


  # make ISO 2009 Slotted countersunk flat head screws
  # make ISO 2010 Slotted raised countersunk head screws
  # make ISO 1580 Pan head slotted screw (Code is nearly identical to iso1207)
  def makeSlottedScrew(self,SType ='ISO1580', ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)
    if SType == 'ISO1580':
      #FreeCAD.Console.PrintMessage("der Kopf mit l: " + str(l) + "\n")
      #P, a, b, dk, dk_mean, da, k, n_min, r, t_min, x = iso1580def[ThreadType]
      P, a, b, dk_max, da, k, n_min, r, rf, t_min, x = iso1580def[ThreadType]
      #FreeCAD.Console.PrintMessage("der Kopf mit iso: " + str(dk_max) + "\n")
      ht = k
      headEnd = r
      
      #Length for calculation of head fillet
      sqrt2_ = 1.0/math.sqrt(2.0)
      r_fil = rf
      beta = math.radians(5.0)   # angle of pan head edge
      alpha = math.radians(90.0 - (90.0+5.0)/2.0)
      tan_beta = math.tan(beta)      
      # top head diameter without fillet
      rK_top = dk_max/2.0 - k * tan_beta     
      fillet_center_x = rK_top - r_fil + r_fil * tan_beta 
      fillet_center_z = k - r_fil
      fillet_arc_x = fillet_center_x + r_fil * math.sin(alpha)
      fillet_arc_z = fillet_center_z + r_fil * math.cos(alpha)
      #FreeCAD.Console.PrintMessage("rK_top: " + str(rK_top) + "\n")
      if (b > (l - 1.0*P)):
        bmax = l- 1.0*P
      else:
        bmax = b

      #Head Points  
      Pnt0 = Base.Vector(0.0,0.0,k)
      Pnt2 = Base.Vector(fillet_center_x,0.0,k)
      Pnt3 = Base.Vector(fillet_arc_x,0.0,fillet_arc_z)      
      Pnt4 = Base.Vector(fillet_center_x + r_fil*math.cos(beta),0.0,fillet_center_z+ r_fil * math.sin(beta))
      Pnt5 = Base.Vector(dk_max/2.0,0.0,0.0)
      Pnt6 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
      Pnt7 = Base.Vector(dia/2.0+r-r*sqrt2_,0.0,-r+r*sqrt2_) #arc-point of fillet
      #Pnt8 = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
      PntR = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
      PntT0 = Base.Vector(0.0,0.0,-r)        # helper point for real thread
      
      edge1 = Part.makeLine(Pnt0,Pnt2)
      edge2 = Part.Arc(Pnt2,Pnt3,Pnt4).toShape()
      edge3 = Part.makeLine(Pnt4,Pnt5)
      edge4 = Part.makeLine(Pnt5,Pnt6)
      edge5 = Part.Arc(Pnt6,Pnt7,PntR).toShape()
      headWire=Part.Wire([edge1,edge2,edge3,edge4,edge5])
      
    if (SType == 'ISO2009') or (SType == 'ISO2010'):
      P, a, b, dk_theo, dk_mean, k, n_min, r, t_mean, x = iso2009def[ThreadType]
      dk_max = dk_theo
      t_min = t_mean
      ht = 0.0 # Head heigth of flat head
      if (SType == 'ISO2010'):
        rf, t_mean, cT, mH, mZ = Raised_countersunk_def[ThreadType]
        #Lengths and angles for calculation of head rounding
        beta = math.asin(dk_mean /2.0 / rf)   # angle of head edge
        tan_beta = math.tan(beta)      
        alpha = beta/2.0 # half angle
        # heigth of raised head top
        ht = rf - (dk_mean/2.0) / tan_beta
        h_arc_x = rf * math.sin(alpha) 
        h_arc_z = ht - rf + rf * math.cos(alpha)

      cham = (dk_theo - dk_mean)/2.0
      rad225 = math.radians(22.5)
      rad45 = math.radians(45.0)
      rtan = r*math.tan(rad225)
      headEnd = k + rtan

      if (b > l - k - rtan/2.0 - 1.0*P):
        bmax = l-k-rtan/2.0 - 1.0*P
      else:
        bmax = b
      
      #Head Points
      Pnt0 = Base.Vector(0.0,0.0,ht)
      Pnt1 = Base.Vector(dk_mean/2.0,0.0,0.0)
      Pnt2 = Base.Vector(dk_mean/2.0,0.0,-cham)
      Pnt3 = Base.Vector(dia/2.0+r-r*math.cos(rad45),0.0,-k-rtan+r*math.sin(rad45))
      # Arc-points
      Pnt4 = Base.Vector(dia/2.0+r-r*(math.cos(rad225)),0.0,-k-rtan+r*math.sin(rad225))
      PntR = Base.Vector(dia/2.0,0.0,-k-rtan)
      #PntA = Base.Vector(dia/2.0,0.0,-a_point)
      PntT0 = Base.Vector(0.0,0.0,-k-rtan)        # helper point for real thread
  
      if (SType == 'ISO2010'): # make raised head rounding
        Pnt0arc = Base.Vector(h_arc_x,0.0,h_arc_z)
        edge1 = Part.Arc(Pnt0,Pnt0arc,Pnt1).toShape()     
      else:
        edge1 = Part.makeLine(Pnt0,Pnt1)  # make flat head
         
      edge2 = Part.makeLine(Pnt1,Pnt2)
      edge3 = Part.makeLine(Pnt2,Pnt3)
      edgeArc = Part.Arc(Pnt3,Pnt4,PntR).toShape()     
      headWire=Part.Wire([edge1,edge2,edge3,edgeArc])


    ### make the new code with math.modf(l)
    residue, turns = math.modf((bmax)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = headEnd - a_point
    PntA = Base.Vector(dia/2.0,0.0,-a_point)        # Start of thread


    if self.rThread:
      edgeZ1 = Part.makeLine(PntR,PntT0)
      edgeZ0 = Part.makeLine(PntT0,Pnt0)
      aWire=Part.Wire([headWire, edgeZ1, edgeZ0])
    
    else:
      # bolt points
      PntB1 = Base.Vector(dia/2.0,0.0,-l)
      PntB2 = Base.Vector(0.0,0.0,-l)
      
      edgeB2 = Part.makeLine(PntB1,PntB2)
      edgeZ0 = Part.makeLine(PntB2,Pnt0)

      if a_point <= r:
        edgeB1 = Part.makeLine(PntR,PntB1)
        aWire=Part.Wire([headWire, edgeB1, edgeB2, edgeZ0])
      else:
        edgeRA = Part.makeLine(PntR,PntA)
        edgeB1 = Part.makeLine(PntA,PntB1)
        aWire=Part.Wire([headWire, edgeRA, edgeB1, edgeB2, edgeZ0])

    aFace =Part.Face(aWire)
    head = aFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")

    #Parameter for slot-recess: dk_max, n_min, k, t_min
    slot = Part.makePlane(dk_max, n_min, \
        Base.Vector(dk_max/2.0,-n_min/2.0,ht+1.0),Base.Vector(0.0,0.0,-1.0))
    slot = slot.extrude(Base.Vector(0.0,0.0,-t_min-1.0))
    #Part.show(slot)
    head = head.cut(slot)
    #FreeCAD.Console.PrintMessage("der Kopf geschnitten: " + str(dia) + "\n")
    #Part.show(head)
    
    if self.rThread:
      rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
      rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
      #Part.show(rthread)
      headFaces = []
      if (SType == 'ISO2009'):
        for i in range(0,len(head.Faces)-2):
          headFaces.append(head.Faces[i])
        headFaces.append(head.Faces[len(head.Faces)-1])
          
      if (SType == 'ISO1580') or (SType == 'ISO2010'):
        for i in range(0,len(head.Faces)-1):
          headFaces.append(head.Faces[i])

      for threadFace in rthread.Faces:
        headFaces.append(threadFace)

      newHeadShell = Part.Shell(headFaces)
      #Part.show(newHeadShell)
      head = Part.Solid(newHeadShell)

    return head






  # ISO 7045 Pan head screws with type H or type Z cross recess
  # ISO 14583 Hexalobular socket pan head screws  
  def makeIso7045(self, SType ='ISO7045', ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)
    #FreeCAD.Console.PrintMessage("der Kopf mit l: " + str(l) + "\n")
    P, a, b, dk_max,da, k, r, rf, x, cT, mH, mZ  = iso7045def[ThreadType]
    #FreeCAD.Console.PrintMessage("der Kopf mit iso: " + str(dk_max) + "\n")

    #Lengths and angles for calculation of head rounding
    beta = math.asin(dk_max /2.0 / rf)   # angle of head edge
    #print 'beta: ', math.degrees(beta)
    tan_beta = math.tan(beta)      


    if SType == 'ISO14583':
       tt, A, t_mean = iso14583def[ThreadType]
       beta_A = math.asin(A/2.0 / rf)   # angle of recess edge
       tan_beta_A = math.tan(beta_A)

       alpha = (beta_A + beta)/2.0 # half angle
       #print 'alpha: ', math.degrees(alpha)
       # heigth of head edge
       he = k - A/2.0/tan_beta_A + (dk_max/2.0) / tan_beta    
       #print 'he: ', he
       h_arc_x = rf * math.sin(alpha) 
       h_arc_z = k - A/2.0/tan_beta_A + rf * math.cos(alpha)
       #FreeCAD.Console.PrintMessage("h_arc_z: " + str(h_arc_z) + "\n")
    else:
       alpha = beta/2.0 # half angle
       #print 'alpha: ', math.degrees(alpha)
       # heigth of head edge
       he = k - rf + (dk_max/2.0) / tan_beta    
       #print 'he: ', he
       h_arc_x = rf * math.sin(alpha) 
       h_arc_z = k - rf + rf * math.cos(alpha)
       #FreeCAD.Console.PrintMessage("h_arc_z: " + str(h_arc_z) + "\n")
    
    if (b > (l - 1.0*P)):
       bmax = l- 1.0*P
    else:
       bmax = b

    ### make the new code with math.modf(l)
    residue, turns = math.modf((bmax)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = r - a_point
    #FreeCAD.Console.PrintMessage("The transition at a: " + str(a) + " turns " + str(turns) + "\n")
       
    sqrt2_ = 1.0/math.sqrt(2.0)
    
    #Head Points  
    Pnt1 = Base.Vector(h_arc_x,0.0,h_arc_z)
    Pnt2 = Base.Vector(dk_max/2.0,0.0,he)      
    Pnt3 = Base.Vector(dk_max/2.0,0.0,0.0)
    Pnt4 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
    Pnt5 = Base.Vector(dia/2.0+r-r*sqrt2_,0.0,-r+r*sqrt2_) #arc-point of fillet
    Pnt6 = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
    Pnt7 = Base.Vector(dia/2.0,0.0,-a_point)        # Start of thread
    #FreeCAD.Console.PrintMessage("Points defined a_point: " + str(a_point) + "\n")


    if (SType == 'ISO14583'):
      #Pnt0 = Base.Vector(0.0,0.0,k-A/4.0)
      Pnt0 = Base.Vector(0.0,0.0,k-A/8.0)
      PntFlat = Base.Vector(A/8.0,0.0,k-A/8.0)
      PntCham = Base.Vector(A/1.99,0.0,k)
      edgeCham0 = Part.makeLine(Pnt0,PntFlat)    
      edgeCham1 = Part.makeLine(PntFlat,PntCham)    
      edgeCham2 = Part.Arc(PntCham,Pnt1,Pnt2).toShape()   
      #edge1 = Part.Wire([edgeCham0,edgeCham1,edgeCham2]) 
      edge1 = Part.Wire([edgeCham0,edgeCham1])
      edge2 = Part.makeLine(Pnt2,Pnt3)
      edge2 = Part.Wire([edgeCham2, edge2])
      # Part.show(edge2)
      
      # Here is the next approach to shorten the head building time
      # Make two helper points to create a cutting tool for the 
      # recess and recess shell.
      PntH1 = Base.Vector(A/1.99,0.0, 2.0*k)
      PntH2 = Base.Vector(0.0,0.0, 2.0*k)
      edgeH1 = Part.makeLine(PntCham,PntH1)
      edgeH2 = Part.makeLine(PntH1,PntH2)
      edgeH3 = Part.makeLine(PntH2,Pnt0)
      
    else:
      Pnt0 = Base.Vector(0.0,0.0,k)
      edge1 = Part.Arc(Pnt0,Pnt1,Pnt2).toShape()  # make round head
      edge2 = Part.makeLine(Pnt2,Pnt3)

      # Here is the next approach to shorten the head building time
      # Make two helper points to create a cutting tool for the 
      # recess and recess shell.
      PntH1 = Base.Vector(dk_max/2.0,0.0, 2.0*k)
      PntH2 = Base.Vector(0.0,0.0, 2.0*k)
      edgeH1 = Part.makeLine(Pnt2,PntH1)
      edgeH2 = Part.makeLine(PntH1,PntH2)
      edgeH3 = Part.makeLine(PntH2,Pnt0)

    edge3 = Part.makeLine(Pnt3,Pnt4)
    edge4 = Part.Arc(Pnt4,Pnt5,Pnt6).toShape()
    #FreeCAD.Console.PrintMessage("Edges made h_arc_z: " + str(h_arc_z) + "\n")

    #if self.RealThread.isChecked():
    if self.rThread:
      aWire=Part.Wire([edge2,edge3,edge4])
    else:
      # bolt points
      PntB1 = Base.Vector(dia/2.0,0.0,-l)
      PntB2 = Base.Vector(0.0,0.0,-l)
      edgeB2 = Part.makeLine(PntB1,PntB2)
      if a_point <= r:
        edgeB1 = Part.makeLine(Pnt6,PntB1)
        aWire=Part.Wire([edge2, edge3, edge4, edgeB1, edgeB2])
      else:
        edge5 = Part.makeLine(Pnt6,Pnt7)
        edgeB1 = Part.makeLine(Pnt7,PntB1)
        aWire=Part.Wire([edge2, edge3, edge4, edge5, edgeB1, edgeB2])


    
    hWire = Part.Wire([edge1,edgeH1,edgeH2,edgeH3]) # Cutter for recess-Shell
    hFace = Part.Face(hWire)
    hCut = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(hWire)

    headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #head = Part.Solid(headShell)
    #Part.show(aWire)
    #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
    headFaces = headShell.Faces
 
    if (SType == 'ISO14583'):
      recess, recessShell = self.makeIso10664_3(tt, t_mean, k)
      recessShell = recessShell.cut(hCut)
      topFace = hCut.Faces[1]
      topFace = topFace.cut(recess)
      #Part.show(topFace)
      #Part.show(recessShell)
      #Part.show(headShell)
      headFaces.append(topFace.Faces[0])
      #headFaces.append(hCut.Faces[2])
      
    else:
      #Lengths and angles for calculation of recess positioning
      beta_cr = math.asin(mH /2.0 / rf)   # angle of recess edge
      tan_beta_cr = math.tan(beta_cr)      
      # heigth of cross recess cutting
      hcr = k - rf + (mH/2.0) / tan_beta_cr
      #print 'hcr: ', hcr
      
      #Parameter for cross-recess type H: cT, mH
      recess, recessShell = self.makeCross_H3(cT, mH, hcr)
      recessShell = recessShell.cut(hCut)
      topFace = hCut.Faces[0]
      topFace = topFace.cut(recess)
      #Part.show(topFace)
      #Part.show(recessShell)
      #Part.show(headShell)
      headFaces.append(topFace.Faces[0])
        
    #Part.show(hCut)
    headFaces.extend(recessShell.Faces)
      

    #if self.RealThread.isChecked():
    if self.rThread:
      #head = self.cutIsoThread(head, dia, P, turns, l)
      rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
      rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
      #head = head.fuse(rthread)
      #Part.show(rthread)
      for threadFace in rthread.Faces:
        headFaces.append(threadFace)

    newHeadShell = Part.Shell(headFaces)
    #Part.show(newHeadShell)
    head = Part.Solid(newHeadShell)

    return head


  # make Cheese head screw
  # ISO 1207 slotted screw
  # ISO 7048 cross recessed screw
  # ISO 14580 Hexalobular socket cheese head screws
  def makeIso1207(self,SType ='ISO1207', ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)
    '''
    if '(' in TreadType:
      threadString = ThreadType.lstrip('(M')
      dia = float(ThreadType.rstrip(')'))
    else:
      dia=float(ThreadType.lstrip('M'))
    '''
    #FreeCAD.Console.PrintMessage("der Kopf mit l: " + str(l) + "\n")
    if (SType == 'ISO1207') or (SType == 'ISO14580'):
       P, a, b, dk, dk_mean, da, k, n_min, r, t_min, x = iso1207def[ThreadType]
    if SType == 'ISO7048':
       P, a, b, dk, dk_mean, da, k, r, x, cT, mH, mZ  = iso7048def[ThreadType]
    if (SType == 'ISO14580'):
       tt, k, A, t_min = iso14580def[ThreadType]

    #FreeCAD.Console.PrintMessage("der Kopf mit iso: " + str(dk) + "\n")
    
    #Length for calculation of head fillet
    r_fil = r*2.0
    beta = math.radians(5.0)   # angle of cheese head edge
    alpha = math.radians(90.0 - (90.0+5.0)/2.0)
    tan_beta = math.tan(beta)      
    # top head diameter without fillet
    rK_top = dk/2.0 - k * tan_beta     
    fillet_center_x = rK_top - r_fil + r_fil * tan_beta 
    fillet_center_z = k - r_fil
    fillet_arc_x = fillet_center_x + r_fil * math.sin(alpha)
    fillet_arc_z = fillet_center_z + r_fil * math.cos(alpha)
    #FreeCAD.Console.PrintMessage("rK_top: " + str(rK_top) + "\n")

    if (b > (l - 1.0*P)):
       bmax = l- 1.0*P
    else:
       bmax = b

    ### make the new code with math.modf(l)
    residue, turns = math.modf((bmax)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = r - a_point
      
    sqrt2_ = 1.0/math.sqrt(2.0)

    #Head Points  
    Pnt2 = Base.Vector(fillet_center_x,0.0,k)
    Pnt3 = Base.Vector(fillet_arc_x,0.0,fillet_arc_z)      
    Pnt4 = Base.Vector(fillet_center_x + r_fil*math.cos(beta),0.0,fillet_center_z+ r_fil * math.sin(beta))
    Pnt5 = Base.Vector(dk/2.0,0.0,0.0)
    Pnt6 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
    Pnt7 = Base.Vector(dia/2.0+r-r*sqrt2_,0.0,-r+r*sqrt2_) #arc-point of fillet
    Pnt8 = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
    Pnt9 = Base.Vector(dia/2.0,0.0,-a_point)        # Start of thread
    #FreeCAD.Console.PrintMessage("Points defined fillet_center_x: " + str(fillet_center_x) + "\n")

    if (SType == 'ISO14580'):
      # Pnt0 = Base.Vector(0.0,0.0,k-A/4.0) #Center Point for countersunk
      Pnt0 = Base.Vector(0.0,0.0,k-A/8.0) #Center Point for flat countersunk
      PntFlat = Base.Vector(A/8.0,0.0,k-A/8.0) # End of flat part
      Pnt1 = Base.Vector(A/1.99,0.0,k)     #countersunk edge at head
      edgeCham0 = Part.makeLine(Pnt0,PntFlat)    
      edgeCham1 = Part.makeLine(PntFlat,Pnt1)
      edgeCham2 = Part.makeLine(Pnt1,Pnt2)
      edge1 = Part.Wire([edgeCham1,edgeCham2]) # make head with countersunk
      PntH1 = Base.Vector(A/1.99,0.0, 2.0*k)
    
    else:
      Pnt0 = Base.Vector(0.0,0.0,k)
      edge1 = Part.makeLine(Pnt0,Pnt2)  # make flat head

        
    edge2 = Part.Arc(Pnt2,Pnt3,Pnt4).toShape()
    edge3 = Part.makeLine(Pnt4,Pnt5)
    edge4 = Part.makeLine(Pnt5,Pnt6)
    edge5 = Part.Arc(Pnt6,Pnt7,Pnt8).toShape()
    #FreeCAD.Console.PrintMessage("Edges made fillet_center_z: " + str(fillet_center_z) + "\n")

    if SType == 'ISO1207':
      #Parameter for slot-recess: dk, n_min, k, t_min
      recess = Part.makePlane(dk, n_min, \
        Base.Vector(dk/2.0,-n_min/2.0,k+1.0),Base.Vector(0.0,0.0,-1.0))
      recess = recess.extrude(Base.Vector(0.0,0.0,-t_min-1.0))

      if self.rThread:
        Pnt11 = Base.Vector(0.0,0.0,-r)        # helper point for real thread
        edgeZ1 = Part.makeLine(Pnt8,Pnt11)
        edgeZ0 = Part.makeLine(Pnt11,Pnt0)
        aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5, \
            edgeZ1, edgeZ0])
      else:
        # bolt points
        PntB1 = Base.Vector(dia/2.0,0.0,-l)
        PntB2 = Base.Vector(0.0,0.0,-l)
        
        edgeB2 = Part.makeLine(PntB1,PntB2)
  
        if a_point <= r:
          edgeB1 = Part.makeLine(Pnt8,PntB1)
          aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5, \
              edgeB1, edgeB2])
        else:
          edge6 = Part.makeLine(Pnt8,Pnt9)
          edgeB1 = Part.makeLine(Pnt9,PntB1)
          aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5,edge6, \
              edgeB1, edgeB2])

      aFace =Part.Face(aWire)
      head = aFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360.0)
      head = head.cut(recess)
      # FreeCAD.Console.PrintMessage("der Kopf geschnitten: " + str(dia) + "\n")
      #Part.show(head)
      if self.rThread:
        screwFaces = []
        for i in range(0, len(head.Faces)-1):
          screwFaces.append(head.Faces[i])
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
        for threadFace in rthread.Faces:
          screwFaces.append(threadFace)
  
        screwShell = Part.Shell(screwFaces)
        head = Part.Solid(screwShell)



    else:
      if self.rThread:
        aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5 ])
      else:
        # bolt points
        PntB1 = Base.Vector(dia/2.0,0.0,-l)
        PntB2 = Base.Vector(0.0,0.0,-l)
        
        edgeB2 = Part.makeLine(PntB1,PntB2)
  
        if a_point <= r:
          edgeB1 = Part.makeLine(Pnt8,PntB1)
          aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5, \
              edgeB1, edgeB2])
        else:
          edge6 = Part.makeLine(Pnt8,Pnt9)
          edgeB1 = Part.makeLine(Pnt9,PntB1)
          aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5,edge6, \
              edgeB1, edgeB2])
  
      #aFace =Part.Face(aWire)
      headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360.0)
      #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
      
      if SType == 'ISO7048':
        # hCut should be just a cylinder
        hCut = Part.makeCylinder(fillet_center_x,k,Pnt0)
        recess, recessShell = self.makeCross_H3(cT, mH, k)
        recessShell = recessShell.cut(hCut)
        topFace = headShell.Faces[0].cut(recess)
        screwFaces = [topFace.Faces[0]]
        screwFaces.extend(recessShell.Faces)
      if (SType == 'ISO14580'):
        # Ring-cutter for recess shell
        PntH2 = Base.Vector(A/8.0,0.0, 2.0*k)
        edgeH1 = Part.makeLine(Pnt1,PntH1)
        edgeH2 = Part.makeLine(PntH1,PntH2)
        edgeH3 = Part.makeLine(PntH2,PntFlat)
        hWire = Part.Wire([edgeCham1,edgeH1,edgeH2,edgeH3]) # Cutter for recess-Shell
        hFace = Part.Face(hWire)
        hCut = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
        #Part.show(hWire)
  
        recess, recessShell = self.makeIso10664_3(tt, t_min, k)
        recessShell = recessShell.cut(hCut)
        topFace = headShell.Faces[0].cut(recess)
        screwFaces = [topFace.Faces[0]]
        screwFaces.extend(recessShell.Faces)
        
      for i in range(1, len(headShell.Faces)):
        screwFaces.append(headShell.Faces[i])
          
      if self.rThread:
        #head = self.cutIsoThread(head, dia, P, turns, l)
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
        #head = head.fuse(rthread)
        #Part.show(rthread)
        for threadFace in rthread.Faces:
          screwFaces.append(threadFace)
  
      screwShell = Part.Shell(screwFaces)
      head = Part.Solid(screwShell)

    return head


  
  # make the ISO 4017 Hex-head-screw
  # make the ISO 4014 Hex-head-bolt
  def makeIso4017_2(self,SType ='ISO4017', ThreadType ='M6',l=40.0):
    dia = self.getDia(ThreadType)
    #FreeCAD.Console.PrintMessage("der Kopf mit l: " + str(l) + "\n")
    if SType == 'ISO4017':
      P, c, dw, e,k,r,s = iso4017head[ThreadType]
      residue, turns = math.modf((l-1*P)/P)
      halfturns = 2*int(turns)

    if SType == 'ISO8676':
      P, c, dw, e,k,r,s = iso8676def[ThreadType]
      residue, turns = math.modf((l-r-1*P)/P)
      halfturns = 2*int(turns)

    if SType == 'ISO4014':
      P, b1, b2, b3, c, dw, e, k, r, s = iso4014head[ThreadType]
      if l<= 125.0:
         b = b1
      else:
         if l<= 200.0:
            b = b2
         else:
            b = b3
      residue, turns = math.modf((b)/P)
      halfturns = 2*int(turns)
      
    if residue < 0.5:
      a = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = r - a
    
    sqrt2_ = 1.0/math.sqrt(2.0)
    cham = (e-s)*math.sin(math.radians(15)) # needed for chamfer at head top
  
    #Head Points  Usage of k, s, cham, c, dw, dia, r, a
    #FreeCAD.Console.PrintMessage("der Kopf mit halfturns: " + str(halfturns) + "\n")
    Pnt0 = Base.Vector(0.0,0.0,k)
    Pnt2 = Base.Vector(s/2.0,0.0,k)
    Pnt3 = Base.Vector(s/math.sqrt(3.0),0.0,k-cham)
    Pnt4 = Base.Vector(s/math.sqrt(3.0),0.0,c)
    Pnt5 = Base.Vector(dw/2.0,0.0,c)
    Pnt6 = Base.Vector(dw/2.0,0.0,0.0)
    Pnt7 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
    Pnt8 = Base.Vector(dia/2.0+r-r*sqrt2_,0.0,-r+r*sqrt2_) #arc-point of fillet
    Pnt9 = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
    Pnt10 = Base.Vector(dia/2.0,0.0,-a)        # Start of thread
    
    edge1 = Part.makeLine(Pnt0,Pnt2)
    edge2 = Part.makeLine(Pnt2,Pnt3)
    edge3 = Part.makeLine(Pnt3,Pnt4)
    edge4 = Part.makeLine(Pnt4,Pnt5)
    edge5 = Part.makeLine(Pnt5,Pnt6)
    edge6 = Part.makeLine(Pnt6,Pnt7)
    edge7 = Part.Arc(Pnt7,Pnt8,Pnt9).toShape()
    
    # create cutting tool for hexagon head 
    # Parameters s, k, outer circle diameter =  e/2.0+10.0     
    extrude = self.makeHextool(s, k, s*2.0)
    
    #if self.RealThread.isChecked():
    if self.rThread:
      Pnt11 = Base.Vector(0.0,0.0,-r)        # helper point for real thread
      edgeZ1 = Part.makeLine(Pnt9,Pnt11)
      edgeZ0 = Part.makeLine(Pnt11,Pnt0)
      aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5,edge6,edge7, \
          edgeZ1, edgeZ0])

      aFace =Part.Face(aWire)
      head = aFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360.0)
      #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
    
      # Part.show(extrude)
      head = head.cut(extrude)		   
      #FreeCAD.Console.PrintMessage("der Kopf geschnitten: " + str(dia) + "\n")
      #Part.show(head)
      
      headFaces = []
      for i in range(18):
        headFaces.append(head.Faces[i])

      if (dia < 3.0) or (dia > 5.0):
        rthread = self.makeShellthread(dia, P, halfturns, True, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a-2.0*P))
        #rthread.translate(Base.Vector(0.0, 0.0,-2.0*P))
        #Part.show(rthread)
        for tFace in rthread.Faces:
          headFaces.append(tFace)
        headShell = Part.Shell(headFaces)
        head = Part.Solid(headShell)
      else:
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a-2.0*P))
        #rthread.translate(Base.Vector(0.0, 0.0,-2.0*P))
        #Part.show(rthread)
        for tFace in rthread.Faces:
          headFaces.append(tFace)
        headShell = Part.Shell(headFaces)
        head = Part.Solid(headShell)
        cyl = self.cutChamfer(dia, P, l)
        #FreeCAD.Console.PrintMessage("vor Schnitt Ende: " + str(dia) + "\n")
        head = head.cut(cyl)

    else:
      # bolt points
      cham_t = P*math.sqrt(3.0)/2.0*17.0/24.0
      
      PntB0 = Base.Vector(0.0,0.0,-a)
      PntB1 = Base.Vector(dia/2.0,0.0,-l+cham_t)
      PntB2 = Base.Vector(dia/2.0-cham_t,0.0,-l)
      PntB3 = Base.Vector(0.0,0.0,-l)
      
      edgeB1 = Part.makeLine(Pnt10,PntB1)
      edgeB2 = Part.makeLine(PntB1,PntB2)
      edgeB3 = Part.makeLine(PntB2,PntB3)
      
      edgeZ0 = Part.makeLine(PntB3,Pnt0)
      if a <= r:
        edgeB1 = Part.makeLine(Pnt9,PntB1)
        aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5,edge6,edge7, \
            edgeB1, edgeB2, edgeB3, edgeZ0])
        
      else:
        edge8 = Part.makeLine(Pnt9,Pnt10)
        edgeB1 = Part.makeLine(Pnt10,PntB1)
        aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5,edge6,edge7,edge8, \
            edgeB1, edgeB2, edgeB3, edgeZ0])

      aFace =Part.Face(aWire)
      head = aFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360.0)
      #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
    
      # Part.show(extrude)
      head = head.cut(extrude)		   
      #FreeCAD.Console.PrintMessage("der Kopf geschnitten: " + str(dia) + "\n")
    
    return head


  # EN 1662 Hex-head-bolt with flange - small series
  # EN 1665 Hexagon bolts with flange, heavy series
  def makeEN1662_2(self,SType ='EN1662', ThreadType ='M8',l=25.0):
    dia = self.getDia(ThreadType)
    #FreeCAD.Console.PrintMessage("der Kopf mit l: " + str(l) + "\n")
    if SType == 'EN1662':
       P, b0, b1, b2, b3, c, dc, dw, e, k, kw,f, r1, s = en1662def[ThreadType]
    else:
       P, b0, b1, b2, b3, c, dc, dw, e, k, kw,f, r1, s = en1665def[ThreadType]
    if l< b0:
       b = l - 2*P
    else:
       if l<= 125.0:
          b = b1
       else:
          if l<= 200.0:
             b = b2
          else:
             b = b3
    
    #FreeCAD.Console.PrintMessage("der Kopf mit isoEN1662: " + str(c) + "\n")
    cham = s*(2.0/math.sqrt(3.0)-1.0)*math.sin(math.radians(25)) # needed for chamfer at head top

    ### make the new code with math.modf(l)
    residue, turns = math.modf((b)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = r1 - a_point

    sqrt2_ = 1.0/math.sqrt(2.0)
 
    # Flange is made with a radius of c
    beta = math.radians(25.0)
    tan_beta = math.tan(beta)
    
    # Calculation of Arc points of flange edge using dc and c
    arc1_x = dc/2.0 - c/2.0 + (c/2.0)*math.sin(beta)
    arc1_z = c/2.0 + (c/2.0)*math.cos(beta)
    
    hF = arc1_z + (arc1_x -s/2.0) * tan_beta  # height of flange at center
    
    kmean = arc1_z + (arc1_x - s/math.sqrt(3.0)) * tan_beta + kw * 1.1 + cham
    #kmean = k * 0.95
    

    #Hex-Head Points
    #FreeCAD.Console.PrintMessage("der Kopf mit math a: " + str(a_point) + "\n")
    PntH0 = Base.Vector(0.0,0.0,kmean*0.9)
    PntH1 = Base.Vector(s/2.0*0.8 - r1/2.0,0.0,kmean*0.9)
    PntH1a = Base.Vector(s/2.0*0.8-r1/2.0+r1/2.0*sqrt2_,0.0,kmean*0.9 +r1/2.0 -r1/2.0*sqrt2_)
    PntH1b = Base.Vector(s/2.0*0.8,0.0,kmean*0.9 +r1/2.0)
    PntH2 = Base.Vector(s/2.0*0.8,0.0,kmean -r1)
    PntH2a = Base.Vector(s/2.0*0.8+r1-r1*sqrt2_,0.0,kmean -r1 +r1*sqrt2_)
    PntH2b = Base.Vector(s/2.0*0.8 + r1 ,0.0,kmean)
    PntH3 = Base.Vector(s/2.0,0.0,kmean)
    #PntH4 = Base.Vector(s/math.sqrt(3.0),0.0,kmean-cham)   #s/math.sqrt(3.0)
    #PntH5 = Base.Vector(s/math.sqrt(3.0),0.0,c)
    #PntH6 = Base.Vector(0.0,0.0,c)
    
    edgeH1 = Part.makeLine(PntH0,PntH1)
    edgeH2 = Part.Arc(PntH1,PntH1a,PntH1b).toShape()
    edgeH3 = Part.makeLine(PntH1b,PntH2)
    edgeH3a = Part.Arc(PntH2,PntH2a,PntH2b).toShape()   
    edgeH3b = Part.makeLine(PntH2b,PntH3)

    hWire=Part.Wire([edgeH1,edgeH2,edgeH3,edgeH3a,edgeH3b])
    topShell = hWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(hWire)
    #Part.show(topShell)
    
    # create a cutter ring to generate the chamfer at the top of the hex
    chamHori = s/math.sqrt(3.0) - s/2.0
    PntC1 = Base.Vector(s/2.0-chamHori,0.0,kmean+kmean)
    PntC2 = Base.Vector(s/math.sqrt(3.0)+chamHori,0.0,kmean+kmean)
    PntC3 = Base.Vector(s/2.0-chamHori,0.0,kmean+cham)
    PntC4 = Base.Vector(s/math.sqrt(3.0)+chamHori,0.0,kmean-cham-cham)   #s/math.sqrt(3.0)
    edgeC1 = Part.makeLine(PntC3, PntC1)
    edgeC2 = Part.makeLine(PntC1, PntC2)
    edgeC3 = Part.makeLine(PntC2, PntC4)
    edgeC4 = Part.makeLine(PntC4, PntC3)
    cWire = Part.Wire([edgeC4, edgeC1, edgeC2, edgeC3])
    cFace = Part.Face(cWire)
    chamCut = cFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(cWire)
    #Part.show(chamCut)


    # create hexagon
    mhex=Base.Matrix()
    mhex.rotateZ(math.radians(60.0))
    polygon = []
    vhex=Base.Vector(s/math.sqrt(3.0),0.0,kmean)
    for i in range(6):
       polygon.append(vhex)
       vhex = mhex.multiply(vhex)
    polygon.append(vhex)
    hexagon = Part.makePolygon(polygon)
    hexFace = Part.Face(hexagon)
    solidHex = hexFace.extrude(Base.Vector(0.0,0.0,c-kmean))
    #Part.show(solidHex)
    hexCham = solidHex.cut(chamCut)
    #Part.show(hexCham)
    
    topFaces = topShell.Faces
    
    topFaces.append(hexCham.Faces[6])
    topFaces.append(hexCham.Faces[12])
    topFaces.append(hexCham.Faces[14])
    topFaces.append(hexCham.Faces[13])
    topFaces.append(hexCham.Faces[8])
    topFaces.append(hexCham.Faces[2])
    topFaces.append(hexCham.Faces[1])
    
    hexFaces = [hexCham.Faces[5], hexCham.Faces[11], hexCham.Faces[10]]
    hexFaces.extend([hexCham.Faces[9], hexCham.Faces[3], hexCham.Faces[0]])
    hexShell = Part.Shell(hexFaces)

    # Center of flange:
    Pnt0 = Base.Vector(0.0,0.0,hF)
    Pnt1 = Base.Vector(s/2.0,0.0,hF)
    
    # arc edge of flange:
    Pnt2 = Base.Vector(arc1_x,0.0,arc1_z)
    Pnt3 = Base.Vector(dc/2.0,0.0,c/2.0)
    Pnt4 = Base.Vector((dc-c)/2.0,0.0,0.0)
    
    Pnt5 = Base.Vector(dia/2.0+r1,0.0,0.0)     #start of fillet between head and shank
    Pnt6 = Base.Vector(dia/2.0+r1-r1*sqrt2_,0.0,-r1+r1*sqrt2_) #arc-point of fillet
    Pnt7 = Base.Vector(dia/2.0,0.0,-r1)        # end of fillet
    Pnt8 = Base.Vector(dia/2.0,0.0,-a_point)        # Start of thread
    
    edge1 = Part.makeLine(Pnt0,Pnt1)
    edge2 = Part.makeLine(Pnt1,Pnt2)
    edge3 = Part.Arc(Pnt2,Pnt3,Pnt4).toShape()
    edge4 = Part.makeLine(Pnt4,Pnt5)
    edge5 = Part.Arc(Pnt5,Pnt6,Pnt7).toShape()

    # make a cutter for the hexShell
    PntHC1 = Base.Vector(0.0,0.0,arc1_z)
    PntHC2 = Base.Vector(0.0,0.0,0.0)
    
    edgeHC1 = Part.makeLine(Pnt2,PntHC1)
    edgeHC2 = Part.makeLine(PntHC1,PntHC2)
    edgeHC3 = Part.makeLine(PntHC2,Pnt0)

    HCWire = Part.Wire([edge2, edgeHC1, edgeHC2, edgeHC3, edge1])
    HCFace = Part.Face(HCWire)
    hex2Cut = HCFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    
    hexShell = hexShell.cut(hex2Cut)
    #Part.show(hexShell)
    
    topFaces.extend(hexShell.Faces)
    
    # bolt points
    cham_t = P*math.sqrt(3.0)/2.0*17.0/24.0
    
    PntB0 = Base.Vector(0.0,0.0,-a_point)
    PntB1 = Base.Vector(dia/2.0,0.0,-l+cham_t)
    PntB2 = Base.Vector(dia/2.0-cham_t,0.0,-l)
    PntB3 = Base.Vector(0.0,0.0,-l)
    
    edgeB2 = Part.makeLine(PntB1,PntB2)
    edgeB3 = Part.makeLine(PntB2,PntB3)
    
    #if self.RealThread.isChecked():
    if self.rThread:
      aWire=Part.Wire([edge2,edge3,edge4,edge5])
      boltIndex = 4
    
    else:
      if a_point <=r1:
        edgeB1 = Part.makeLine(Pnt7,PntB1)
        aWire=Part.Wire([edge2,edge3,edge4,edge5, edgeB1, edgeB2, edgeB3])
        boltIndex = 7
      else:
        edgeB1 = Part.makeLine(Pnt8,PntB1)
        edge6 = Part.makeLine(Pnt7,Pnt8)
        aWire=Part.Wire([edge2,edge3,edge4,edge5,edge6, \
            edgeB1, edgeB2, edgeB3])
        boltIndex = 8


    #aFace =Part.Face(aWire)
    #Part.show(aWire)
    headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
    #Part.show(headShell)
    chamFace = headShell.Faces[0].cut(solidHex)
    #Part.show(chamFace)
    
    topFaces.append(chamFace.Faces[0])
    for i in range(1,boltIndex):
      topFaces.append(headShell.Faces[i])

    
    if self.rThread:
      if (dia < 3.0) or (dia > 5.0):
        rthread = self.makeShellthread(dia, P, halfturns, True, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point-2.0*P))
        for tFace in rthread.Faces:
          topFaces.append(tFace)
        headShell = Part.Shell(topFaces)
        screw = Part.Solid(headShell)
      else:
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point-2.0*P))
        for tFace in rthread.Faces:
          topFaces.append(tFace)
        headShell = Part.Shell(topFaces)
        head = Part.Solid(headShell)
        cyl = self.cutChamfer(dia, P, l)
        #FreeCAD.Console.PrintMessage("vor Schnitt Ende: " + str(dia) + "\n")
        screw = head.cut(cyl)
    else:
      screwShell = Part.Shell(topFaces)
      screw = Part.Solid(screwShell)

    return screw


  # also used for ISO 7046 countersunk flat head screws with H cross recess
  # also used for ISO 7047 raised countersunk head screws with H cross recess
  # also used for ISO 10642 Hexagon socket countersunk head screws
  # also used for ISO 14582 Hexalobular socket countersunk head screws, high head
  # also used for ISO 14584 Hexalobular socket raised countersunk head screws
  def makeIso7046(self, SType ='ISO7046', ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)
    #FreeCAD.Console.PrintMessage("der 2009Kopf mit l: " + str(l) + "\n")
    if (SType == 'ISO10642'):
      P,b,dk_theo,dk_mean,da, ds_min, e, k, r, s_mean, t, w =iso10642def[ThreadType]
      ePrax = s_mean / math.sqrt(3.0) / 0.99
      ht = 0.0
      a = 2*P
      t_mean = t
    else: #still need the data from iso2009def, but this screw can not created here
      P, a, b, dk_theo, dk_mean, k, n_min, r, t_mean, x = iso2009def[ThreadType]
      ht = 0.0 # Head heigth of flat head
    if SType == 'ISO7046':
      cT, mH, mZ  = iso7046def[ThreadType]
    if (SType == 'ISO7047'):
      rf, t_mean, cT, mH, mZ = Raised_countersunk_def[ThreadType]
      #Lengths and angles for calculation of head rounding
      beta = math.asin(dk_mean /2.0 / rf)   # angle of head edge
      tan_beta = math.tan(beta)      
      alpha = beta/2.0 # half angle
      # heigth of raised head top
      ht = rf - (dk_mean/2.0) / tan_beta
      #print 'he: ', he
      h_arc_x = rf * math.sin(alpha) 
      h_arc_z = ht - rf + rf * math.cos(alpha)
      #FreeCAD.Console.PrintMessage("h_arc_z: " + str(h_arc_z) + "\n")

    if (SType == 'ISO14582'):
      P, a, b, dk_theo, dk_mean, k, r, tt, A, t_mean = iso14582def[ThreadType]
      ePrax = A / 2.0 / 0.99

    if (SType == 'ISO14584'):
      P, b, dk_theo, dk_mean, f, k, r, rf, x, tt, A, t_mean = iso14584def[ThreadType]
      ePrax = A / 2.0 / 0.99
      #Lengths and angles for calculation of head rounding
      beta = math.asin(dk_mean /2.0 / rf)   # angle of head edge
      tan_beta = math.tan(beta)      
      ctp = - (dk_mean/2.0) / tan_beta # Center Top Edge = center for rf
      betaA = math.asin(ePrax / rf)   # angle of head edge at start of recess
      ht = ctp + ePrax / math.tan(betaA)
      alpha = betaA + (beta - betaA)/2.0 # half angle of top Arc
      h_arc_x = rf * math.sin(alpha) 
      h_arc_z = ctp + rf * math.cos(alpha)
      
           
    FreeCAD.Console.PrintMessage("der Kopf mit iso r: " + str(r) + "\n")
    cham = (dk_theo - dk_mean)/2.0
    rad225 = math.radians(22.5)
    rad45 = math.radians(45.0)
    rtan = r*math.tan(rad225)
    #FreeCAD.Console.PrintMessage("Checking rtan: " + str(rtan) + "\n")
    
    if (b > (l - k - rtan/2.0 - 1.0*P)):
      bmax = l - k - rtan/2.0 - 1.0*P
    else:
      bmax = b

    ### make the new code with math.modf(l)
    residue, turns = math.modf((bmax)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = k + rtan - a_point
       
    #Head Points
    Pnt1 = Base.Vector(dk_mean/2.0,0.0,0.0)
    Pnt2 = Base.Vector(dk_mean/2.0,0.0,-cham)
    Pnt3 = Base.Vector(dia/2.0+r-r*math.cos(rad45),0.0,-k-rtan+r*math.sin(rad45))
    
    # Arc-points
    Pnt4 = Base.Vector(dia/2.0+r-r*(math.cos(rad225)),0.0,-k-rtan+r*math.sin(rad225))
    Pnt5 = Base.Vector(dia/2.0,0.0,-k-rtan)
    Pnt6 = Base.Vector(dia/2.0,0.0,-a_point)

    if (SType == 'ISO10642') or (SType == 'ISO14582'):
      if (SType == 'ISO10642'):
        recess, recessShell = self.makeAllen2(s_mean, t_mean, 0.0 )
        Pnt0 = Base.Vector(ePrax/2.0,0.0,-ePrax/2.0)
        PntCham = Base.Vector(ePrax,0.0,0.0)
        edge1 = Part.makeLine(Pnt0,PntCham)    
        edgeCham2 = Part.makeLine(PntCham,Pnt1)    
        edge2 = Part.makeLine(Pnt1,Pnt2)
        edge2 = Part.Wire([edgeCham2,edge2])
        PntH0 = Base.Vector(ePrax/2.0,0.0, ht + k)
        PntH1 = Base.Vector(ePrax,0.0, ht + k)
      if (SType == 'ISO14582'):
        recess, recessShell = self.makeIso10664_3(tt, t_mean, 0.0) # hexalobular recess
        Pnt0 = Base.Vector(0.0,0.0,0.0)
        edge1 = Part.makeLine(Pnt0,Pnt1)    
        edge2 = Part.makeLine(Pnt1,Pnt2)


      # bolt points with bolt chamfer
      cham_b = P*math.sqrt(3.0)/2.0*17.0/24.0
      
      PntB1 = Base.Vector(dia/2.0,0.0,-l+cham_b)
      PntB2 = Base.Vector(dia/2.0-cham_b,0.0,-l)
      PntB3 = Base.Vector(0.0,0.0,-l)
      if a_point <= (k + rtan):
        edgeB0 = Part.makeLine(Pnt5,PntB1)
      else:
        edgeB0 = Part.makeLine(Pnt6,PntB1)
      edgeB2 = Part.makeLine(PntB1,PntB2)
      edgeB3 = Part.makeLine(PntB2,PntB3)
      edgeB1 = Part.Wire([edgeB2,edgeB3])

    else:
      # bolt points
      PntB1 = Base.Vector(dia/2.0,0.0,-l)
      PntB2 = Base.Vector(0.0,0.0,-l)
      if a_point <= (k + rtan):
        edgeB0 = Part.makeLine(Pnt5,PntB1)
      else:
        edgeB0 = Part.makeLine(Pnt6,PntB1)
      edgeB1 = Part.makeLine(PntB1,PntB2)

      if (SType == 'ISO7047'): # make raised head rounding
        Pnt0 = Base.Vector(0.0,0.0,ht)
        Pnt0arc = Base.Vector(h_arc_x,0.0,h_arc_z)
        edge1 = Part.Arc(Pnt0,Pnt0arc,Pnt1).toShape()     
        edge2 = Part.makeLine(Pnt1,Pnt2)
        PntH0 = Base.Vector(0.0,0.0, ht + k)
        PntH1 = Base.Vector(dk_mean/2.0,0.0, ht + k)
        recess, recessShell = self.makeCross_H3(cT, mH, ht)
      if (SType == 'ISO7046'):
        # ISO7046
        FreeCAD.Console.PrintMessage("ISO7046: " + str(ht) + "\n")
        Pnt0 = Base.Vector(0.0,0.0,ht)
        edge1 = Part.makeLine(Pnt0,Pnt1)  # make flat head
        edge2 = Part.makeLine(Pnt1,Pnt2)
        recess, recessShell = self.makeCross_H3(cT, mH, ht)

      if (SType == 'ISO14584'): # make raised head rounding with chamfer
        Pnt0 = Base.Vector(ePrax/2.0,0.0,ht-ePrax/4.0)
        PntCham = Base.Vector(ePrax,0.0,ht)
        PntArc = Base.Vector(h_arc_x,0.0,h_arc_z)
        edge1 = Part.makeLine(Pnt0,PntCham)    
        edgeArc = Part.Arc(PntCham,PntArc,Pnt1).toShape() 
        edge2 = Part.makeLine(Pnt1,Pnt2)
        edge2 = Part.Wire([edgeArc,edge2])
        PntH0 = Base.Vector(ePrax/2.0,0.0, ht + k)
        PntH1 = Base.Vector(ePrax,0.0, ht + k)
        recess, recessShell = self.makeIso10664_3(tt, t_mean, ht) # hexalobular recess
       
    edge3 = Part.makeLine(Pnt2,Pnt3)
    edgeArc = Part.Arc(Pnt3,Pnt4,Pnt5).toShape()     
    edgeArc1 = Part.makeLine(Pnt3,Pnt4)     
    edgeArc2 = Part.makeLine(Pnt4,Pnt5)
    edge6 = Part.makeLine(Pnt5,Pnt6)
    
    if self.rThread:
      #aWire=Part.Wire([edge1,edge2,edge3,edgeArc])
      aWire=Part.Wire([edge2,edge3,edgeArc])
    else:
      if a_point <= (k + rtan):
        aWire=Part.Wire([edge2,edge3,edgeArc, edgeB0, edgeB1])
      else:
        aWire=Part.Wire([edge2,edge3,edgeArc,edge6, edgeB0, edgeB1])

    #Part.show(aWire)
    headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    headFaces = headShell.Faces
    #Part.show(headShell)

    if (SType == 'ISO7046') or (SType == 'ISO14582'):
      # hCut is just a cylinder for ISO7046
      hCut = Part.makeCylinder(dk_mean/2.0,k,Pnt0)
      #Part.show(hCut)
      topFace = hCut.Faces[2]
    else:
      if (SType == 'ISO7047'):
        edgeH1 = Part.makeLine(Pnt1,PntH1)
      else:
        edgeH1 = Part.makeLine(PntCham,PntH1)
      edgeH2 = Part.makeLine(PntH1,PntH0)
      edgeH3 = Part.makeLine(PntH0,Pnt0)
      hWire = Part.Wire([edge1,edgeH1,edgeH2,edgeH3]) # Cutter for recess-Shell
      hFace = Part.Face(hWire)
      hCut = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
      Part.show(hWire)
      #Part.show(hCut)
      topFace = hCut.Faces[0]

    recessShell = recessShell.cut(hCut)
    topFace = topFace.cut(recess)
    #Part.show(topFace)
    #Part.show(recessShell)
    #Part.show(headShell)
    headFaces.append(topFace.Faces[0])
    headFaces.extend(recessShell.Faces)
    

    if (SType == 'ISO10642') or (SType == 'ISO14582'):
      if self.rThread:
        if (dia < 3.0) or (dia > 5.0):
          #if True:
          rthread = self.makeShellthread(dia, P, halfturns, True, offSet)
          rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
          #head = head.fuse(rthread)
          #Part.show(rthread)
          for threadFace in rthread.Faces:
            headFaces.append(threadFace)

          screwShell = Part.Shell(headFaces)
          screw = Part.Solid(screwShell)
        else:
          '''
          # head = self.cutIsoThread(head, dia, P, turns, l)
          rthread = self.makeShellthread(dia, P, halfturns, False)
          rthread.translate(Base.Vector(0.0, 0.0,-a_point-2.0*P))
          head = head.fuse(rthread)
          head = head.removeSplitter()
          cyl = self.cutChamfer(dia, P, l)
          #FreeCAD.Console.PrintMessage("vor Schnitt Ende: " + str(dia) + "\n")
          head = head.cut(cyl)
          '''
          
          rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
          rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
          #head = head.fuse(rthread)
          #Part.show(rthread)
          for threadFace in rthread.Faces:
            headFaces.append(threadFace)

          screwShell = Part.Shell(headFaces)
          screw = Part.Solid(screwShell)
          cyl = self.cutChamfer(dia, P, l)
          screw = screw.cut(cyl)
      else:
        screwShell = Part.Shell(headFaces)
        screw = Part.Solid(screwShell)

    else:
      if self.rThread:
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
        #head = head.fuse(rthread)
        #Part.show(rthread)
        for threadFace in rthread.Faces:
          headFaces.append(threadFace)

      screwShell = Part.Shell(headFaces)
      screw = Part.Solid(screwShell)


    
    return screw






  # make ISO 4762 Allan Screw head
  # ISO 14579 Hexalobular socket head cap screws
  def makeIso4762(self, SType ='ISO4762', ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)
    #FreeCAD.Console.PrintMessage("der 4762Kopf mit l: " + str(l) + "\n")
    P, b, dk_max, da, ds_mean, e, lf, k, r, s_mean, t, v, dw, w = iso4762def[ThreadType]
    #FreeCAD.Console.PrintMessage("der Kopf mit iso r: " + str(r) + "\n")
    if SType == 'ISO14579':
      tt, A, t = iso14579def[ThreadType]
      #Head Points 30° countersunk
      # Pnt0 = Base.Vector(0.0,0.0,k-A/4.0) #Center Point for countersunk
      Pnt0 = Base.Vector(0.0,0.0,k-A/8.0) #Center Point for flat countersunk
      PntFlat = Base.Vector(A/8.0,0.0,k-A/8.0) # End of flat part
      Pnt1 = Base.Vector(A/1.99,0.0,k)     #countersunk edge at head
      edgeCham0 = Part.makeLine(Pnt0,PntFlat)    
      edgeCham1 = Part.makeLine(PntFlat,Pnt1)    
      edge1 = Part.Wire([edgeCham0,edgeCham1])
      
      # Here is the next approach to shorten the head building time
      # Make two helper points to create a cutting tool for the 
      # recess and recess shell.
      PntH1 = Base.Vector(A/1.99,0.0, 2.0*k)

    else:
      e_cham = 2.0 * s_mean / math.sqrt(3.0)
      #Head Points 45° countersunk
      Pnt0 = Base.Vector(0.0,0.0,k-e_cham/1.99/2.0) #Center Point for countersunk
      PntFlat = Base.Vector(e_cham/1.99/2.0,0.0,k-e_cham/1.99/2.0) # End of flat part
      Pnt1 = Base.Vector(e_cham/1.99,0.0,k)     #countersunk edge at head
      edgeCham0 = Part.makeLine(Pnt0,PntFlat)    
      edgeCham1 = Part.makeLine(PntFlat,Pnt1)    
      edge1 = Part.Wire([edgeCham0,edgeCham1])
      PntH1 = Base.Vector(e_cham/1.99,0.0, 2.0*k)
      
    
    PntH2 = Base.Vector(0.0,0.0, 2.0*k)
    edgeH1 = Part.makeLine(Pnt1,PntH1)
    edgeH2 = Part.makeLine(PntH1,PntH2)
    edgeH3 = Part.makeLine(PntH2,Pnt0)
    hWire = Part.Wire([edge1,edgeH1,edgeH2,edgeH3]) # Cutter for recess-Shell
    hFace = Part.Face(hWire)
    hCut = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(hWire)
    '''


    PntH2 = Base.Vector(A/8.0,0.0, 2.0*k)
    edgeH1 = Part.makeLine(Pnt1,PntH1)
    edgeH2 = Part.makeLine(PntH1,PntH2)
    edgeH3 = Part.makeLine(PntH2,PntFlat)
    hWire = Part.Wire([edgeCham1,edgeH1,edgeH2,edgeH3]) # Cutter for recess-Shell
    hFace = Part.Face(hWire)
    hCut = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(hWire)
    '''


    sqrt2_ = 1.0/math.sqrt(2.0)
    #depth = s_mean / 3.0

    '''
    if (b > l - 2*P):
       bmax = l-2*P
    else:
       bmax = b
    halfturns = round(2.0*(bmax+P)/P) # number of thread turns
    if self.RealThread.isChecked():
      a_real = l-(halfturns+2)*P/2.0  # point to fuse real thread
    else:
      a_real = l-halfturns*P/2.0  # starting point of thread
    if a_real < r:
      a_point = r*1.3
    else:
      a_point = a_real
    '''


    if (b > (l - 1.0*P)):
       bmax = l- 1.0*P
    else:
       bmax = b

    ### make the new code with math.modf(l)
    residue, turns = math.modf((bmax)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    #halfturns = halfturns + 2
    offSet = r - a_point
    #FreeCAD.Console.PrintMessage("The transition at a: " + str(a) + " turns " + str(turns) + "\n")



         
    #rad30 = math.radians(30.0)
    #Head Points
    Pnt2 = Base.Vector(dk_max/2.0-v,0.0,k)   #start of fillet
    Pnt3 = Base.Vector(dk_max/2.0-v+v*sqrt2_,0.0,k-v+v*sqrt2_) #arc-point of fillet
    Pnt4 = Base.Vector(dk_max/2.0,0.0,k-v)   #end of fillet
    Pnt5 = Base.Vector(dk_max/2.0,0.0,(dk_max-dw)/2.0) #we have a chamfer here
    Pnt6 = Base.Vector(dw/2.0,0.0,0.0)           #end of chamfer
    Pnt7 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
    Pnt8 = Base.Vector(dia/2.0+r-r*sqrt2_,0.0,-r+r*sqrt2_) #arc-point of fillet
    Pnt9 = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
    Pnt10 = Base.Vector(dia/2.0,0.0,-a_point)        # start of thread
    
    edge1 = Part.makeLine(Pnt0,Pnt1)
    edge2 = Part.makeLine(Pnt1,Pnt2)
    edge3 = Part.Arc(Pnt2,Pnt3,Pnt4).toShape()
    edge4 = Part.makeLine(Pnt4,Pnt5)
    edge5 = Part.makeLine(Pnt5,Pnt6)
    edge6 = Part.makeLine(Pnt6,Pnt7)
    edge7 = Part.Arc(Pnt7,Pnt8,Pnt9).toShape()
    
    '''
    # bolt points
    PntB1 = Base.Vector(dia/2.0,0.0,-l-P)  # Chamfer is made with a cut later
    PntB2 = Base.Vector(0.0,0.0,-l-P)
    #PntB3 = Base.Vector(0.0,0.0,-l)

    edgeB0 = Part.makeLine(Pnt10,PntB1)
    edgeB1 = Part.makeLine(PntB1,PntB2)
    #edgeB2 = Part.makeLine(PntB2,PntB3)
    edgeZ0 = Part.makeLine(PntB2,Pnt0)
    
    
    aWire=Part.Wire([edge1,edge2,edge3,edge4,edge5,edge6,edge7,edge8, \
        edgeB0, edgeB1, edgeZ0])
    '''


    
    if self.rThread:
      aWire=Part.Wire([edge2,edge3,edge4,edge5,edge6,edge7])
    
    else:
      # bolt points
      cham_t = P*math.sqrt(3.0)/2.0*17.0/24.0
      
      PntB1 = Base.Vector(dia/2.0,0.0,-l+cham_t)
      PntB2 = Base.Vector(dia/2.0-cham_t,0.0,-l)
      PntB3 = Base.Vector(0.0,0.0,-l)
      
      #edgeB1 = Part.makeLine(Pnt10,PntB1)
      edgeB2 = Part.makeLine(PntB1,PntB2)
      edgeB3 = Part.makeLine(PntB2,PntB3)

      if a_point <= r:
        edgeB1 = Part.makeLine(Pnt9,PntB1)
        aWire=Part.Wire([edge2,edge3,edge4,edge5,edge6,edge7, \
            edgeB1, edgeB2, edgeB3])
      else:
        edge8 = Part.makeLine(Pnt9,Pnt10)
        edgeB1 = Part.makeLine(Pnt10,PntB1)
        aWire=Part.Wire([edge2,edge3,edge4,edge5,edge6,edge7,edge8, \
            edgeB1, edgeB2, edgeB3])
      #Part.show(aWire)

    headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #head = Part.Solid(headShell)
    #Part.show(aWire)
    #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
    headFaces = headShell.Faces

    
    if SType == 'ISO14579':
      #recess = self.makeIso10664(tt, t, k) # hexalobular recess
      recess, recessShell = self.makeIso10664_3(tt, t, k) # hexalobular recess
    else:
      recess, recessShell = self.makeAllen2(s_mean, t, k )

    recessShell = recessShell.cut(hCut)
    topFace = hCut.Faces[1]
    #topFace = hCut.Faces[0]
    topFace = topFace.cut(recess)
    #Part.show(topFace)
    #Part.show(recessShell)
    #Part.show(headShell)
    headFaces.append(topFace.Faces[0])
    #headFaces.append(hCut.Faces[2])

    #allenscrew = head.cut(recess)
    #Part.show(hCut)
    headFaces.extend(recessShell.Faces)

    #if self.RealThread.isChecked():
    if self.rThread:
      #if (dia < 3.0) or (dia > 5.0):
      if True:
        # head = self.cutIsoThread(head, dia, P, turns, l)
        rthread = self.makeShellthread(dia, P, halfturns, True, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point-2.0*P))
        #Part.show(rthread)
        for tFace in rthread.Faces:
          headFaces.append(tFace)
        headShell = Part.Shell(headFaces)
        allenscrew = Part.Solid(headShell)

      else:
        # head = self.cutIsoThread(head, dia, P, turns, l)
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point-2.0*P))
        for tFace in rthread.Faces:
          headFaces.append(tFace)
        headShell = Part.Shell(headFaces)
        allenscrew = Part.Solid(headShell)
        cyl = self.cutChamfer(dia, P, l)
        # FreeCAD.Console.PrintMessage("vor Schnitt Ende: " + str(dia) + "\n")
        allenscrew = allenscrew.cut(cyl)
    else:
      headShell = Part.Shell(headFaces)
      allenscrew = Part.Solid(headShell)
      

    return allenscrew




  # make ISO 7380-1 Button head Screw 
  # make ISO 7380-2 Button head Screw with collar 
  # make DIN 967 cross recessed pan head Screw with collar 
  def makeIso7380(self, SType ='ISO7380-1', ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)
    #todo: different radii for screws with thread to head or with shaft?
    sqrt2_ = 1.0/math.sqrt(2.0)
    
    if (SType =='DIN967'):
      P, b, c, da, dk, r, k, rf, x, cT, mH, mZ = din967def[ThreadType]
      
      rH = rf # radius of button arc
      alpha = math.acos((rf-k+c)/rf)

      #Head Points
      Pnt0 = Base.Vector(0.0,0.0,k) 
      PntArc = Base.Vector(rf*math.sin(alpha/2.0),0.0,k-rf + rf*math.cos(alpha/2.0)) #arc-point of button
      Pnt1 = Base.Vector(rf*math.sin(alpha),0.0,c)     #end of button arc
      PntC0 = Base.Vector((dk)/2.0,0.0,c)     #collar points
      PntC2 = Base.Vector((dk)/2.0,0.0,0.0)     #collar points
      Pnt4 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank

      edge1 = Part.Arc(Pnt0,PntArc,Pnt1).toShape()
      edgeC0 = Part.makeLine(Pnt1,PntC0)
      edgeC1 = Part.makeLine(PntC0,PntC2)
      edge2 = Part.Wire([edgeC0, edgeC1])
      edge3 = Part.makeLine(PntC2,Pnt4)
      #Points for recessShell cutter
      PntH0 = Base.Vector(0.0,0.0,2.0*k) 
      PntH1 = Base.Vector(rf*math.sin(alpha),0.0,2.0*k)  
      recess, recessShell = self.makeCross_H3(cT, mH, k)
      
    else:
      if (SType =='ISO7380-1'):
        P, b, a, da, dk, dk_mean,s_mean, t_min, r, k, e, w = iso7380def[ThreadType]
        
        # Bottom of recess
        e_cham = 2.0 * s_mean / math.sqrt(3.0) / 0.99
        #depth = s_mean / 3.0
        
        ak = -(4*k**2 + e_cham**2 - dk**2)/(8*k) # helper value for button arc
        rH = math.sqrt((dk/2.0)**2 + ak**2) # radius of button arc
        alpha = (math.atan(2*(k + ak)/e_cham) + math.atan((2*ak)/dk))/2
  
        Pnt2 = Base.Vector(rH*math.cos(alpha),0.0,-ak + rH*math.sin(alpha)) #arc-point of button
        Pnt3 = Base.Vector(dk/2.0,0.0,0.0)   #end of fillet
        Pnt4 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
        edge3 = Part.makeLine(Pnt3,Pnt4)
  
      if (SType =='ISO7380-2'):
        P, b, c, da, dk, dk_c,s_mean,t_min, r, k, e, w = iso7380_2def[ThreadType]
        
        # Bottom of recess
        e_cham = 2.0 * s_mean / math.sqrt(3.0) / 0.99
        #depth = s_mean / 3.0
        
        ak = -(4*(k-c)**2 + e_cham**2 - dk**2)/(8*(k-c)) # helper value for button arc
        rH = math.sqrt((dk/2.0)**2 + ak**2) # radius of button arc
        alpha = (math.atan(2*(k -c + ak)/e_cham) + math.atan((2*ak)/dk))/2
  
        Pnt2 = Base.Vector(rH*math.cos(alpha),0.0,c -ak + rH*math.sin(alpha)) #arc-point of button
        Pnt3 = Base.Vector(dk/2.0,0.0,c)   #end of fillet
        Pnt4 = Base.Vector(dia/2.0+r,0.0,0.0)     #start of fillet between head and shank
        PntC0 = Base.Vector((dk_c-c)/2.0,0.0,c)     #collar points
        PntC1 = Base.Vector(dk_c/2.0,0.0,c/2.0)     #collar points
        PntC2 = Base.Vector((dk_c-c)/2.0,0.0,0.0)     #collar points
  
        edgeC0 = Part.makeLine(Pnt3,PntC0)
        edgeC1 = Part.Arc(PntC0,PntC1,PntC2).toShape()
        edge3 = Part.makeLine(PntC2,Pnt4)
        edge3 = Part.Wire([edgeC0, edgeC1, edge3])
  
      #Head Points
      Pnt0 = Base.Vector(e_cham/4.0,0.0,k-e_cham/4.0) #Center Point for chamfer
      Pnt1 = Base.Vector(e_cham/2.0,0.0,k)     #inner chamfer edge at head
      #Points for recessShell cutter
      PntH0 = Base.Vector(e_cham/4.0,0.0,2.0*k) 
      PntH1 = Base.Vector(e_cham/2.0,0.0,2.0*k)  
      
      edge1 = Part.makeLine(Pnt0,Pnt1)
      edge2 = Part.Arc(Pnt1,Pnt2,Pnt3).toShape()
      recess, recessShell = self.makeAllen2(s_mean, t_min, k)

    if (b > (l - 1.0*P)):
       bmax = l- 1.0*P
    else:
       bmax = b

    ### make the new code with math.modf(l)
    residue, turns = math.modf((bmax)/P)
    halfturns = 2*int(turns)
    if residue < 0.5:
      a_point = l - (turns+1.0) * P 
      halfturns = halfturns +1
    else:
      halfturns = halfturns + 2
      a_point = l - (turns+2.0) * P
    offSet = r - a_point
         

    Pnt5 = Base.Vector(dia/2.0+r-r*sqrt2_,0.0,-r+r*sqrt2_) #arc-point of fillet
    Pnt6 = Base.Vector(dia/2.0,0.0,-r)        # end of fillet
    Pnt7 = Base.Vector(dia/2.0,0.0,-a_point)        # start of thread

    edge4 = Part.Arc(Pnt4,Pnt5,Pnt6).toShape()
    edge5 = Part.makeLine(Pnt6,Pnt7)

    if (SType =='DIN967'):
      # bolt points
      PntB1 = Base.Vector(dia/2.0,0.0,-l)
      PntB2 = Base.Vector(0.0,0.0,-l)
      edgeB2 = Part.makeLine(PntB1,PntB2)
    else:
      # bolt points
      cham_b = P*math.sqrt(3.0)/2.0*17.0/24.0
      
      PntB1 = Base.Vector(dia/2.0,0.0,-l+cham_b)
      PntB2 = Base.Vector(dia/2.0-cham_b,0.0,-l)
      PntB3 = Base.Vector(0.0,0.0,-l)
      
      edgeB2 = Part.makeLine(PntB1,PntB2)
      edgeB3 = Part.makeLine(PntB2,PntB3)
      edgeB2 = Part.Wire([edgeB2, edgeB3])

    if self.rThread:
      aWire=Part.Wire([edge2,edge3,edge4])
    else:
      if a_point <= r:
        edgeB1 = Part.makeLine(Pnt6,PntB1)
        aWire=Part.Wire([edge2,edge3,edge4, edgeB1, edgeB2])
      else:
        edge5 = Part.makeLine(Pnt6,Pnt7)
        edgeB1 = Part.makeLine(Pnt7,PntB1)
        aWire=Part.Wire([edge2,edge3,edge4,edge5, edgeB1, edgeB2])

    #Part.show(aWire)
    headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(headShell)
    headFaces = headShell.Faces
    
    edgeH1 = Part.makeLine(Pnt1,PntH1)
    edgeH2 = Part.makeLine(PntH1,PntH0)
    edgeH3 = Part.makeLine(PntH0,Pnt0)
    hWire = Part.Wire([edge1,edgeH1,edgeH2,edgeH3]) # Cutter for recess-Shell
    hFace = Part.Face(hWire)
    hCut = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(hWire)
    topFace = hCut.Faces[0]

    recessShell = recessShell.cut(hCut)
    topFace = topFace.cut(recess)
    #Part.show(topFace)
    #Part.show(recessShell)
    #Part.show(headShell)
    headFaces.append(topFace.Faces[0])
    headFaces.extend(recessShell.Faces)


    if self.rThread:
      #if (dia < 3.0) or (dia > 5.0):
      if True:
        if (SType =='DIN967'):
          rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        else:
          rthread = self.makeShellthread(dia, P, halfturns, True, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
        for threadFace in rthread.Faces:
          headFaces.append(threadFace)

        screwShell = Part.Shell(headFaces)
        screw = Part.Solid(screwShell)
      else:
        rthread = self.makeShellthread(dia, P, halfturns, False, offSet)
        rthread.translate(Base.Vector(0.0, 0.0,-a_point -2.0*P))
        for threadFace in rthread.Faces:
          headFaces.append(threadFace)

        screwShell = Part.Shell(headFaces)
        screw = Part.Solid(screwShell)
        cyl = self.cutChamfer(dia, P, l)
        screw = screw.cut(cyl)
    else:
      screwShell = Part.Shell(headFaces)
      screw = Part.Solid(screwShell)
      
    return screw




  def makeHextool(self,s_hex, k_hex, cir_hex):
    # makes a cylinder with an inner hex hole, used as cutting tool
    # create hexagon
    mhex=Base.Matrix()
    mhex.rotateZ(math.radians(60.0))
    polygon = []
    vhex=Base.Vector(s_hex/math.sqrt(3.0),0.0,-k_hex*0.1)
    for i in range(6):
       polygon.append(vhex)
       vhex = mhex.multiply(vhex)
    polygon.append(vhex)
    hexagon = Part.makePolygon(polygon)
    # create circle
    circ=Part.makeCircle(cir_hex/2.0,Base.Vector(0.0,0.0,-k_hex*0.1),self.circleAxis)
    # Create the face with the circle as outline and the hexagon as hole
    face=Part.Face([Part.Wire(circ),hexagon])
    
    # Extrude in z to create the final cutting tool
    exHex=face.extrude(Base.Vector(0.0,0.0,k_hex*1.2))
    # Part.show(exHex)
    return exHex


  def makeShellthread(self, d, P, halfrots, withcham, offSet):
    d = float(d)
    
    #rotations = int(rots)-1
    halfrots_int = int(halfrots)
    rotations = int((halfrots_int / 2)-1)
    print ("halfrots_int: ", halfrots_int, " rotations: ", rotations)
    if halfrots_int % 2 == 1:
      #FreeCAD.Console.PrintMessage("got half turn: " + str(halfrots_int) + "\n")
      halfturn = True
      # bot_off = - P/2.0 # transition of half a turn
      bot_off = 0.0 # nominal length
    else:
      halfturn = False
      bot_off = 0.0 # nominal length

    H=P*math.cos(math.radians(30)) # Gewindetiefe H
    r=d/2.0
    
    # helix = Part.makeHelix(P,P,d*511/1000.0,0) # make just one turn, length is identical to pitch
    helix = Part.makeHelix(P,P,d*self.Tuner/1000.0,0) # make just one turn, length is identical to pitch
    helix.translate(FreeCAD.Vector(0.0, 0.0,-P*9.0/16.0))
  
    extra_rad = P
    # points for screw profile
    ps0 = (r,0.0, 0.0)
    ps1 = (r-H*5.0/8.0,0.0, -P*5.0/16.0)
    ps2 = (r-H*17.0/24.0,0.0, -P*7.0/16.0) # Center of Arc
    ps3 = (r-H*5.0/8.0,0.0, -P*9.0/16.0 )
    ps4 =  (r, 0.0, -P*14.0/16.0)
    ps5 = (r,0.0, -P)
    ps6 = (r+extra_rad,0.0, -P)
    ps7 = (r+extra_rad,0.0, 0.0) 
     
    edge0 = Part.makeLine(ps0,ps1)
    edge1 = Part.Arc(FreeCAD.Vector(ps1),FreeCAD.Vector(ps2),FreeCAD.Vector(ps3)).toShape()
    edge2 = Part.makeLine(ps3,ps4)
    edge3 = Part.makeLine(ps4,ps5)
    edge4 = Part.makeLine(ps5,ps6)
    edge5 = Part.makeLine(ps6,ps7)
    edge6 = Part.makeLine(ps7,ps0)
     
    W0 = Part.Wire([edge0, edge1, edge2, edge3, edge4, edge5, edge6])
    
    makeSolid=True
    isFrenet=True
    pipe0 = Part.Wire(helix).makePipeShell([W0],makeSolid,isFrenet)
    # pipe1 = pipe0.copy()
  
    TheFaces = [] 
    TheFaces.append(pipe0.Faces[0])
    #Part.show(pipe0.Faces[0])
    TheFaces.append(pipe0.Faces[1])
    #Part.show(pipe0.Faces[1])
    TheFaces.append(pipe0.Faces[2])
    #Part.show(pipe0.Faces[2])
    TheFaces.append(pipe0.Faces[3])
    #Part.show(pipe0.Faces[3])
    
    TheShell = Part.Shell(TheFaces)
    # print "Shellpoints: ", len(TheShell.Vertexes)

    
    i = 1
    for i in range(rotations-2):
       TheShell.translate(FreeCAD.Vector(0.0, 0.0,- P))
  
       for flaeche in TheShell.Faces:
         TheFaces.append(flaeche)
    
    #FreeCAD.Console.PrintMessage("Base-Shell: " + str(i) + "\n")
    # Make separate faces for the tip of the screw
    botFaces = []
    for i in range(rotations-2, rotations, 1):
       TheShell.translate(FreeCAD.Vector(0.0, 0.0,- P))
  
       for flaeche in TheShell.Faces:
         botFaces.append(flaeche)
    #FreeCAD.Console.PrintMessage("Bottom-Shell: " + str(i) + "\n")
  
    # making additional faces for transition to cylinder
  
    pc1 = (r + H/16.0,0.0,P*1/32.0)
    pc2 = (r-H*5.0/8.0,0.0,-P*5.0/16.0 )
    pc3 = (r-H*17.0/24.0,0.0, -P*7.0/16.0 ) # Center of Arc
    pc4 = (r-H*5.0/8.0,0.0, -P*9.0/16.0 )
    pc5 =  (r+ H/16.0, 0.0, -P*29.0/32.0 )    
       
    edgec0 = Part.makeLine(pc5,pc1)
    edgec1 = Part.makeLine(pc1,pc2)
    edgec2 = Part.Arc(FreeCAD.Vector(pc2),FreeCAD.Vector(pc3),FreeCAD.Vector(pc4)).toShape()
    edgec3 = Part.makeLine(pc4,pc5)
  
    cut_profile = Part.Wire([edgec1, edgec2, edgec3, edgec0 ])
    
    alpha_rad = math.atan(2*H*17.0/24.0/P)
    alpha = math.degrees(alpha_rad)
    Hyp = P/math.cos(alpha_rad)
    # tuning = 511/1000.0
    tuning = self.Tuner/1000.0
    angled_Helix = Part.makeHelix(Hyp,Hyp*1.002/2.0,d*tuning,alpha)
    
    SH_faces = []
    
    if halfturn:
      half_Helix = Part.makeHelix(P,P/2.0,d*self.Tuner/1000.0,0) # make just half a turn
      angled_Helix.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),180)
      angled_Helix.translate(FreeCAD.Vector(0.0, 0.0,P/2.0))
      # Part.show(half_Helix)
      # Part.show(angled_Helix)
      pipe_cut = Part.Wire([half_Helix, angled_Helix]).makePipeShell([cut_profile],True,isFrenet)
      SH_faces.append(pipe_cut.Faces[0])
      SH_faces.append(pipe_cut.Faces[1])
      SH_faces.append(pipe_cut.Faces[2])
      SH_faces.append(pipe_cut.Faces[4])
      SH_faces.append(pipe_cut.Faces[5])
      SH_faces.append(pipe_cut.Faces[6])
      
    else:
      pipe_cut = Part.Wire(angled_Helix).makePipeShell([cut_profile],True,isFrenet)
      SH_faces.append(pipe_cut.Faces[0])
      SH_faces.append(pipe_cut.Faces[1])
      SH_faces.append(pipe_cut.Faces[2])
        
    # Part.show(pipe_cut)
  
    
    Shell_helix = Part.Shell(SH_faces)
    
    # rect_helix_profile, needed for cutting a tube-shell
    pr1 = (r +H/16.0, 0.0, 0.0)
    pr2 = (r -H/16.0, 0.0, 0.0)
    pr3 = (r -H/16.0, 0.0, P)
    pr4 = (r +H/16.0, 0.0, P)
  
    edge_r1 = Part.makeLine(pr1,pr2)
    edge_r2 = Part.makeLine(pr2,pr3)
    edge_r3 = Part.makeLine(pr3,pr4)
    edge_r4 = Part.makeLine(pr4,pr1)
    rect_profile = Part.Wire([edge_r1, edge_r2, edge_r3, edge_r4 ])
    rect_helix = Part.Wire(helix).makePipeShell([rect_profile], True, isFrenet)
    # if halfturn:
    #   rect_helix.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),180)
    rect_helix.translate(FreeCAD.Vector(0.0, 0.0,- P))
    # Part.show(rect_helix)
    
    # rect_ring, nedded for cutting the Shell_helix
    pr5 = (r +H*1.1, 0.0, P*1.1)
    pr6 = (r, 0.0, P*1.1)
    pr7 = (r, 0.0, -P*1.1)
    pr8 = (r +H*1.1, 0.0, -P*1.1)
    
    edge_r5 = Part.makeLine(pr5,pr6)
    edge_r6 = Part.makeLine(pr6,pr7)
    edge_r7 = Part.makeLine(pr7,pr8)
    edge_r8 = Part.makeLine(pr8,pr5)
    rect_profile = Part.Wire([edge_r5, edge_r6, edge_r7, edge_r8 ])
    
    rect_Face =Part.Face(rect_profile)
    rect_ring= rect_Face.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(rect_ring)
    
    Shell_helix = Shell_helix.cut(rect_ring)
    Shell_helix.translate(FreeCAD.Vector(0.0, 0.0, P))
    # Part.show(Shell_helix)
    
    # shell_ring, the transition to a cylinder
    pr9 = (r, 0.0, P-offSet)
    pr10 = (r, 0.0, -P )
    edge_r9 = Part.makeLine(pr9,pr10)
    shell_ring= edge_r9.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
  
    shell_ring = shell_ring.cut(pipe_cut)
    #Part.show(shell_ring)
    shell_ring = shell_ring.cut(rect_helix)
    shell_ring.translate(FreeCAD.Vector(0.0, 0.0, P))
    #Part.show(shell_ring)
    
    for flaeche in shell_ring.Faces:
      TheFaces.append(flaeche)
  
    for flaeche in Shell_helix.Faces:
      TheFaces.append(flaeche)
  
    if withcham:
      #FreeCAD.Console.PrintMessage("with chamfer: " + str(i) + "\n")
      # cutting of the bottom Faces
      # bot_off = 0.0 # nominal length
      cham_off = H/8.0
      cham_t = P*math.sqrt(3.0)/2.0*17.0/24.0
      
      # points for chamfer: common-Method
      pch0 =  (0.0, 0.0, -(rotations)*P + bot_off) # bottom center
      pch1 =  (r-cham_t,0.0, -(rotations)*P + bot_off)
      pch2 =  (r+cham_off, 0.0, -(rotations)*P + cham_t +cham_off  + bot_off)
      pch3 =  (r+cham_off, 0.0, -(rotations)*P + 3.0*P + bot_off)
      pch4 =  (0.0, 0.0, -(rotations)*P + 3.0*P + bot_off)
    
      edgech0 = Part.makeLine(pch0,pch1)
      edgech1 = Part.makeLine(pch1,pch2)
      edgech2 = Part.makeLine(pch2,pch3)
      edgech3 = Part.makeLine(pch3,pch4)
      edgech4 = Part.makeLine(pch4,pch0)
    
      Wch_wire = Part.Wire([edgech0, edgech1, edgech2, edgech3, edgech4])
      cham_Face =Part.Face(Wch_wire)
      cham_Solid = cham_Face.revolve(Base.Vector(0.0,0.0,-(rotations-1)*P),Base.Vector(0.0,0.0,1.0),360)
      # Part.show(cham_Solid)
      
      BotShell = Part.Shell(botFaces)
      BotShell = BotShell.common(cham_Solid)
      # Part.show(BotShell)
      
      cham_faces = []
      cham_faces.append(cham_Solid.Faces[0])
      cham_faces.append(cham_Solid.Faces[1])
      cham_Shell = Part.Shell(cham_faces)
      # Part.show(cham_Shell)
    
      pipe0.translate(FreeCAD.Vector(0.0, 0.0, -(rotations-1)*P))
      # Part.show(pipe0)
      
      # Part.show(Fillet_shell)
      cham_Shell = cham_Shell.cut(pipe0)
      pipe0.translate(FreeCAD.Vector(0.0, 0.0, -P))
      # Part.show(pipe0)
      cham_Shell = cham_Shell.cut(pipe0)
    
      '''
      botFaces2 = []
      for flaeche in BotShell.Faces:
        botFaces2.append(flaeche)
      for flaeche in cham_Shell.Faces:
        botFaces2.append(flaeche)
      '''
        
    else: # tip of screw without chamfer
      #FreeCAD.Console.PrintMessage("without chamfer: " + str(i) + "\n")

      commonbox = Part.makeBox(d+4.0*P, d+4.0*P, 3.0*P)
      commonbox.translate(FreeCAD.Vector(-(d+4.0*P)/2.0, -(d+4.0*P)/2.0,-(rotations)*P+bot_off))
      #commonbox.translate(FreeCAD.Vector(-(d+4.0*P)/2.0, -(d+4.0*P)/2.0,-(rotations+3)*P+bot_off))
      #Part.show(commonbox)
     
      BotShell = Part.Shell(botFaces)
      #Part.show(BotShell)
    
      BotShell = BotShell.common(commonbox)
      #BotShell = BotShell.cut(commonbox)
      bot_edges =[]
      bot_z =  1.0e-5 -(rotations)*P + bot_off
      
      for kante in BotShell.Edges:
         if (kante.Vertexes[0].Point.z<=bot_z) and (kante.Vertexes[1].Point.z<=bot_z):
            bot_edges.append(kante)
            # Part.show(kante)
      bot_wire = Part.Wire(Part.__sortEdges__(bot_edges))
         
      #botFaces2 = []
      #for flaeche in BotShell.Faces:
      #  botFaces2.append(flaeche)      
      
      bot_face = Part.Face(bot_wire)
      bot_face.reverse()
      #botFaces2.append(bot_face)
    
    '''

    BotShell2 = Part.Shell(botFaces2)
    # Part.show(BotShell2)
    
    TheShell2 = Part.Shell(TheFaces)
    
    # This gives a shell
    FaceList = []
    for flaeche in TheShell2.Faces:
      FaceList.append(flaeche)
    for flaeche in BotShell2.Faces:
      FaceList.append(flaeche)
    
    TheShell = Part.Shell(FaceList)
    # Part.show(TheShell)
    '''
    for flaeche in BotShell.Faces:
      TheFaces.append(flaeche)
    if withcham:
      for flaeche in cham_Shell.Faces:
        TheFaces.append(flaeche)
    else:  
      TheFaces.append(bot_face)
    TheShell = Part.Shell(TheFaces)
    
    #print self.Tuner, " ", TheShell.ShapeType, " ", TheShell.isValid(), " hrots: ", halfrots_int, " Shellpunkte: ", len(TheShell.Vertexes)

    return TheShell





  # if da<>None: make Shell for a nut else: make a screw tap
  def makeInnerThread_2(self, d, P, rotations, da, l):
    d = float(d)
    bot_off = 0.0 # nominal length
    
    if d>52.0:
      fuzzyValue = 5e-5
    else:
      fuzzyValue = 0.0

    H=P*math.cos(math.radians(30)) # Gewindetiefe H
    r=d/2.0
    
    
    helix = Part.makeHelix(P,P,d*self.Tuner/1000.0,0) # make just one turn, length is identical to pitch
    helix.translate(FreeCAD.Vector(0.0, 0.0,-P*9.0/16.0))
  
    extra_rad = P

    # points for inner thread profile
    ps0 = (r,0.0, 0.0)
    ps1 = (r-H*5.0/8.0,0.0, -P*5.0/16.0)
    ps2 = (r-H*5.0/8.0,0.0, -P*9.0/16.0 )
    ps3 =  (r, 0.0, -P*14.0/16.0)
    ps4 = (r+H*1/24.0,0.0, -P*31.0/32.0) # Center of Arc
    ps5 = (r,0.0, -P)
    
    
    ps6 = (r+extra_rad,0.0, -P)
    ps7 = (r+extra_rad,0.0, 0.0) 
     
    edge0 = Part.makeLine(ps0,ps1)
    edge1 = Part.makeLine(ps1,ps2)
    edge2 = Part.makeLine(ps2,ps3)
    edge3 = Part.Arc(FreeCAD.Vector(ps3),FreeCAD.Vector(ps4),FreeCAD.Vector(ps5)).toShape()
    edge4 = Part.makeLine(ps5,ps6)
    edge5 = Part.makeLine(ps6,ps7)
    edge6 = Part.makeLine(ps7,ps0)
     
    W0 = Part.Wire([edge0, edge1, edge2, edge3, edge4, edge5, edge6])
    # Part.show(W0, 'W0')
    
    makeSolid=True
    isFrenet=True
    pipe0 = Part.Wire(helix).makePipeShell([W0],makeSolid,isFrenet)
    #pipe1 = pipe0.copy()
  
    TheFaces = [] 
    TheFaces.append(pipe0.Faces[0])
    TheFaces.append(pipe0.Faces[1])
    TheFaces.append(pipe0.Faces[2])
    TheFaces.append(pipe0.Faces[3])
    #topHeliFaces = [pipe0.Faces[6], pipe0.Faces[8]]
    #innerHeliFaces = [pipe0.Faces[5]]
    #bottomFaces = [pipe0.Faces[4], pipe0.Faces[7]]
    
    TheShell = Part.Shell(TheFaces)
    #singleThreadShell = TheShell.copy()
    # print "Shellpoints: ", len(TheShell.Vertexes)
    if da is None:
      commonbox = Part.makeBox(d+4.0*P, d+4.0*P, 3.0*P)
      commonbox.translate(FreeCAD.Vector(-(d+4.0*P)/2.0, -(d+4.0*P)/2.0,-(3.0)*P))
      topShell = TheShell.common(commonbox)
      top_edges =[]
      top_z =  -1.0e-5 
      
      for kante in topShell.Edges:
         if (kante.Vertexes[0].Point.z>=top_z) and (kante.Vertexes[1].Point.z>=top_z):
            top_edges.append(kante)
            # Part.show(kante)
      top_wire = Part.Wire(Part.__sortEdges__(top_edges))
      top_face = Part.Face(top_wire)
      
      TheFaces = [top_face.Faces[0]]
      TheFaces.extend(topShell.Faces)
  
      for i in range(rotations-2):
         TheShell.translate(FreeCAD.Vector(0.0, 0.0,- P))
         for flaeche in TheShell.Faces:
           TheFaces.append(flaeche)
      
      #FreeCAD.Console.PrintMessage("Base-Shell: " + str(i) + "\n")
      # Make separate faces for the tip of the screw
      botFaces = []
      for i in range(rotations-2, rotations, 1):
         TheShell.translate(FreeCAD.Vector(0.0, 0.0,- P))
    
         for flaeche in TheShell.Faces:
           botFaces.append(flaeche)
      #FreeCAD.Console.PrintMessage("Bottom-Shell: " + str(i) + "\n")
      #FreeCAD.Console.PrintMessage("without chamfer: " + str(i) + "\n")
  
      commonbox = Part.makeBox(d+4.0*P, d+4.0*P, 3.0*P)
      commonbox.translate(FreeCAD.Vector(-(d+4.0*P)/2.0, -(d+4.0*P)/2.0,-(rotations)*P+bot_off))
      #commonbox.translate(FreeCAD.Vector(-(d+4.0*P)/2.0, -(d+4.0*P)/2.0,-(rotations+3)*P+bot_off))
      #Part.show(commonbox)
     
      BotShell = Part.Shell(botFaces)
      #Part.show(BotShell)
    
      BotShell = BotShell.common(commonbox)
      #BotShell = BotShell.cut(commonbox)
      bot_edges =[]
      bot_z =  1.0e-5 -(rotations)*P + bot_off
      
      for kante in BotShell.Edges:
         if (kante.Vertexes[0].Point.z<=bot_z) and (kante.Vertexes[1].Point.z<=bot_z):
            bot_edges.append(kante)
            # Part.show(kante)
      bot_wire = Part.Wire(Part.__sortEdges__(bot_edges))
         
      bot_face = Part.Face(bot_wire)
      bot_face.reverse()
    
      for flaeche in BotShell.Faces:
        TheFaces.append(flaeche)
      # if da is not None:
        # for flaeche in cham_Shell.Faces:
          # TheFaces.append(flaeche)
      # else:  
      TheFaces.append(bot_face)
      TheShell = Part.Shell(TheFaces)
      TheSolid = Part.Solid(TheShell)
      #print self.Tuner, " ", TheShell.ShapeType, " ", TheShell.isValid(), " rotations: ", rotations, " Shellpoints: ", len(TheShell.Vertexes)
      return TheSolid

    else:
      # Try to make the inner thread shell of a nut
      cham_i = 2* H * math.tan(math.radians(15.0)) # inner chamfer
      
      # points for chamfer: cut-Method
      pch0 =  (da/2.0 - 2*H, 0.0, +cham_i) # bottom chamfer
      pch1 =  (da/2.0, 0.0, 0.0)  #
      pch2 =  (da/2.0, 0.0, - 2.1*P)
      pch3 =  (da/2.0 - 2*H, 0.0, - 2.1*P) # 


      # pch2 =  (da/2.0, 0.0, l)
      # pch3 =  (da/2.0 - 2*H, 0.0, l - cham_i)
    
      edgech0 = Part.makeLine(pch0,pch1)
      edgech1 = Part.makeLine(pch1,pch2)
      edgech2 = Part.makeLine(pch2,pch3)
      edgech3 = Part.makeLine(pch3,pch0)
    
      Wch_wire = Part.Wire([edgech0, edgech1, edgech2, edgech3])
      bottom_Face =Part.Face(Wch_wire)
      #bottom_Solid = bottom_Face.revolve(Base.Vector(0.0,0.0,-(rotations-1)*P),Base.Vector(0.0,0.0,1.0),360)
      bottom_Solid = bottom_Face.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
      #Part.show(cham_Solid, 'cham_Solid')
      #Part.show(Wch_wire)
      bottomChamferFace = bottom_Solid.Faces[0]

      # points for chamfer: cut-Method
      pch0t =  (da/2.0 - 2*H, 0.0, l -cham_i) # top chamfer
      pch1t =  (da/2.0, 0.0, l)  #
      pch2t =  (da/2.0, 0.0, l + 4*P)
      pch3t =  (da/2.0 - 2*H, 0.0, l + 4*P) # 
    
      edgech0t = Part.makeLine(pch0t,pch1t)
      edgech1t = Part.makeLine(pch1t,pch2t)
      edgech2t = Part.makeLine(pch2t,pch3t)
      edgech3t = Part.makeLine(pch3t,pch0t)
    
      Wcht_wire = Part.Wire([edgech0t, edgech1t, edgech2t, edgech3t])
      top_Face =Part.Face(Wcht_wire)
      top_Solid = top_Face.revolve(Base.Vector(0.0,0.0,(rotations-1)*P),Base.Vector(0.0,0.0,1.0),360)
      #Part.show(top_Solid, 'top_Solid')
      #Part.show(Wch_wire)
      topChamferFace = top_Solid.Faces[0]
      
      threeThreadFaces = TheFaces.copy()
      for k in range(1):
        TheShell.translate(FreeCAD.Vector(0.0, 0.0, P))
        for threadFace in TheShell.Faces:
          threeThreadFaces.append(threadFace)
          
      chamferShell = Part.Shell(threeThreadFaces)
      #Part.show(chamferShell, 'chamferShell')
      #Part.show(bottomChamferFace, 'bottomChamferFace')

      
      bottomPart = chamferShell.cut(bottom_Solid)
      #Part.show(bottomPart, 'bottomPart')
      bottomFuse, bottomMap = bottomChamferFace.generalFuse([chamferShell], fuzzyValue)
      #print ('bottomMap: ', bottomMap)
      #chamFuse, chamMap = chamferShell.generalFuse([bottomChamferFace])
      #print ('chamMap: ', chamMap)
      #Part.show(bottomFuse, 'bottomFuse')
      #Part.show(bottomMap[0][0], 'bMap0')
      #Part.show(bottomMap[0][1], 'bMap1')
      innerThreadFaces = [bottomMap[0][1]]
      for face in bottomPart.Faces:
        innerThreadFaces.append(face)
      #bottomShell = Part.Shell(innerThreadFaces)
      #Part.show(bottomShell)
      bottomFaces =[]
      #TheShell.translate(FreeCAD.Vector(0.0, 0.0, P))
      for k in range(1, rotations -2):
        TheShell.translate(FreeCAD.Vector(0.0, 0.0, P))
        for threadFace in TheShell.Faces:
          innerThreadFaces.append(threadFace)
      #testShell = Part.Shell(innerThreadFaces)
      #Part.show(testShell, 'testShell')
      
      chamferShell.translate(FreeCAD.Vector(0.0, 0.0, (rotations - 1)*P))
      #Part.show(chamferShell, 'chamferShell')
      #Part.show(topChamferFace, 'topChamferFace')
      topPart = chamferShell.cut(top_Solid)
      #Part.show(topPart, 'topPart')
      for face in topPart.Faces:
        innerThreadFaces.append(face)
           
      topFuse, topMap = topChamferFace.generalFuse([chamferShell], fuzzyValue)
      #print ('topMap: ', topMap)
      #Part.show(topMap[0][0], 'tMap0')
      #Part.show(topMap[0][1], 'tMap1')
      #Part.show(topFuse, 'topFuse')
      innerThreadFaces.append(topMap[0][1])
      
      #topFaces = []
      #for face in topPart.Faces:
      #  topFaces.append(face)
      #topFaces.append(topMap[0][1])
      #testTopShell = Part.Shell(topFaces)
      #Part.show(testTopShell, 'testTopShell')

      threadShell = Part.Shell(innerThreadFaces)
      #Part.show(threadShell, 'threadShell')
      
      return threadShell






  # make the ISO 4032 Hex-nut
  # make the ISO 4033 Hex-nut
  def makeIso4032(self,SType ='ISO4032', ThreadType ='M6'):
    dia = self.getDia(ThreadType)
    #         P, tunIn, tunEx   
    #Ptun, self.tuning, tunEx = tuningTable[ThreadType]
    if SType == 'ISO4032':
      # P, c, damax,  dw,    e,     m,   mw,   s_nom
      P, c, da, dw, e, m, mw, s = iso4032def[ThreadType]
    if SType == 'ISO4033':
      # P, c, damax,  dw,    e,     m,   mw,   s_nom
      P, c, da, dw, e, m, mw, s = iso4033def[ThreadType]
    if SType == 'ISO4035':
      # P, c, damax,  dw,    e,     m,   mw,   s_nom
      P, c, da, dw, e, m, mw, s = iso4035def[ThreadType]
      
    residue, turns = math.modf(m/P)
    #halfturns = 2*int(turns)
      
    if residue > 0.0:
      turns += 1.0
    if SType == 'ISO4033' and ThreadType == '(M14)':
      turns -= 1.0
    if SType == 'ISO4035' and ThreadType == 'M56':
      turns -= 1.0

    
    sqrt2_ = 1.0/math.sqrt(2.0)
    cham = (e-s)*math.sin(math.radians(15)) # needed for chamfer at nut top
    H=P*math.cos(math.radians(30)) # Gewindetiefe H
    cham_i_delta = da/2.0 - (dia/2.0-H*5.0/8.0)
    cham_i = cham_i_delta * math.tan(math.radians(15.0))
  

    if self.rThread:
      Pnt0 = Base.Vector(da/2.0-2.0*cham_i_delta,0.0,m - 2.0*cham_i)
      Pnt7 = Base.Vector(da/2.0-2.0*cham_i_delta,0.0,0.0+ 2.0*cham_i)
    else:
      Pnt0 = Base.Vector(dia/2.0-H*5.0/8.0,0.0,m - cham_i)
      Pnt7 = Base.Vector(dia/2.0-H*5.0/8.0,0.0,0.0+ cham_i)

    Pnt1 = Base.Vector(da/2.0,0.0,m)
    Pnt2 = Base.Vector(s/2.0,0.0,m)
    Pnt3 = Base.Vector(s/math.sqrt(3.0),0.0,m-cham)
    Pnt4 = Base.Vector(s/math.sqrt(3.0),0.0,cham)
    Pnt5 = Base.Vector(s/2.0,0.0,0.0)
    Pnt6 = Base.Vector(da/2.0,0.0,0.0)
    
    edge0 = Part.makeLine(Pnt0,Pnt1)
    edge1 = Part.makeLine(Pnt1,Pnt2)
    edge2 = Part.makeLine(Pnt2,Pnt3)
    edge3 = Part.makeLine(Pnt3,Pnt4)
    edge4 = Part.makeLine(Pnt4,Pnt5)
    edge5 = Part.makeLine(Pnt5,Pnt6)
    edge6 = Part.makeLine(Pnt6,Pnt7)
    edge7 = Part.makeLine(Pnt7,Pnt0)
    
    # create cutting tool for hexagon head 
    # Parameters s, k, outer circle diameter =  e/2.0+10.0     
    extrude = self.makeHextool(s, m, s*2.0)

    aWire=Part.Wire([edge0,edge1,edge2,edge3,edge4,edge5,edge6,edge7])
    # Part.show(aWire)
    aFace =Part.Face(aWire)
    head = aFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360.0)
    #Part.show(head)
  
    # Part.show(extrude)
    nut = head.cut(extrude)
    #Part.show(nut, 'withoutTread')

    if self.rThread:
      #if (dia < 1.6)or (dia > 52.0):
      if (dia < 1.6)or (dia > 64.0):
        #if (dia < 3.0):
        threadCutter = self.makeInnerThread_2(dia, P, int(turns+1), None, m)
        threadCutter.translate(Base.Vector(0.0, 0.0,turns*P+0.5*P))
        #Part.show(threadCutter, 'threadCutter')
        nut = nut.cut(threadCutter)
        #chamFace = nut.Faces[0].cut(threadCutter)
        #Part.show(chamFace, 'chamFace0_')
      else:
        nutFaces = [nut.Faces[2]]
        for i in range(4,25):
          nutFaces.append(nut.Faces[i])
        # Part.show(Part.Shell(nutFaces), 'OuterNutshell')
  
        threadShell = self.makeInnerThread_2(dia, P, int(turns), da, m)
        #threadShell.translate(Base.Vector(0.0, 0.0,turns*P))
        # Part.show(threadShell, 'threadShell')
        nutFaces.extend(threadShell.Faces)
        
        nutShell = Part.Shell(nutFaces)
        nut = Part.Solid(nutShell)
        #Part.show(nutShell)
    
    return nut




  # EN 1661 Hexagon nuts with flange
  # chamfer at top of hexagon is wrong = more than 30°
  def makeEN1661(self, ThreadType ='M8'):
    dia = self.getDia(ThreadType)
    P, da, c, dc, dw, e, m, mw, r1, s = en1661def[ThreadType]

    residue, turns = math.modf(m/P)
    #halfturns = 2*int(turns)
      
    if residue > 0.0:
      turns += 1.0
    
    #FreeCAD.Console.PrintMessage("the nut with isoEN1661: " + str(c) + "\n")
    cham = s*(2.0/math.sqrt(3.0)-1.0)*math.sin(math.radians(25)) # needed for chamfer at head top

    sqrt2_ = 1.0/math.sqrt(2.0)
 
    # Flange is made with a radius of c
    beta = math.radians(25.0)
    tan_beta = math.tan(beta)
    
    # Calculation of Arc points of flange edge using dc and c
    arc1_x = dc/2.0 - c/2.0 + (c/2.0)*math.sin(beta)
    arc1_z = c/2.0 + (c/2.0)*math.cos(beta)
    
    hF = arc1_z + (arc1_x -s/2.0) * tan_beta  # height of flange at center
    
    #kmean = arc1_z + (arc1_x - s/math.sqrt(3.0)) * tan_beta + mw * 1.1 + cham
    #kmean = k * 0.95
    

    #Hex-Head Points
    #FreeCAD.Console.PrintMessage("the nut with kmean: " + str(m) + "\n")
    PntH0 = Base.Vector(da/2.0,0.0,m)
    PntH1 = Base.Vector(s/2.0,0.0,m)
    edgeH1 = Part.makeLine(PntH0,PntH1)

    hWire=Part.Wire([edgeH1])
    topShell = hWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(hWire)
    #Part.show(topShell)
    
    # create a cutter ring to generate the chamfer at the top of the hex
    chamHori = s/math.sqrt(3.0) - s/2.0
    PntC1 = Base.Vector(s/2.0-chamHori,0.0,m+m)
    PntC2 = Base.Vector(s/math.sqrt(3.0)+chamHori,0.0,m+m)
    PntC3 = Base.Vector(s/2.0-chamHori,0.0,m+cham)
    PntC4 = Base.Vector(s/math.sqrt(3.0)+chamHori,0.0,m-cham-cham)   #s/math.sqrt(3.0)
    edgeC1 = Part.makeLine(PntC3, PntC1)
    edgeC2 = Part.makeLine(PntC1, PntC2)
    edgeC3 = Part.makeLine(PntC2, PntC4)
    edgeC4 = Part.makeLine(PntC4, PntC3)
    cWire = Part.Wire([edgeC4, edgeC1, edgeC2, edgeC3])
    cFace = Part.Face(cWire)
    chamCut = cFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #Part.show(cWire)
    #Part.show(chamCut)


    # create hexagon
    mhex=Base.Matrix()
    mhex.rotateZ(math.radians(60.0))
    polygon = []
    vhex=Base.Vector(s/math.sqrt(3.0),0.0,m)
    for i in range(6):
       polygon.append(vhex)
       vhex = mhex.multiply(vhex)
    polygon.append(vhex)
    hexagon = Part.makePolygon(polygon)
    hexFace = Part.Face(hexagon)
    solidHex = hexFace.extrude(Base.Vector(0.0,0.0,c-m))
    #Part.show(solidHex)
    hexCham = solidHex.cut(chamCut)
    #Part.show(hexCham)
    
    topFaces = topShell.Faces
    
    topFaces.append(hexCham.Faces[1])
    topFaces.append(hexCham.Faces[2])
    topFaces.append(hexCham.Faces[8])
    topFaces.append(hexCham.Faces[13])
    topFaces.append(hexCham.Faces[14])
    topFaces.append(hexCham.Faces[12])
    topFaces.append(hexCham.Faces[6])
    
    hexFaces = [hexCham.Faces[5], hexCham.Faces[11], hexCham.Faces[10]]
    hexFaces.extend([hexCham.Faces[9], hexCham.Faces[3], hexCham.Faces[0]])
    hexShell = Part.Shell(hexFaces)


    H=P*math.cos(math.radians(30)) # Gewindetiefe H
    cham_i_delta = da/2.0 - (dia/2.0-H*5.0/8.0)
    cham_i = cham_i_delta * math.tan(math.radians(15.0))
  
    # Center of flange:
    Pnt0 = Base.Vector(0.0,0.0,hF)
    Pnt1 = Base.Vector(s/2.0,0.0,hF)
    
    # arc edge of flange:
    Pnt2 = Base.Vector(arc1_x,0.0,arc1_z)
    Pnt3 = Base.Vector(dc/2.0,0.0,c/2.0)
    Pnt4 = Base.Vector((dc-c)/2.0,0.0,0.0)
    Pnt5 = Base.Vector(da/2.0,0.0,0.0)     #start of fillet between flat and thread
    
    edge1 = Part.makeLine(Pnt0,Pnt1)
    edge2 = Part.makeLine(Pnt1,Pnt2)
    edge3 = Part.Arc(Pnt2,Pnt3,Pnt4).toShape()
    edge4 = Part.makeLine(Pnt4,Pnt5)

    # make a cutter for the hexShell
    PntHC1 = Base.Vector(0.0,0.0,arc1_z)
    PntHC2 = Base.Vector(0.0,0.0,0.0)
    
    edgeHC1 = Part.makeLine(Pnt2,PntHC1)
    edgeHC2 = Part.makeLine(PntHC1,PntHC2)
    edgeHC3 = Part.makeLine(PntHC2,Pnt0)

    HCWire = Part.Wire([edge2, edgeHC1, edgeHC2, edgeHC3, edge1])
    HCFace = Part.Face(HCWire)
    hex2Cut = HCFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    
    hexShell = hexShell.cut(hex2Cut)
    #Part.show(hexShell)
    
    topFaces.extend(hexShell.Faces)
    
    if self.rThread and (dia > 4.0):
      aWire=Part.Wire([edge2,edge3,edge4])
      boltIndex = 3
    
    else:
      if self.rThread:
        Pnt7 = Base.Vector(dia/2.1-H*5.0/8.0,0.0,m - cham_i)
        Pnt6 = Base.Vector(dia/2.1-H*5.0/8.0,0.0,0.0+ cham_i)
        
      else:
        Pnt7 = Base.Vector(dia/2.0-H*5.0/8.0,0.0,m - cham_i)
        Pnt6 = Base.Vector(dia/2.0-H*5.0/8.0,0.0,0.0+ cham_i)
      edge5 = Part.makeLine(Pnt5,Pnt6)
      edge6 = Part.makeLine(Pnt6,Pnt7)
      edge7 = Part.makeLine(Pnt7,PntH0)
      aWire=Part.Wire([edge2,edge3,edge4,edge5,edge6,edge7])
      boltIndex = 6


    #aFace =Part.Face(aWire)
    #Part.show(aWire)
    headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    #FreeCAD.Console.PrintMessage("der Kopf mit revolve: " + str(dia) + "\n")
    #Part.show(headShell)
    chamFace = headShell.Faces[0].cut(solidHex)
    #Part.show(chamFace)
    
    topFaces.append(chamFace.Faces[0])
    for i in range(1,boltIndex):
      topFaces.append(headShell.Faces[i])

    
    if self.rThread:
      if dia < 5.0:
        nutShell = Part.Shell(topFaces)
        nut = Part.Solid(nutShell)
        #Part.show(nut, 'unthreadedNut')
        threadCutter = self.makeInnerThread_2(dia, P, int(turns+1), None, m)
        threadCutter.translate(Base.Vector(0.0, 0.0,turns*P+0.5*P))
        #Part.show(threadCutter, 'threadCutter')
        nut = nut.cut(threadCutter)
        
      else:
        threadShell = self.makeInnerThread_2(dia, P, int(turns), da, m)
        #threadShell.translate(Base.Vector(0.0, 0.0,turns*P))
        #Part.show(threadShell)
        for tFace in threadShell.Faces:
          topFaces.append(tFace)
        headShell = Part.Shell(topFaces)
        nut = Part.Solid(headShell)
    else:
      nutShell = Part.Shell(topFaces)
      nut = Part.Solid(nutShell)

    return nut





  def makeScrewTap(self, ThreadType ='M6',l=25.0):
    dia = self.getDia(ThreadType)

    P, tunIn, tunEx  = tuningTable[ThreadType]

    residue, turns = math.modf((l)/P)
    turns += 1.0
    #FreeCAD.Console.PrintMessage("ScrewTap residue: " + str(residue) + " turns: " + str(turns) + "\n")
    

    if self.rThread:
      screwTap = self.makeInnerThread_2(dia, P, int(turns), None, 0.0)
      screwTap.translate(Base.Vector(0.0, 0.0,(1-residue)*P))
    else:
      H=P*math.cos(math.radians(30)) # Gewindetiefe H
      r=dia/2.0
    
      # points for inner thread profile
      Pnt0 = Base.Vector(0.0,0.0,(1-residue)*P) 
      Pnt1 = Base.Vector(r-H*5.0/8.0,0.0,(1-residue)*P) 
      Pnt2 = Base.Vector(r-H*5.0/8.0,0.0,-l) 
      Pnt3 = Base.Vector(0.0,0.0,-l) 
      
      edge1 = Part.makeLine(Pnt0,Pnt1)
      edge2 = Part.makeLine(Pnt1,Pnt2)
      edge3 = Part.makeLine(Pnt2,Pnt3)
      aWire=Part.Wire([edge1,edge2,edge3])
      headShell = aWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360.0)
      screwTap = Part.Solid(headShell)

    return screwTap









  def cutChamfer(self, dia_cC, P_cC, l_cC):
    cham_t = P_cC*math.sqrt(3.0)/2.0*17.0/24.0
    PntC0 = Base.Vector(0.0,0.0,-l_cC)
    PntC1 = Base.Vector(dia_cC/2.0-cham_t,0.0,-l_cC)
    PntC2 = Base.Vector(dia_cC/2.0+cham_t,0.0,-l_cC+cham_t+cham_t)
    PntC3 = Base.Vector(dia_cC/2.0+cham_t,0.0,-l_cC-P_cC-cham_t)
    PntC4 = Base.Vector(0.0,0.0,-l_cC-P_cC-cham_t)
    
    edgeC1 = Part.makeLine(PntC0,PntC1)
    edgeC2 = Part.makeLine(PntC1,PntC2)
    edgeC3 = Part.makeLine(PntC2,PntC3)
    edgeC4 = Part.makeLine(PntC3,PntC4)
    edgeC5 = Part.makeLine(PntC4,PntC0)
    CWire=Part.Wire([edgeC1,edgeC2,edgeC3,edgeC4,edgeC5])
    #Part.show(CWire)
    CFace =Part.Face(CWire)
    cyl = CFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    return cyl


  # cross recess type H
  def makeCross_H3(self, CrossType = '2', m = 6.9, h = 0.0):
    # m = diameter of cross at top of screw at reference level for penetration depth
    b, e_mean, g, f_mean, r, t1, alpha, beta = iso4757def[CrossType]
    
    rad265 = math.radians(26.5)
    rad28 = math.radians(28.0)
    tg = (m-g)/2.0/math.tan(rad265) # depth at radius of g
    t_tot = tg + g/2.0 * math.tan(rad28) # total depth
    #FreeCAD.Console.PrintMessage("Cross H3: " + str(b) + "\n")
    
    # print 'tg: ', tg,' t_tot: ', t_tot
    hm = m / 4.0
    hmc = m / 2.0
    rmax = m / 2.0 + hm*math.tan(rad265)
    
    Pnt0 = Base.Vector(0.0,0.0,hm)
    Pnt1 = Base.Vector(rmax,0.0,hm)
    Pnt3 = Base.Vector(0.0,0.0,0.0)
    Pnt4 = Base.Vector(g/2.0,0.0,-tg)
    Pnt5 = Base.Vector(0.0,0.0,-t_tot)
    
    edge1 = Part.makeLine(Pnt0,Pnt1)
    edge3 = Part.makeLine(Pnt1,Pnt4)
    edge4 = Part.makeLine(Pnt4,Pnt5)
    # FreeCAD.Console.PrintMessage("Edges made Pnt1: " + str(Pnt1) + "\n")
    
    aWire=Part.Wire([edge1,edge3,edge4])
    crossShell = aWire.revolve(Pnt3,Base.Vector(0.0,0.0,1.0),360)
    #FreeCAD.Console.PrintMessage("Peak-wire revolved: " + str(e_mean) + "\n")
    cross = Part.Solid(crossShell)
    #Part.show(cross)
 
    # the need to cut 4 corners out of the above shape.
    # Definition of corner
    # The angles 92 degrees and alpha are defined on a plane which has 
    # an angle of beta against our coordinate system.
    # The projected angles are needed for easier calculation!
    rad_alpha = math.radians(alpha/2.0)
    rad92 = math.radians(92.0/2.0)
    rad_beta = math.radians(beta)
    
    rad_alpha_p = math.atan(math.tan(rad_alpha)/math.cos(rad_beta))
    rad92_p = math.atan(math.tan(rad92)/math.cos(rad_beta))
    
    tb = tg + (g-b)/2.0 * math.tan(rad28) # depth at dimension b
    rbtop = b/2.0 + (hmc + tb)*math.tan(rad_beta) # radius of b-corner at hm
    rbtot = b/2.0 - (t_tot - tb)*math.tan(rad_beta) # radius of b-corner at t_tot
    
    dre = e_mean/2.0 / math.tan(rad_alpha_p)  # delta between corner b and corner e in x direction
    #FreeCAD.Console.PrintMessage("delta calculated: " + str(dre) + "\n")
 
    dx = m/2.0 * math.cos(rad92_p)
    dy = m/2.0 * math.sin(rad92_p)
 
    PntC0 = Base.Vector(rbtop,0.0,hmc)
    PntC1 = Base.Vector(rbtot,0.0,-t_tot)
    PntC2 = Base.Vector(rbtop+dre,+e_mean/2.0,hmc)
    PntC3 = Base.Vector(rbtot+dre,+e_mean/2.0,-t_tot)
    PntC4 = Base.Vector(rbtop+dre,-e_mean/2.0,hmc)
    PntC5 = Base.Vector(rbtot+dre,-e_mean/2.0,-t_tot)
    
    PntC6 = Base.Vector(rbtop+dre+dx,+e_mean/2.0+dy,hmc)
    #PntC7 = Base.Vector(rbtot+dre+dx,+e_mean/2.0+dy,-t_tot)
    PntC7 = Base.Vector(rbtot+dre+2.0*dx,+e_mean+2.0*dy,-t_tot)
    PntC8 = Base.Vector(rbtop+dre+dx,-e_mean/2.0-dy,hmc)
    #PntC9 = Base.Vector(rbtot+dre+dx,-e_mean/2.0-dy,-t_tot)
    PntC9 = Base.Vector(rbtot+dre+2.0*dx,-e_mean-2.0*dy,-t_tot)
 
    #wire_hm = Part.makePolygon([PntC0,PntC2,PntC6,PntC8,PntC4,PntC0])
    #face_hm =Part.Face(wire_hm)
    #Part.show(face_hm)
 
    wire_t_tot = Part.makePolygon([PntC1,PntC3,PntC7,PntC9,PntC5,PntC1])
    # Part.show(wire_t_tot)
    edgeC1 = Part.makeLine(PntC0,PntC1)
    #FreeCAD.Console.PrintMessage("edgeC1 mit PntC9" + str(PntC9) + "\n")
 
    makeSolid=True
    isFrenet=False
    corner = Part.Wire(edgeC1).makePipeShell([wire_t_tot],makeSolid,isFrenet)
    #Part.show(corner)
    
    rot_axis = Base.Vector(0.,0.,1.0)
    sin_res = math.sin(math.radians(90)/2.0)
    cos_res = math.cos(math.radians(90)/2.0)
    rot_axis.multiply(-sin_res) # Calculation of Quaternion-Elements
    #FreeCAD.Console.PrintMessage("Quaternion-Elements" + str(cos_res) + "\n")
 
    pl_rot = FreeCAD.Placement()
    pl_rot.Rotation = (rot_axis.x,rot_axis.y,rot_axis.z,cos_res) #Rotation-Quaternion 90° z-Axis
    
    crossShell = crossShell.cut(corner)
    # Part.show(crossShell)
    cutplace = corner.Placement
    
    cornerFaces = []
    cornerFaces.append(corner.Faces[0])
    cornerFaces.append(corner.Faces[1])
    cornerFaces.append(corner.Faces[3])
    cornerFaces.append(corner.Faces[4])
      
    cornerShell = Part.Shell(cornerFaces)
    cornerShell = cornerShell.common(cross)
    addPlace = cornerShell.Placement
    
    crossFaces = cornerShell.Faces
 
    for i in range(3):
      #cutplace.Rotation = pl_rot.Rotation.multiply(corner.Placement.Rotation)
      corner.Placement.Rotation = pl_rot.Rotation.multiply(corner.Placement.Rotation)
      crossShell = crossShell.cut(corner)
      #addPlace.Rotation = pl_rot.Rotation.multiply(cornerShell.Placement.Rotation)
      cornerShell.Placement.Rotation = pl_rot.Rotation.multiply(cornerShell.Placement.Rotation)
      for coFace in cornerShell.Faces:
        crossFaces.append(coFace)

    # Part.show(crossShell)
    for i in range(1,6):
      crossFaces.append(crossShell.Faces[i])

    crossShell0 = Part.Shell(crossFaces)
    
    crossFaces.append(crossShell.Faces[0])
    crossShell = Part.Shell(crossFaces)
    
    cross = Part.Solid(crossShell)
    

    #FreeCAD.Console.PrintMessage("Placement: " + str(pl_rot) + "\n")
       
    cross.Placement.Base = Base.Vector(0.0,0.0,h)
    crossShell0.Placement.Base = Base.Vector(0.0,0.0,h)
    #Part.show(crossShell0)
    #Part.show(cross)
    return cross, crossShell0



  # Allen recess cutting tool
  # Parameters used: s_mean, k, t_min, dk
  def makeAllen2(self, s_a = 3.0, t_a = 1.5, h_a = 2.0 ):
    # h_a  top height location of cutting tool 
    # s_a hex width
    # t_a dept of the allen
    # dk_a diameter not needed anymore

    e_cham = 2.0 * s_a / math.sqrt(3.0)
    depth = s_a / 3.0
    #FreeCAD.Console.PrintMessage("allen tool: " + str(s_a) + "\n")

    # Points for an arc at the peak of the cone
    rCone = e_cham/4.0
    hyp = (depth*math.sqrt(e_cham**2/depth**2+1.0)*rCone)/e_cham
    radAlpha = math.atan(e_cham/depth)
    radBeta = math.pi/2.0 - radAlpha
    zrConeCenter=hyp - depth -t_a
    xArc1=math.sin(radBeta)*rCone
    zArc1=zrConeCenter - math.cos(radBeta)*rCone
    xArc2=math.sin(radBeta/2.0)*rCone
    zArc2=zrConeCenter - math.cos(radBeta/2.0)*rCone
    zArc3 = zrConeCenter - rCone

    # The round part of the cutting tool, we need for the allen hex recess
    PntH1 = Base.Vector(0.0,0.0,-t_a-depth-depth)
    PntH2 = Base.Vector(e_cham,0.0,-t_a-depth-depth)
    PntH3 = Base.Vector(e_cham,0.0,-t_a+depth)
    PntH4 = Base.Vector(0.0,0.0,-t_a-depth)

    PntA1 = Base.Vector(xArc1,0.0,zArc1)
    PntA2 = Base.Vector(xArc2,0.0,zArc2)
    PntA3 = Base.Vector(0.0,0.0,zArc3)
    
    edgeA1 = Part.Arc(PntA1,PntA2,PntA3).toShape()
    
    edgeH1 = Part.makeLine(PntH1,PntH2)
    edgeH2 = Part.makeLine(PntH2,PntH3)
    edgeH3 = Part.makeLine(PntH3,PntA1)
    edgeH4 = Part.makeLine(PntA3,PntH1)

    hWire=Part.Wire([edgeH1,edgeH2,edgeH3,edgeA1,edgeH4])
    # Part.show(hWire)
    hFace =Part.Face(hWire)
    roundtool = hFace.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)

    # create hexagon
    mhex=Base.Matrix()
    mhex.rotateZ(math.radians(60.0))
    polygon = []
    vhex=Base.Vector(s_a/math.sqrt(3.0),0.0,1.0)
    for i in range(6):
       polygon.append(vhex)
       vhex = mhex.multiply(vhex)
    polygon.append(vhex)
    hexagon = Part.makePolygon(polygon)
    hexFace = Part.Face(hexagon)
    solidHex = hexFace.extrude(Base.Vector(0.0,0.0,-1.0-t_a-depth*1.1))
    allen = solidHex.cut(roundtool)
    # Part.show(allen)

    allenFaces = [allen.Faces[0]]
    for i in range(2,9):
      allenFaces.append(allen.Faces[i])
    allenShell = Part.Shell(allenFaces)
    solidHex.Placement.Base = Base.Vector(0.0,0.0,h_a)
    allenShell.Placement.Base = Base.Vector(0.0,0.0,h_a)
    return solidHex, allenShell  



  # ISO 10664 Hexalobular internal driving feature for bolts and screws
  def makeIso10664_3(self,RType ='T20',t_hl=3.0, h_hl = 0):
    # t_hl depth of the recess
    # h_hl top height location of Cutting tool
    A, B, Re = iso10664def[RType]
    sqrt_3 = math.sqrt(3.0)
    depth=A/4.0
    offSet = 1.0

    # Chamfer cutter for the hexalobular recess
    PntH1 = Base.Vector(0.0,0.0,-t_hl-depth-1.0)
    #PntH2 = Base.Vector(A/2.0*1.02,0.0,-t_hl-depth-1.0)
    #PntH3 = Base.Vector(A/2.0*1.02,0.0,-t_hl)
    PntH2 = Base.Vector(A,0.0,-t_hl-depth-1.0)
    PntH3 = Base.Vector(A,0.0,-t_hl+depth)
    PntH4 = Base.Vector(0.0,0.0,-t_hl-depth)
    
    # Points for an arc at the peak of the cone
    rCone = A/4.0
    hyp = (depth*math.sqrt(A**2/depth**2+1.0)*rCone)/A
    radAlpha = math.atan(A/depth)
    radBeta = math.pi/2.0 - radAlpha
    zrConeCenter=hyp - depth -t_hl
    xArc1=math.sin(radBeta)*rCone
    zArc1=zrConeCenter - math.cos(radBeta)*rCone
    xArc2=math.sin(radBeta/2.0)*rCone
    zArc2=zrConeCenter - math.cos(radBeta/2.0)*rCone
    zArc3 = zrConeCenter - rCone

    PntA1 = Base.Vector(xArc1,0.0,zArc1)
    PntA2 = Base.Vector(xArc2,0.0,zArc2)
    PntA3 = Base.Vector(0.0,0.0,zArc3)
    
    edgeA1 = Part.Arc(PntA1,PntA2,PntA3).toShape()
    
    edgeH1 = Part.makeLine(PntH1,PntH2)
    edgeH2 = Part.makeLine(PntH2,PntH3)
    edgeH3 = Part.makeLine(PntH3,PntA1)
    edgeH4 = Part.makeLine(PntA3,PntH1)

    hWire=Part.Wire([edgeH1,edgeH2,edgeH3,edgeA1])
    cutShell = hWire.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
    cutTool = Part.Solid(cutShell)
    
    
    Ri = -((B+sqrt_3*(2.*Re-A))*B+(A-4.*Re)*A)/(4.*B-2.*sqrt_3*A+(4.*sqrt_3-8.)*Re)
    #print '2nd  Ri last solution: ', Ri
    beta=math.acos(A/(4*Ri+4*Re)-(2*Re)/(4*Ri+4*Re))-math.pi/6
    #print 'beta: ', beta
    Rh=(sqrt_3*(A/2.0-Re))/2.0
    Re_x = A/2.0 - Re + Re*math.sin(beta)
    Re_y = Re*math.cos(beta)
    Ri_y = B/4.0
    Ri_x = sqrt_3*B/4.0
    
    mhex=Base.Matrix()
    mhex.rotateZ(math.radians(60.0))
    hexlobWireList = []
    
    PntRe0=Base.Vector(Re_x,-Re_y,offSet)
    PntRe1=Base.Vector(A/2.0,0.0,offSet)
    PntRe2=Base.Vector(Re_x,Re_y,offSet)
    edge0 = Part.Arc(PntRe0,PntRe1,PntRe2).toShape()
    #Part.show(edge0)
    hexlobWireList.append(edge0)
    
    PntRi = Base.Vector(Ri_x,Ri_y,offSet)
    PntRi2 = mhex.multiply(PntRe0)
    edge1 = Part.Arc(PntRe2,PntRi,PntRi2).toShape()
    #Part.show(edge1)
    hexlobWireList.append(edge1)
  
    for i in range(5):
       PntRe1 = mhex.multiply(PntRe1)
       PntRe2 = mhex.multiply(PntRe2)
       edge0 = Part.Arc(PntRi2,PntRe1,PntRe2).toShape()
       hexlobWireList.append(edge0)
       PntRi = mhex.multiply(PntRi)
       PntRi2 = mhex.multiply(PntRi2)
       if i == 5:
          edge1 = Part.Arc(PntRe2,PntRi,PntRe0).toShape()
       else:
          edge1 = Part.Arc(PntRe2,PntRi,PntRi2).toShape()
       hexlobWireList.append(edge1)
    hexlobWire=Part.Wire(hexlobWireList)
    #Part.show(hWire)
  
    face=Part.Face(hexlobWire)
    
    # Extrude in z to create the cutting tool for the screw-head-face
    Helo=face.extrude(Base.Vector(0.0,0.0,-t_hl-depth-offSet))
    # Make the recess-shell for the screw-head-shell
    
    hexlob = Helo.cut(cutTool)
    #Part.show(hexlob)
    hexlobFaces = [hexlob.Faces[0]]
    for i in range(2,15):
      hexlobFaces.append(hexlob.Faces[i])

    hexlobShell = Part.Shell(hexlobFaces)
      
    hexlobShell.Placement.Base = Base.Vector(0.0,0.0,h_hl)
    Helo.Placement.Base = Base.Vector(0.0,0.0,h_hl)

    return Helo, hexlobShell

  def setThreadType(self, TType = 'simple'):
    self.simpThread = False
    self.symThread = False
    self.rThread = False
    if TType == 'simple':
      self.simpThread = True
    if TType == 'symbol':
      self.symThread = True
    if TType == 'real':
      self.rThread = True

  def setTuner(self, myTuner = 511):
    self.Tuner = myTuner

  def getDia(self,ThreadType):
    if '(' in ThreadType:
      threadString = ThreadType.lstrip('(M')
      if 'x' in threadString:
        dia = float(threadString.split('x')[0])
      else:
        dia = float(threadString.rstrip(')'))
    else:
      threadString = ThreadType.lstrip('M')
      if 'x' in threadString:
        dia = float(threadString.split('x')[0])
      else:
        dia=float(threadString.lstrip('M'))
    return dia

    
class ScrewMacro(object):
  d = QtGui.QWidget()
  d.ui = Ui_ScrewMaker()
  d.ui.setupUi(d)
  if __name__ == '__main__':
    d.show()


def main():
  o = ScrewMacro()

if __name__ == '__main__':
  main()

