Example #1
0
def dslope_array(loop, resolution=0.001):
    length = loop.length
    pnt_amount = round(length / resolution)
    sarray = []
    dsarray = []
    for i in range(pnt_amount):
        distance = i * resolution
        pt = loop.interpolate(distance)
        p = (pt.x, pt.y)
        if i != 0:
            slope = abs(angle(p, oldp))
            sarray.append((distance, slope * -0.01))
        oldp = p
    #    derivative = LineString(sarray)
    for i, p in enumerate(sarray):
        distance = p[0]
        if i != 0:
            slope = find_slope(p, oldp)
            if abs(slope) > 10:
                print(distance)
            dsarray.append((distance, slope * -0.1))
        oldp = p
    dderivative = LineString(dsarray)
    utils.shapelyToCurve('doublederivative', dderivative, 0.0)
    return sarray
Example #2
0
def slope_array(loop):
    simple.remove_multiple("-")
    coords = list(loop.coords)
    #    pnt_amount = round(length / resolution)
    sarray = []
    dsarray = []
    for i, p in enumerate(coords):
        distance = loop.project(Point(p))
        if i != 0:
            slope = find_slope(p, oldp)
            sarray.append((distance, slope * -0.001))
        oldp = p
    for i, p in enumerate(sarray):
        distance = p[0]
        if i != 0:
            slope = find_slope(p, oldp)
            if abs(slope) > 10:
                print(distance)
            dsarray.append((distance, slope * -0.00001))
        oldp = p
    derivative = LineString(sarray)
    dderivative = LineString(dsarray)
    utils.shapelyToCurve('-derivative', derivative, 0.0)
    utils.shapelyToCurve('-doublederivative', dderivative, 0.0)
    return sarray
Example #3
0
def rack(mm_per_tooth=0.01,
         number_of_teeth=11,
         height=0.012,
         pressure_angle=0.3488,
         backlash=0.0,
         hole_diameter=0.003175,
         tooth_per_hole=4):
    simple.deselect()
    pi = math.pi
    mm_per_tooth *= 1000
    a = mm_per_tooth / pi  # addendum
    t = (a * math.sin(pressure_angle)
         )  # tooth side is tilted so top/bottom corners move this amount
    a /= 1000
    mm_per_tooth /= 1000
    t /= 1000

    shapely_gear = Polygon([(-mm_per_tooth * 2 / 4 * 1.001, a - height),
                            (-mm_per_tooth * 2 / 4 * 1.001 - backlash, -a),
                            (-mm_per_tooth * 1 / 4 + backlash - t, -a),
                            (-mm_per_tooth * 1 / 4 + backlash + t, a),
                            (mm_per_tooth * 1 / 4 - backlash - t, a),
                            (mm_per_tooth * 1 / 4 - backlash + t, -a),
                            (mm_per_tooth * 2 / 4 * 1.001 + backlash, -a),
                            (mm_per_tooth * 2 / 4 * 1.001, a - height)])

    utils.shapelyToCurve('_tooth', shapely_gear, 0.0)
    i = number_of_teeth
    while i > 1:
        simple.duplicate(x=mm_per_tooth)
        i -= 1
    simple.union('_tooth')
    simple.move(y=height / 2)
    if hole_diameter > 0:
        bpy.ops.curve.simple(align='WORLD',
                             location=(mm_per_tooth / 2, 0, 0),
                             rotation=(0, 0, 0),
                             Simple_Type='Circle',
                             Simple_radius=hole_diameter / 2,
                             shape='3D',
                             use_cyclic_u=True,
                             edit_mode=False)
        simple.active_name('_hole')
        distance = (number_of_teeth - 1) * mm_per_tooth
        while distance > tooth_per_hole * mm_per_tooth:
            simple.duplicate(x=tooth_per_hole * mm_per_tooth)
            distance -= tooth_per_hole * mm_per_tooth
        simple.difference('_', '_tooth')

    name = 'rack-' + str(round(mm_per_tooth * 1000, 1))
    name += '-PA-' + str(round(math.degrees(pressure_angle), 1))
    simple.active_name(name)
