kopia lustrzana https://github.com/villares/sketch-a-day
2020_09_23a
rodzic
45762bcafc
commit
1643ea271a
|
|
@ -0,0 +1,127 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
|
||||
def arc_filleted_poly(p_list, r_list, open_poly=False, arc_func=arc):
|
||||
"""
|
||||
draws a 'filleted' polygon with variable radius
|
||||
dependent on roundedCorner()
|
||||
"""
|
||||
p_list = list(p_list)
|
||||
r_list = list(r_list)
|
||||
|
||||
if not open_poly:
|
||||
# with pushStyle():
|
||||
# noStroke()
|
||||
# beginShape()
|
||||
# for p0, p1 in zip(p_list, [p_list[-1]] + p_list[:-1]):
|
||||
# m = (PVector(p0.x, p0.y) + PVector(p1.x, p1.y)) / 2
|
||||
# vertex(m.x, m.y)
|
||||
# endShape(CLOSE)
|
||||
for p0, p1, p2, r in zip(p_list,
|
||||
[p_list[-1]] + p_list[:-1],
|
||||
[p_list[-2]] + [p_list[-1]] + p_list[:-2],
|
||||
[r_list[-1]] + r_list[:-1]
|
||||
):
|
||||
m1 = (PVector(p0.x, p0.y) + PVector(p1.x, p1.y)) / 2
|
||||
m2 = (PVector(p2.x, p2.y) + PVector(p1.x, p1.y)) / 2
|
||||
roundedCorner(p1, m1, m2, r, arc_func)
|
||||
else:
|
||||
for p0, p1, p2, r in zip(p_list[:-1],
|
||||
[p_list[-1]] + p_list[:-2],
|
||||
[p_list[-2]] + [p_list[-1]] + p_list[:-3],
|
||||
[r_list[-1]] + r_list[:-2]
|
||||
):
|
||||
m1 = (PVector(p0.x, p0.y) + PVector(p1.x, p1.y)) / 2
|
||||
m2 = (PVector(p2.x, p2.y) + PVector(p1.x, p1.y)) / 2
|
||||
roundedCorner(p1, m1, m2, r, arc_func)
|
||||
|
||||
|
||||
def roundedCorner(pc, p1, p2, r, arc_func):
|
||||
"""
|
||||
Based on Stackoverflow C# rounded corner post
|
||||
https://stackoverflow.com/questions/24771828/algorithm-for-creating-rounded-corners-in-a-polygon
|
||||
"""
|
||||
|
||||
def GetProportionPoint(pt, segment, L, dx, dy):
|
||||
factor = float(segment) / L if L != 0 else segment
|
||||
return PVector((pt.x - dx * factor), (pt.y - dy * factor))
|
||||
|
||||
# Vector 1
|
||||
dx1 = pc.x - p1.x
|
||||
dy1 = pc.y - p1.y
|
||||
|
||||
# Vector 2
|
||||
dx2 = pc.x - p2.x
|
||||
dy2 = pc.y - p2.y
|
||||
|
||||
# Angle between vector 1 and vector 2 divided by 2
|
||||
angle = (atan2(dy1, dx1) - atan2(dy2, dx2)) / 2
|
||||
|
||||
# The length of segment between angular point and the
|
||||
# points of intersection with the circle of a given radius
|
||||
tng = abs(tan(angle))
|
||||
segment = r / tng if tng != 0 else r
|
||||
|
||||
# Check the segment
|
||||
length1 = sqrt(dx1 * dx1 + dy1 * dy1)
|
||||
length2 = sqrt(dx2 * dx2 + dy2 * dy2)
|
||||
|
||||
min_len = min(length1, length2)
|
||||
|
||||
if segment > min_len:
|
||||
segment = min_len
|
||||
max_r = min_len * abs(tan(angle))
|
||||
else:
|
||||
max_r = r
|
||||
|
||||
# Points of intersection are calculated by the proportion between
|
||||
# length of vector and the length of the segment.
|
||||
p1Cross = GetProportionPoint(pc, segment, length1, dx1, dy1)
|
||||
p2Cross = GetProportionPoint(pc, segment, length2, dx2, dy2)
|
||||
|
||||
# Calculation of the coordinates of the circle
|
||||
# center by the addition of angular vectors.
|
||||
dx = pc.x * 2 - p1Cross.x - p2Cross.x
|
||||
dy = pc.y * 2 - p1Cross.y - p2Cross.y
|
||||
|
||||
L = sqrt(dx * dx + dy * dy)
|
||||
d = sqrt(segment * segment + max_r * max_r)
|
||||
|
||||
circlePoint = GetProportionPoint(pc, d, L, dx, dy)
|
||||
|
||||
# StartAngle and EndAngle of arc
|
||||
startAngle = atan2(p1Cross.y - circlePoint.y, p1Cross.x - circlePoint.x)
|
||||
endAngle = atan2(p2Cross.y - circlePoint.y, p2Cross.x - circlePoint.x)
|
||||
|
||||
# Sweep angle
|
||||
sweepAngle = endAngle - startAngle
|
||||
|
||||
# Some additional checks
|
||||
if sweepAngle < 0:
|
||||
startAngle, endAngle = endAngle, startAngle
|
||||
sweepAngle = -sweepAngle
|
||||
|
||||
if sweepAngle > PI:
|
||||
startAngle, endAngle = endAngle, startAngle
|
||||
sweepAngle = TWO_PI - sweepAngle
|
||||
|
||||
# Draw result using graphics
|
||||
# noStroke()
|
||||
# with pushStyle():
|
||||
# noStroke()
|
||||
# beginShape()
|
||||
# vertex(p1.x, p1.y)
|
||||
# vertex(p1Cross.x, p1Cross.y)
|
||||
# vertex(p2Cross.x, p2Cross.y)
|
||||
# vertex(p2.x, p2.y)
|
||||
# endShape(CLOSE)
|
||||
|
||||
circle(p1.x, p1.y, 5)
|
||||
circle(p1Cross.x, p1Cross.y, 5)
|
||||
circle(p2Cross.x, p2Cross.y, 5)
|
||||
circle(p2.x, p2.y, 5)
|
||||
|
||||
line(p1.x, p1.y, p1Cross.x, p1Cross.y)
|
||||
line(p2.x, p2.y, p2Cross.x, p2Cross.y)
|
||||
arc_func(circlePoint.x, circlePoint.y, 2 * max_r, 2 * max_r,
|
||||
startAngle, startAngle + sweepAngle)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
|
||||
class Ponto():
|
||||
|
||||
SIZE = 5
|
||||
|
||||
def __init__(self, x, y):
|
||||
self.ox = x
|
||||
self.oy = y
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.f = 255
|
||||
|
||||
def __len__(self):
|
||||
return 2
|
||||
|
||||
def __iter__(self):
|
||||
return iter((self.x, self.y))
|
||||
|
||||
def __getitem__(self, i):
|
||||
return (self.x, self.y)[i]
|
||||
|
||||
def draw(self):
|
||||
fill(self.f)
|
||||
circle(self.x, self.y, Ponto.SIZE)
|
||||
Plik binarny nie jest wyświetlany.
|
Po Szerokość: | Wysokość: | Rozmiar: 166 KiB |
|
|
@ -0,0 +1,81 @@
|
|||
from random import sample
|
||||
from itertools import product
|
||||
from villares.line_geometry import * # github.com/villares/villares
|
||||
from arc_filleted_poly import arc_filleted_poly
|
||||
from ponto import Ponto
|
||||
|
||||
|
||||
|
||||
BORDER = 50
|
||||
SIZE = 150
|
||||
r_list = [10, 20, 30, 40, -10, -20, -30, -40]
|
||||
p_list = []
|
||||
dragg = []
|
||||
|
||||
def setup():
|
||||
global grid
|
||||
size(400, 400)
|
||||
grid = list(product(range(BORDER, height - BORDER + 1, SIZE),
|
||||
range(BORDER, height - BORDER + 1, SIZE)))
|
||||
make_points(8)
|
||||
|
||||
def draw():
|
||||
background(200)
|
||||
|
||||
if len(dragg) == 2:
|
||||
d_line = Line(*dragg)
|
||||
strokeWeight(0.5)
|
||||
d_line.draw()
|
||||
lines = inter_lines(d_line, p_list)
|
||||
for inter_line in lines:
|
||||
strokeWeight(2)
|
||||
inter_line.draw()
|
||||
|
||||
|
||||
noFill()
|
||||
strokeWeight(1)
|
||||
stroke(255)
|
||||
poly(map(tuple, p_list))
|
||||
stroke(0)
|
||||
fill(100, 100)
|
||||
arc_filleted_poly(p_list, map(abs, r_list))
|
||||
|
||||
for p in p_list:
|
||||
if len(dragg) == 2:
|
||||
if area(p, dragg[0], dragg[1]) > 0:
|
||||
p.f = color(255, 0, 0)
|
||||
else:
|
||||
p.f = color(0, 0, 255)
|
||||
else:
|
||||
p.f = 255
|
||||
p.draw()
|
||||
|
||||
|
||||
def keyPressed():
|
||||
if key == ' ': make_points(8); saveFrame("###.png")
|
||||
if key == 'm': move_points()
|
||||
|
||||
def mousePressed():
|
||||
dragg[:] = [(mouseX, mouseY)]
|
||||
|
||||
def mouseDragged():
|
||||
if len(dragg) == 1:
|
||||
dragg.append((mouseX, mouseY))
|
||||
else:
|
||||
dragg[1] = (mouseX, mouseY)
|
||||
|
||||
def area(p0, p1, p2):
|
||||
a = (p1[0] * (p2[1] - p0[1]) +
|
||||
p2[0] * (p0[1] - p1[1]) +
|
||||
p0[0] * (p1[1] - p2[1]))
|
||||
return a
|
||||
|
||||
# def mouseReleased():
|
||||
# dragg[:] = []
|
||||
|
||||
|
||||
def make_points(num):
|
||||
p_list[:] = []
|
||||
for x, y in sample(grid, num):
|
||||
p_list.append(Ponto(x, y))
|
||||
|
||||
|
|
@ -26,6 +26,12 @@ Some of the tools I have used:
|
|||
|
||||
---
|
||||
|
||||

|
||||
|
||||
[sketch_2020_09_23a](https://github.com/villares/sketch-a-day/tree/master/2020/sketch_2020_09_23a) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)]
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
[sketch_2020_09_22a](https://github.com/villares/sketch-a-day/tree/master/2020/sketch_2020_09_22a) [[Py.Processing](https://villares.github.io/como-instalar-o-processing-modo-python/index-EN)]
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue