use of org.twak.utils.Line in project chordatlas by twak.
the class SkelFootprint method minMax.
private static double[] minMax(double expand, List<Line> footprint) {
double[] out = new double[] { Double.MAX_VALUE, -Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE };
for (Line l : footprint) {
out[0] = Math.min(l.start.x, out[0]);
out[1] = Math.max(l.start.x, out[1]);
out[2] = Math.min(l.start.y, out[2]);
out[3] = Math.max(l.start.y, out[3]);
}
out[0] -= expand;
out[1] += expand;
out[2] -= expand;
out[3] += expand;
return out;
}
use of org.twak.utils.Line in project chordatlas by twak.
the class SkelFootprint method fractureOnFeatures.
private void fractureOnFeatures(MultiMap<MegaFeatures, MFPoint> minis, List<Line> footprint, HalfMesh2 mesh) {
for (MegaFeatures mf : minis.keySet()) pt: for (MFPoint pt : minis.get(mf)) {
if (!Mathz.inRange(mf.megafacade.findPPram(pt), 0, 1))
continue;
Vector2d dir = pt.mega.megafacade.dir();
dir.set(dir.y, -dir.x);
Point2d probe = new Point2d(dir);
probe.scale(2 / dir.length());
probe.add(pt);
for (// don't fracture near minifacade boundaries...we can't distinguish nice block bondaries
Point2d avoid : // don't fracture near minifacade boundaries...we can't distinguish nice block bondaries
pt.mega.megafacade.points()) if (avoid.distanceSquared(pt) < 4)
continue pt;
double bestDist = Double.MAX_VALUE;
for (HalfFace f : mesh.faces) for (HalfEdge e : f) if (e.line().dir().angle(dir) < 0.4) {
double dist = e.line().distance(probe);
if (dist < bestDist)
bestDist = dist;
}
if (bestDist > 0.3) {
Vector2d end = new Vector2d(dir);
end.scale(3 / end.length());
end.add(probe);
Vector2d start = new Vector2d(dir);
start.scale(0.5 / start.length());
start.add(pt);
Line extra = new Line(new Point2d(start), new Point2d(end));
SkelFootprint.insert(mesh, extra, 2, false, false);
}
}
}
use of org.twak.utils.Line in project chordatlas by twak.
the class LineGen method calculate.
@Override
public void calculate() {
for (Spatial s : gNode.getChildren()) s.removeFromParent();
Mesh m = new Mesh();
m.setMode(Mesh.Mode.Lines);
List<Float> coords = new ArrayList();
List<Integer> inds = new ArrayList();
for (Line l : getLines()) {
inds.add(inds.size());
inds.add(inds.size());
coords.add((float) l.start.x);
coords.add(0f);
coords.add((float) l.start.y);
coords.add((float) l.end.x);
coords.add(0f);
coords.add((float) l.end.y);
}
m.setBuffer(VertexBuffer.Type.Position, 3, Arrayz.toFloatArray(coords));
m.setBuffer(VertexBuffer.Type.Index, 2, Arrayz.toIntArray(inds));
geom = new Geometry(filename, m);
Material lineMaterial = new Material(tweed.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
lineMaterial.setColor("Color", new ColorRGBA(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1f));
geom.setMaterial(lineMaterial);
for (Spatial s : gNode.getChildren()) s.removeFromParent();
geom.setLocalTranslation(0, height * 30, 0);
gNode.attachChild(geom);
geom.updateModelBound();
super.calculate();
}
use of org.twak.utils.Line in project chordatlas by twak.
the class ProfileGen method findMegaFaces.
private List<MegaFacade> findMegaFaces(double delta) {
SliceParameters P = new SliceParameters(SLICE_SCALE);
List<LineAtHeight> lines = new ArrayList();
Map<Integer, LineSoup> slices = new HashMap<>();
for (int hi = 0; getHeight(hi) < extent[3]; hi++) {
int _i = hi;
boolean error;
int count = 0;
do {
error = false;
try {
LineSoup soup = new LineSoup(ObjSlice.sliceTri(blockGen.getCroppedMesh(), getHeight(hi), majorAxis));
FindLines foundLines = new FindLines(soup, TweedSettings.settings.useGis ? gisBias : null, -1, null, P);
foundLines.result.all.stream().forEach(x -> lines.add(new LineAtHeight(_i, delta, x, foundLines.result.all)));
slices.put(hi, foundLines.result);
} catch (Throwable th) {
th.printStackTrace();
error = true;
}
} while (error && count++ < 10);
}
Collections.sort(lines, new LAHComparator());
// new Plot(lines.stream().map (lah -> lah.line).collect(Collectors.toList() ), gis);
faces = new ArrayList<>();
while (!lines.isEmpty()) {
System.out.println("clustering megafacdes " + lines.size());
// longest line
LineAtHeight start = lines.get(0);
lines.remove(start);
MegaFacade face = new MegaFacade(start);
Set<LineAtHeight> toProcess = new HashSet<>();
toProcess.add(start);
while (!toProcess.isEmpty()) {
LineAtHeight lah = toProcess.iterator().next();
toProcess.remove(lah);
for (int _pmDelta : new int[] { -2, -1, 1, 2 }) {
int hi = lah.height + _pmDelta;
LineSoup ls = slices.get(hi);
if (ls != null) {
for (Line l : ls.all) {
double lps = start.line.findPPram(l.start), lpe = start.line.findPPram(l.end);
double overlap = 0;
if (lpe < lps)
overlap = 0;
else if (lps > face.minP && lpe < face.maxP || lps < face.minP && lpe > face.maxP)
overlap = 1;
else if (lps < face.minP && lpe > face.minP)
overlap = (lpe - face.minP) / (lpe - lps);
else if (lps < face.maxP && lpe > face.maxP)
overlap = (face.maxP - lps) / (lpe - lps);
double angle = l.absAngle(start.line);
if (overlap > 0.8 && angle < 0.3 || overlap > 0.5 && /* 0.1 for aggressive clustering */
angle < 0.1) {
// if (overlap > 0.1 && angle < 0.5 ) {
if (l.distance(lah.line) < delta * TweedSettings.settings.megafacacadeClusterGradient) {
LineAtHeight toProc = new LineAtHeight(hi, l);
if (lines.contains(toProc)) {
toProcess.add(toProc);
face.put(hi, l);
lines.remove(toProc);
// bit strange: depends on the processing order of the set
face.minP = Mathz.min(face.minP, lps);
face.maxP = Mathz.max(face.maxP, lpe);
}
}
}
}
}
}
}
if (face.values().stream().flatMap(x -> x.stream()).count() > 5)
faces.add(face);
else
System.out.println("skipping small megafacade");
}
Collections.sort(faces);
processMegaFaces();
return faces;
}
Aggregations