use of org.twak.utils.geom.DRectangle.Bounds in project chordatlas by twak.
the class Regularizer method cluster1.
private void cluster1(List<FRect> rects, double tol, double alpha, Bounds... axis) {
class Wrapper {
FRect rect;
public Wrapper(FRect rect) {
this.rect = rect;
}
public void set(double neu, Bounds b) {
double old = rect.get(b);
rect.set(b, neu * alpha + old * (1 - alpha));
}
}
if (rects.isEmpty())
return;
for (Bounds b : axis) {
List<Wrapper> toCluster = new ArrayList<>();
for (FRect r : rects) toCluster.add(new Wrapper(r));
DumbCluster1D<Wrapper> clusterer = new DumbCluster1D<Wrapper>(tol, toCluster) {
@Override
public double toDouble(Wrapper e) {
return e.rect.get(b);
}
};
for (DumbCluster1D.Cluster<Wrapper> e : clusterer) for (Wrapper w : e.things) w.set(e.mean, b);
}
}
use of org.twak.utils.geom.DRectangle.Bounds in project chordatlas by twak.
the class Regularizer method average.
private DRectangle average(FRect... rs_) {
FRect out = new FRect();
List<FRect> rs = new ArrayList();
for (FRect f : rs_) rs.add(f);
for (int r1 = 0; r1 < rs.size(); r1++) {
// overlapping features
FRect f1 = rs.get(r1);
for (int r2 = 0; r2 < rs.size(); r2++) {
FRect f2 = rs.get(r2);
if (r2 == r1 || f2.area() > f1.area())
continue;
double area = f2.union(f1).area();
if (area * 0.7 > f1.area()) {
rs.remove(r2);
if (r2 < r1)
r1--;
r2--;
}
}
}
// while (fit.hasNext()) {
// FRect i = fit.next();
//
// for (FRect f : new Array)
//
// }
boolean onlyInGrid = rs.stream().mapToInt(r -> r.outer == null ? 0 : 1).sum() >= 1;
for (Bounds b : new Bounds[] { Bounds.XMIN, Bounds.XMAX, Bounds.YMIN, Bounds.YMAX }) {
double norm = 0, avg = 0;
for (FRect r : rs) {
if (onlyInGrid && r.outer == null)
continue;
double sl = r.sideLength(b);
norm += sl;
avg += r.get(b) * sl;
}
out.set(b, avg / norm);
}
return out;
}
use of org.twak.utils.geom.DRectangle.Bounds in project chordatlas by twak.
the class MiniFacade method getDistance.
@Override
public double getDistance(Point2d pt) {
pt = flip(pt);
if (contains(pt))
return 0;
double dist = Double.MAX_VALUE;
for (Bounds b : new Bounds[] { XMIN, YMIN, XMAX, YMAX }) {
Line l = getAsRect().getEdge(b);
dist = Math.min(dist, l.distance(pt));
}
return dist;
}
use of org.twak.utils.geom.DRectangle.Bounds in project chordatlas by twak.
the class Regularizer method clusterDeltas.
private void clusterDeltas(List<FRect> rects, double tol, double alpha, Dir dir) {
if (rects.isEmpty())
return;
List<FRect> toCluster = new ArrayList<>();
for (FRect r : rects) {
FRect da = r.getAdj(dir);
if (// only strong adjacencies
da != null && da.getAdj(dir.opposite) == r)
toCluster.add(r);
}
DumbCluster1D<FRect> clusterer = new DumbCluster1D<FRect>(tol, toCluster) {
@Override
public double toDouble(FRect rect) {
return rect.distanceToAdjacent(dir);
}
};
Bounds b = (dir == Dir.L || dir == Dir.R) ? Bounds.XCEN : Bounds.YCEN;
int moveDirection = dir == Dir.L || dir == Dir.D ? 1 : -1;
Map<FRect, Double> desiredSpacings = new HashMap<>();
for (DumbCluster1D.Cluster<FRect> e : clusterer) {
for (FRect rect : e.things) desiredSpacings.put(rect, e.mean);
}
Collections.sort(rects, DRectangle.comparator(b, dir == Dir.L || dir == Dir.D ? false : true));
for (FRect r : rects) {
Double spacing = desiredSpacings.get(r);
if (spacing == null)
continue;
DRectangle adj = r.getAdj(dir);
adj.set(b, adj.get(b) - (spacing - r.distanceToAdjacent(dir)) * alpha * moveDirection);
}
}
use of org.twak.utils.geom.DRectangle.Bounds in project chordatlas by twak.
the class Regularizer method combine.
private MiniFacade combine(List<MiniFacade> in) {
MiniFacade out = new MiniFacade();
out.left = lp;
out.width = rp - lp;
out.imageFeatures = in.get(0).imageFeatures;
out.color = new double[] { 0, 0, 0, 1 };
out.groundColor = new double[] { 0, 0, 0, 1 };
int gcc = 0;
for (MiniFacade mf : in) for (int i = 0; i < 3; i++) {
out.color[i] += mf.color[i];
if (mf.groundColor != null) {
out.groundColor[i] += mf.groundColor[i];
gcc++;
}
}
for (int i = 0; i < 3; i++) {
out.color[i] /= in.size();
if (gcc > 0)
out.groundColor[i] /= gcc;
}
Cache2<Outer, Integer, List<FRect>> corniceX = new ArrayCache2();
Cache2<Outer, Integer, List<FRect>> sillX = new ArrayCache2();
Cache2<Outer, Integer, List<FRect>> balX = new ArrayCache2();
out.height = in.stream().mapToDouble(mf -> mf.height).average().getAsDouble();
out.groundFloorHeight = in.stream().mapToDouble(mf -> mf.groundFloorHeight).average().getAsDouble();
for (int i = 0; i < ids; i++) {
int yay = 0, nay = 0;
int ii = i;
List<FRect> found = in.stream().map(mf -> m2i2r.get(mf, ii)).filter(x -> x != null).flatMap(l -> l.stream()).collect(Collectors.toList());
Point2d avg = found.stream().map(r -> r.getCenter()).collect(new Point2DMeanCollector());
for (MiniFacade mf : in) {
List<FRect> r = m2i2r.get(mf, i);
if (mf.contains(avg)) {
if (r.isEmpty()) {
if (mf.left + 3 < avg.x && mf.left + mf.width - 3 > avg.x)
nay++;
} else
yay++;
}
}
if (yay >= nay) {
// if we believe it exists add it as average of observed sizes
FRect o;
if (dimensionSpread(found) > 1.4) {
// scattered -> union (typically shop windows)
o = new FRect(found.get(0));
for (FRect n : found) o.setFrom(o.union(n));
} else
// about same size: average position: windows on a grid
o = new FRect(average(found.toArray(new FRect[found.size()])));
{
FRect t = found.get(0);
o.f = t.f;
o.id = i;
o.outer = null;
o.attachedHeight.get(Feature.SILL).d = averageAttached(o, Feature.SILL, found);
o.attachedHeight.get(Feature.CORNICE).d = averageAttached(o, Feature.CORNICE, found);
o.attachedHeight.get(Feature.BALCONY).d = averageAttached(o, Feature.BALCONY, found);
if (t.f == Feature.WINDOW || t.f == Feature.SHOP) {
for (FRect r : found) {
corniceX.get(r.outer, r.yi).add(o);
sillX.get(r.outer, r.yi).add(o);
balX.get(r.outer, r.yi).add(o);
}
}
}
out.rects.put(o.f, o);
}
}
spreadAttachedOverGrid(Feature.SILL, sillX);
spreadAttachedOverGrid(Feature.CORNICE, corniceX);
spreadAttachedOverGrid(Feature.BALCONY, balX);
fixOverlaps(out);
mergeRemoveSmall(out);
DRectangle mr = out.getAsRect();
// ensure everything is comfortably within the bounds
mr.width -= 0.2;
mr.x += 0.1;
for (Feature f : Feature.values()) {
// clip to all
Iterator<FRect> rit = out.rects.get(f).iterator();
while (rit.hasNext()) {
FRect r = rit.next();
DRectangle section = r.intersect(mr);
if (section == null || section.area() < 0.5)
rit.remove();
else
r.setFrom(section);
}
}
{
// door height
Double hf = Double.valueOf(0);
while (out.groundFloorHeight < 6 && ((hf = horizontalEmpty(out, out.groundFloorHeight)) != null)) out.groundFloorHeight = hf + 0.3;
if (out.groundFloorHeight >= 6)
// no ground floor!
out.groundFloorHeight = 0;
}
return out;
}
Aggregations