use of org.twak.viewTrace.SuperLine in project chordatlas by twak.
the class ProfileGen method processMegaFaces.
private void processMegaFaces() {
addOnJmeThread.clear();
if (faces == null || faces.isEmpty()) {
JOptionPane.showMessageDialog(tweed.frame(), "Failed to cluster facades");
return;
}
Node mfNode = new Node();
// Node cProfileNode = new Node();
Random randy = new Random(2);
dbgProfileLookup.clear();
final boolean DBG = true;
computeProfiles(faces);
int i = 0;
for (MegaFacade mf : faces) {
// if (i == 4)
{
System.out.println("building profiles over megafacade " + i + "/" + faces.size());
ColorRGBA dispCol = new ColorRGBA(color.getRed() * randy.nextFloat() / 255f, color.getGreen() * randy.nextFloat() / 255f, color.getBlue() * randy.nextFloat() / 255f, 1);
if (DBG) {
List<Line3d> dbg = new ArrayList();
for (int d : mf.keySet()) {
for (Line l2 : mf.get(d)) {
Line3d oLine = new Line3d(l2.start.x, getHeight(d), l2.start.y, l2.end.x, getHeight(d), l2.end.y);
dbg.add(oLine);
}
}
mfNode.attachChild(Jme3z.lines(tweed.getAssetManager(), dbg, dispCol, 0.1f, true));
Line l2 = mf.origin.line;
Line3d oLine = new Line3d(l2.start.x, getHeight(mf.origin.height), l2.start.y, l2.end.x, getHeight(mf.origin.height), l2.end.y);
// mfNode.attachChild( Jme3z.lines( tweed.getAssetManager(), Collections.singletonList( oLine ), dispCol, 0.5f, true ) );
}
{
Line l3 = mf.origin.line;
// if ( mf.profiles.values().stream().mapToDouble( p -> p.get( 0 ).y ).min().getAsDouble() > 8 )
// continue;
totalPlanLineLength += l3.length();
Line3d oLine = new Line3d(l3.start.x, getHeight(mf.origin.height), l3.start.y, l3.end.x, getHeight(mf.origin.height), l3.end.y);
List<SuperLine> pLines = Prof.findProfileLines(mf.profiles.values(), oLine);
for (int pi = 0; pi < pLines.size(); pi++) {
SuperLine profileLine = pLines.get(pi);
// if ( distance ( gis, profileLine.start ) > 2 || distance ( gis, profileLine.end ) > 2 )
// continue;
Node profileNode = new Node();
// dispCol = new ColorRGBA( randy.nextFloat(), randy.nextFloat(), randy.nextFloat(), 1 );
MegaFacade pMF = mf.moveTo(profileLine);
if (pi >= 1) {
Line newOrigin = null;
double bestDist = Double.MAX_VALUE;
Point3d plCen = Pointz.to3(profileLine.fromPPram(0.5), getHeight(mf.hExtentMin));
for (int li = mf.hExtentMin; li <= mf.hExtentMax; li++) for (Line l : mf.get(li)) {
double dist = Pointz.to3(l.fromPPram(0.5), getHeight(li)).distance(plCen);
if (dist < bestDist) {
newOrigin = l;
bestDist = dist;
}
}
if (newOrigin != null) {
pMF.setOrigin(new LineAtHeight(pMF.hExtentMin, newOrigin));
pMF.computeProfiles(ProfileGen.this);
}
}
profileLine.setMega(pMF);
footprint.add(profileLine);
dbgProfileLookup.put(i++, pMF);
if (DBG) {
profileNode.attachChild(Jme3z.lines(tweed.getAssetManager(), Collections.singletonList(new Line3d(profileLine.start.x, 0, profileLine.start.y, profileLine.end.x, 0, profileLine.end.y)), dispCol, 0.3f, true));
render(new ArrayList<>(pMF.profiles.values()), tweed, dispCol, profileNode);
// List<Prof> cleans = new ArrayList<>();
// for ( Prof p : pMF.profiles.values() ) {
// p.render( tweed, profileNode, dispCol, 1f );
// cleans.add( new Prof( p ).parameterize() );
// .render( tweed, cProfileNode, dispCol.add( ColorRGBA.Gray ), 1f );
//
// }
// render ( cleans, tweed, cProfileNode );
profileNode.attachChild(Jme3z.lines(tweed.getAssetManager(), Collections.singletonList(oLine), dispCol, 0.3f, true));
profileNode.setUserData(ProfileGen.class.getSimpleName(), i);
addOnJmeThread.add(profileNode);
}
}
}
}
}
if (DBG)
tweed.frame.addGen(new JmeGen("horizontal lines", tweed, mfNode), false);
// tweed.frame.addGen( new JmeGen( "clean profiles", tweed, cProfileNode ), false );
calculateOnJmeThread();
}
use of org.twak.viewTrace.SuperLine in project chordatlas by twak.
the class Prof method findProfileLines.
/**
* We find an initial base offset. Then we cluster the start point of all
* (clean) profiles. If any are a good distance from the initial base, we
* add those as their own profile lines.
*
* The original line is offset by the remaiing data.
*/
public static List<SuperLine> findProfileLines(Collection<Prof> profiles, Line3d line) {
List<SuperLine> out = new ArrayList();
// PaintThing.debug.clear();
SuperLine superLine = new SuperLine(line.start.x, line.start.z, line.end.x, line.end.z);
double outLen = superLine.length();
double min = Double.MAX_VALUE, max = -Double.MAX_VALUE;
Cache<Prof, Double> vLength = new Cache<Prof, Double>() {
@Override
public Double create(Prof i) {
return i.verticalLength(0.5);
}
};
double vLen = profiles.stream().mapToDouble(p -> vLength.get(p)).sum();
boolean useVertical = vLen / profiles.size() > 1;
class Wrapper implements Clusterable {
double[] pt;
public Wrapper(Point2d pt) {
this.pt = new double[] { pt.x, pt.y };
}
@Override
public double[] getPoint() {
return pt;
}
}
List<Wrapper> toCluster = new ArrayList();
List<Double> baseLineOffset = new ArrayList();
for (Prof p : profiles) {
if (// vLen / (5*profiles.size()))
useVertical && vLength.get(p) < 1)
continue;
Prof clean = p.parameterize();
Point2d pt = clean.get(0);
Point3d pt3 = clean.to3d(pt);
double ppram = superLine.findPPram(new Point2d(pt3.x, pt3.z));
baseLineOffset.add(pt.x);
toCluster.add(new Wrapper(new Point2d(pt.x, ppram * outLen)));
min = Math.min(min, ppram);
max = Math.max(max, ppram);
}
if (min == max || toCluster.isEmpty())
return out;
if (true) {
baseLineOffset.sort(Double::compareTo);
double modeBaselineOffset = baseLineOffset.get(baseLineOffset.size() / 2);
DBSCANClusterer<Wrapper> cr = new DBSCANClusterer<>(1.5, 0);
List<Cluster<Wrapper>> results = cr.cluster(toCluster);
Iterator<Cluster<Wrapper>> cit = results.iterator();
while (cit.hasNext()) {
Cluster<Wrapper> cw = cit.next();
if (cw.getPoints().size() < 2 / TweedSettings.settings.profileHSampleDist) {
cit.remove();
double cMeanY = cw.getPoints().stream().mapToDouble(x -> x.pt[1]).average().getAsDouble();
double bestDist = Double.MAX_VALUE;
Cluster<Wrapper> bestWrapper = null;
for (Cluster<Wrapper> near : results) {
double meanY = near.getPoints().stream().mapToDouble(x -> x.pt[1]).average().getAsDouble();
double dist = Math.abs(meanY - cMeanY);
if (dist < bestDist) {
bestDist = dist;
bestWrapper = near;
}
}
if (bestWrapper != null)
bestWrapper.getPoints().addAll(cw.getPoints());
}
}
{
baseLineOffset.clear();
int c = 0;
for (Cluster<Wrapper> cw : results) {
double[] minMax = cw.getPoints().stream().map(p -> new double[] { p.pt[1] }).collect(new InAxDoubleArray());
double[] offsetA = cw.getPoints().stream().mapToDouble(p -> p.pt[0]).sorted().toArray();
double offset = offsetA[offsetA.length / 2];
if (offset - modeBaselineOffset < 1) {
for (Wrapper w : cw.getPoints()) baseLineOffset.add(w.pt[0]);
continue;
}
SuperLine sl = new SuperLine(superLine.fromPPram(minMax[0] / outLen), superLine.fromPPram(minMax[1] / outLen));
sl.moveLeft(offset);
out.add(sl);
List<Point2d> pts = cw.getPoints().stream().map(w -> new Point2d(w.pt[0], w.pt[1])).collect(Collectors.toList());
PaintThing.debug(Rainbow.getColour(c++), 1, pts);
}
}
}
Point2d nStart = superLine.fromPPram(min), nEnd = superLine.fromPPram(max);
superLine.start = nStart;
superLine.end = nEnd;
baseLineOffset.sort(Double::compare);
if (!baseLineOffset.isEmpty())
superLine.moveLeft(baseLineOffset.get(baseLineOffset.size() / 2));
out.add(0, superLine);
return out;
}
use of org.twak.viewTrace.SuperLine in project chordatlas by twak.
the class SkelFootprint method debugFindCleanProfiles.
public static void debugFindCleanProfiles(List<Line> footprint, SkelGen skelGen, ProgressMonitor m, Tweed tweed) {
MultiMap<SuperLine, List<Prof>> profSets = new MultiMap<>();
for (Line l : footprint) profileRuns((SuperLine) l, profSets);
List<List<Prof>> ordered = new ArrayList<>();
Map<List<Prof>, SuperLine> pairs = new LinkedHashMap<>();
for (SuperLine l : profSets.keySet()) for (List<Prof> lp : profSets.get(l)) {
pairs.put(lp, l);
ordered.add(lp);
}
JSlider bunch = new JSlider(0, ordered.size() - 1);
JButton button = new JButton("go");
Plot plot = new Plot(bunch, button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PaintThing.debug.clear();
plot.toPaint.clear();
List<Prof> ps = ordered.get(bunch.getValue());
SuperLine sl = pairs.get(ps);
if (sl != null && ps != null) {
PaintThing.debug(new Color(0, 0, 0, 50), 1, ps);
Prof clean = Prof.parameterize(ps);
Prof c2 = new Prof(clean);
for (Point2d p : c2) p.x += 10;
// plot.toPaint.add( clean ) );
PaintThing.debug(new Color(0, 170, 255), 3f, c2);
Prof mid = ps.get(ps.size() / 2);
tweed.enqueue(new Runnable() {
@Override
public void run() {
Jme3z.removeAllChildren(tweed.debug);
for (Prof p : ps) {
// p = p.moveToX0();
p.render(tweed, tweed.debug, ColorRGBA.Blue, (float) TweedSettings.settings.profileHSampleDist);
}
Point3d pt = mid.to3d(mid.get(0));
pt.y = 0;
Geometry geom = new Geometry("material_", clean.renderStrip(1, null));
Material mat = new Material(tweed.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setColor("Diffuse", ColorRGBA.Blue);
mat.setColor("Ambient", ColorRGBA.Red);
geom.setMaterial(mat);
// tweed.debug.attachChild( geom );
tweed.debug.updateGeometricState();
tweed.debug.updateModelBound();
tweed.gainFocus();
}
});
}
plot.repaint();
}
});
bunch.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
button.doClick();
}
});
}
use of org.twak.viewTrace.SuperLine in project chordatlas by twak.
the class SkelFootprint method assignGreedyProfiles.
private static void assignGreedyProfiles(SolverState SS) {
Prof defaultProf = defaultProf(null);
for (HalfFace f : SS.mesh) for (List<HalfEdge> le : f.parallelFaces(0.1)) {
List<Prof> profs = new ArrayList();
for (HalfEdge he : le) {
SuperLine sl = ((SuperEdge) he).profLine;
if (sl != null) {
MegaFacade mf = sl.getMega();
if (mf != null)
profs.addAll(mf.getTween(he.start, he.end, 0));
}
}
Prof p = null;
if (!profs.isEmpty())
p = Prof.parameterize(profs);
else
p = defaultProf;
for (HalfEdge he : le) ((SuperEdge) he).prof = p;
}
}
use of org.twak.viewTrace.SuperLine in project chordatlas by twak.
the class SkelFootprint method findProfiles.
private void findProfiles(List<Line> footprint, List<Prof> globalProfs) {
MultiMap<SuperLine, List<Prof>> profSets = new MultiMap<>();
System.out.println("clustering " + globalProfs.size() + " profiles over sweep edges...");
for (Line l : footprint) profileRuns((SuperLine) l, profSets);
Prof example = null;
System.out.println("cleaning " + profSets.values().stream().flatMap(c -> c.stream()).count() + " profiles...");
for (SuperLine sl : profSets.keySet()) for (List<Prof> lp : profSets.get(sl)) {
if (example == null)
example = lp.get(0);
Prof p = Prof.parameterize(lp);
if (p != null && p.size() > 1)
globalProfs.add(SkelGen.moveToX0(p));
}
Iterator<Prof> git = globalProfs.iterator();
int c = 0;
// remove trivial
while (git.hasNext()) {
Prof p = git.next();
if (p.size() < 2)
git.remove();
else if (p.size() == 2) {
if (p.get(0).x == p.get(1).x) {
git.remove();
c++;
}
} else if (p.size() == 3) {
if (p.get(0).x == p.get(1).x && p.get(2).y == p.get(1).y)
git.remove();
}
}
System.out.println("found " + globalProfs.size() + " interesting profiles" + " from " + profSets.size() + " runs");
removeSimilarB(globalProfs, TweedSettings.settings.profilePrune);
System.out.println("after remove similar " + globalProfs.size());
// insert single vertical profile
{
Prof vertical = defaultProf(example);
globalProfs.add(0, vertical);
}
}
Aggregations