Example #4
0
def open_curve(line, thick, diameter, tolerance, amount=0, stem=1, twist=False, t_neck=0.5, t_thick=0.01,
               twist_amount=1, which='MF', twist_keep=False):
    # puts puzzle connectors at the end of an open curve
    # optionally puts twist lock connectors at the puzzle connection
    # optionally puts twist lock connectors along the open curve
    # line = shapely linestring
    # thick = thickness of the bar
    # diameter = diameter of the tool for joint creation
    # tolerance = Tolerance in the joint
    # amount = amount of fingers in the joint 0 means auto generate
    # stem = amount of radius the stem or neck of the joint will have
    # twist = twist lock addition
    # twist_amount = twist amount distributed on the curve not counting the joint twist locks
    # tneck = percentage the twist neck will have compared to thick
    # tthick = thicknest of the twist material
    # Which M,F, MF, MM, FF

    coords = list(line.coords)

    start_angle = joinery.angle(coords[0], coords[1]) + math.pi/2
    end_angle = joinery.angle(coords[-1], coords[-2]) + math.pi/2
    p_start = coords[0]
    p_end = coords[-1]

    print('start angle', start_angle)
    print('end angle', end_angle)

    bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle',
                         Simple_width=thick*2, Simple_length=thick * 2, use_cyclic_u=True, edit_mode=False, shape='3D')
    simple.active_name('tmprect')
    simple.move(y=thick)
    simple.duplicate()
    simple.rotate(start_angle)
    simple.move(x=p_start[0], y=p_start[1])
    simple.make_active('tmprect')
    simple.rotate(end_angle)
    simple.move(x=p_end[0], y=p_end[1])
    simple.union('tmprect')
    dilated = line.buffer(thick/2)  # expand shapely object to thickness
    utils.shapelyToCurve('tmp_curve', dilated, 0.0)
    simple.difference('tmp', 'tmp_curve')   # truncate curve at both ends with the rectangles

    fingers(diameter, tolerance, amount, stem=stem)
    simple.make_active('fingers')
    simple.rotate(end_angle)
    simple.move(x=p_end[0], y=p_end[1])
    simple.active_name('tmp_fingers')
    simple.union('tmp_')
    simple.active_name('tmp_curve')
    twistm('tmp_curve', thick, diameter, tolerance, twist, t_neck, t_thick, end_angle, x=p_end[0], y=p_end[1],
           twist_keep=twist_keep)

    twistf('receptacle', thick, diameter, tolerance, twist, t_neck, t_thick, twist_keep=twist_keep)
    simple.rename('receptacle', 'tmp')
    simple.rotate(start_angle+math.pi)
    simple.move(x=p_start[0], y=p_start[1])
    simple.difference('tmp', 'tmp_curve')
    if twist_keep:
        simple.make_active('twist_keep_f')
        simple.rotate(start_angle + math.pi)
        simple.move(x=p_start[0], y=p_start[1])

    if twist_amount > 0 and twist:
        twist_start = line.length / (twist_amount+1)
        joinery.distributed_interlock(line, line.length, thick, t_thick, tolerance, twist_amount,
                                      tangent=math.pi/2, fixed_angle=0, start=twist_start, end=twist_start,
                                      closed=False, type='TWIST', twist_percentage=t_neck)
        if twist_keep:
            simple.duplicate()
            simple.active_name('twist_keep')
            simple.join_multiple('twist_keep')
            simple.make_active('interlock')

        simple.active_name('tmp_twist')
        simple.difference('tmp', 'tmp_curve')
        simple.active_name('puzzle_curve')
