use of org.twak.utils.geom.HalfMesh2 in project chordatlas by twak.
the class SkelFootprint method removeExposedFaces.
public static void removeExposedFaces(HalfMesh2 mesh) {
System.out.println("removing exposed faces....");
Set<HalfFace> togo = new HashSet<>(mesh.faces);
while (!togo.isEmpty()) {
// for ( HalfFace hf : new ArrayList<HalfFace>( mesh.faces ) ) {
HalfFace hf = togo.iterator().next();
togo.remove(hf);
double exposed = 0, safe = 0;
for (HalfEdge e : hf.edges()) {
if (e.over == null && ((SuperEdge) e).profLine == null)
exposed += e.length();
else
safe += e.length();
}
if (exposed > exposedFaceFrac * safe) {
togo.addAll(hf.getNeighbours());
hf.remove(mesh);
}
}
}
use of org.twak.utils.geom.HalfMesh2 in project chordatlas by twak.
the class SkelFootprint method boundMesh.
public static HalfMesh2 boundMesh(List<Line> footprint) {
double[] minMax = minMax(10, footprint);
HalfMesh2.Builder builder = new HalfMesh2.Builder(SuperEdge.class, SuperFace.class);
builder.newPoint(new Point2d(minMax[0], minMax[3]));
builder.newPoint(new Point2d(minMax[1], minMax[3]));
builder.newPoint(new Point2d(minMax[1], minMax[2]));
builder.newPoint(new Point2d(minMax[0], minMax[2]));
builder.newFace();
HalfMesh2 mesh = builder.done();
return mesh;
}
use of org.twak.utils.geom.HalfMesh2 in project chordatlas by twak.
the class SkelFootprint method calcProfFit.
// private static Prof boringProf( double h ) {
// Prof prof = Prof.buildProfile( new Line3d( new Point3d( 0, 0, 0 ), new Point3d( 1, 0, 0 ) ), new Point3d( 0, 0, 0 ) );
// prof.add(new Point2d (0,0));
// prof.add(new Point2d (0,h));
// return prof;
// }
private void calcProfFit(HalfMesh2 mesh, List<Prof> globalProfs, Map<SuperEdge, double[]> out, ProgressMonitor m) {
System.out.println("Building F...");
boolean[] used = new boolean[globalProfs.size()];
Map<SuperEdge, double[]> tmp = new HashMap();
double[] noData = new double[globalProfs.size()];
Arrays.fill(noData, 0);
noData[0] = -1;
used[0] = true;
for (int i = 0; i < mesh.faces.size(); i++) {
// System.out.println( "calculating profile fit for face " + i + "/" + mesh.faces.size() );
HalfFace f = mesh.faces.get(i);
for (HalfEdge e : f) {
double[] fits = new double[globalProfs.size()];
for (int g = 0; g < fits.length; g++) {
Double d = meanDistance(globalProfs.get(g), (SuperEdge) e);
if (d == null || Double.isNaN(d)) {
fits = noData;
break;
} else
fits[g] = d;
}
tmp.put((SuperEdge) e, fits);
used[Arrayz.min(fits)] = true;
}
if (m.isCanceled())
return;
}
Arrays.fill(used, true);
int count = 0;
for (boolean u : used) if (u)
count++;
for (Map.Entry<SuperEdge, double[]> e : tmp.entrySet()) {
double[] fits = new double[count];
int c = 0;
for (int i = 0; i < e.getValue().length; i++) if (used[i])
fits[c++] = e.getValue()[i];
out.put(e.getKey(), fits);
}
for (int g = globalProfs.size() - 1; g >= 0; g--) if (!used[g])
globalProfs.remove(g);
}
use of org.twak.utils.geom.HalfMesh2 in project chordatlas by twak.
the class SkelFootprint method dbgShowProfiles.
private void dbgShowProfiles(HalfMesh2 mesh, List<Prof> globalProfs, Map<SuperEdge, double[]> profFit, String name) {
Node n = new Node();
Jme3z.removeAllChildren(n);
int colI = 0;
for (HalfFace f : mesh) {
ColorRGBA col = Jme3z.toJme(Rainbow.getColour(colI++));
colI = colI % 6;
Material mat = new Material(tweed.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setColor("Diffuse", col);
mat.setColor("Ambient", col);
mat.setBoolean("UseMaterialColors", true);
if (true) {
Loop<Point3d> loop = new Loop<>();
for (HalfEdge e : f) loop.append(new Point3d(e.start.x, 0, e.start.y));
MeshBuilder mb = new MeshBuilder();
mb.add(loop.singleton(), null, false);
Geometry g = new Geometry("floorplan", mb.getMesh());
g.setMaterial(mat);
n.attachChild(g);
}
for (HalfEdge e : f) {
SuperEdge se = (SuperEdge) e;
Prof bestProf = null;
if (globalProfs == null)
bestProf = se.prof;
else {
// if (se.profLine != null) {
//
// SuperLine sl = ((SuperLine)se.profLine);
// MegaFacade mf = (MegaFacade) sl.properties.get( MegaFacade.class.getName() );
//
// List<Prof> pfs = mf.getTween( se.start, se.end, 0.3 );
//
// if (!pfs.isEmpty())
// bestProf = Prof.parameterize( sl, pfs );
// else {
// bestProf = clean.get( 0 );
// double bestScore = Double.MAX_VALUE;
//
// for ( Prof c : clean ) {
//
// double score = 0;
// boolean good = false;
// for ( Prof r : mf.getTween( se.start, se.end, 0.3 ) ) {
// score += c.distance( r, true, false, true );
// good = true;
// }
// if ( good && score < bestScore ) {
// bestScore = score;
// bestProf = c;
// }
//
// }
// }
//
//
// }
// if (bestProf)
// ((SuperLine))
//
double[] fitV = profFit.get(se);
if (fitV == null)
continue;
double bestScore = Double.MAX_VALUE;
for (int ii = 0; ii < fitV.length; ii++) {
double d = fitV[ii];
if (d < bestScore) {
bestScore = d;
bestProf = globalProfs.get(ii);
}
}
//
// double bestScore = Double.MAX_VALUE;
//
// for ( int ii = 0; ii < fitV.length; ii++ ) {
// double d = fitV[ ii ];
// if ( d < bestScore ) {
// bestScore = d;
// bestProf = globalProfs.get( ii );
// }
// }
// if (false)
// se.prof = bestProf;
}
if (bestProf != null) {
Geometry g = new Geometry();
Point3d cen = Pointz.to3(se.line().fromPPram(0.5));
Prof goodOrientation = Prof.buildProfile(Pointz.to3(se.line()), cen);
for (Point2d p : bestProf) goodOrientation.add(p);
g.setMesh(goodOrientation.renderStrip(1.5, cen));
g.setMaterial(mat);
n.attachChild(g);
g.updateGeometricState();
g.updateModelBound();
}
}
}
skelGen.tweed.frame.addGen(new JmeGen(name, tweed, n), false);
}
use of org.twak.utils.geom.HalfMesh2 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