use of org.twak.utils.collections.MultiMap in project chordatlas by twak.
the class CutHoles method cutHoles.
public static void cutHoles(LoopL<Point2d> out, double tol, Map<Point2d, Line> created) {
MultiMap<Boolean, Loop<Point2d>> holeToLoop = new MultiMap<>();
Iterator<Loop<Point2d>> lit = out.iterator();
while (lit.hasNext()) {
// a hole can be a backwards loop...
Loop<Point2d> loop = lit.next();
double area = Loopz.area(loop);
if (Math.abs(area) < tol * tol)
lit.remove();
boolean isHole = area > 0;
holeToLoop.put(isHole, loop);
for (Loop<Point2d> h : loop.holes) {
if (Loopz.area(h) > 0)
h.reverse();
holeToLoop.put(false, h);
}
}
for (Loop<Point2d> hole : holeToLoop.get(false)) {
Point2d origin = new Point2d(Double.MAX_VALUE, 0);
Loopable<Point2d> originL = null;
for (Loopable<Point2d> p : hole.loopableIterator()) {
if (p.get().x < origin.x) {
originL = p;
origin = originL.get();
}
}
LinearForm ray = new LinearForm(0, 1);
ray.findC(origin);
double nearestD = Double.MAX_VALUE;
Loopable<Point2d> nearestL = null;
Point2d nearestH = null;
for (Loop<Point2d> loop : out) {
for (Loopable<Point2d> line : loop.loopableIterator()) {
Point2d a = line.get(), b = line.getNext().get();
if (a.y > origin.y && b.y < origin.y || a.y < origin.y && b.y > origin.y) {
Point2d hit = new Line(a, b).intersects(ray);
if (hit != null && hit.x < origin.x && (origin.x - hit.x < nearestD)) {
nearestD = origin.x - hit.x;
nearestL = line;
nearestH = hit;
}
}
}
}
if (nearestH == null)
System.err.println("failed to find outer ring for hole");
else {
if (created != null)
created.put(nearestH, new Line(nearestL.get(), nearestL.getNext().get()));
Loopable<Point2d> hitPtF = new Loopable<Point2d>(nearestH), hitPtS = new Loopable<Point2d>(nearestH), originL2 = new Loopable(origin);
hitPtS.setNext(nearestL.getNext());
hitPtF.setPrev(nearestL);
hitPtS.getNext().setPrev(hitPtS);
hitPtF.getPrev().setNext(hitPtF);
originL.getNext().setPrev(originL2);
originL2.setNext(originL.getNext());
originL.setNext(hitPtS);
hitPtS.setPrev(originL);
hitPtF.setNext(originL2);
originL2.setPrev(hitPtF);
}
out.remove(hole);
}
}
use of org.twak.utils.collections.MultiMap in project chordatlas by twak.
the class FeatureCache method createMinis.
public MultiMap<MegaFeatures, MFPoint> createMinis(BlockGen blockGen) {
MultiMap<MegaFeatures, MFPoint> out = new MultiMap();
for (MegaFeatures m : getBlock(blockGen.center).getFeatures()) {
double mLen = m.megafacade.length();
for (ImageFeatures i : m.features) {
for (int mi = 0; mi <= i.miniFacades.size(); mi++) {
MiniFacade n = mi < i.miniFacades.size() ? i.miniFacades.get(mi) : null, p = (mi - 1) >= 0 ? i.miniFacades.get(mi - 1) : null;
if (// skinny mf filter
n != null && (n.width < MFWidthTol || (n.rects.countValue() == 0 && n.width < MFWidthTol * 3)))
n = null;
if (p != null && (p.width < MFWidthTol || (p.rects.countValue() == 0 && p.width < MFWidthTol * 3)))
p = null;
if (n == null && p == null || n == null && p.softRight || p == null && n.softLeft || p != null && n != null && p.softRight && n.softLeft)
continue;
double ptDist = n == null ? (p.left + p.width) : n.left;
Point2d pt = m.megafacade.fromPPram(ptDist / mLen);
double covTol = 2;
Set<ImageFeatures> covering = m.features.stream().filter(ii -> ii.start + covTol < ptDist && ii.end > ptDist + covTol).collect(Collectors.toSet());
// stuff beyond the end of the facade
double pa = m.megafacade.findPPram(pt) * mLen;
if (pa < -5 || pa > mLen + 5)
continue;
out.put(m, new MFPoint(pt, covering, m, i, p, n));
}
}
}
return out;
}
use of org.twak.utils.collections.MultiMap in project chordatlas by twak.
the class SkelFootprint method profileRuns.
private static void profileRuns(SuperLine sl, MultiMap<SuperLine, List<Prof>> profSets) {
MegaFacade mf = sl.getMega();
Cache<Integer, Double> distance2Next = new Cache<Integer, Double>() {
@Override
public Double create(Integer i) {
Prof pc = mf.profiles.get(i), pn = mf.profiles.get(i + 1);
if (pc == null || pn == null)
return 1e6;
return pc.distance(pn, true, false, false);
}
};
// i -> mf.profiles.get( i ).distance( mf.profiles.get(i+1), true ));
int start = mf.hExtentMin;
for (int i = mf.hExtentMin; i < mf.hExtentMax; i++) {
if (distance2Next.get(i) > 4 || i == mf.hExtentMax - 1) {
// if ( (Math.random() > 0.95 || i == mf.hExtentMax - 1) ){//0.5 / ProfileGen.HORIZ_SAMPLE_DIST) {
if (i - start > 0.5 / TweedSettings.settings.profileHSampleDist) {
List<Prof> lp = IntStream.range(start, i + 1).mapToObj(p -> mf.profiles.get(p)).filter(p -> p != null).collect(Collectors.toList());
if (lp != null && !lp.isEmpty())
profSets.put(sl, lp);
}
start = i + 1;
// i++;
// }
}
}
// System.out.println( (mf.hExtentMax - mf.hExtentMin)+ " mm " + min+ " / " + max +" found " + profSets.size() );
}
Aggregations