use of org.twak.utils.Cache2 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;
}
use of org.twak.utils.Cache2 in project chordatlas by twak.
the class GurobiSkelSolver method buildProfiles.
private void buildProfiles() throws GRBException {
for (HalfEdge e : edges) {
if (// when a profile ends, we assume it can't start again...
((SuperEdge) e).profLine == null)
continue;
EdgeVars ev = edgeInfo.get(e);
ev.profile = new GRBVar[globalProfs.size()];
for (int p = 0; p < globalProfs.size(); p++) {
ev.profile[p] = model.addVar(0.0, 1.0, 0, GRB.BINARY, PROFILE_SELECT);
set(ev.profile[p], p == 0 ? 1 : 0);
}
}
Cache2<HalfEdge, HalfEdge, GRBVar> isProfileDifferent = new Cache2<HalfMesh2.HalfEdge, HalfMesh2.HalfEdge, GRBVar>() {
@Override
public GRBVar create(HalfEdge e1, HalfEdge e2) {
try {
GRBVar s = model.addVar(0.0, 1.0, 0.0, GRB.BINARY, PROFILE_DIFFERENT);
buildIsDifferentColor(s, edgeInfo.get(e1).profile, edgeInfo.get(e2).profile, "profile");
s.set(DoubleAttr.Start, 0);
return s;
} catch (GRBException e) {
e.printStackTrace();
}
return null;
}
};
for (HalfEdge e1 : edges) {
// if (e1.over != null)
// continue;
EdgeVars ev = edgeInfo.get(e1);
if (ev.profile == null)
continue;
double[] fit = profFit.get(e1);
GRBLinExpr pickOneProfile = new GRBLinExpr();
for (int p = 0; p < globalProfs.size(); p++) {
GRBVar a = ev.profile[p];
pickOneProfile.addTerm(1, a);
target.addTerm(.001 * fit[p] * e1.length(), a);
}
model.addConstr(pickOneProfile, GRB.EQUAL, 1, /*ev.isEdge*/
"pick only one profile for " + e1);
List<HalfEdge> atEnd = e1.collectAroundEnd();
for (HalfEdge e2 : atEnd) {
if (e1 != e2 && edgeInfo.get(e2).profile != null && // only constrain if ~parallel
e1.line().absAngle(e2.line()) < 0.1) {
GRBVar s = isProfileDifferent.get(e1, e2);
// ev.debug = s;
// Point2d dbg = new Point2d(e1.end);
// dbg.add(new Point2d(Math.random() * 0.1, Math.random() * 0.1));
GRBLinExpr perpIsEdge = new GRBLinExpr();
for (HalfEdge e3 : atEnd) {
if (e3 == e1 || e3 == e2 || e3 == e1.over || e3 == e2.over || (e3.over != null && (e3.over == e1.over || e3.over == e2.over)))
continue;
if (!e1.line().isOnLeft(e1.end.distanceSquared(e3.start) > e1.end.distanceSquared(e3.end) ? e3.start : e3.end))
continue;
perpIsEdge.addTerm(1, edgeInfo.get(e3).isEdge);
// PaintThing.debug.put(e2, dbg);
// Point2d d2 = new Point2d(e3.line().dir());
// d2.scale (0.1/new Vector2d(d2).length());
// d2.add(dbg);
// PaintThing.debug.put(e2, new Line (dbg, d2));
// model.addConstr( s, GRB.LESS_EQUAL, edgeInfo.get(e3).isEdge, "only change profile if no adjacent edge "+e1 );
}
model.addConstr(s, GRB.LESS_EQUAL, perpIsEdge, "dont' change profile over " + e1);
// PaintThing.debug.put(e2, dbg);
// Point2d d2 = new Point2d(e2.line().dir());
// d2.scale (0.2/new Vector2d(d2).length());
// d2.add(dbg);
// PaintThing.debug.put(e2, new Line (dbg, d2));
}
}
}
countNearbyProfiles = 0;
if (false)
for (int i = 0; i < edges.size(); i++) {
HalfEdge e1 = edges.get(i);
if (edgeInfo.get(e1).profile == null)
continue;
print("building edge locality term " + i + " / " + edges.size());
for (HalfEdge e2 : edges) if (lt(e1, e2) && edgeInfo.get(e2).profile != null) {
if (e1.line().distance(e2.line()) < 2) {
GRBVar s = isProfileDifferent.get(e1, e2);
target.addTerm(0.1 * (e1.length() + e2.length()), s);
countNearbyProfiles++;
}
}
}
}
Aggregations