Example #5
0
	def execute(self, context):
		o1 = bpy.context.active_object
		shapes = utils.curveToShapely(o1)
		negative_overcuts = []
		positive_overcuts = []
		# count all the corners including inside and out
		cornerCnt = 0
		# a list of tuples for defining the inside corner 
		# tuple is: (pos, v1, v2, angle, allCorners list index)
		insideCorners = []
		diameter = self.diameter * 1.001
		radius = diameter / 2
		anglethreshold = math.pi - self.threshold
		centerv = Vector((0,0))
		extendedv = Vector((0,0))
		pos = Vector((0,0))
		sign = -1 if self.do_invert else 1
		isTBone = self.style == 'TBONE'
		# indexes in insideCorner tuple
		POS, V1, V2, A, IDX = range(5)
		
		def addOvercut(a):
			nonlocal pos, centerv, radius, extendedv, sign, negative_overcuts, positive_overcuts
			# move the overcut shape center position 1 radius in direction v
			pos -= centerv * radius
			if abs(a) < math.pi/2:
				shape = utils.Circle(radius, 64)
				shape = shapely.affinity.translate(shape, pos.x, pos.y)
			else: # elongate overcut circle to make sure tool bit can fit into slot
				p1 = pos + (extendedv * radius)
				l = shapely.geometry.LineString((pos, p1))
				shape = l.buffer(radius, resolution = 64)
			
			if sign>0:
				negative_overcuts.append(shape)
			else:	
				positive_overcuts.append(shape)


		def setOtherEdge(v1, v2, a):
			nonlocal centerv, extendedv
			if self.otherEdge:
				centerv = v1
				extendedv = v2
			else:
				centerv = -v2
				extendedv = -v1
			addOvercut(a)
				
		def setCenterOffset(a):
			nonlocal centerv, extendedv, sign
			centerv = v1 - v2
			centerv.normalize()
			extendedv = centerv * math.tan(a/2) * -sign
			addOvercut(a)
			
			
		def getCorner(idx, offset):
			nonlocal insideCorners
			idx += offset
			if idx >= len(insideCorners):
				idx -= len(insideCorners)
			return insideCorners[idx]
			
		def getCornerDelta(curidx, nextidx):
			nonlocal cornerCnt
			delta = nextidx - curidx
			if delta < 0:
				delta += cornerCnt
			return delta
			

		for s in shapes:
			s = shapely.geometry.polygon.orient(s,1)
			loops = [s.boundary] if s.boundary.type == 'LineString'	else s.boundary
			outercurve = self.do_outer or len(loops)==1
			for ci,c in enumerate(loops):
				if ci>0 or outercurve:
					if isTBone:
						cornerCnt = 0
						insideCorners = []
						
					for i,co in enumerate(c.coords):
						i1 = i-1
						if i1==-1:
							i1 = -2
						i2 = i+1
						if i2 == len(c.coords):
							i2 = 0
							
						v1 = Vector(co).xy - Vector(c.coords[i1]).xy
						v2 = Vector(c.coords[i2]).xy - Vector(co).xy

						if not v1.length==0 and not v2.length == 0:
							a = v1.angle_signed(v2)
							insideCornerFound = False
							outsideCornerFound = False
							if a<-anglethreshold:
								if sign<0:
									insideCornerFound = True
								else:
									outsideCornerFound = True
							elif a>anglethreshold:
								if sign>0:
									insideCornerFound = True
								else:
									outsideCornerFound = True
									
							
							if insideCornerFound:
								# an inside corner with an overcut has been found
								# which means a new side has been found
								pos = Vector((co[0],co[1]))
								v1.normalize()
								v2.normalize()
								# figure out which direction vector to use
								# v is the main direction vector to move the overcut shape along
								# ev is the direction vector used to elongate the overcut shape
								if self.style != 'DOGBONE':
									# t-bone and opposite edge styles get treated nearly the same
									if isTBone:
										cornerCnt += 1
										#insideCorner tuplet: (pos, v1, v2, angle, corner index)
										insideCorners.append((pos, v1, v2, a, cornerCnt-1))
										#processing of corners for T-Bone are done after all points are processed
										continue
									
									setOtherEdge(v1, v2, a)
										
								else: # DOGBONE style
									setCenterOffset(a)
									
								
							elif isTBone and outsideCornerFound:
								# add an outside corner to the list
								cornerCnt += 1	

					# check if t-bone processing required
					# if no inside corners then nothing to do
					if isTBone and len(insideCorners) > 0:
						#print(cornerCnt, len(insideCorners))
						# process all of the inside corners
						for i, corner in enumerate(insideCorners):
							pos, v1, v2, a, idx = corner
							# figure out which side of the corner to do overcut
							# if prev corner is outside corner
							# calc index distance between current corner and prev
							prevCorner = getCorner(i, -1)
							#print('first:', i, idx, prevCorner[IDX])
							if getCornerDelta(prevCorner[IDX], idx) == 1:
								# make sure there is an outside corner
								#print(getCornerDelta(getCorner(i, -2)[IDX], idx))
								if getCornerDelta(getCorner(i, -2)[IDX], idx) > 2:
									setOtherEdge(v1, v2, a)
									#print('first won')
									continue
									
							nextCorner = getCorner(i, 1)
							#print('second:', i, idx, nextCorner[IDX])
							if getCornerDelta(idx, nextCorner[IDX]) == 1:
								# make sure there is an outside corner 
								#print(getCornerDelta(idx, getCorner(i, 2)[IDX]))
								if getCornerDelta(idx, getCorner(i, 2)[IDX]) > 2:
									#print('second won')
									setOtherEdge(-v2, -v1, a)
									continue
							
							#print('third')
							if getCornerDelta(prevCorner[IDX], idx) == 3:
								# check if they share the same edge
								a1 = v1.angle_signed(prevCorner[V2])*180.0/math.pi
								#print('third won', a1)
								if a1 < -135 or a1 > 135:
									setOtherEdge(-v2, -v1, a)
									continue
							
							#print('fourth')
							if getCornerDelta(idx, nextCorner[IDX]) == 3:
								# check if they share the same edge
								a1 = v2.angle_signed(nextCorner[V1])*180.0/math.pi
								#print('fourth won', a1)
								if a1 < -135 or a1 > 135:
									setOtherEdge(v1, v2, a)
									continue
							
							#print('***No Win***')
							# the default if no other rules pass	
							setCenterOffset(a)
								
							
						
						
		negative_overcuts = shapely.ops.unary_union(negative_overcuts)
		positive_overcuts = shapely.ops.unary_union(positive_overcuts)
		fs = shapely.ops.unary_union(shapes)
		fs = fs.union(positive_overcuts)
		fs = fs.difference(negative_overcuts)
		o=utils.shapelyToCurve(o1.name+'_overcuts',fs,o1.location.z)
		return {'FINISHED'}	
