use of org.twak.tweed.Tweed in project chordatlas by twak.
the class GreebleCGA method cga.
protected double cga(Loop<Point2d> rect, Matrix4d to3d, WallTag wallTag, MeshBuilder normalWall, MeshBuilder ground, Cache<float[], MeshBuilder> mbs, List<DRectangle> occlusions) {
double[] bounds = Loopz.minMax2d(rect);
GreebleGrid gg = new GreebleGrid(tweed, new MMeshBuilderCache());
DRectangle all = new DRectangle(bounds[0], bounds[2], bounds[1] - bounds[0], bounds[3] - bounds[2]);
// for (DRectangle d : occlusions)
// mbs.get( new float[] {1,1,0,1} ).add( d, to3d );
float[] windowColor = new float[] { 0.8f, .8f, 0.8f, 1 }, glassColor = new float[] { 0.3f, 0.3f, 1, 1 }, mouldingColor = new float[] { 0.7f, .7f, 0.7f, 1 };
double groundFloorHeight = 0;
List<DRectangle> floors = all.splitY(r -> splitFloors(r, 3, 2.5, 2));
for (int f = 0; f < floors.size(); f++) {
boolean isGround = f == 0 && wallTag.isGroundFloor;
DRectangle floor = floors.get(f);
MeshBuilder wall = isGround ? ground : normalWall;
List<DRectangle> edges = floor.splitX(r -> split3(r, 1, 1));
if (isGround)
groundFloorHeight = floor.height;
if (edges.size() != 3) {
wall.add(floor, to3d);
} else {
wall.add(edges.get(0), to3d);
wall.add(edges.get(edges.size() - 1), to3d);
DRectangle cen = edges.get(1);
if (cen.height < 1.8)
wall.add(cen, to3d);
else {
if (f == 0 && wallTag.isGroundFloor) {
List<DRectangle> groundPanel = cen.splitX(r -> split1(r, 0.9));
if (groundPanel.get(0).width < 0.7)
wall.add(groundPanel.get(0), to3d);
else if (wallTag.makeDoor) {
List<DRectangle> doorHeight = groundPanel.get(0).splitY(r -> split1(r, 2.2));
if (visible(doorHeight.get(0), occlusions))
greebleGrid.createDoor(doorHeight.get(0), to3d, wall, mbs.get(windowColor), wallTag.doorDepth);
else
wall.add(doorHeight.get(0), to3d);
if (doorHeight.size() > 1)
wall.add(doorHeight.get(1), to3d);
if (groundPanel.size() > 1) {
List<DRectangle> gWindowPanelH = groundPanel.get(1).splitX(r -> split3(r, 0.5, 0.0));
if (gWindowPanelH.size() > 2) {
wall.add(gWindowPanelH.get(0), to3d);
wall.add(gWindowPanelH.get(2), to3d);
List<DRectangle> gWindowPanelV = gWindowPanelH.get(1).splitY(r -> split3(r, 0.5, 0.5));
if (gWindowPanelV.size() > 2) {
wall.add(gWindowPanelV.get(0), to3d);
wall.add(gWindowPanelV.get(2), to3d);
if (visible(gWindowPanelV.get(1), occlusions))
greebleGrid.createWindow(gWindowPanelV.get(1), to3d, wall, mbs.get(windowColor), mbs.get(glassColor), wallTag.windowDepth, -1, -1, -1, 0.6, 0.9);
else
wall.add(gWindowPanelV.get(1), to3d);
} else
for (DRectangle d : gWindowPanelV) wall.add(d, to3d);
} else
for (DRectangle d : gWindowPanelH) wall.add(d, to3d);
}
} else
windowStrip(to3d, wallTag, mbs.get(windowColor), mbs.get(glassColor), wall, cen, false, occlusions, greebleGrid);
} else {
windowStrip(to3d, wallTag, mbs.get(windowColor), mbs.get(glassColor), wall, cen, f > 0 && f < floors.size() - 1 && wallTag.makeBalcony, occlusions, greebleGrid);
if (f == 1 && wallTag.isGroundFloor)
greebleGrid.moulding(to3d, new DRectangle(floor.x, floor.y, floor.width, 0.5), mbs.get(mouldingColor));
}
}
}
}
return groundFloorHeight;
}
use of org.twak.tweed.Tweed in project chordatlas by twak.
the class FacadeTool method renderFacades.
private void renderFacades(Node gNode, String blockName, FacadeFinder ff) {
Thread thread = new Thread() {
@Override
public void run() {
File blockFile = new File(Tweed.DATA + File.separator + FeatureCache.FEATURE_FOLDER + File.separator + blockName);
if (GISGen.mode == Mode.RENDER_SELECTED_BLOCK)
try {
FileUtils.deleteDirectory(blockFile);
} catch (IOException e1) {
e1.printStackTrace();
}
for (int mfi = 0; mfi < ff.results.size(); mfi++) {
ToProjMega tpm = ff.results.get(mfi);
if (tpm.size() == 0 || tpm.stream().mapToInt(x -> tpm.size()).sum() == 0)
continue;
File megaFolder = new File(blockFile, "" + mfi);
megaFolder.mkdirs();
try {
new XStream().toXML(tpm.megafacade, new FileOutputStream(new File(megaFolder, LINE_XML)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// print a list of panoramas on this side.
// List<Double> rots = new ArrayList();
//
// for (ToProject tp : tpm)
// for ( Pano pano : tp.toProject ) {
// ImagePlaneGen pg = new ImagePlaneGen( tweed, (float) tp.e.x, (float) tp.e.y, (float) tp.s.x, (float) tp.s.y, (float) tp.minHeight, (float) tp.maxHeight, tp.toProject );
// pg.fudgeToDepth( pixelsPerMeter, pano, rots );
// }
//
double rot = 0;
// if (!rots.isEmpty())
// rot = biggestClusterMean(rots);// rots.stream().mapToDouble( x -> x ).average().getAsDouble();
// System.out.println ( "avg rot was "+rot );
List<BufferedImage> images = new ArrayList<>();
for (int fc = 0; fc < tpm.size(); fc++) {
// if (mfi != 2 || fc != 0)
// continue;
ToProject tp = tpm.get(fc);
// if (!tp.toProject.iterator().next().name.contains( "hfhGoIsR24hezjXpuIqklw" ))
// continue;
System.out.println("mega " + mfi + " pano " + fc);
File imageFolder;
String imageFilename = null;
// if ( GISGen.mode == Mode.RENDER_SELECTED_FACADE ) {
imageFolder = new File(megaFolder, "" + fc);
imageFilename = FeatureCache.RENDERED_IMAGE;
// }
// else
// imageFolder = new File( blockName );
imageFolder.mkdirs();
if (tp.toProject.size() != 1)
throw new Error();
ImagePlaneGen pg = new ImagePlaneGen(tweed, (float) tp.e.x, (float) tp.e.y, (float) tp.s.x, (float) tp.s.y, (float) tp.minHeight, (float) tp.maxHeight, tp.toProject);
if (GISGen.mode != Mode.RENDER_ALL_BLOCKS)
tweed.frame.addGen(pg, true);
for (Pano pano_ : tp.toProject) {
Pano pano = new Pano(pano_);
pano.set(pano.oa1 - (float) rot, pano.oa2, pano.oa3);
if (imageFilename == null)
imageFilename = new File(pano.name).getName() + "_" + tpm.megafacade.start + "_" + tpm.megafacade.end;
BufferedImage bi = pg.render(imageFolder, pixelsPerMeter, pano, tpm.megafacade, imageFilename);
if (GISGen.mode == Mode.RENDER_SELECTED_BLOCK)
images.add(bi);
try {
FileWriter out = new FileWriter(new File(imageFolder, "meta.txt"));
out.write(pixelsPerMeter * 10 + " " + (tp.s.distance(tp.e) * pixelsPerMeter - pixelsPerMeter * 20) + " " + (tp.maxHeight - tp.minHeight) * pixelsPerMeter + "\n");
out.write(pg.toString() + "\n");
out.write(pano.orig.getName() + "\n");
Point2d cen = tpm.megafacade.project(new Point2d(pano.location.x, pano.location.z), false);
out.write(tp.s.x + " " + tp.s.y + " " + tp.e.x + " " + tp.e.y + " " + cen.x + " " + cen.y + " " + pano.location.x + " " + pano.location.z + "\n");
out.close();
} catch (Throwable th) {
th.printStackTrace();
}
}
}
if (GISGen.mode == Mode.RENDER_SELECTED_BLOCK)
Imagez.writeSummary(new File(megaFolder, "summary.png"), images);
}
}
};
if (GISGen.mode == Mode.RENDER_SELECTED_BLOCK)
thread.start();
else
thread.run();
}
use of org.twak.tweed.Tweed in project chordatlas by twak.
the class GreebleSkel method createMesh.
public void createMesh(Output output) {
float[] roofColor = new float[] { 0.3f, 0.3f, 0.3f, 1 }, wallColor = new float[] { 228 / 255f, 223 / 255f, 206 / 255f, 1.0f };
if (output.faces == null)
return;
double bestWallArea = 0, bestRoofArea = 0;
for (Face f : output.faces.values()) {
double area = Loopz.area3(f.getLoopL());
Tag t = getTag(f.profile, RoofTag.class);
if (t != null && area > bestRoofArea && ((RoofTag) t).color != null) {
roofColor = ((RoofTag) t).color;
bestRoofArea = area;
}
t = getTag(f.profile, WallTag.class);
if (t != null && area > bestWallArea && ((WallTag) t).color != null) {
wallColor = ((WallTag) t).color;
bestWallArea = area;
}
}
greebleGrid = new GreebleGrid(tweed, mbs = new MMeshBuilderCache());
output.addNonSkeletonSharedEdges(new RoofTag(roofColor));
edges(output, roofColor);
for (List<Face> chain : Campz.findChains(output)) {
// for ( Face f : output.faces.values() )
// mbs.get(roofColor).add3d( Loopz.insertInnerEdges( f.getLoopL() ), zToYup );
Optional<Tag> opt = chain.stream().flatMap(f -> f.profile.stream()).filter(tag -> tag instanceof WallTag).findAny();
WallTag wt = null;
Set<QuadF> features = new HashSet<>();
MiniFacade mf = null;
if (opt.isPresent() && (wt = (WallTag) opt.get()).miniFacade != null) {
MiniFacade mf2 = new MiniFacade(wt.miniFacade);
Line facadeLine;
{
Edge e = chain.get(0).edge;
// we might rotate the facade to apply a set of features to a different side of the building.
facadeLine = new Line(e.end.x, e.end.y, e.start.x, e.start.y);
}
if (TweedSettings.settings.snapFacadeWidth) {
// move/scale mf horizontally from mean-image-location to mesh-facade-location
double[] meshSE = findSE(wt.miniFacade, facadeLine, chain);
mf2.scaleX(meshSE[0], meshSE[1]);
}
// find window locations in 3 space
mf2.rects.values().stream().flatMap(f -> f.stream()).map(r -> new QuadF(r, facadeLine)).forEach(q -> features.add(q));
mf = mf2;
}
for (Face f : chain) {
face(f, mf, features, roofColor, wallColor);
}
for (QuadF w : features) if ((w.original.f == Feature.WINDOW || w.original.f == Feature.SHOP) && w.foundAll()) {
greebleGrid.createDormerWindow(w, mbs.WOOD, mbs.GLASS, (float) wt.sillDepth, (float) wt.sillHeight, (float) wt.corniceHeight, 0.6, 0.9);
}
// for ( String mName : mbs.cache.keySet() )
// for (float[] mCol : mbs.cache.get( mName ).keySet() )
// node.attachChild( mb2Geom( output, chain, mName, mCol ) );
greebleGrid.attachAll(node, chain, output, new ClickMe() {
@Override
public void clicked(Object data) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
selected(output, node, findSuperEdge(output, chain));
}
});
} catch (Throwable th) {
th.printStackTrace();
}
}
});
}
}
use of org.twak.tweed.Tweed in project chordatlas by twak.
the class GISGen method importMesh.
private void importMesh(int index) {
LoopL<Point3d> polies = blocks.get(index);
List<Vector2D> verts = polies.stream().flatMap(ll -> ll.streamAble()).map(x -> {
Line3d l = new Line3d(x.get(), x.getNext().get());
l.move(perp(l.dir(), EXPAND_MESH));
return new Vector2D(l.start.x, l.start.z);
}).collect(Collectors.toList());
double tol = 0.0001;
ConvexHull2D chull = null;
while (tol < 10) {
try {
chull = new MonotoneChain(false, tol).generate(verts);
tol = 1000;
} catch (ConvergenceException e) {
tol *= 10;
}
}
if (chull == null) {
System.out.println("unable to find hull");
return;
}
Loop<Point3d> hull = new Loop<Point3d>((Arrays.stream(chull.getLineSegments()).map(x -> new Point3d(x.getStart().getX(), 0, x.getStart().getY())).collect(Collectors.toList())));
File root = new File(Tweed.SCRATCH + "meshes" + File.separator);
int i = 0;
File l;
while ((l = new File(root, "" + i)).exists()) i++;
l.mkdirs();
File croppedFile = new File(l, CROPPED_OBJ);
boolean found = false;
for (Gen gen : tweed.frame.gens(MiniGen.class)) {
// minigen == optimised obj
((MiniGen) gen).clip(hull, croppedFile);
found = true;
}
if (!found)
for (Gen gen : tweed.frame.gens(MeshGen.class)) {
// obj == just import whole obj
ObjGen objg = (ObjGen) gen;
try {
Files.asByteSource(objg.getFile()).copyTo(Files.asByteSink(croppedFile));
objg.setVisible(false);
found = true;
} catch (IOException e) {
e.printStackTrace();
}
}
if (found) {
Graph2D g2 = new Graph2D();
polies.stream().flatMap(ll -> ll.streamAble()).forEach(x -> g2.add(new Point2d(x.get().x, x.get().z), new Point2d(x.getNext().get().x, x.getNext().get().z)));
g2.removeInnerEdges();
// new Plot (true, g2 );
UnionWalker uw = new UnionWalker();
for (Point2d p : g2.map.keySet()) for (Line line : g2.map.get(p)) uw.addEdge(line.end, line.start);
// new Plot (true, new ArrayList( uw.map.keySet()) );
Loopz.writeXZObj(uw.findAll(), new File(l, "gis.obj"), true);
Loopz.writeXZObj(Loopz.to2dLoop(polies, 1, null), new File(l, "gis_footprints.obj"), false);
BlockGen bg = new BlockGen(l, tweed, polies);
lastMesh.put(index, bg);
tweed.frame.addGen(bg, true);
tweed.frame.setSelected(bg);
} else
JOptionPane.showMessageDialog(tweed.frame(), "Failed to find mesh from minimesh or gml layers");
}
Aggregations