- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个我自己创建的平面图。我想找到这个图的面,但我找不到这样做的工作算法。到目前为止我所做的是使用一种算法来查找图中的所有循环,但这给了我所有可能的循环,我已经尝试过但没有找到一种方法来只对面部进行排序。我的一个想法是使用 Path2Ds contains
方法来查看另一个形状是否重叠,但由于面共享节点,这不起作用。下图展示了我想要的内容,之后的代码展示了我的可复制示例。
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class PolygonFinder {
// Graph modeled as list of edges
static int[][] graph
= {
{1, 2}, {1, 6}, {1, 5}, {2, 6},
{2, 3}, {3, 7}, {7, 4}, {3, 4},
{5, 4}, {6, 5}
};
static List<int[]> cycles = new ArrayList<>();
/**
* @param args
*/
public static void main(String[] args) {
for (int[] graph1 : graph) {
for (int j = 0; j < graph1.length; j++) {
findNewCycles(new int[]{graph1[j]});
}
}
cycles.stream().map(cy -> {
String s = "" + cy[0];
for (int i = 1; i < cy.length; i++) {
s += "," + cy[i];
}
return s;
}).forEachOrdered(s -> {
System.out.println(s);
});
}
static void findNewCycles(int[] path) {
int n = path[0];
int x;
int[] sub = new int[path.length + 1];
for (int[] graph1 : graph) {
for (int y = 0; y <= 1; y++) {
if (graph1[y] == n) {
x = graph1[(y + 1) % 2];
if (!visited(x, path)) // neighbor node not on path yet
{
sub[0] = x;
System.arraycopy(path, 0, sub, 1, path.length);
// explore extended path
findNewCycles(sub);
} else if ((path.length > 2) && (x == path[path.length - 1])) // cycle found
{
int[] p = normalize(path);
int[] inv = invert(p);
if (isNew(p) && isNew(inv)) {
cycles.add(p);
}
}
}
}
}
}
// check of both arrays have same lengths and contents
static Boolean equals(int[] a, int[] b) {
Boolean ret = (a[0] == b[0]) && (a.length == b.length);
for (int i = 1; ret && (i < a.length); i++) {
if (a[i] != b[i]) {
ret = false;
}
}
return ret;
}
// create a path array with reversed order
static int[] invert(int[] path) {
int[] p = new int[path.length];
for (int i = 0; i < path.length; i++) {
p[i] = path[path.length - 1 - i];
}
return normalize(p);
}
// rotate cycle path such that it begins with the smallest node
static int[] normalize(int[] path) {
int[] p = new int[path.length];
int x = smallest(path);
int n;
System.arraycopy(path, 0, p, 0, path.length);
while (p[0] != x) {
n = p[0];
System.arraycopy(p, 1, p, 0, p.length - 1);
p[p.length - 1] = n;
}
return p;
}
// compare path against known cycles
// return true, iff path is not a known cycle
static Boolean isNew(int[] path) {
Boolean ret = true;
for (int[] p : cycles) {
if (equals(p, path)) {
ret = false;
break;
}
}
return ret;
}
// return the int of the array which is the smallest
static int smallest(int[] path) {
int min = path[0];
for (int p : path) {
if (p < min) {
min = p;
}
}
return min;
}
// check if vertex n is contained in path
static Boolean visited(int n, int[] path) {
Boolean ret = false;
for (int p : path) {
if (p == n) {
ret = true;
break;
}
}
return ret;
}
}
运行上述代码后的结果是:
1,6,2
1,5,6,2
1,5,4,7,3,2
1,6,5,4,7,3,2
1,5,4,3,2
1,6,5,4,3,2
1,5,4,7,3,2,6
1,5,4,3,2,6
1,5,6
2,3,7,4,5,6
2,3,4,5,6
3,4,7
我解决这个问题的最佳尝试之一是使用以下代码。坐标来自顶部的图片。
List<Polygon> polys = new LinkedList<>();
Polygon p1 = new Polygon();
p1.addPoint(new Point2D.Double(-4, 4));
p1.addPoint(new Point2D.Double(-1, 3));
p1.addPoint(new Point2D.Double(-1, 5));
Polygon p2 = new Polygon();
p2.addPoint(new Point2D.Double(-4, 4));
p2.addPoint(new Point2D.Double(0, -2));
p2.addPoint(new Point2D.Double(-1, 3));
p2.addPoint(new Point2D.Double(-1, 5));
Polygon p3 = new Polygon();
p3.addPoint(new Point2D.Double(-4, 4));
p3.addPoint(new Point2D.Double(0, -2));
p3.addPoint(new Point2D.Double(4, 1));
p3.addPoint(new Point2D.Double(2, 2));
p3.addPoint(new Point2D.Double(3, 4));
p3.addPoint(new Point2D.Double(-1, 5));
Polygon p4 = new Polygon();
p4.addPoint(new Point2D.Double(-4, 4));
p4.addPoint(new Point2D.Double(-1, 3));
p4.addPoint(new Point2D.Double(0, -2));
p4.addPoint(new Point2D.Double(4, 1));
p4.addPoint(new Point2D.Double(2, 2));
p4.addPoint(new Point2D.Double(3, 4));
p4.addPoint(new Point2D.Double(-1, 5));
Polygon p5 = new Polygon();
p5.addPoint(new Point2D.Double(-4, 4));
p5.addPoint(new Point2D.Double(0, -2));
p5.addPoint(new Point2D.Double(4, 1));
p5.addPoint(new Point2D.Double(3, 4));
p5.addPoint(new Point2D.Double(-1, 5));
Polygon p6 = new Polygon();
p6.addPoint(new Point2D.Double(-4, 4));
p6.addPoint(new Point2D.Double(-1, 3));
p6.addPoint(new Point2D.Double(0, -2));
p6.addPoint(new Point2D.Double(4, 1));
p6.addPoint(new Point2D.Double(3, 4));
p6.addPoint(new Point2D.Double(-1, 5));
Polygon p7 = new Polygon();
p7.addPoint(new Point2D.Double(-4, 4));
p7.addPoint(new Point2D.Double(0, -2));
p7.addPoint(new Point2D.Double(4, 1));
p7.addPoint(new Point2D.Double(2, 2));
p7.addPoint(new Point2D.Double(3, 4));
p7.addPoint(new Point2D.Double(-1, 5));
p7.addPoint(new Point2D.Double(-1, 3));
Polygon p8 = new Polygon();
p8.addPoint(new Point2D.Double(-4, 4));
p8.addPoint(new Point2D.Double(0, -2));
p8.addPoint(new Point2D.Double(4, 1));
p8.addPoint(new Point2D.Double(3, 4));
p8.addPoint(new Point2D.Double(-1, 5));
p8.addPoint(new Point2D.Double(-1, 3));
Polygon p9 = new Polygon();
p9.addPoint(new Point2D.Double(-4, 4));
p9.addPoint(new Point2D.Double(0, -2));
p9.addPoint(new Point2D.Double(-1, 3));
Polygon p10 = new Polygon();
p10.addPoint(new Point2D.Double(-1, 5));
p10.addPoint(new Point2D.Double(3, 4));
p10.addPoint(new Point2D.Double(2, 2));
p10.addPoint(new Point2D.Double(4, 1));
p10.addPoint(new Point2D.Double(0, -2));
p10.addPoint(new Point2D.Double(-1, 3));
Polygon p11 = new Polygon();
p11.addPoint(new Point2D.Double(-1, 5));
p11.addPoint(new Point2D.Double(3, 4));
p11.addPoint(new Point2D.Double(4, 1));
p11.addPoint(new Point2D.Double(0, -2));
p11.addPoint(new Point2D.Double(-1, 3));
Polygon p12 = new Polygon();
p12.addPoint(new Point2D.Double(3, 4));
p12.addPoint(new Point2D.Double(4, 1));
p12.addPoint(new Point2D.Double(2, 2));
polys.add(p1);
polys.add(p2);
polys.add(p3);
polys.add(p4);
polys.add(p5);
polys.add(p6);
polys.add(p7);
polys.add(p8);
polys.add(p9);
polys.add(p10);
polys.add(p11);
polys.add(p12);
Set<Integer> toRemove = new HashSet<>();
for (Polygon polyI : polys) {
for (Polygon polyJ : polys) {
if (polyI.equals(polyJ)) {
continue;
}
if (polyI.contains(polyJ)) {
toRemove.add(polys.indexOf(polyI));
}
}
}
List<Integer> list = new LinkedList<>(toRemove);
Collections.sort(list);
Collections.reverse(list);
list.forEach((t) -> {
polys.remove(t.intValue());
});
System.out.println("");
polys.forEach((t) -> {
System.out.println(t.getPoints());
});
此处列出了使用的多边形方法。
@Override
public boolean contains(Point2D point) {
return getPath().contains(point);
}
@Override
public boolean contains(IPolygon polygon) {
List<Point2D> p2Points = polygon.getPoints();
for (Point2D point : p2Points) {
if (getPath().contains(point)) {
if (!points.contains(point)) {
return true;
}
}
}
return false;
}
private Path2D getPath() {
Path2D path = new Path2D.Double();
path.moveTo(points.get(0).getX(), points.get(0).getY());
for (int i = 1; i < points.size(); i++) {
path.lineTo(points.get(i).getX(), points.get(i).getY());
}
path.closePath();
return path;
}
这段代码给了我下面的结果,不需要第 2-4 个。
[Point2D.Double[-4.0, 4.0], Point2D.Double[-1.0, 3.0], Point2D.Double[-1.0, 5.0]]
[Point2D.Double[-4.0, 4.0], Point2D.Double[0.0, -2.0], Point2D.Double[-1.0, 3.0], Point2D.Double[-1.0, 5.0]]
[Point2D.Double[-4.0, 4.0], Point2D.Double[-1.0, 3.0], Point2D.Double[0.0, -2.0], Point2D.Double[4.0, 1.0], Point2D.Double[2.0, 2.0], Point2D.Double[3.0, 4.0], Point2D.Double[-1.0, 5.0]]
[Point2D.Double[-4.0, 4.0], Point2D.Double[0.0, -2.0], Point2D.Double[4.0, 1.0], Point2D.Double[2.0, 2.0], Point2D.Double[3.0, 4.0], Point2D.Double[-1.0, 5.0], Point2D.Double[-1.0, 3.0]]
[Point2D.Double[-4.0, 4.0], Point2D.Double[0.0, -2.0], Point2D.Double[-1.0, 3.0]]
[Point2D.Double[-1.0, 5.0], Point2D.Double[3.0, 4.0], Point2D.Double[2.0, 2.0], Point2D.Double[4.0, 1.0], Point2D.Double[0.0, -2.0], Point2D.Double[-1.0, 3.0]]
[Point2D.Double[3.0, 4.0], Point2D.Double[4.0, 1.0], Point2D.Double[2.0, 2.0]]
最佳答案
Math.atan2(y2-y1,x2-x1)
给出。import java.awt.geom.Point2D;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.text.MessageFormat;
public class GraphFaces
{
static class Vertex
{
final int index;
final Point2D point;
final ArrayList<Edge> outboundEdges = new ArrayList<>();
public Vertex( final int index, final Point2D point )
{
this.index = index;
this.point = point;
}
public void addEdge( final Edge edge )
{
this.outboundEdges.add( edge );
}
public void sortEdges()
{
this.outboundEdges.sort((e1,e2)->Double.compare(e1.angle,e2.angle));
Edge prev = this.outboundEdges.get(this.outboundEdges.size() - 1);
for ( final Edge edge: this.outboundEdges )
{
edge.setNextEdge( prev );
prev = edge;
}
}
@Override
public String toString()
{
return Integer.toString(this.index);
// return MessageFormat.format("({0},{1})",this.point.getX(),this.point.getY());
}
}
static class Edge
{
final Vertex from;
final Vertex to;
final double angle;
boolean visited = false;
Edge next = null;
Edge reverse = null;
public Edge( final Vertex from, final Vertex to )
{
this.from = from;
this.to = to;
this.angle = Math.atan2(to.point.getY() - from.point.getY(), to.point.getX() - from.point.getX());
from.addEdge( this );
}
public Vertex getFrom()
{
return this.from;
}
public Vertex getTo()
{
return this.to;
}
public void setNextEdge( final Edge edge )
{
this.next = edge;
}
public void setReverseEdge( final Edge edge )
{
this.reverse = edge;
}
@Override
public String toString()
{
return MessageFormat.format("{0} -> {1}", this.from, this.to);
}
}
public static void main(final String[] args)
{
final Vertex[] vertices = {
new Vertex( 1, new Point2D.Double(-4,+4) ),
new Vertex( 2, new Point2D.Double(-1,+5) ),
new Vertex( 3, new Point2D.Double(+3,+4) ),
new Vertex( 4, new Point2D.Double(+4,+1) ),
new Vertex( 5, new Point2D.Double(+0,-2) ),
new Vertex( 6, new Point2D.Double(-1,+3) ),
new Vertex( 7, new Point2D.Double(+2,+2) )
};
final int[][] graph = {
{1, 2}, {1, 6}, {1, 5}, {2, 6}, {2, 3}, {3, 7}, {7, 4}, {3, 4}, {5, 4}, {6, 5}
};
final Edge[] edges = new Edge[2 * graph.length];
for ( int i = 0; i < graph.length; i++ )
{
final Vertex from = vertices[graph[i][0]-1];
final Vertex to = vertices[graph[i][1]-1];
edges[2*i] = new Edge( from, to );
edges[2*i+1] = new Edge( to, from );
edges[2*i].setReverseEdge(edges[2*i+1]);
edges[2*i+1].setReverseEdge(edges[2*i]);
}
for ( final Vertex vertex: vertices )
{
vertex.sortEdges();
}
final ArrayList<ArrayList<Edge>> faces = new ArrayList<>();
for ( final Edge edge: edges )
{
if ( edge.visited )
{
continue;
}
final ArrayList<Edge> face = new ArrayList<>();
faces.add( face );
Edge e = edge;
do
{
face.add(e);
e.visited = true;
e = e.reverse.next;
}
while (e != edge);
System.out.println( face.stream().map(Edge::getFrom).collect(Collectors.toList()) );
}
}
}
哪些输出:
[1, 2, 3, 4, 5]
[2, 1, 6]
[6, 1, 5]
[2, 6, 5, 4, 7, 3]
[3, 7, 4]
关于用于在图中查找人脸的 Java 算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67097270/
我在为 MacOSX 构建的独立包中添加 DMG 背景的自定义图标时遇到问题。我在项目的根目录中添加了一个包。正在从中加载自定义图标,但没有加载 DMG 背景图标。我正在使用 Java fx 2.2.
Qt for Symbian 和 Qt for MeeGo 有什么区别?我知道 Qt 是一个交叉编译平台。这是否意味着如果我使用来自 Qt 的库,完全相同的库可以在所有支持 Qt 的设备(例如 Sym
我正在尝试使用 C# .NET 3.5/4.0 务实地运行 SQL Server 数据库的备份。我已经找到了如何完成此操作,但是我似乎找不到用于备份的命名空间库。 我正在寻找 Microsoft.Sq
我最近在疯狂学习 Java,但我通常是一名 .NET 开发人员。 (所以请原谅我的新手问题。) 在 .Net 中,我可以在不使用 IIS 的情况下开发 ASP.Net 页面,因为它有一个简化的 Web
这post仅当打印命令中有字符串时才有用。现在我有大量的源代码,其中包含一条声明,例如 print milk,butter 应该格式化为 print(milk,butter) 用\n 捕获行尾并不成功
所以我的问题是: https://gist.github.com/panSarin/4a221a0923927115584a 当我保存这个表格时,我收到了标题中的错误 NoMethodError (u
如何让 Html5 音频在点击时播放声音? (ogg 用于 Firefox 等浏览器,mp3 用于 chrome 等浏览器) 到目前为止,我可以通过 onclick 更改为单个文件类型,但我无法像在普
如果it1和it2有什么区别? std::set s; auto it1 = std::inserter(s, s.begin()); auto it2 = std::inserter(s, s.en
4.0.0 com.amkit myapp SpringMVCFirst
我目前使用 Eclipse 作为其他语言的 IDE,而且我习惯于不必离开 IDE 做任何事情 - 但是我真的很难为纯 ECMAScript-262 找到相同或类似的设置。 澄清一下,我不是在寻找 DO
我想将带有字符串数组的C# 结构发送到C++ 函数,该函数接受void * 作为c# 结构和char** 作为c# 结构字符串数组成员。 我能够将结构发送到 c++ 函数,但问题是,无法从 c++ 函
我正在使用动态创建的链接: 我想为f:param附加自定义转换器,以从#{name}等中删除空格。 但是f:param中没有转换器
是否可以利用Redis为.NET创建后写或直写式缓存?理想情况下,透明的高速缓存是由单个进程写入的,并且支持从数据库加载丢失的数据,并每隔一段时间持久保存脏块? 我已经搜查了好几个小时,也许是goog
我正在通过bash执行命令的ssh脚本。 FILENAMES=( "export_production_20200604.tgz" "export_production_log_2020060
我需要一个正则表达式来出现 0 到 7 个字母或 0 到 7 个数字。 例如:匹配:1234、asdbs 不匹配:123456789、absbsafsfsf、asf12 我尝试了([a-zA-Z]{0
我有一个用于会计期间的表格,该表格具有期间结束和开始的开始日期和结束日期。我使用此表来确定何时发生服务交易以及何时在查询中收集收入,例如... SELECT p.PeriodID, p.FiscalY
我很难为只接受字符或数字的 Laravel 构建正则表达式验证。它是这样的: 你好<-好的 123 <- 好的 你好123 <-不行 我现在的正则表达式是这样的:[A-Za-z]|[0-9]。 reg
您实际上会在 Repeater 上使用 OnItemDataBound 做什么? 最佳答案 “此事件为您提供在客户端显示数据项之前访问数据项的最后机会。引发此事件后,数据项将被清空,不再可用。” ~
我有一个 fragment 工作正常的项目,我正在使用 jeremyfeinstein 的 actionbarsherlock 和滑动菜单, 一切正常,但是当我想自定义左侧抽屉列表单元格时,出现异常
最近几天,我似乎平均分配时间在构建我的第一个应用程序和在这里发布问题!! 这是我的第一个应用程序,也是我们的设计师完成的第一个应用程序。我试图满足他所做的事情的外观和感觉,但我认为他没有做适当的事情。
我是一名优秀的程序员,十分优秀!