Example #6
0
	def execute(self, context):
		#utils.silhoueteOffset(context,-self.diameter)
		o1=bpy.context.active_object
		shapes=utils.curveToShapely(o1)
		negative_overcuts=[]
		positive_overcuts=[]
		diameter = self.diameter*1.001
		for s in shapes:
				s=shapely.geometry.polygon.orient(s,1)
				if s.boundary.type == 'LineString':
					loops = [s.boundary]#s=shapely.geometry.asMultiLineString(s)
				else:	
					loops = s.boundary
				
				for ci,c in enumerate(loops):
					if ci>0 or self.do_outer:
						#c=s.boundary
						for i,co in enumerate(c.coords):
							i1=i-1
							if i1==-1:
								i1=-2
							i2=i+1
							if i2 == len(c.coords):
								i2=0
								
							v1 = Vector(co) - Vector(c.coords[i1])
							v1 = v1.xy#Vector((v1.x,v1.y,0))
							v2 = Vector(c.coords[i2]) - Vector(co)
							v2 = v2.xy#v2 = Vector((v2.x,v2.y,0))
							if not v1.length==0 and not v2.length == 0:
								a=v1.angle_signed(v2)
								sign=1
								#if ci==0:
								#	sign=-1
								#else:
								#	sign=1
								
								if self.invert:# and ci>0:
									sign*=-1
								if (sign<0 and a<-self.threshold) or (sign>0 and a>self.threshold):
									p=Vector((co[0],co[1]))
									v1.normalize()
									v2.normalize()
									v=v1-v2
									v.normalize()
									p=p-v*diameter/2
									if abs(a)<math.pi/2:
										shape=utils.Circle(diameter/2,64)
										shape= shapely.affinity.translate(shape,p.x,p.y)
									else:
										l=math.tan(a/2)*diameter/2
										p1=p-sign*v*l
										l=shapely.geometry.LineString((p,p1))
										shape=l.buffer(diameter/2, resolution = 64)
									
									if sign>0:
										negative_overcuts.append(shape)
									else:	
										positive_overcuts.append(shape)
									
								print(a)
					
							
				#for c in s.boundary:
		negative_overcuts = shapely.ops.unary_union(negative_overcuts)
		positive_overcuts = shapely.ops.unary_union(positive_overcuts)
		#shapes.extend(overcuts)
		fs=shapely.ops.unary_union(shapes)
		fs = fs.union(positive_overcuts)
		fs = fs.difference(negative_overcuts)
		o=utils.shapelyToCurve(o1.name+'_overcuts',fs,o1.location.z)
		#o=utils.shapelyToCurve('overcuts',overcuts,0)
		return {'FINISHED'}	
