use of org.twak.utils.Pair in project chordatlas by twak.
the class Tube method tube.
public static void tube(MeshBuilder out, Collection<LinearForm3D> before, Collection<LinearForm3D> after, Line3d line, LinearForm3D left, LinearForm3D right, CrossGen gen) {
if (angle(before, line) < 0.1 || angle(after, line) < 0.1)
// too pointy to touch
return;
Point3d middle = line.fromPPram(0.5);
Vector3d along = line.dir();
along.normalize();
Vector3d nAlong = new Vector3d(along);
nAlong.negate();
Vector3d o1 = left.normal(), u1 = new Vector3d();
u1.cross(along, o1);
Frame frame = Mathz.buildFrame(o1, u1, along, middle);
Vector3d u2 = right.normal();
u2.cross(u2, along);
// u2.add( middle );
Vector2d leftDir = Mathz.toXY(frame, u1);
Vector2d rightDir = Mathz.toXY(frame, u2);
List<Point3d> profilePts = gen.gen(leftDir, rightDir).stream().map(p -> Mathz.fromXY(frame, p)).collect(Collectors.toList());
List<LinearForm3D> dummy = new ArrayList<>();
for (Pair<Point3d, Point3d> pair : new ConsecutivePairs<Point3d>(profilePts, true)) {
Point3d f1 = clip(pair.first(), along, after, dummy), f2 = clip(pair.second(), along, after, dummy), b1 = clip(pair.first(), nAlong, before, dummy), b2 = clip(pair.second(), nAlong, before, dummy);
out.add(f2, f1, b1, b2);
}
// cap( out, after , along, profilePts, true );
// cap( out, before, nAlong, profilePts, false );
}
use of org.twak.utils.Pair 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.Pair in project chordatlas by twak.
the class GreebleGrid method createDormerWindow.
protected void createDormerWindow(QuadF l, MeshBuilder window, MeshBuilder glass, float sillDepth, float sillHeight, float corniceHeight, double panelWidth, double panelHeight) {
Vector3d along = new Vector3d(l.corners[3]);
along.sub(l.corners[0]);
along.normalize();
Vector3d up = new Vector3d(0, 1, 0);
Vector3d out = new Vector3d();
out.cross(along, up);
out.scale(1 / out.length());
Line3d lout;
{
Point3d away = new Point3d(l.corners[0]);
away.add(out);
lout = new Line3d(new Point3d(l.corners[0]), away);
}
Vector3d loc = new Vector3d(l.found[0]);
if (lout.findPPram(l.found[0]) < lout.findPPram(l.found[1])) {
// outwards going wall...
loc = new Vector3d(up);
loc.scale(-l.original.height);
loc.add(l.found[1]);
}
{
Vector3d avoidRoof = new Vector3d(out);
avoidRoof.scale(0.09);
;
loc.add(avoidRoof);
}
Point3d deepest = Arrays.stream(l.found).map(p -> new Pair<Point3d, Double>(p, lout.findPPram(p))).max((a, b) -> b.second().compareTo(a.second())).get().first();
double depth = lout.closestPointOn(deepest, false).distance(lout.closestPointOn(new Point3d(loc), false));
// MUtils.max(
// Math.abs (l.corners[0].distance( l.found[0] )),
// Math.abs (l.corners[1].distance( l.found[1] )),
// Math.abs (l.corners[2].distance( l.found[2] )),
// Math.abs (l.corners[3].distance( l.found[3] ))
// ) ;
WindowGen.createWindow(window, glass, new Window(Jme3z.to(loc), Jme3z.to(along), Jme3z.to(up), l.original.width, l.original.height, depth, panelWidth, panelHeight));
// Vector3f u = Jme3z.to(up), o = Jme3z.to( out );
// if (sillDepth > 0)
// window.addCube( Jme3z.to ( ptt[0] ).add( u.mult( -sillHeight + 0.01f ) ).add( o.mult( -sillDepth) ),
// Jme3z.to(out), Jme3z.to(along), Jme3z.to(up),
// (float)depth + sillDepth, (float)winPanel.width,(float) sillHeight );
//
// if (corniceHeight > 0)
// moulding( to3d, new DRectangle(winPanel.x, winPanel.getMaxY(), winPanel.width, corniceHeight), wall );
}
use of org.twak.utils.Pair in project chordatlas by twak.
the class Regularizer method goDebug.
public List<MiniFacade> goDebug(List<MiniFacade> in, double debugFrac, MegaFeatures megaFeatures) {
miniFacadesUsed += in.size();
regularised++;
for (MiniFacade mf : in) if (mf.imageFeatures != null)
seenImages.add(mf.imageFeatures.ortho);
if (in.isEmpty())
return Collections.singletonList(gridMini());
System.out.println("starting to regularize " + in.size() + " facades...");
in = augmentWithTween(in, megaFeatures);
System.out.println(" adding tween for " + in.size() + " facades");
double alpha = 0.2;
List<MiniFacade> out;
if (true)
out = newFromWindows(in);
else
out = in.stream().map(mf -> new MiniFacade(mf)).collect(Collectors.toList());
System.out.println(" included grids for " + out.size() + " facades...");
if (debugFrac < 0) {
out.add(0, new MiniFacade());
return out;
}
alignMFs(out);
if (debugFrac == 0) {
out.add(0, new MiniFacade());
return out;
}
for (MiniFacade mf : out) {
assignFeaturesToWindows(mf.getRects(Feature.WINDOW, Feature.SHOP).stream().collect(Collectors.toList()), mf.rects);
mf.rects.get(Feature.CORNICE).clear();
mf.rects.get(Feature.BALCONY).clear();
mf.rects.get(Feature.SILL).clear();
mf.rects.get(Feature.GRID).clear();
}
for (MiniFacade mf : out) {
mergeRemoveSmall(mf);
mergeRemoveSimilar(mf);
}
for (Feature f : Feature.values()) for (MiniFacade mf : out) mf.rects.get(f).stream().forEach(r -> r.f = f);
for (int i = 0; i < 50 * debugFrac; i++) {
for (MiniFacade mf : out) for (Feature f : toReg) cluster1(mf.getRects(f), 1, alpha, Bounds.XMIN, Bounds.XMAX, Bounds.YMIN, Bounds.YMAX);
// for (MiniFacade mf : out)
// cluster1 ( mf.getRects(toReg), 1, alpha, Bounds.XMIN, Bounds.XMAX, Bounds.YMIN, Bounds.YMAX);
List<FRect> allRects = new ArrayList<>();
for (MiniFacade mf : out) for (Feature f : toReg) allRects.addAll(mf.rects.get(f));
for (Feature f : toReg) {
List<FRect> allF = out.stream().flatMap(mf -> mf.rects.get(f).stream()).collect(Collectors.toList());
cluster1(allF, 0.5, alpha, Bounds.WIDTH, Bounds.HEIGHT);
}
cluster1(allRects, 0.3, alpha, Bounds.XMIN, Bounds.XMAX, Bounds.YMIN, Bounds.YMAX);
if (i % 5 == 0)
for (MiniFacade mf : out) findNeighbours(mf.getRects(Feature.WINDOW));
for (Dir dir : Dir.values()) clusterDeltas(allRects, 0.2, alpha, dir);
for (MiniFacade mf : out) {
for (FRect d : mf.rects.get(Feature.DOOR)) constrainDoor(mf, d, alpha);
for (FRect m : mf.rects.get(Feature.MOULDING)) constrainMoulding(mf, m, alpha);
}
for (MiniFacade mf : out) {
for (Feature f : toReg) {
Iterator<FRect> rit = mf.rects.get(f).iterator();
while (rit.hasNext()) {
FRect r = rit.next();
if (r.width <= 0.4 || r.height <= 0.4)
rit.remove();
else
for (FRect n : r.adjacent) if (n != null && similar(n, r)) {
n.attached.putAll(r.attached);
rit.remove();
break;
}
}
}
}
}
if (debugFrac < 1) {
out.add(0, new MiniFacade());
return out;
}
for (MiniFacade mf : out) {
findOuters(mf);
mergeRemoveSmall(mf);
}
ids = 0;
for (// find ids...starting with the biggest
Feature f : // find ids...starting with the biggest
toReg) {
List<Pair<MiniFacade, FRect>> allRects = new ArrayList<>();
for (MiniFacade mf : out) for (FRect r : mf.rects.get(f)) allRects.add(new Pair<>(mf, r));
Collections.sort(allRects, new Comparator<Pair<MiniFacade, FRect>>() {
@Override
public int compare(Pair<MiniFacade, FRect> a_, Pair<MiniFacade, FRect> b_) {
FRect a = a_.second(), b = b_.second();
if (a.gridCoords != null && b.gridCoords == null)
return -1;
if (b.gridCoords != null && a.gridCoords == null)
return 1;
if (a.gridCoords != null && b.gridCoords != null) {
int out = -Integer.compare(countCoords(a.gridCoords), countCoords(b.gridCoords));
if (out != 0)
return out;
}
return Double.compare(a.area(), b.area());
}
private int countCoords(int[] gridCoords) {
int out = 0;
for (int i : gridCoords) if (i != -Integer.MAX_VALUE)
out++;
return out;
}
});
for (Pair<MiniFacade, FRect> pair : allRects) {
FRect w = pair.second();
if (w.id == -1)
findId(w, f, out, pair.first(), ids++);
}
}
out.add(0, combine(out));
totalFeature += out.get(0).getRects(Feature.values()).size();
System.out.println("done");
return out;
}
Aggregations