数学背景
1。代数
2。平面几何
-
一个平面由(无限)个点组成:让我们通过它的坐标来引用一个点,它可以被称为:
-
横坐标或水平坐标或(简单)x
-
纵坐标或纵坐标或(简单)y
-
平面中的点分布在二维上
-
在平面上,每个点都可以通过它的x和y
唯一标识
-
平面上的一些点可能有一些共同的特征:例如直线上的一堆点... 直线上的一个点满足直线 方程 (这是一个表达式,通常定义为 ${函数(来自上一段)结果} = ${value})
-
所以,简而言之:对于一个点 P0(x0, y0),如果<strong>y<sub>0</sub> == f(x<sub>0</sub>)</strong>,点是位于那条直线上(以及更多:取决于y0 大于 / 低于 f(x0), P0 位于 xOy 平面中的直线上方 / 下方 )。再次声明,对于非线性函数,y = f(x) 仍然适用(因为它是一般方程公式),但其他运算符(例如 、 >)不要
-
!重要提示!:这里讨论的所有内容都适用于各种函数(不想说全部),但我仅限于线性函数,为了清楚起见
-
一条直线由2个不同点确定(例如P0(x0, y0), P1(x1, y1)) - 方程因为那条直线是y = a * x + b(在我们的例子中:<strong>y = ((y<sub>0</sub> - y<sub>1</sub>) / (x<sub>0</sub> - x<sub>1</sub>)) * x + (y<sub>0</sub> - x<sub>0</sub> * ((y<sub>0</sub> - y<sub>1</sub>) / (x<sub>0</sub> - x<sub>1</sub>)))</strong>); !! 当然值得一提的是“垂直”(平行于Oy)线,即!!不是函数!!
-
示例:有 2 个不同平行(非 Bolyai :))行:f<sub>0</sub>(x) = a * x + b<sub>0</sub> 和 f<sub>1</sub>(x) = a * x + b<sub>1</sub>(a 对于两条线是相同的 - 这是它们平行的条件)和外部点 P0(x0, y0) (显然不属于任何行)。如何确定 P0 是否在两行之间?好吧,该点必须高于(较低的)一个,低于另一个(较高的)。翻译成数学(考虑到 f0 是较低的):
-
<strong>y<sub>0</sub> > f<sub>0</sub>(x<sub>0</sub>)</strong> (y<sub>0</sub> - f<sub>0</sub>(x<sub>0</sub>) > 0)
-
<strong>y<sub>0</sub> < f<sub>1</sub>(x<sub>0</sub>)</strong> (y<sub>0</sub> - f<sub>1</sub>(x<sub>0</sub>) < 0)
从以上观察(可能还有更多智慧),这是点坐标应该满足的条件:<strong>(y<sub>0</sub> - f<sub>0</sub>(x<sub>0</sub>)) * (y<sub>0</sub> - f<sub>1</sub>(x<sub>0</sub>)) < 0</strong>
-
更进一步:一个正方形由 2 组平行线(它的边)组成;如果一个点在每对线对之间,则该点在正方形中。
code00.py:
#!/usr/bin/env python3
import sys
from random import random, seed
from math import pi, sin, cos, sqrt
import matplotlib.pyplot as plt
pi_2 = pi / 2
MINX = MINY = 0
MAXX = MAXY = 1
DEFAULT_SIDE = 0.1
DEFAULT_SAFETY_MARGIN = DEFAULT_SIDE * sqrt(2)
MAX_SQUARES = 30
__global_generation_counter = 0
def get_func_deg1(p0, p1):
(x0, y0), (x1, y1) = p0, p1
if x0 == x1:
return None
a = (y0 - y1)/(x0 - x1)
b = y0 - x0 * a
return lambda x: a * x + b
def is_point_in_square(p, sq):
x, y = p
p0, p1, p2, p3 = sq
side_func0 = get_func_deg1(p0, p1)
side_func1 = get_func_deg1(p1, p2)
side_func2 = get_func_deg1(p2, p3)
side_func3 = get_func_deg1(p3, p0)
if not side_func0 or not side_func1 or not side_func2 or not side_func3:
xmin = min(p0[0], p2[0])
xmax = max(p0[0], p2[0])
ymin = min(p0[1], p2[1])
ymax = max(p0[1], p2[1])
return xmin <= x <= xmax and ymin <= y <= ymax
return ((y - side_func0(x)) * (y - side_func2(x))) <= 0 and \
((y - side_func1(x)) * (y - side_func3(x))) <= 0
def squares_overlap(square0, square1):
for p0 in square0:
if is_point_in_square(p0, square1):
return True
for p1 in square1:
if is_point_in_square(p1, square0):
return True
xc0 = (square0[0][0] + square0[2][0]) / 2
yc0 = (square0[0][1] + square0[2][1]) / 2
if is_point_in_square((xc0, yc0), square1):
return True
# The "reverse center check" not needed, since squares are congruent
"""
xc1 = (square1[0][0] + square1[2][0]) / 2
yc1 = (square1[0][1] + square1[2][1]) / 2
if is_point_in_square((xc1, yc1), square0):
return True
"""
return False
def __generation_monitor():
global __global_generation_counter
__global_generation_counter += 1
def generate_random_point(minx=MINX, miny=MINY, maxx=MAXX, maxy=MAXY, safety_margin=DEFAULT_SAFETY_MARGIN):
if maxx - minx < 2 * safety_margin or maxy - miny < 2 * safety_margin:
print("MUEEE")
safety_margin = 0
x = safety_margin + random() * (maxx - minx - 2 * safety_margin)
y = safety_margin + random() * (maxy - miny - 2 * safety_margin)
__generation_monitor()
return x, y
def generate_random_angle(max_val=pi_2):
return random() * max_val
def generate_random_square(side=DEFAULT_SIDE, squares_to_avoid=()):
while 1:
restart = False
x0, y0 = generate_random_point()
angle = generate_random_angle()
x1 = x0 + side * cos(angle)
y1 = y0 + side * sin(angle)
angle += pi_2
x2 = x1 + side * cos(angle)
y2 = y1 + side * sin(angle)
angle += pi_2
x3 = x2 + side * cos(angle)
y3 = y2 + side * sin(angle)
ret = (x0, y0), (x1, y1), (x2, y2), (x3, y3)
for square in squares_to_avoid:
if squares_overlap(ret, square):
restart = True
if restart:
continue
return ret
def square_to_plot(square):
xs, ys = zip(square[0], square[1], square[2], square[3])
return xs + (xs[0],), ys + (ys[0],)
def main():
seed()
squares = list()
allow_overlapping = False # CHANGE to True to allow square to overlap
for _ in range(MAX_SQUARES):
#print("Generating:", _)
if allow_overlapping:
square = generate_random_square()
else:
square = generate_random_square(squares_to_avoid=squares)
squares.append(square)
plot_squares = tuple()
for sq in squares:
plot_squares += square_to_plot(sq)
print("STATS:\n Squares: {}\n Allow overlapping: {}\n Generated values: {}".format(MAX_SQUARES, allow_overlapping, __global_generation_counter))
plt.plot(*plot_squares)
plt.axis([MINX, MAXX, MINY, MAXY])
plt.show()
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
注意事项:
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q046081491]> "e:\Work\Dev\VEnvs\py_064_03.05.04_test0\Scripts\python.exe" code00.py
STATS:
Squares: 30
Allow overlapping: False
Generated values: 1135
关于正方形生成的几句话
- 从输出中可以看出,对于 30 个显示的正方形,生成了 1135(在本次运行中)。那是因为它们重叠
- 如果从 main
allow_overlapping = True 更改,输出中的生成值 将匹配正方形的数量 (MAX_SQUARES)
- 如果将 MAX_SQUARES 增加到高于 50 的值,则生成的值的数量将呈指数增长(生成它们所需的时间也会增加),并且机会程序将进入无限循环(因为它无法生成不与另一个正方形重叠的正方形)也会增长