Example #7
0
    def execute(self, context):
        #utils.silhoueteOffset(context,-self.diameter)
        o1 = bpy.context.active_object
        shapes = utils.curveToShapely(o1)
        negative_overcuts = []
        positive_overcuts = []
        diameter = self.diameter * 1.001
        for s in shapes:
            s = shapely.geometry.polygon.orient(s, 1)
            if s.boundary.type == 'LineString':
                loops = [s.boundary]  #s=shapely.geometry.asMultiLineString(s)
            else:
                loops = s.boundary

            for ci, c in enumerate(loops):
                if ci > 0 or self.do_outer:
                    #c=s.boundary
                    for i, co in enumerate(c.coords):
                        i1 = i - 1
                        if i1 == -1:
                            i1 = -2
                        i2 = i + 1
                        if i2 == len(c.coords):
                            i2 = 0

                        v1 = Vector(co) - Vector(c.coords[i1])
                        v1 = v1.xy  #Vector((v1.x,v1.y,0))
                        v2 = Vector(c.coords[i2]) - Vector(co)
                        v2 = v2.xy  #v2 = Vector((v2.x,v2.y,0))
                        if not v1.length == 0 and not v2.length == 0:
                            a = v1.angle_signed(v2)
                            sign = 1
                            #if ci==0:
                            #	sign=-1
                            #else:
                            #	sign=1

                            if self.invert:  # and ci>0:
                                sign *= -1
                            if (sign < 0 and a < -self.threshold) or (
                                    sign > 0 and a > self.threshold):
                                p = Vector((co[0], co[1]))
                                v1.normalize()
                                v2.normalize()
                                v = v1 - v2
                                v.normalize()
                                p = p - v * diameter / 2
                                if abs(a) < math.pi / 2:
                                    shape = utils.Circle(diameter / 2, 64)
                                    shape = shapely.affinity.translate(
                                        shape, p.x, p.y)
                                else:
                                    l = math.tan(a / 2) * diameter / 2
                                    p1 = p - sign * v * l
                                    l = shapely.geometry.LineString((p, p1))
                                    shape = l.buffer(diameter / 2,
                                                     resolution=64)

                                if sign > 0:
                                    negative_overcuts.append(shape)
                                else:
                                    positive_overcuts.append(shape)

                            print(a)

            #for c in s.boundary:
        negative_overcuts = shapely.ops.unary_union(negative_overcuts)
        positive_overcuts = shapely.ops.unary_union(positive_overcuts)
        #shapes.extend(overcuts)
        fs = shapely.ops.unary_union(shapes)
        fs = fs.union(positive_overcuts)
        fs = fs.difference(negative_overcuts)
        o = utils.shapelyToCurve(o1.name + '_overcuts', fs, o1.location.z)
        #o=utils.shapelyToCurve('overcuts',overcuts,0)
        return {'FINISHED'}
