- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
Midpoint subdivision algorithm [page-93(104)]的工作原理是将一条线分成更小的段,并测试每个段以发现它们是否在裁剪区域的可见边界内。
在二进制搜索算法中,我们找到中间元素,然后选择右侧或左侧。
但是,在这里,如下图所示,在第一次分割之后,我们发现这两个小节实际上是有争议的。因此,它们都是进一步 segmentation 的候选对象。所以,我们不能像二分查找那样进行。
我正在使用迭代方法。但是,以下代码不起作用:
Line2d GetClippedLine()
{
Line2d clippingCandidate = this->line;
std::vector<Line2d> lines = clippingCandidate.GetMidpointSubLines();
while(lines[0] != lines[1])
{
lines = clippingCandidate.GetMidpointSubLines();
Line2d one = lines[0];
Line2d two = lines[1];
if(one.IsClippingCandidate(rectangle))
{
clippingCandidate = one;
}
if(two.IsClippingCandidate(rectangle))
{
clippingCandidate = two;
}
if(one.IsVisible(rectangle))
{
Coordinates2d::Draw(one, Yellow);
}
if(two.IsVisible(rectangle))
{
Coordinates2d::Draw(two, Yellow);
}
clippingCandidate.Show();
//std::cout<<"++";
//two.Show();
std::cout<<"\n";
}
return clippingCandidate;
}
最佳答案
你问的很对。 Explanations of midpoint subdivision have arisen that are very sloppy or just wrong .看起来您的代码是基于这些不良来源之一。
M-S 仅在您已经知道线段横跨裁剪边界(每侧一个端点)时才可用于查找交点,并且它通常用整数实现。它最初用作 Cohen 和 Sutherland 的完整裁剪算法变体中的子例程。
参见 the Wikipedia article如果你不熟悉 C-S。 “输出代码”指导对包含视口(viewport)边界的无限线进行连续裁剪。在那里的伪代码中,您将用 M-S 替换 float 学。
假设您在 x=C 处对左边界进行剪裁,并且横跨它的线段是 P0(x0,y0)---P1(x1,y1)
.也说x0<C<=x1
, 所以 P0
已知在边界之外。那么M-S算法就是:
tx1 = x1; // don't modify P1; it's inside the boundary
ty1 = y1;
while (x0 < C) {
xm = (x0 + tx1 + 1) >> 1;
ym = (y0 + ty1 + 1) >> 1;
if (xm <= C) { // the midpoint is on or outside the boundary
x0 = xm; // move P0
y0 = ym;
} else { // the midpoint is strictly inside
tx1 = xm; // move P1
ty1 = ym;
}
}
// The clipped segment is (x0,x1)--(y0,y1).
对于其他 3 个边界,您需要其他 3 个较小的变化。
终止条件很棘手。 + 1
s 是避免在 x0 = C-1
情况下永远循环的必要条件。和 tx1 = C
: (C + C - 1 + 1) >> 1 == C
,所以下一次迭代将终止。
话虽如此,中点 segmentation 几乎已经过时了。它对只有整数运算的处理器很有用(至少在 90 年代中期之前都是这种情况;我在 1984 年用 8088 汇编语言实现了它)。找到中点只需要除以 2,即整数右移,因此可以对最大大小为 n 的坐标进行不超过 ceiling(log_2 n) 次快速迭代的裁剪。如今,随着浮点单元以 gigaflop 的速率运行,用浮点进行裁剪可能会更快,当然也更容易。
添加只是为了好玩,用 C 实现:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned OUTCODE;
typedef int COORD;
typedef int BOOL;
#define TRUE 1
#define FALSE 0
#define XMIN 0
#define YMIN 0
#define XMAX 5000
#define YMAX 3000
// Not strictly portable, but usually fine.
#define SIGN_BIT (~(~0u >> 1))
#define LEFT SIGN_BIT
#define TOP (LEFT >> 1)
#define RIGHT (TOP >> 1)
#define BOTTOM (RIGHT >> 1)
#define ALL (LEFT | BOTTOM | RIGHT | TOP)
// Mask the sign bit.
#define M(X) ((X) & SIGN_BIT)
// Shift previous value and mask in the new sign bit.
#define SM(Prev, New) (((OUTCODE)(Prev) >> 1) | M(New))
__inline OUTCODE outcode(COORD x, COORD y) {
return SM(SM(SM(M(YMAX - y), XMAX - x), y - YMIN), x - XMIN);
}
// In the S-T coordinate system, pO is outside boundary C and will be moved
// to the boundary while pI doesn't move. I is the termination correction.
#define MOVE_TO_BOUNDARY(SO, TO, SI, TI, C, I, IS_OUTSIDE) do { \
COORD tsi = SI, tti = TI; \
while (SO IS_OUTSIDE C) { \
COORD sm = (tsi + SO + I) >> 1; \
COORD tm = (tti + TO + I) >> 1; \
if (sm IS_OUTSIDE ## = C) { \
SO = sm; \
TO = tm; \
} else { \
tsi = sm; \
tti = tm; \
} \
} \
} while (0)
BOOL clip(COORD *x0p, COORD *y0p, COORD *x1p, COORD *y1p) {
COORD x0 = *x0p, y0 = *y0p, x1 = *x1p, y1 = *y1p;
OUTCODE code0 = outcode(x0, y0);
OUTCODE code1 = outcode(x1, y1);
for (;;) {
if ((code0 | code1) == 0) {
*x0p = x0; *y0p = y0; *x1p = x1; *y1p = y1;
return TRUE;
} else if (code0 & code1) {
return FALSE;
} else if (code0) {
if (code0 & BOTTOM) MOVE_TO_BOUNDARY(y0, x0, y1, x1, YMAX, 0, >);
else if (code0 & RIGHT) MOVE_TO_BOUNDARY(x0, y0, x1, y1, XMAX, 0, >);
else if (code0 & TOP) MOVE_TO_BOUNDARY(y0, x0, y1, x1, YMIN, 1, <);
else /* LEFT */ MOVE_TO_BOUNDARY(x0, y0, x1, y1, XMIN, 1, <);
code0 = outcode(x0, y0);
} else {
if (code1 & BOTTOM) MOVE_TO_BOUNDARY(y1, x1, y0, x0, YMAX, 0, >);
else if (code1 & RIGHT) MOVE_TO_BOUNDARY(x1, y1, x0, y0, XMAX, 0, >);
else if (code1 & TOP) MOVE_TO_BOUNDARY(y1, x1, y0, x0, YMIN, 1, <);
else /* LEFT */ MOVE_TO_BOUNDARY(x1, y1, x0, y0, XMIN, 1, <);
code1 = outcode(x1, y1);
}
}
}
int main(void) {
int n = 0, margin = 2000;
for (;;) {
// Generate some random points around the viewport.
int x0 = rand() % (2 * margin + XMAX - XMIN) - margin;
int y0 = rand() % (2 * margin + YMAX - YMIN) - margin;
int x1 = rand() % (2 * margin + XMAX - XMIN) - margin;
int y1 = rand() % (2 * margin + YMAX - YMIN) - margin;
printf("a(%d, %d)--(%d, %d) %x--%x\n", x0, y0, x1, y1,
outcode(x0,y0) >> 28, outcode(x1,y1) >> 28);
BOOL r = clip(&x0, &y0, &x1, &y1);
printf("a(%d, %d)--(%d, %d): %d\n", x0, y0, x1, y1, r);
}
return 0;
}
在我的 MacBook 上,它在 90 秒内剪辑了 10 亿个片段。看看这与浮点 C-S 相比如何会很有趣。
关于c++ - 修正剪线算法的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31430544/
我将 Bootstrap 与 css 和 java 脚本结合使用。在不影响前端代码的情况下,我真的很难在css中绘制这个背景。在许多问题中,人们将宽度和高度设置为 0%。但是由于我的导航栏,我不能使用
我正在用 c 编写一个程序来读取文件的内容。代码如下: #include void main() { char line[90]; while(scanf("%79[^\
我想使用 javascript 获取矩阵数组的所有对 Angular 线。假设输入输出如下: input = [ [1,2,3], [4,5,6], [7,8,9], ] output =
可以用pdfmake绘制lines,circles和other shapes吗?如果是,是否有documentation或样本?我想用jsPDF替换pdfmake。 最佳答案 是的,有可能。 pdfm
我有一个小svg小部件,其目的是显示角度列表(参见图片)。 现在,角度是线元素,仅具有笔触,没有填充。但是现在我想使用一种“内部填充”颜色和一种“笔触/边框”颜色。我猜想line元素不能解决这个问题,
我正在为带有三角对象的 3D 场景编写一个非常基本的光线转换器,一切都工作正常,直到我决定尝试从场景原点 (0/0/0) 以外的点转换光线。 但是,当我将光线原点更改为 (0/1/0) 时,相交测试突
这个问题已经有答案了: Why do people write "#!/usr/bin/env python" on the first line of a Python script? (22 个回
如何使用大约 50 个星号 * 并使用 for 循环绘制一条水平线?当我尝试这样做时,结果是垂直(而不是水平)列出 50 个星号。 public void drawAstline() { f
这是一个让球以对角线方式下降的 UI,但球保持静止;线程似乎无法正常工作。你能告诉我如何让球移动吗? 请下载一个球并更改目录,以便程序可以找到您的球的分配位置。没有必要下载足球场,但如果您愿意,也可以
我在我的一个项目中使用 Jmeter 和 Ant,当我们生成报告时,它会在报告中显示 URL、#Samples、失败、成功率、平均时间、最短时间、最长时间。 我也想在报告中包含 90% 的时间线。 现
我有一个不寻常的问题,希望有人能帮助我。我想用 Canvas (android) 画一条 Swing 或波浪线,但我不知道该怎么做。它将成为蝌蚪的尾部,所以理想情况下我希望它的形状更像三角形,一端更大
这个问题已经有答案了: Checking Collision of Shapes with JavaFX (1 个回答) 已关闭 8 年前。 我正在使用 JavaFx 8 库。 我的任务很简单:我想检
如何按编号的百分比拆分文件。行数? 假设我想将我的文件分成 3 个部分(60%/20%/20% 部分),我可以手动执行此操作,-_-: $ wc -l brown.txt 57339 brown.tx
我正在努力实现这样的目标: 但这就是我设法做到的。 你能帮我实现预期的结果吗? 更新: 如果我删除 bootstrap.css 依赖项,问题就会消失。我怎样才能让它与 Bootstrap 一起工作?
我目前正在构建一个网站,但遇到了 transform: scale 的问题。我有一个按钮,当用户将鼠标悬停在它上面时,会发生两件事: 背景以对 Angular 线“扫过” 按钮标签颜色改变 按钮稍微变
我需要使用直线和仿射变换绘制大量数据点的图形(缩放图形以适合 View )。 目前,我正在使用 NSBezierPath,但我认为它效率很低(因为点在绘制之前被复制到贝塞尔路径)。通过将我的数据切割成
我正在使用基于 SVM 分类的 HOG 特征检测器。我可以成功提取车牌,但提取的车牌除了车牌号外还有一些不必要的像素/线。我的图像处理流程如下: 在灰度图像上应用 HOG 检测器 裁剪检测到的区域 调
我有以下图片: 我想填充它的轮廓(即我想在这张图片中填充线条)。 我尝试了形态学闭合,但使用大小为 3x3 的矩形内核和 10 迭代并没有填满整个边界。我还尝试了一个 21x21 内核和 1 迭代,但
我必须找到一种算法,可以找到两组数组之间的交集总数,而其中一个数组已排序。 举个例子,我们有这两个数组,我们向相应的数字画直线。 这两个数组为我们提供了总共 7 个交集。 有什么样的算法可以帮助我解决
简单地说 - 我想使用透视投影从近裁剪平面绘制一条射线/线到远裁剪平面。我有我认为是使用各种 OpenGL/图形编程指南中描述的方法通过单击鼠标生成的正确标准化的世界坐标。 我遇到的问题是我的光线似乎
我是一名优秀的程序员,十分优秀!