use of org.twak.utils.Line in project chordatlas by twak.
the class GurobiSkelSolver method buildBadGeom.
private void buildBadGeom(boolean isContraint) throws GRBException {
countBadCorners = countBadEdges = 0;
for (HalfEdge e1 : edges) {
if (e1.over != null && e1.next.over != null)
if (e1.line().absAngle(e1.next.line()) > Math.PI - TweedSettings.settings.badGeomAngle) {
notBoth(e1, e1.next, isContraint, totalEdgeLength * 0.5);
countBadCorners++;
}
}
// if over both h
for (HalfFace f : mesh) {
Set<HalfEdge> togo = new HashSet<>();
for (HalfEdge e : f) togo.add(e);
while (!togo.isEmpty()) {
HalfEdge start = togo.iterator().next();
togo.remove(start);
// if (start.over == null)
// continue;
boolean parallelHasOverProfile = start.over == null ? false : ((SuperEdge) start.over).profLine != null, oppositeHasOverProfile = false;
Line sl = start.line();
LinearForm slf = new LinearForm(sl);
Map<HalfFace, HalfEdge> parallel = new HashMap<>();
parallel.put(start.over == null ? null : start.over.face, start);
Iterator<HalfEdge> tig = togo.iterator();
while (tig.hasNext()) {
HalfEdge e2 = tig.next();
HalfFace f2 = e2.over == null ? null : e2.over.face;
if (sl.absAngle(e2.line()) < 0.05) {
// one from each non-f face
parallel.put(f2, e2);
tig.remove();
parallelHasOverProfile |= (e2.over != null && ((SuperEdge) e2.over).profLine != null);
}
}
Map<HalfFace, HalfEdge> opposite = new HashMap();
tig = togo.iterator();
while (tig.hasNext()) {
HalfEdge e2 = tig.next();
HalfFace f2 = e2.over == null ? null : e2.over.face;
if (// e2l.lengthSquared() > 1 &&
sl.absAngle(e2.line()) > Math.PI - 0.3 && (slf.distance(e2.start) < 0.3 || slf.distance(e2.end) < 0.3)) {
opposite.put(f2, e2);
tig.remove();
oppositeHasOverProfile |= (e2.over != null && ((SuperEdge) e2.over).profLine != null);
}
}
if (parallelHasOverProfile && oppositeHasOverProfile)
continue;
for (HalfEdge e1 : parallel.values()) for (HalfEdge e2 : opposite.values()) {
notBoth(e1, e2, isContraint, totalEdgeLength * 0.5);
countBadEdges++;
}
}
}
print(countBadCorners + " " + countBadEdges);
}
use of org.twak.utils.Line in project chordatlas by twak.
the class Prof method at3DHeight.
public Point3d at3DHeight(double h3) {
double h = to2d(new Point3d(0, h3, 0)).y;
int i = 0;
while (get(i).y <= h && i < size() - 1) i++;
if (i == 0)
return null;
else if (get(i).y <= h)
return null;
else
return to3d(new Point2d(new Line(get(i - 1), get(i)).xAtY(h), h));
}
use of org.twak.utils.Line in project chordatlas by twak.
the class Prof method parameterize.
public Prof parameterize() {
// find and subtract vertical lines
Set<Line> lines = new HashSet<>();
for (int i = 1; i < size(); i++) lines.add(new Line(get(i - 1), get(i)));
double avgMinY = get(0).y;
SliceParameters P = new SliceParameters(5);
P.FL_REGRESS = false;
P.FL_BINS = 20;
// simple = 0.4
double A = 0.4;
// simple = 1;
double B = 1;
lines = new FindLines(lines, P) {
protected double nextAngle(Set<Line> remaining, int iteration) {
double delta = Math.PI / P.FL_BINS;
// angle bin
Bin<Line> aBin = new Bin(-Math.PI - delta, Math.PI + delta, P.FL_BINS * 2, true);
for (Line l : remaining) {
double len = l.length();
double angle = l.aTan2();
aBin.add(angle, len, l);
}
// return MUtils.PI2;
if (iteration < 1 && aBin.getWeight(Mathz.PI2) >= 5)
return Mathz.PI2;
int aBinI = aBin.maxI();
return aBin.val(aBinI);
}
protected double getTolNearLine(Point2d p) {
return P.FL_NEAR_LINE * (p.y < avgMinY + 5 ? 5 : B);
}
protected double getTolNearLine2(Point2d p) {
return P.FL_NEAR_LINE_2 * (p.y < avgMinY + 5 ? 10 : B);
}
}.result.all;
clean = new Prof(this);
clean.clear();
if (lines.isEmpty()) {
clean.add(new Point2d(0, 0));
clean.add(new Point2d(0, 1));
return clean;
}
List<Line> llines = new ArrayList(lines);
llines.stream().filter(l -> l.start.y > l.end.y).forEach(l -> l.reverseLocal());
Collections.sort(llines, new Comparator<Line>() {
public int compare(Line o1, Line o2) {
return Double.compare(o1.start.y + o1.end.y, o2.start.y + o2.end.y);
}
});
for (int i = 0; i < llines.size(); i++) {
Line l = llines.get(i);
double angle = l.aTan2();
if (angle < Mathz.PI2 + 0.1 && angle > Mathz.PI2 - 0.4)
llines.set(i, FindLines.rotateToAngle(l, l.fromPPram(0.5), Mathz.PI2));
}
Line bottomLine = llines.get(0);
llines.add(0, new Line(new Point2d(bottomLine.start.x, get(0).y), new Point2d(bottomLine.start.x, get(0).y)));
double lastY = -Double.MAX_VALUE, lastX = Double.MAX_VALUE;
for (Line l : llines) {
boolean startAbove = l.start.y >= lastY && l.start.x <= lastX, endAbove = l.end.y >= lastY && l.end.x <= lastX;
if (startAbove && endAbove) {
clean.add(l.start);
clean.add(l.end);
} else if (!startAbove && endAbove) {
if (l.start.y < lastY) {
Point2d sec = new LinearForm(new Vector2d(1, 0)).findC(new Point2d(0, lastY)).intersect(new LinearForm(l));
if (sec != null)
l.start = sec;
}
if (l.start.x > lastX) {
Point2d sec = new LinearForm(new Vector2d(0, 1)).findC(new Point2d(lastX, 0)).intersect(new LinearForm(l));
if (sec != null)
l.start = sec;
}
if (l.end.distanceSquared(l.start) < 100)
clean.add(l.start);
clean.add(l.end);
} else {
Vector2d dir = l.dir();
if (Math.abs(dir.x) > Math.abs(dir.y)) {
LinearForm x = new LinearForm(new Vector2d(1, 0)).findC(new Point2d(0, lastY));
l.start = x.project(l.start);
l.end = x.project(l.end);
l.start.x = Math.min(l.start.x, lastX);
l.end.x = Math.min(l.end.x, lastX);
} else {
LinearForm y = new LinearForm(new Vector2d(0, 1)).findC(new Point2d(lastX, 0));
l.start = y.project(l.start);
l.end = y.project(l.end);
l.start.y = Math.max(l.start.y, lastY);
l.end.y = Math.max(l.end.y, lastY);
}
clean.add(l.start);
clean.add(l.end);
}
lastY = l.end.y;
lastX = l.end.x;
}
clean.clean(0.2);
return clean;
}
use of org.twak.utils.Line in project chordatlas by twak.
the class SkelFootprint method findOcclusions.
private static void findOcclusions(HalfMesh2 mesh) {
int count = 0;
for (HalfFace hf : mesh.faces) for (HalfEdge e1 : hf.edges()) {
Line el1 = e1.line();
for (HalfFace hf2 : mesh.faces) {
for (HalfEdge e2 : hf2.edges()) if (e1 != e2) {
Line e2l = e2.line();
if (el1.distance(e2l) < 1 && e2l.absAngle(el1) > Math.PI * 0.7) // !el1.isOnLeft( e2l.fromPPram( 0.5 ) )
{
((SuperEdge) e1).occlusions.add(new LineHeight(el1.project(e2l.start, true), el1.project(e2l.end, true), 0, ((SuperFace) hf2).height));
count++;
}
}
}
}
System.out.println("found " + count + " occluding surfaces");
}
use of org.twak.utils.Line in project chordatlas by twak.
the class SkelFootprint method buildFootprint.
public SolverState buildFootprint(List<Line> footprint, ProgressMonitor m, FeatureCache features, BlockGen blockGen) {
MultiMap<MegaFeatures, MFPoint> minis = features == null ? null : features.createMinis(blockGen);
Map<SuperEdge, double[]> profFit = new HashMap();
HalfMesh2 mesh = boundMesh(footprint);
globalProfs = null;
Collections.sort(footprint, megaAreaComparator);
for (Line l : footprint) {
MegaFacade mf = ((SuperLine) l).getMega();
if (mf.area < megaFacadeAreaThreshold)
break;
insert(mesh, l, 2, true, true);
if (m.isCanceled())
return null;
}
if (features != null)
fractureOnFeatures(minis, footprint, mesh);
m.setProgress(2);
if (!TweedSettings.settings.useGreedyProfiles) {
globalProfs = new ArrayList();
findProfiles(footprint, globalProfs);
calcProfFit(mesh, globalProfs, profFit, m);
}
if (FALSE && profMergeTol > 0)
mergeOnProfiles(mesh, footprint);
if (exitA)
return new SolverState(mesh, minis, globalProfs, profFit, footprint);
System.out.println("sampling...");
for (HalfFace f : mesh) meanModeHeightColor(Loopz.from(f), (SuperFace) f, blockGen);
pushHeightsToSmallFaces(mesh);
for (HalfFace f : new ArrayList<>(mesh.faces)) {
SuperFace sf = (SuperFace) f;
if (sf.height < heightCutoff)
sf.remove(mesh);
}
removeExposedFaces(mesh);
return new SolverState(mesh, minis, globalProfs, profFit, footprint);
}
Aggregations