对 4 点图像变换施加限制
我正在为一个应用程序进行 4 点图像转换。用户可以拖动每个角来创建有效的四边形形状,或者使用其“边界框”垂直、水平和按比例调整其大小。
到目前为止,我已经完成了图像转换部分的工作。但是,我很难对其施加限制,以便......
- 顶点不会相互交叉。换句话说,我不允许用户创建沙漏形状。它必须始终是四边形。
- 同样,每个角之间的角度必须大于 0。否则,顶点将最终形成一条线。
- 此图像上有最小尺寸。也就是说,每个角必须彼此之间以及它们的相对线之间有一定的距离。
- 用户无法将图像“翻转”到其背面。 4 个角(p1、p2、p3 和 p4)必须按顺时针顺序出现。
- 凹风筝形状和三角形是有效的。
我想知道是否有关于这些问题的公式或论文。我目前有用于查找两条线段是否相交(以及相交位置)以及查找一条线上到另一点最近的点的公式。我的大多数实现并不像我喜欢的那样用户友好,因为在施加限制时角落会跳得到处都是。
PS 我在这个项目中使用 C# 和 DirectX。然而,该应用程序只是二维的。
I'm working on a 4-point image transformation for an application. The user would either drag each corner around to create a valid quadrilateral shape, or use its "bounding box" to resize it vertically, horizontally, and proportionally.
So far, I have the image transformation part working. However, I'm having a hard time imposing limitations to it so that...
- The vertices doesn't cross over each other. In another words, I don't allow the user to create an hour-glass shape. It must always be a quadrilateral.
- Likewise, the angle between each corner must be greater than 0. Otherwise, the vertices will end up in a line.
- It has a minimum size on this image. That is, each corner has to be a certain distance away from each other, and their opposing lines.
- The user cannot "flip" the image to its backside. The 4 corners (p1, p2, p3, and p4) must appear in clockwise order.
- Concave kite shapes and triangles are valid.
I was wondering if there was a formula or a paper regarding these issues. I do currently have the formulas for finding if 2 line segments intersect (and where), as well as finding the closest point on a line to another point. Most of my implementations hasn't been user-friendly as I liked, as the corners would jump all over the place when imposing restrictions.
P.S. I'm using C# for this project, with DirectX. The application is solely 2D, however.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我的建议是不要施加限制,而只是绘制一个红色线框多边形(如果对您来说这是不可接受的)。
这或多或少就像程序员对表单输入字段施加限制,例如开始日期必须早于结束日期,并且不允许您在开始字段中输入在结束字段中的日期之后的日期...强制用户首先按 Tab 键切换到结束字段,然后输入结束日期,然后按 Tab 键返回开始字段以输入正确的开始日期。
仅以红色显示字段更有用......并且实际上需要更少的编码。
捕获用户鼠标移动并不是一个明智的想法。如果您无法应用用户所要求的内容,只需让这一点变得明显,而不是限制移动...可能是用户正在移动第一个顶点,并希望稍后将另一个顶点移动到使您的变换有效的位置(与两个日期字段示例)。
如果您确实认为必须始终防止无效位置(例如,即使您的变换允许毫无问题的翻转操作,也会禁止用户翻转图像),那么我想到的最简单的解决方案就是有一个
isValid()
函数,如果关键点无效,则不会将其移动到新位置。在我看来,拥有围绕无效状态空间区域“滑动”的代码很难很好地处理,这也是因为无效区域将非常接近“几乎无效”区域。
即使“滑动”是一个要求,我也可能会通过围绕关键点位置进行本地搜索来实现隐式 isValid() 方法,以找到距离该点最近的有效点。用户正在要求。
如果您需要更改转换算法中的某些内容(从而更改有效和无效的内容),则显式计算所有滑动可能性将是一场噩梦,无论是正确还是维护。
My suggestion is not to impose restriction but just drawing say just a red wireframe polygon if for you it's unacceptable.
It's more or less like when programmers put restriction on form input fields e.g. begin date must come before end date and don't allow you to type in a date in the begin field that's after the date in the end field... forcing users to tab to end field first, then entering the end date, then tabbing back to the begin field to enter the correct begin date.
Just showing the fields in red is MUCH more usable... and actually requires less coding.
Trapping user mouse movements is rarely a sensible idea. If you can't apply what user is asking just make this evident instead of constraining the movement... may be the user is moving the first vertex and wants to move another vertex later to a position that will make your transform valid (exactly like the two date fields example).
If you really think you MUST prevent invalid positions at all times (and that for example will forbid the user from flipping the image even if your transform would allow a flipping operation without problems) then the simplest solution that comes to my mind is just having an
isValid()
function and just not moving the keypoint to the new position if it's invalid.Having code that "slides" around invalid state space areas is IMO quite difficult to handle nicely, also because invalid areas are going to be quite close to "almost invalid" areas.
Even in case "sliding" is a requirement I'd probably go for implementing an implicit
isValid()
approach by doing a local search around the keypoint position to find what is the closest valid point to the point the user is asking for.Explicitly computing all sliding possibilities would be a nightmare to get correct and also to maintain if you need to change something in the transformation algorithm (and consequently in what is valid and what is not).
开始时,每次用户移动手柄时,请确定其他手柄无法通过的一组水平线和垂直线,并在拖动过程中强制执行这些边界。这将解决您的第一个问题。
对于第二个,当鼠标在拖动过程中移动时,计算光标与其他 3 个手柄中每一个手柄之间的距离;如果它小于您定义的最小距离,则以围绕其他手柄的圆形路径移动手柄。
When you start out, and each time the user moves a handle, determine the set of horizontal and vertical lines that the other handles cannot pass, and enforce those boundaries during a drag. This will solve your first problem.
For the second, when the mouse moves during a drag, calculate the distance between the cursor and each of the other 3 handles; if it is less than your defined minimum distance then move the handle in a circular path around the other handle(s).