use of org.twak.utils.collections.ConsecutiveItPairs in project chordatlas by twak.
the class Concarnie method apply.
private List<Problem> apply(Problem problem, int count) {
if (depth > 10 || problem.soup.isEmpty()) {
problem.addPortal();
return Collections.emptyList();
}
Set<Line> portals = new HashSet<>();
Set<Line> in = new HashSet<>(problem.soup);
for (Line sl : problem.hull) {
RangeMerge<Line> rm = new RangeMerge<>(P.CON_TOL, P.CON_TOL);
LinearForm lf = new LinearForm(sl);
for (Line l : problem.soup) {
if (onHull(sl, l)) {
double pps = lf.findPParam(l.start), ppe = lf.findPParam(l.end);
rm.add(pps, ppe, l);
in.remove(l);
}
}
List<Double> rmGet = rm.get();
if (rmGet.isEmpty()) {
if (!sl.start.equals(sl.end)) {
if (Double.isNaN(sl.start.x))
System.out.println("help!");
// whole thing is portal
portals.add(sl);
}
} else {
List<Point2d> occupied = new ArrayList();
{
double lf1 = lf.findPParam(sl.start), lf2 = lf.findPParam(sl.end);
if (lf1 > lf2) {
double tmp = lf1;
lf1 = lf2;
lf2 = tmp;
}
for (double d : rmGet) {
d = Mathz.clamp(d, lf1, lf2);
occupied.add(lf.fromPParam(d));
}
}
boolean onHull = false;
{
Point2d snapE = occupied.get(0), snapS = occupied.get(occupied.size() - 1);
if (snapS.distance(sl.start) < P.CON_TOL)
snapS.set(sl.start);
else {
occupied.add(new Point2d(sl.start));
}
if (snapE.distance(sl.end) < P.CON_TOL)
snapE.set(sl.end);
else {
occupied.add(0, new Point2d(sl.end));
onHull = true;
}
}
for (Pair<Point2d, Point2d> pair : new ConsecutiveItPairs<Point2d>(occupied)) {
onHull = !onHull;
if (pair.first().equals(pair.second()))
continue;
Line line = new Line(pair.first(), pair.second());
if (onHull) {
if (depth % 2 == 0)
line = line.reverse();
graph.add(line);
} else {
portals.add(line.reverse());
}
}
}
}
if (in.size() == problem.soup.size()) {
// we didn't do anything! remove something, anything...
List<Line> d = new ArrayList(in);
Collections.sort(d, (a, b) -> Double.compare(a.length(), b.length()));
for (// remove the shortest 1/3 lines
int i = 0; // remove the shortest 1/3 lines
i < Math.max(1, in.size() * 0.33); // remove the shortest 1/3 lines
i++) in.remove(d.get(i));
}
List<Portal> mergedPortals = mergeConsecutive(portals);
// assign each member of in to a portal
MultiMapSet<Portal, Line> subproblems = new MultiMapSet();
if (!mergedPortals.isEmpty()) {
// O(n^3) closest-clique assignment
MultiMapSet<Portal, Line> sub2 = new MultiMapSet();
for (Portal p : mergedPortals) sub2.putAll(p, p.lines);
while (!in.isEmpty()) {
double bestDist = Double.MAX_VALUE;
Portal bestP = null;
Line bestL = null;
for (Line l : in) for (Portal p : sub2.keySet()) for (Line sl : sub2.get(p)) {
double dlsl = l.distance(sl);
if (// ignore lines a long way away
dlsl > Math.max(P.CON_TOL * 3, p.length * 0.5))
continue;
double dist = dlsl + 0.1 * l.distance(p.summary);
if (dist < bestDist) {
bestP = p;
bestDist = dist;
bestL = l;
}
}
if (bestL == null)
break;
in.remove(bestL);
double lenBestL = bestL.length();
if (lenBestL > P.CON_TOL && lenBestL > 0.5 * bestP.summary.length()) {
in.add(new Line(bestL.start, bestL.fromPPram(0.5)));
in.add(new Line(bestL.fromPPram(0.5), bestL.end));
} else {
subproblems.put(bestP, bestL);
sub2.put(bestP, bestL);
}
}
} else {
mergedPortals.add(null);
subproblems.putAll(null, in);
}
return mergedPortals.stream().map(x -> new Problem(x == null ? Collections.emptyList() : x.lines, subproblems.get(x))).collect(Collectors.toList());
}
use of org.twak.utils.collections.ConsecutiveItPairs in project chordatlas by twak.
the class Prof method render.
public void render(Tweed tweed, Node gNode, ColorRGBA color, float width) {
Mesh m = new Mesh();
m.setMode(Mesh.Mode.Lines);
List<Float> coords = new ArrayList();
List<Integer> inds = new ArrayList();
for (Pair<Point3d, Point3d> p : new ConsecutiveItPairs<>(get3D())) {
inds.add(inds.size());
inds.add(inds.size());
coords.add((float) p.first().x);
coords.add((float) p.first().y);
coords.add((float) p.first().z);
coords.add((float) p.second().x);
coords.add((float) p.second().y);
coords.add((float) p.second().z);
}
m.setBuffer(VertexBuffer.Type.Position, 3, Arrayz.toFloatArray(coords));
m.setBuffer(VertexBuffer.Type.Index, 2, Arrayz.toIntArray(inds));
Geometry geom = new Geometry("profile", m);
Material lineMaterial = new Material(tweed.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
lineMaterial.getAdditionalRenderState().setLineWidth(Math.max(1f, width));
lineMaterial.setColor("Color", color == null ? ColorRGBA.Blue : color);
geom.setMaterial(lineMaterial);
geom.updateGeometricState();
geom.updateModelBound();
gNode.attachChild(geom);
}
use of org.twak.utils.collections.ConsecutiveItPairs in project chordatlas by twak.
the class Prof method verticalLength.
protected Double verticalLength(double tol) {
double length = 0;
for (Pair<Point2d, Point2d> pts : new ConsecutiveItPairs<>(this)) {
Line line = new Line(pts.first(), pts.second());
double angle = line.aTan2();
if (angle > Mathz.PI2 - tol && angle < Mathz.PI2 + tol)
length += line.length();
}
return length;
}
use of org.twak.utils.collections.ConsecutiveItPairs in project chordatlas by twak.
the class Prof method renderStrip.
public Mesh renderStrip(double width, Point3d point3d) {
Mesh m = new Mesh();
m.setMode(Mesh.Mode.Triangles);
List<Float> coords = new ArrayList();
List<Integer> inds = new ArrayList();
Vector3d perp = new Vector3d(dir);
perp.scale(width / 2);
Point3d delta = new Point3d();
if (point3d != null) {
delta.set(point3d);
delta.sub(to3d(get(0)));
}
for (Pair<Point3d, Point3d> p : new ConsecutiveItPairs<>(get3D())) {
int o = coords.size() / 3;
inds.add(o + 0);
inds.add(o + 1);
inds.add(o + 2);
inds.add(o + 2);
inds.add(o + 1);
inds.add(o + 0);
inds.add(o + 1);
inds.add(o + 3);
inds.add(o + 2);
inds.add(o + 2);
inds.add(o + 3);
inds.add(o + 1);
Point3d a1 = new Point3d(p.first()), a2 = new Point3d(p.first()), b1 = new Point3d(p.second()), b2 = new Point3d(p.second());
a1.add(delta);
a2.add(delta);
b1.add(delta);
b2.add(delta);
a1.sub(perp);
a2.add(perp);
b1.sub(perp);
b2.add(perp);
for (Point3d pt : new Point3d[] { a1, a2, b1, b2 }) {
coords.add((float) pt.x);
coords.add((float) pt.y);
coords.add((float) pt.z);
}
}
{
Point3d p1 = to3d(get(size() - 1)), p2 = to3d(get(size() - 1));
Point2d arrowT = new Point2d(get(size() - 1)), arrowB = null;
for (int e = size() - 2; e >= 0; e--) if (!get(e).equals(get(size() - 1))) {
arrowB = new Point2d(get(e));
break;
}
if (arrowB != null) {
arrowT.sub(arrowB);
arrowT.scale(width * 1.3 / new Vector2d(arrowT).length());
arrowT.add(get(size() - 1));
Point3d p3 = to3d(arrowT);
p1.add(perp);
p2.sub(perp);
p1.add(delta);
p2.add(delta);
p3.add(delta);
int o = coords.size() / 3;
inds.add(o + 0);
inds.add(o + 1);
inds.add(o + 2);
inds.add(o + 2);
inds.add(o + 1);
inds.add(o + 0);
for (Point3d pt : new Point3d[] { p1, p2, p3 }) {
coords.add((float) pt.x);
coords.add((float) pt.y);
coords.add((float) pt.z);
}
}
}
m.setBuffer(VertexBuffer.Type.Position, 3, Arrayz.toFloatArray(coords));
m.setBuffer(VertexBuffer.Type.Index, 2, Arrayz.toIntArray(inds));
return m;
}
Aggregations