我正在尝试实现一个函数,在Gareth Rees的伟大指令之后在python中找到光线/段交叉点: https://stackoverflow.com/a/14318254/7235455和https://stackoverflow.com/a/565282/7235455
这是我的功能:
14:18:09.950 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] The daemon has finished executing the build.
14:18:10.013 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientInputForwarder] Dispatching close input message: org.gradle.launcher.daemon.protocol.CloseInput@de542e
14:18:10.013 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientConnection] thread 10: dispatching class org.gradle.launcher.daemon.protocol.CloseInput
14:18:10.013 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClient] Received result Failure[value=org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: A problem occurred configuring root project '_app_'.] from daemon DaemonInfo{pid=7464, address=[093d98c5-c3fb-4d52-8769-f354b16ed886 port:59558, addresses:[/127.0.0.1]], state=Idle, lastBusy=1504514729826, context=DefaultDaemonContext[uid=1fa87ce9-9184-48a6-9489-499fe27fffa0,javaHome=C:\Program Files (x86)\Java\jdk1.8.0_131,daemonRegistryDir=D:\Users\RMuthu\.gradle\daemon,pid=7464,idleTimeout=10800000,daemonOpts=-XX:+HeapDumpOnOutOfMemoryError,-Xmx1024m,-Dfile.encoding=windows-1252,-Duser.country=US,-Duser.language=en,-Duser.variant]} (build should be done).
14:18:10.013 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientConnection] thread 1: dispatching class org.gradle.launcher.daemon.protocol.Finished
14:18:10.013 [DEBUG] [org.gradle.launcher.daemon.client.DaemonClientConnection] thread 1: connection stop
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve org.pitest:pitest-command-line:1.1.10.
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.resolveComponentMet
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ComponentMetaDataResolveState.process(ComponentMetaDataResolveState.java:66)
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ComponentMetaDataResolveState.resolve(ComponentMetaDataResolveState.java:58)
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.findBestMatch(RepositoryChainComponentMetaDataResolver.java:13
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.findBestMatch(RepositoryChainComponentMetaDataResolver.java:11
at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.resolveModule(RepositoryChainComponentMetaDataResolver.java:89
... 20 more
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.gradle.internal.resource.transport.http.AlwaysRedirectRedirectStrategy
当有交叉点时,该功能正常工作。但它不能识别并行性或共线性,因为条件rxs == 0和qpxr == 0不符合(永远?)。运行例如:
from math import radians, sin, cos
import numpy as np
def find_intersection(point0, theta, point1, point2):
# convert arguments to arrays:
p = np.array(point0, dtype=np.float) # ray origin
q = np.array(point1, dtype=np.float) # segment point 1
q2 = np.array(point2, dtype=np.float) # segment point 2
r = np.array((cos(theta),sin(theta))) # theta as vector (= ray as vector)
s = q2 - q # vector from point1 to point2
rxs = np.cross(r,s)
qpxs = np.cross(q-p,s)
qpxr = np.cross(q-p,r)
t = qpxs/rxs
u = qpxr/rxs
if rxs == 0 and qpxr == 0:
t0 = np.dot(q-p,r)/np.dot(r,r)
t1 = np.dot(t0+s,r)/np.dot(r,r)
return "collinear"
elif rxs == 0 and qpxr != 0:
return "parallel"
elif rxs != 0 and 0 <= t and 0 <= u and u <= 1: # removed t <= 1 since ray is inifinte
intersection = p+t*r
return "intersection is {0}".format(intersection)
else:
return None
返回None。在if-block之前为rxs和qpxr添加print语句
p0 = (0.0,0.0)
theta = radians(45.0)
p1 = (1.0,1.0)
p2 = (3.0,3.0)
c = find_intersection(p0,theta,p1,p2)
我的结论是,由于浮点问题,函数无法捕获第一个if语句的条件。 2.22044604925e-16和-1.11022302463e-16非常小,但遗憾的是不完全是0.我理解浮点数不能用二进制表示。
我的结论是正确的还是我错过了什么?对于避免此问题的实施有什么想法吗? 非常感谢!
答案 0 :(得分:0)
是的,你的结论是对的,问题在于&#34; parallel&#34;谓语。
您可以将结果与较小的数字进行比较(例如,eps=1.0E-9
)。它的大小可能取决于坐标范围(请注意,交叉乘积会给出加倍的三角形区域,因此eps
MaxVecLen**2
的标准化看起来合理。)
更复杂但更精确的选项 - 使用强大的几何谓词,如these ones。也许用于计算几何的Python / NumPy库包含一些用于此类操作的实现。
答案 1 :(得分:0)
有一种简单而安全的方法可以解决这个问题。
写出光线的隐式方程(S(X, Y) = a X + b Y + c = 0
)。当您在函数S
中插入细分的端点坐标时,您会得到两个值,即S0
和S1
。如果它们符号相反,则光线的支撑线与线段之间存在交叉。
在这种情况下,沿着段的交点的位置由参数的值给出,等于
- S0 / (S1 - S0).
此表达式具有始终可计算的属性(如果符号发生更改)且范围为[0, 1]
。它允许安全地计算交叉点。
要仅选择所需半线(光线)上的交点,只需在光线原点计算S(Xo, Yo)
的符号。
此程序不会检测平行光线或共线光线,但无关紧要。无论如何,它会产生合理的结果。