Example #8
0
    def execute(self, context):
        o1 = bpy.context.active_object
        shapes = utils.curveToShapely(o1)
        negative_overcuts = []
        positive_overcuts = []
        # count all the corners including inside and out
        cornerCnt = 0
        # a list of tuples for defining the inside corner
        # tuple is: (pos, v1, v2, angle, allCorners list index)
        insideCorners = []
        diameter = self.diameter * 1.001
        radius = diameter / 2
        anglethreshold = math.pi - self.threshold
        centerv = mathutils.Vector((0, 0))
        extendedv = mathutils.Vector((0, 0))
        pos = mathutils.Vector((0, 0))
        sign = -1 if self.do_invert else 1
        isTBone = self.style == 'TBONE'
        # indexes in insideCorner tuple
        POS, V1, V2, A, IDX = range(5)

        def addOvercut(a):
            nonlocal pos, centerv, radius, extendedv, sign, negative_overcuts, positive_overcuts
            # move the overcut shape center position 1 radius in direction v
            pos -= centerv * radius
            if abs(a) < math.pi / 2:
                shape = utils.Circle(radius, 64)
                shape = shapely.affinity.translate(shape, pos.x, pos.y)
            else:  # elongate overcut circle to make sure tool bit can fit into slot
                p1 = pos + (extendedv * radius)
                l = shapely.geometry.LineString((pos, p1))
                shape = l.buffer(radius, resolution=64)

            if sign > 0:
                negative_overcuts.append(shape)
            else:
                positive_overcuts.append(shape)

        def setOtherEdge(v1, v2, a):
            nonlocal centerv, extendedv
            if self.otherEdge:
                centerv = v1
                extendedv = v2
            else:
                centerv = -v2
                extendedv = -v1
            addOvercut(a)

        def setCenterOffset(a):
            nonlocal centerv, extendedv, sign
            centerv = v1 - v2
            centerv.normalize()
            extendedv = centerv * math.tan(a / 2) * -sign
            addOvercut(a)

        def getCorner(idx, offset):
            nonlocal insideCorners
            idx += offset
            if idx >= len(insideCorners):
                idx -= len(insideCorners)
            return insideCorners[idx]

        def getCornerDelta(curidx, nextidx):
            nonlocal cornerCnt
            delta = nextidx - curidx
            if delta < 0:
                delta += cornerCnt
            return delta

        for s in shapes:
            s = shapely.geometry.polygon.orient(s, 1)
            loops = [s.boundary
                     ] if s.boundary.type == 'LineString' else s.boundary
            outercurve = self.do_outer or len(loops) == 1
            for ci, c in enumerate(loops):
                if ci > 0 or outercurve:
                    if isTBone:
                        cornerCnt = 0
                        insideCorners = []

                    for i, co in enumerate(c.coords):
                        i1 = i - 1
                        if i1 == -1:
                            i1 = -2
                        i2 = i + 1
                        if i2 == len(c.coords):
                            i2 = 0

                        v1 = mathutils.Vector(co).xy - mathutils.Vector(
                            c.coords[i1]).xy
                        v2 = mathutils.Vector(
                            c.coords[i2]).xy - mathutils.Vector(co).xy

                        if not v1.length == 0 and not v2.length == 0:
                            a = v1.angle_signed(v2)
                            insideCornerFound = False
                            outsideCornerFound = False
                            if a < -anglethreshold:
                                if sign < 0:
                                    insideCornerFound = True
                                else:
                                    outsideCornerFound = True
                            elif a > anglethreshold:
                                if sign > 0:
                                    insideCornerFound = True
                                else:
                                    outsideCornerFound = True

                            if insideCornerFound:
                                # an inside corner with an overcut has been found
                                # which means a new side has been found
                                pos = mathutils.Vector((co[0], co[1]))
                                v1.normalize()
                                v2.normalize()
                                # figure out which direction vector to use
                                # v is the main direction vector to move the overcut shape along
                                # ev is the direction vector used to elongate the overcut shape
                                if self.style != 'DOGBONE':
                                    # t-bone and opposite edge styles get treated nearly the same
                                    if isTBone:
                                        cornerCnt += 1
                                        # insideCorner tuplet: (pos, v1, v2, angle, corner index)
                                        insideCorners.append(
                                            (pos, v1, v2, a, cornerCnt - 1))
                                        # processing of corners for T-Bone are done after all points are processed
                                        continue

                                    setOtherEdge(v1, v2, a)

                                else:  # DOGBONE style
                                    setCenterOffset(a)

                            elif isTBone and outsideCornerFound:
                                # add an outside corner to the list
                                cornerCnt += 1

                    # check if t-bone processing required
                    # if no inside corners then nothing to do
                    if isTBone and len(insideCorners) > 0:
                        # print(cornerCnt, len(insideCorners))
                        # process all of the inside corners
                        for i, corner in enumerate(insideCorners):
                            pos, v1, v2, a, idx = corner
                            # figure out which side of the corner to do overcut
                            # if prev corner is outside corner
                            # calc index distance between current corner and prev
                            prevCorner = getCorner(i, -1)
                            # print('first:', i, idx, prevCorner[IDX])
                            if getCornerDelta(prevCorner[IDX], idx) == 1:
                                # make sure there is an outside corner
                                # print(getCornerDelta(getCorner(i, -2)[IDX], idx))
                                if getCornerDelta(getCorner(i, -2)[IDX],
                                                  idx) > 2:
                                    setOtherEdge(v1, v2, a)
                                    # print('first won')
                                    continue

                            nextCorner = getCorner(i, 1)
                            # print('second:', i, idx, nextCorner[IDX])
                            if getCornerDelta(idx, nextCorner[IDX]) == 1:
                                # make sure there is an outside corner
                                # print(getCornerDelta(idx, getCorner(i, 2)[IDX]))
                                if getCornerDelta(idx,
                                                  getCorner(i, 2)[IDX]) > 2:
                                    # print('second won')
                                    setOtherEdge(-v2, -v1, a)
                                    continue

                            # print('third')
                            if getCornerDelta(prevCorner[IDX], idx) == 3:
                                # check if they share the same edge
                                a1 = v1.angle_signed(
                                    prevCorner[V2]) * 180.0 / math.pi
                                # print('third won', a1)
                                if a1 < -135 or a1 > 135:
                                    setOtherEdge(-v2, -v1, a)
                                    continue

                            # print('fourth')
                            if getCornerDelta(idx, nextCorner[IDX]) == 3:
                                # check if they share the same edge
                                a1 = v2.angle_signed(
                                    nextCorner[V1]) * 180.0 / math.pi
                                # print('fourth won', a1)
                                if a1 < -135 or a1 > 135:
                                    setOtherEdge(v1, v2, a)
                                    continue

                            # print('***No Win***')
                            # the default if no other rules pass
                            setCenterOffset(a)

        negative_overcuts = shapely.ops.unary_union(negative_overcuts)
        positive_overcuts = shapely.ops.unary_union(positive_overcuts)
        fs = shapely.ops.unary_union(shapes)
        fs = fs.union(positive_overcuts)
        fs = fs.difference(negative_overcuts)
        o = utils.shapelyToCurve(o1.name + '_overcuts', fs, o1.location.z)
        return {'FINISHED'}
