# -*- coding: utf-8 -*-
"""
Written by Daniel M. Aukes and CONTRIBUTORS
Email: danaukes<at>asu.edu.
Please see LICENSE for full license.
"""
import numpy
import math
[docs]def close_to(a,b,tolerance=1e-5):
result = ((a-b)**2)**.5
return result < tolerance
[docs]def distance(p1,p2):
p1 = numpy.array(p1)
p2 = numpy.array(p2)
v = p2-p1
return(length(v))
[docs]def length(v1):
'''
finds the length of a vector
:param v1: the vector
:type v1: tuple or list of floats
:rtype: float
'''
v1 = numpy.array(v1).flatten()
l = (v1.dot(v1))**.5
return l
[docs]def inner_angle(v1,v2):
'''
finds the interior angle between two vectors
:param v1: the first vector
:type v1: tuple or list of floats
:param v2: the second vector
:type v2: tuple or list of floats
:rtype: float
'''
v1 = numpy.array(v1).flatten()
l1 = length(v1)
v2 = numpy.array(v2).flatten()
l2 = length(v2)
cost = numpy.dot(v1,v2)/l1/l2
t = math.acos(cost)
return t
[docs]def total_angle(v1,v2,v3=None):
'''
finds the interior angle between two vectors
:param v1: the first vector
:type v1: tuple or list of floats
:param v2: the second vector
:type v2: tuple or list of floats
:rtype: float
'''
v1 = numpy.array(v1).flatten()
if len(v1)==2:
v1 = numpy.r_[v1,0]
v3 = numpy.array([0,0,1])
v2 = numpy.array(v2).flatten()
if len(v2)==2:
v2 = numpy.r_[v2,0]
v3 = numpy.array([0,0,1])
costheta = numpy.dot(v1,v2)
sintheta = numpy.cross(v1,v2)
l_sintheta = length(sintheta)
neg = sintheta.dot(v3)
if neg<0:
neg = -1
else:
neg=1
theta = math.atan2(neg*l_sintheta,costheta)
return theta
[docs]def heal_polylines(lines, tolerance=1e-3):
polylines=[]
while len(lines)>0:
polyline = []
polyline.append(lines.pop(0))
finding = True
while finding:
finding = False
for ii in range(len(lines)):
item = lines[ii]
if distance(polyline[-1][1],item[0])<tolerance:
polyline.append(item)
lines.pop(ii)
finding = True
break
elif distance(polyline[-1][1],item[-1])<tolerance:
polyline.append(item[::-1])
lines.pop(ii)
finding = True
break
polyline2 = numpy.array([item[0] for item in polyline]+[polyline[-1][-1]])
# polyline = numpy.array([item for segment in polyline for item in segment])
polylines.append(polyline2)
print(len(lines))
return polylines
# def vec_error(v1,v2):
# v1 = numpy.r_[v1]
# v2 = numpy.r_[v2]
# error = (v1-v2)**2
# error = error.sum()
# error = error**.5
# return error
[docs]def slope_intercept(p1,p2):
if len(p1)==2:
p1 = numpy.r_[p1,0]
else:
p1 = numpy.r_[p1]
if len(p2)==2:
p2 = numpy.r_[p2,0]
else:
p2 = numpy.r_[p2]
v = p2-p1
l = (v.dot(v))**.5
n = v/l
p = numpy.cross(p1,n)
i = numpy.cross(p,n)
return tuple(n[:2]),tuple(i[:2])
[docs]def interior(seg,p):
pA1,pA2 = seg
pA1 = numpy.r_[pA1]
pA2 = numpy.r_[pA2]
p = numpy.r_[p]
vA = pA2-pA1
lA = length(vA)
v = p-pA1
l = length(v)
if lA==0:
return-1,lA
if l==0:
return l,lA
nA = vA/lA
n = v/l
d = nA.dot(n)
n *=d
l *=d
return l,lA
[docs]def colinear_segment_interior_points(segA,segB,tolerance=1e-5):
'''
requires that you check slope and intercept first
Parameters
----------
(pA1,pA2) : TYPE
DESCRIPTION.
(pB1,pB2) : TYPE
DESCRIPTION.
Returns
-------
interior : TYPE
DESCRIPTION.
'''
(pA1,pA2) = segA
(pB1,pB2) = segB
lB1,lA = interior(segA,pB1)
lB2,lA = interior(segA,pB2)
interiors = []
if lB1<tolerance or close_to(lB1,0,tolerance):
if lB2<tolerance or close_to(lB2,0,tolerance):
pass
elif lB2<lA-tolerance:
interiors = [pA1,pB2]
else: #lB>lA
interiors = [pA1,pA2]
elif lB1<lA-tolerance:
if lB2<tolerance or close_to(lB2,0,tolerance):
interiors = [pA1,pB1]
elif lB2<lA-tolerance:
interiors = [pB1,pB2]
else: #lB>lA
interiors = [pB1,pA2]
else:
if lB2<tolerance or close_to(lB2,0,tolerance):
interiors = [pA1,pA2]
elif lB2<lA-tolerance:
interiors = [pB2,pA2]
else: #lB>lA
pass
return interiors
if __name__=='__main__':
a = [(0,0),(1,1),(1,0),(0,0)]
# a = numpy.array(a)
# a = numpy.hstack((a,a[:,0:1]*0))
for p1,p2 in zip(a[:-1],a[1:]):
n,i = slope_intercept(p1,p2)
print('n:',n,'i:',i)