Home Forums Nazca Bent Taper Reply To: Bent Taper

#5258

And here comes a big code…
I managed to reuse your polyline2polygon in a brute force way.
Solved my problem for some cases, but not for all.
On my code I see some spurious points in the beginning of the bent taper.
Would you know why, and mainly, how to solve that?

Thanks

``````import nazca as nd
import nazca.generic_bend as gb
import nazca.util as util

def polyline2polygonTapered(xy, widthIn=0.49, widthOut=0.49, miter=0.5):
"""Return a polygon that contains the outline points of a tapered polyline

Since we have to specify the outline of two or more segments that make
an angle, we have to know what to do with the gap between those
segments at the outside of the corner. In order to determine which
points are on the outside of the corner we use the following algorithm:
Given a line segment between P0 (x0,y0) and P1 (x1,y1), another point P
(x,y) has the following relationship to the line segment. Compute
(y - y0) (x1 - x0) - (x - x0) (y1 - y0). If it is less than 0 then P is
to the right of the line segment, if greater than 0 it is to the left,
if equal to 0 then it lies on the line segment.
The routine fills an array from the start with the anticlockwise points
and from the end with the clockwise points.

Args:
xy (list): list of (x,y) points that hold the polygon
width (float): width of the polyline (default 2)
miter (float): maximum fraction of the width before an extra point
is added in outside corners (default 0.5)

Returns:
list of (float, float): the polygon
"""

# the fraction of the width of the line segments that is used to
# determine if a single point is sufficient to describe the outline, or
# that two points are needed (miter limit).
dsqrmax = (miter * widthIn)**2
n = len(xy)
if n < 2:
raise ValueError("Polyline2polygon: need at least 2 points for polyline.")
# Compute array of widths
widths = []
for i in range(len(xy)):
widths.append(widthIn+(widthOut-widthIn)/(len(xy)+1)*(i+1))
dxy1 = util.pointdxdy(xy, 0, widths)
cxy1 = util.corner(xy, 0, dxy1)
xy_start = [cxy1]
xy_end = [cxy1]
for i in range(1, n-1): # loop over the points in the polyline
dxy0 = dxy1
# Shift corner points from next to current segment.
cxy0 = cxy1
# Get corner points for next segment.
dxy1 = util.pointdxdy(xy, i, widths[i+1])
cxy1 = util.corner(xy, i, dxy1)
# left or right turn
lrt = (xy[i+1]-xy[i-1]) * (xy[i]-xy[i-1]) -\
(xy[i+1]-xy[i-1]) * (xy[i]-xy[i-1])
# Distance (squared) between the two points at the kink (2->4 == 3->5)
dsqr = (cxy1 - cxy0)**2 + (cxy1 - cxy0)**2
# the inside corner point is on the intersection of the two inside
# lines.
if lrt > 0: # Left turn
# Outside corner: use two points, unless these points are close.
if dsqr < dsqrmax:
xy_start.append(util.intersect(cxy0, cxy0, cxy1, cxy1))
else:
xy_start.append((xy[i]+dxy0, xy[i]+dxy0))
xy_start.append((xy[i]+dxy1, xy[i]+dxy1))
# Inside corner: always intersect.
xy_end.append(util.intersect(cxy0, cxy0, cxy1, cxy1))
elif lrt < 0: # Right turn
# Outside corner: use two points, unless these points are close.
if dsqr < dsqrmax:
xy_end.append(util.intersect(cxy0, cxy0, cxy1, cxy1))
else:
xy_end.append((xy[i]-dxy0, xy[i]-dxy0))
xy_end.append((xy[i]-dxy1, xy[i]-dxy1))
# Inside corner: always intersect.
xy_start.append(util.intersect(cxy0, cxy0, cxy1, cxy1))
else:
continue # No turn: goto next point
# Last two points.
xy_start.append(cxy1)
xy_end.append(cxy1)
return xy_start + list(reversed(xy_end))

########
# Actual testing code
########
# Define interconnect

# TESTING THE TAPERED BEND - From bend to str
# Defining bends
OutStr = myIC.strt(length=10).put(70,0)

xya = nd.diff(InBend.pin['b0'],OutStr.pin['a0'].rot(180))
A, B, L ,Rmin = gb.gb_coefficients(xya,Rin=30, Rout=-30) # Curve parameters
xy = gb.curve2polyline(gb.gb_point,
xya,
0.001, (A, B, L)) # Curve points
xy = polyline2polygonTapered(xy,widthIn=0.45,widthOut=0.49)
nd.Polygon(layer=10, points=xy).put(InBend.pin['b0'])

# TESTING THE TAPERED BEND  - From bend to str with initial radius not as desired
# Defining bends
InStr = myIC.strt(length=10).put(0,18)

xya = nd.diff(InStr.pin['b0'],OutBend.pin['a0'].rot(180))
A, B, L ,Rmin = gb.gb_coefficients(xya,Rin=30,Rout=30) # Curve parameters
xy = gb.curve2polyline(gb.gb_point,
xya,
0.001, (A, B, L)) # Curve points
xy = polyline2polygonTapered(xy,widthIn=0.49,widthOut=0.45)
nd.Polygon(layer=10, points=xy).put(InStr.pin['b0'])

# TESTING THE TAPERED BEND  - From bend to str - with desired initial radius
# Defining bends
InStr = myIC.strt(length=10).put(0,36)