我在Java(特别是Android)中创建了一些显示如下内容的东西:
用户可以拖动框的角落,并且正如预期的那样,虚线应该相应地移动,总是有3条水平线(一半,一条25%,一条75%在顶部和底部之间)和3条垂直线。但是,如果左边缘或右边缘是无穷大(当用户第一次看到屏幕时),它看起来像这样:
如何更改代码以便考虑无限斜率边缘并仍显示所需的屏幕?这是我的代码,用于检测虚线的位置,它们的斜率,最后它们被绘制到屏幕上。
//get edge slopes to calculate dashed lines
//c1X is the top left corner X position, c2X is for the top right corner, etc.
float topLineSlope = (c2Y - c1Y)/(c2X - c1X);
float rightLineSlope = (c3Y - c2Y)/(c3X - c2X);
float bottomLineSlope = (c4Y - c3Y)/(c4X - c3X);
float leftLineSlope = (c1Y - c4Y)/(c1X - c4X);
//b in y=mx+b
float topLineB = c1Y - (topLineSlope * c1X);
float rightLineB = c2Y - (rightLineSlope * c2X);
float bottomLineB = c3Y - (bottomLineSlope * c3X);
float leftLineB = c4Y - (leftLineSlope * c4X);
//final dashed line coordinates
float topLineMiddleX = (c1X + c2X) / 2.0f;
float topLineMiddleY = topLineSlope * topLineMiddleX + topLineB;
float bottomLineMiddleX = (c3X + c4X) / 2.0f;
float bottomLineMiddleY = bottomLineSlope * bottomLineMiddleX + bottomLineB;
float leftLineMiddleX = (c4X + c1X) / 2.0f;
float leftLineMiddleY = leftLineSlope * leftLineMiddleX + leftLineB;
float rightLineMiddleX = (c2X + c3X) / 2.0f;
float rightLineMiddleY = rightLineSlope * rightLineMiddleX + rightLineB;
float topLineLeftX = (c1X + topLineMiddleX) / 2.0f;
float topLineLeftY = topLineSlope * topLineLeftX + topLineB;
float bottomLineLeftX = (c4X + bottomLineMiddleX) / 2.0f;
float bottomLineLeftY = bottomLineSlope * bottomLineLeftX + bottomLineB;
float topLineRightX = (topLineMiddleX + c2X) / 2.0f;
float topLineRightY = topLineSlope * topLineRightX + topLineB;
float bottomLineRightX = (c3X + bottomLineMiddleX) / 2.0f;
float bottomLineRightY = bottomLineSlope * bottomLineRightX + bottomLineB;
float leftLineTopX = (c1X + leftLineMiddleX) / 2.0f;
float leftLineTopY = leftLineSlope * leftLineTopX + leftLineB;
float rightLineTopX = (c2X + rightLineMiddleX) / 2.0f;
float rightLineTopY = rightLineSlope * rightLineTopX + rightLineB;
float leftLineBottomX = (leftLineMiddleX + c4X) / 2.0f;
float leftLineBottomY = leftLineSlope * leftLineBottomX + leftLineB;
float rightLineBottomX = (c3X + rightLineMiddleX) / 2.0f;
float rightLineBottomY = rightLineSlope * rightLineBottomX + rightLineB;
canvas.drawLine(topLineMiddleX, topLineMiddleY, bottomLineMiddleX, bottomLineMiddleY, dashedLine);
canvas.drawLine(leftLineMiddleX, leftLineMiddleY, rightLineMiddleX, rightLineMiddleY, dashedLine);
canvas.drawLine(topLineLeftX, topLineLeftY, bottomLineLeftX, bottomLineLeftY, dashedLine);
canvas.drawLine(topLineRightX, topLineRightY, bottomLineRightX, bottomLineRightY, dashedLine);
canvas.drawLine(leftLineTopX, leftLineTopY, rightLineTopX, rightLineTopY, dashedLine);
canvas.drawLine(leftLineBottomX, leftLineBottomY, rightLineBottomX, rightLineBottomY, dashedLine);
答案 0 :(得分:1)
如果不使用直线或斜率方程,这很容易。你所做的是通过找到x坐标对的平均值来计算所有x坐标。然后,您已将这些x坐标替换为边的方程。正如您所知,如果斜坡是无限的,这将不起作用。有一个非常简单的解决方案。您所要做的就是以与计算x坐标完全相同的方式计算y坐标,问题就消失了。
答案 1 :(得分:0)
如果它总是一个底边完全水平的矩形,你根本不需要使用斜面,只需在两个内部层从左到右画一条水平线,例如:
bottom + (top - bottom) / 3
bottom + 2 * (top - bottom) / 3
垂直线从上到下也是如此。
这基本上只是执行以下操作,假设左下角是距离原点最近的点:
hspread = (right - left) / 3
line (top, left + hspread) - (bottom, left + hspread)
line (top, left + 2 * hspread) - (bottom, left + 2 * hspread)
vspread = (top - bottom) / 3
line (bottom + vspread, left) - (bottom + vspread, right)
line (bottom + 2 * vspread, left) - (bottom + 2 * vspread, right)
如果角落可以独立移动(即,它不必是矩形),你仍然不需要让自己卷入斜坡。
然后你需要做的是找到沿着每条线相等于沿线的1/3和2/3距离的点,并加入它们。对于行(x1,y1)-(x2,y2)
,您只需使用以下命令就可以找到4/5
点:
x = x1 + (x2-x1) * 4/5
y = y1 + (y2-y1) * 4/5
例如,如果形状如此:
(x1,y1) (x2,y2)
___--+
+----' \
| \
| \
| \
| \
+----------------+
(x3,y3) (x4,y4)
:
:
:......
(0,0)
(“图形”的道歉),最上面的水平线可以画成:
line (x3 + (x1-x3) * 2/3, y3 + (y1-y3) * 2/3)
- (x4 + (x2-x4) * 2/3, y4 + (y2-y4) * 2/3)
这是我an earlier answer的更广义形式,可以找到给定线的中点。
因此,在这两种情况下,你所需要的只是一个基于起点和终点(你已经拥有)的线条绘制原语,没有可能无限斜率的混乱。
答案 2 :(得分:0)
在不了解该计划的情况下,我无法明确回答。也就是说,我对你可以尝试的事情有一些想法,但我有各自的问题:
我觉得很奇怪,当屏幕首次加载时,左右边缘等于无穷大。你的左右边缘位置是什么?它们是否提前存放?根据屏幕尺寸和密度?如果它基于屏幕尺寸,则您不应该遇到此问题。测量屏幕宽度如下(可能因Android版本而异,但有很多在线教程):
Display d = getWindowManager().getDefaultDisplay();
Point point = new Point();
d.getSize(point);
int width = point.x;
int height = point.y;
在计算任何东西之前都要有这些值。根据屏幕边缘调整初始坐标位置。
盒子每次都以相同的坐标开头吗?在您之前运行的应用之前,应用中是否有一个屏幕?如果两者都是这样,那么:
运行该方法的Activity / Fragment生命周期的哪个部分?如果您在onResume()中运行它,请尝试在周期的早期运行它的各个方面,或提前进行特殊计算。更具体地说:
您是否能够提供启动它的完整活动或片段以及方法的其余部分?
请注意,我只是简单地看一下数学本身,并没有发现任何问题,所以我会假设它很好,因为你说加载完成后没有问题。