use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.
the class VizSkelGen method toHalf.
private SuperFace toHalf(Loop<Point3d> loop) {
Cache<Point3d, Point2d> look = new Cach<>(x -> Pointz.to2(x));
HalfEdge last = null, first = null;
SuperFace out = new SuperFace();
for (Loopable<Point3d> edge : loop.loopableIterator()) {
SuperEdge e = new SuperEdge(look.get(edge.get()), look.get(edge.getNext().get()), null);
if (first == null)
first = e;
if (last != null)
last.next = e;
e.face = out;
// !
e.prof = null;
e.mini = Collections.EMPTY_LIST;
if (mode == Mode.Profiles)
for (Line l : footprint) {
if (l.absAngle(e.line()) < 0.1 && l.distance(e.start, true) < 1.5 && l.distance(e.end, true) < 1.5) {
SuperLine sl = (SuperLine) l;
MegaFacade mf = sl.getMega();
e.prof = findProf(e.start, e.end, sl, mf);
}
}
last = e;
}
last.next = first;
out.e = first;
SkelFootprint.meanModeHeightColor(Loopz.toXZLoop(loop), out, blockGen);
if (mode == Mode.CE) {
for (HalfEdge ee : out) {
SuperEdge e = (SuperEdge) ee;
Matrix4d m = new Matrix4d();
m.setIdentity();
e.prof = new Prof(m, new Vector3d());
e.prof.add(new Point2d(0, 0));
e.prof.add(new Point2d(0, out.height));
e.prof.add(new Point2d(-1, out.height + 1));
}
}
return out;
}
use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.
the class GurobiSkelSolver method solve.
public void solve() {
try {
for (HalfFace f : mesh.faces) for (HalfEdge e : f.edges()) {
edges.add(e);
totalEdgeLength += e.length();
}
print("total edge length " + totalEdgeLength);
progress.setProgress((int) (Math.random() * 90));
buildProblem();
model.getEnv().set(GRB.DoubleParam.TimeLimit, GRB.INFINITY);
long time = System.currentTimeMillis();
new Thread(() -> {
while (!gurobiDone) {
try {
Thread.sleep(300);
if ((System.currentTimeMillis() - time) / 1000 > maxTimeSecs) {
print("time's up");
model.terminate();
progress.close();
return;
}
} catch (InterruptedException e1) {
}
progress.setProgress((int) (Math.random() * 90));
if (progress.isCanceled()) {
print("user cancelled");
model.terminate();
}
}
progress.setProgress(100);
}).start();
try {
String file = Tweed.SCRATCH + "problem_" + System.currentTimeMillis() + ".mps";
new File(file).getParentFile().mkdirs();
model.write(file);
model.optimize();
} finally {
gurobiDone = true;
progress.setProgress(100);
}
print("time " + (System.currentTimeMillis() - time) / 1000. + " seconds");
if (model.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) {
print("Can't solve; won't solve");
return;
}
for (HalfFace f : mesh.faces) ((SuperFace) f).classification = index(faceInfo.get(f).color);
if (minis != null)
for (MegaFeatures mf : minis.keySet()) {
if (mega2clusters.containsKey(mf))
for (MiniPtCluster pt : mega2clusters.get(mf)) {
for (Map.Entry<MFPoint, MiniSelectEdge> selectPt : pt.entrySet()) {
for (Map.Entry<HalfEdge, GRBVar> selectEdge : selectPt.getValue().edge.entrySet()) {
if (selectEdge.getValue().get(GRB.DoubleAttr.X) > 0.5) {
HalfEdge e = selectEdge.getKey();
selectPt.getKey().selectedEdge = e;
selectPt.getKey().sameCluster = pt.keySet();
if (e.over != null && e.next.over == null) {
for (MFPoint p : pt.keySet()) ((SuperEdge) e.next).addMini(p.right);
for (MFPoint p : pt.keySet()) ((SuperEdge) e.over.findBefore()).addMini(p.left);
}
if (e.over == null && e.next.over == null) {
Line parallel = selectPt.getKey().mega.megafacade;
if (parallel.absAngle(e.line()) < parallel.absAngle(e.next.line()))
for (MFPoint p : pt.keySet()) ((SuperEdge) e).addMini(p.left);
else
for (MFPoint p : pt.keySet()) ((SuperEdge) e.next).addMini(p.right);
}
}
}
}
}
}
if (false)
for (HalfEdge he : edges) {
if (he.over != null && he.next.over == null) {
// face comes to boundary
boolean viz = false;
EdgeVars ei = edgeInfo.get(he);
if (ei.edgeNoMini != null) {
viz = true;
}
if (viz)
PaintThing.debug.put("dd", new Point2d(he.end));
}
}
if (globalProfs != null)
for (HalfEdge e : edges) {
EdgeVars ei = edgeInfo.get(e);
GRBVar plot = ei.debug;
if (plot != null) {
// && plot.get(GRB.DoubleAttr.X) > 0.5 ) {
Point2d o = new Point2d(e.end);
PaintThing.debug.put(1, o);
}
int p = index(ei.profile);
((SuperEdge) e).profI = p;
((SuperEdge) e).prof = p < 0 ? null : globalProfs.get(p);
}
dumpModelStats(edges);
model.getEnv().dispose();
model.dispose();
} catch (GRBException e) {
print("Error code: " + e.getErrorCode() + ". " + e.getMessage());
e.printStackTrace();
}
}
use of org.twak.utils.geom.HalfMesh2.HalfEdge 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++;
}
}
}
}
use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.
the class GurobiSkelSolver method buildBadGeom.
private void buildBadGeom(boolean isContraint) throws GRBException {
countBadCorners = countBadEdges = 0;
for (HalfEdge e1 : edges) {
if (e1.over != null && e1.next.over != null)
if (e1.line().absAngle(e1.next.line()) > Math.PI - TweedSettings.settings.badGeomAngle) {
notBoth(e1, e1.next, isContraint, totalEdgeLength * 0.5);
countBadCorners++;
}
}
// if over both h
for (HalfFace f : mesh) {
Set<HalfEdge> togo = new HashSet<>();
for (HalfEdge e : f) togo.add(e);
while (!togo.isEmpty()) {
HalfEdge start = togo.iterator().next();
togo.remove(start);
// if (start.over == null)
// continue;
boolean parallelHasOverProfile = start.over == null ? false : ((SuperEdge) start.over).profLine != null, oppositeHasOverProfile = false;
Line sl = start.line();
LinearForm slf = new LinearForm(sl);
Map<HalfFace, HalfEdge> parallel = new HashMap<>();
parallel.put(start.over == null ? null : start.over.face, start);
Iterator<HalfEdge> tig = togo.iterator();
while (tig.hasNext()) {
HalfEdge e2 = tig.next();
HalfFace f2 = e2.over == null ? null : e2.over.face;
if (sl.absAngle(e2.line()) < 0.05) {
// one from each non-f face
parallel.put(f2, e2);
tig.remove();
parallelHasOverProfile |= (e2.over != null && ((SuperEdge) e2.over).profLine != null);
}
}
Map<HalfFace, HalfEdge> opposite = new HashMap();
tig = togo.iterator();
while (tig.hasNext()) {
HalfEdge e2 = tig.next();
HalfFace f2 = e2.over == null ? null : e2.over.face;
if (// e2l.lengthSquared() > 1 &&
sl.absAngle(e2.line()) > Math.PI - 0.3 && (slf.distance(e2.start) < 0.3 || slf.distance(e2.end) < 0.3)) {
opposite.put(f2, e2);
tig.remove();
oppositeHasOverProfile |= (e2.over != null && ((SuperEdge) e2.over).profLine != null);
}
}
if (parallelHasOverProfile && oppositeHasOverProfile)
continue;
for (HalfEdge e1 : parallel.values()) for (HalfEdge e2 : opposite.values()) {
notBoth(e1, e2, isContraint, totalEdgeLength * 0.5);
countBadEdges++;
}
}
}
print(countBadCorners + " " + countBadEdges);
}
use of org.twak.utils.geom.HalfMesh2.HalfEdge in project chordatlas by twak.
the class ResultsGen method readMesh.
private MeshFile readMesh(File f, boolean plot) {
System.out.println("reading solution " + f.getParentFile().getName());
try {
SolverState SS = (SolverState) new XStream().fromXML(f);
for (HalfFace hf : SS.mesh) plansIn.incrementAndGet();
SkelFootprint.postProcesss(SS);
for (HalfFace hf : SS.mesh) {
plansOut.incrementAndGet();
for (HalfEdge e : hf) {
SuperEdge se = (SuperEdge) e;
if (se.proceduralFacade != null) {
meshFacades.getAndIncrement();
}
}
}
if (plot)
SS.debugSolverResult();
return new MeshFile(SS.mesh, f);
} catch (Throwable t) {
t.printStackTrace();
return null;
}
}
Aggregations