Example #9
0
def gear(mm_per_tooth=0.003,
         number_of_teeth=5,
         hole_diameter=0.003175,
         pressure_angle=0.3488,
         clearance=0.0,
         backlash=0.0,
         rim_size=0.0005,
         hub_diameter=0.006,
         spokes=4):
    simple.deselect()
    pi = math.pi
    p = mm_per_tooth * number_of_teeth / pi / 2  # radius of pitch circle
    c = p + mm_per_tooth / pi - clearance  # radius of outer circle
    b = p * math.cos(pressure_angle)  # radius of base circle
    r = p - (c - p) - clearance  # radius of root circle
    t = mm_per_tooth / 2 - backlash / 2  # tooth thickness at pitch circle
    k = -gear_iang(
        b, p
    ) - t / 2 / p  # angle to where involute meets base circle on each side of tooth
    shapely_gear = Polygon([(0, 0),
                            gear_polar(r,
                                       k if r < b else -pi / number_of_teeth),
                            gear_q7(0, r, b, c, k, 1),
                            gear_q7(0.1, r, b, c, k, 1),
                            gear_q7(0.2, r, b, c, k, 1),
                            gear_q7(0.3, r, b, c, k, 1),
                            gear_q7(0.4, r, b, c, k, 1),
                            gear_q7(0.5, r, b, c, k, 1),
                            gear_q7(0.6, r, b, c, k, 1),
                            gear_q7(0.7, r, b, c, k, 1),
                            gear_q7(0.8, r, b, c, k, 1),
                            gear_q7(0.9, r, b, c, k, 1),
                            gear_q7(1.0, r, b, c, k, 1),
                            gear_q7(1.0, r, b, c, k, -1),
                            gear_q7(0.9, r, b, c, k, -1),
                            gear_q7(0.8, r, b, c, k, -1),
                            gear_q7(0.7, r, b, c, k, -1),
                            gear_q7(0.6, r, b, c, k, -1),
                            gear_q7(0.5, r, b, c, k, -1),
                            gear_q7(0.4, r, b, c, k, -1),
                            gear_q7(0.3, r, b, c, k, -1),
                            gear_q7(0.2, r, b, c, k, -1),
                            gear_q7(0.1, r, b, c, k, -1),
                            gear_q7(0.0, r, b, c, k, -1),
                            gear_polar(r,
                                       -k if r < b else pi / number_of_teeth)])
    utils.shapelyToCurve('tooth', shapely_gear, 0.0)
    i = number_of_teeth
    while i > 1:
        simple.duplicate()
        simple.rotate(2 * math.pi / number_of_teeth)
        i -= 1
    simple.join_multiple('tooth')
    simple.active_name('_teeth')

    bpy.ops.curve.simple(align='WORLD',
                         location=(0, 0, 0),
                         rotation=(0, 0, 0),
                         Simple_Type='Circle',
                         Simple_radius=r,
                         shape='3D',
                         use_cyclic_u=True,
                         edit_mode=False)
    simple.active_name('_hub')
    simple.union('_')
    simple.active_name('_gear')
    simple.remove_doubles()

    if spokes > 0:
        bpy.ops.curve.simple(align='WORLD',
                             location=(0, 0, 0),
                             rotation=(0, 0, 0),
                             Simple_Type='Circle',
                             Simple_radius=r - rim_size,
                             shape='3D',
                             use_cyclic_u=True,
                             edit_mode=False)
        simple.active_name('_hole')
        simple.difference('_', '_gear')
        bpy.ops.curve.simple(align='WORLD',
                             location=(0, 0, 0),
                             rotation=(0, 0, 0),
                             Simple_Type='Circle',
                             Simple_radius=hub_diameter / 2,
                             shape='3D',
                             use_cyclic_u=True,
                             edit_mode=False)
        simple.active_name('_hub')
        bpy.ops.curve.simple(align='WORLD',
                             location=(0, 0, 0),
                             rotation=(0, 0, 0),
                             Simple_Type='Circle',
                             Simple_radius=hole_diameter / 2,
                             shape='3D',
                             use_cyclic_u=True,
                             edit_mode=False)
        simple.active_name('_hub_hole')
        simple.difference('_hub', '_hub')

        simple.join_multiple('_')

        simple.add_rectangle(
            r - rim_size -
            ((hub_diameter - hole_diameter) / 4 + hole_diameter / 2),
            hub_diameter / 2,
            center_x=False)
        simple.move(x=(hub_diameter - hole_diameter) / 4 + hole_diameter / 2)
        simple.active_name('_spoke')

        angle = 2 * pi / spokes
        while spokes > 0:
            simple.duplicate()
            simple.rotate(angle)
            spokes -= 1
        simple.union('_spoke')
        simple.remove_doubles()
        simple.union('_')
    else:
        bpy.ops.curve.simple(align='WORLD',
                             location=(0, 0, 0),
                             rotation=(0, 0, 0),
                             Simple_Type='Circle',
                             Simple_radius=hole_diameter,
                             shape='3D',
                             use_cyclic_u=True,
                             edit_mode=False)
        simple.active_name('_hole')
        simple.difference('_', '_gear')

    name = 'gear-' + str(round(mm_per_tooth * 1000, 1))
    name += 'mm-pitch-' + str(number_of_teeth)
    name += 'teeth-PA-' + str(round(math.degrees(pressure_angle), 1))
    simple.active_name(name)