下面列出了java.awt.geom.Line2D#getX2 ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void refitOverlappedIntervals(int st, int en, int newFrom, int newTo) {
List<Line2D> checkLimits = new ArrayList<>(intervalLimits.subList(st, en));
float newLimitX1, newLimitX2;
if (!checkLimits.isEmpty()) {
Line2D firstLimit = checkLimits.get(0);
Line2D lastLimit = checkLimits.get(checkLimits.size() - 1);
newLimitX1 = (float) ((newFrom < firstLimit.getX1()) ? newFrom : firstLimit.getX1());
newLimitX2 = (float) ((newTo > lastLimit.getX2()) ? newTo : lastLimit.getX2());
for (Line2D limit : checkLimits) {
intervalLimits.remove(st);
}
} else {
newLimitX1 = newFrom;
newLimitX2 = newTo;
}
intervalLimits.add(st, new Line2D.Float((float) newLimitX1, 0, (float) newLimitX2, 0));
}
/**
* Define an area on desired horizontal side of the beam.
*
* @param kind kind of area (meant for attachment debug)
* @param beam the beam inter
* @param side desired side
* @param double extDy ordinate extension
* @param double extDx abscissa extension
* @param double intDx abscissa offset towards beam interior
* @return the area
*/
private Area sideAreaOf (String kind,
AbstractBeamInter beam,
HorizontalSide side,
double extDy,
double extDx,
double intDx)
{
final Line2D median = beam.getMedian();
final double height = beam.getHeight() + (2 * extDy);
final double intX = (side == LEFT) ? (median.getX1() - 1 + intDx)
: ((median.getX2() + 1) - intDx);
final Point2D intPt = LineUtil.intersectionAtX(median, intX);
final double extX = (side == LEFT) ? (median.getX1() - extDx) : (median.getX2() + extDx);
final Point2D extPt = LineUtil.intersectionAtX(median, extX);
Area area = (side == LEFT) ? AreaUtil.horizontalParallelogram(extPt, intPt, height)
: AreaUtil.horizontalParallelogram(intPt, extPt, height);
if (kind != null) {
beam.addAttachment(kind + ((side == LEFT) ? "L" : "R"), area);
}
return area;
}
/**
* Creates a new line by extending an existing line.
*
* @param line the line (<code>null</code> not permitted).
* @param startPercent the amount to extend the line at the start point
* end.
* @param endPercent the amount to extend the line at the end point end.
*
* @return A new line.
*/
private Line2D extendLine(Line2D line, double startPercent,
double endPercent) {
if (line == null) {
throw new IllegalArgumentException("Null 'line' argument.");
}
double x1 = line.getX1();
double x2 = line.getX2();
double deltaX = x2 - x1;
double y1 = line.getY1();
double y2 = line.getY2();
double deltaY = y2 - y1;
x1 = x1 - (startPercent * deltaX);
y1 = y1 - (startPercent * deltaY);
x2 = x2 + (endPercent * deltaX);
y2 = y2 + (endPercent * deltaY);
return new Line2D.Double(x1, y1, x2, y2);
}
public Point2D.Double findIntersection(Line2D line1, Line2D line2)
{
// calculate differences
double xD1 = line1.getX2() - line1.getX1();
double yD1 = line1.getY2() - line1.getY1();
double xD2 = line2.getX2() - line2.getX1();
double yD2 = line2.getY2() - line2.getY1();
double xD3 = line1.getX1() - line2.getX1();
double yD3 = line1.getY1() - line2.getY1();
// find intersection Pt between two lines
Point2D.Double pt = new Point2D.Double(0, 0);
double div = yD2 * xD1 - xD2 * yD1;
if(div == 0)//lines are parallel
return null;
double ua = (xD2 * yD3 - yD2 * xD3) / div;
pt.x = line1.getX1() + ua * xD1;
pt.y = line1.getY1() + ua * yD1;
if(ptOnLineInSegment(pt, line1) && ptOnLineInSegment(pt, line2))
return pt;
return null;
}
/**
* Returns a shape that is (more or less) equivalent to the supplied shape.
* For some known shape implementations ({@code Line2D},
* {@code Rectangle2D}, {@code RoundRectangle2D}, {@code Arc2D},
* {@code Ellipse2D}, and {@code Polygon}) the copy will be an instance of
* that class. For other shapes, a {@code Path2D} containing the outline
* of the shape is returned.
*
* @param shape the shape ({@code null} not permitted).
*
* @return A copy of the shape or shape outline (never {@code null}).
*/
public static Shape copyOf(Shape shape) {
Args.nullNotPermitted(shape, "shape");
if (shape instanceof Line2D) {
Line2D l = (Line2D) shape;
return new Line2D.Double(l.getX1(), l.getY1(), l.getX2(), l.getY2());
}
if (shape instanceof Rectangle2D) {
Rectangle2D r = (Rectangle2D) shape;
return new Rectangle2D.Double(r.getX(), r.getY(), r.getWidth(),
r.getHeight());
}
if (shape instanceof RoundRectangle2D) {
RoundRectangle2D rr = (RoundRectangle2D) shape;
return new RoundRectangle2D.Double(rr.getX(), rr.getY(),
rr.getWidth(), rr.getHeight(), rr.getArcWidth(),
rr.getArcHeight());
}
if (shape instanceof Arc2D) {
Arc2D arc = (Arc2D) shape;
return new Arc2D.Double(arc.getX(), arc.getY(), arc.getWidth(),
arc.getHeight(), arc.getAngleStart(), arc.getAngleExtent(),
arc.getArcType());
}
if (shape instanceof Ellipse2D) {
Ellipse2D ell = (Ellipse2D) shape;
return new Ellipse2D.Double(ell.getX(), ell.getY(), ell.getWidth(),
ell.getHeight());
}
if (shape instanceof Polygon) {
Polygon p = (Polygon) shape;
return new Polygon(p.xpoints, p.ypoints, p.npoints);
}
return new Path2D.Double(shape);
}
/**
* This method calculates intersections of two lines.
* @param a Line 1
* @param b Line 2
* @return Intersection point
*/
private static Point getLinesIntersection(Line2D a, Line2D b) {
double d = (a.getX1()-a.getX2())*(b.getY2()-b.getY1()) - (a.getY1()-a.getY2())*(b.getX2()-b.getX1());
double da = (a.getX1()-b.getX1())*(b.getY2()-b.getY1()) - (a.getY1()-b.getY1())*(b.getX2()-b.getX1());
// double db = (a.getX1()-a.getX2())*(a.getY1()-b.getY1()) - (a.getY1()-a.getY2())*(a.getX1()-b.getX1());
double ta = da/d;
// double tb = db/d;
Point p = new Point();
p.setLocation(a.getX1()+ta*(a.getX2()-a.getX1()), a.getY1()+ta*(a.getY2()-a.getY1()));
return p;
}
/**
* This method calculates intersections of two lines.
*
* @param a
* Line 1
* @param b
* Line 2
* @return Intersection point
*/
private static Point getLinesIntersection(Line2D a, Line2D b) {
double d = (a.getX1() - a.getX2()) * (b.getY2() - b.getY1()) - (a.getY1() - a.getY2()) * (b.getX2() - b.getX1());
double da = (a.getX1() - b.getX1()) * (b.getY2() - b.getY1()) - (a.getY1() - b.getY1()) * (b.getX2() - b.getX1());
// double db = (a.getX1()-a.getX2())*(a.getY1()-b.getY1()) - (a.getY1()-a.getY2())*(a.getX1()-b.getX1());
double ta = da / d;
// double tb = db/d;
Point p = new Point();
p.setLocation(a.getX1() + ta * (a.getX2() - a.getX1()), a.getY1() + ta * (a.getY2() - a.getY1()));
return p;
}
/**
* Compute bisector vector.
*
* @param above is the slur above (or below)
* @return the unit bisector
*/
protected Point2D.Double computeBisector (boolean above)
{
Line2D bisector = LineUtil.bisector(getEnd(above), getEnd(!above));
double length = bisector.getP1().distance(bisector.getP2());
return new Point2D.Double(
(bisector.getX2() - bisector.getX1()) / length,
(bisector.getY2() - bisector.getY1()) / length);
}
/**
* Creates a region surrounding a line segment by 'widening' the line
* segment. A typical use for this method is the creation of a
* 'clickable' region for a line that is displayed on-screen.
*
* @param line the line (<code>null</code> not permitted).
* @param width the width of the region.
*
* @return A region that surrounds the line.
*/
public static Shape createLineRegion(Line2D line, float width) {
GeneralPath result = new GeneralPath();
float x1 = (float) line.getX1();
float x2 = (float) line.getX2();
float y1 = (float) line.getY1();
float y2 = (float) line.getY2();
if ((x2 - x1) != 0.0) {
double theta = Math.atan((y2 - y1) / (x2 - x1));
float dx = (float) Math.sin(theta) * width;
float dy = (float) Math.cos(theta) * width;
result.moveTo(x1 - dx, y1 + dy);
result.lineTo(x1 + dx, y1 - dy);
result.lineTo(x2 + dx, y2 - dy);
result.lineTo(x2 - dx, y2 + dy);
result.closePath();
}
else {
// special case, vertical line
result.moveTo(x1 - width / 2.0f, y1);
result.lineTo(x1 + width / 2.0f, y1);
result.lineTo(x2 + width / 2.0f, y2);
result.lineTo(x2 - width / 2.0f, y2);
result.closePath();
}
return result;
}
/**
* Creates a region surrounding a line segment by 'widening' the line
* segment. A typical use for this method is the creation of a
* 'clickable' region for a line that is displayed on-screen.
*
* @param line the line (<code>null</code> not permitted).
* @param width the width of the region.
*
* @return A region that surrounds the line.
*/
public static Shape createLineRegion(final Line2D line, final float width) {
final GeneralPath result = new GeneralPath();
final float x1 = (float) line.getX1();
final float x2 = (float) line.getX2();
final float y1 = (float) line.getY1();
final float y2 = (float) line.getY2();
if ((x2 - x1) != 0.0) {
final double theta = Math.atan((y2 - y1) / (x2 - x1));
final float dx = (float) Math.sin(theta) * width;
final float dy = (float) Math.cos(theta) * width;
result.moveTo(x1 - dx, y1 + dy);
result.lineTo(x1 + dx, y1 - dy);
result.lineTo(x2 + dx, y2 - dy);
result.lineTo(x2 - dx, y2 + dy);
result.closePath();
}
else {
// special case, vertical line
result.moveTo(x1 - width / 2.0f, y1);
result.lineTo(x1 + width / 2.0f, y1);
result.lineTo(x2 + width / 2.0f, y2);
result.lineTo(x2 - width / 2.0f, y2);
result.closePath();
}
return result;
}
public int getNearestSegment(Point2D pt, Point2D outPointOnSegment) {
double min = Double.MAX_VALUE;
int nearest = -1;
for (int i = 0; i < getSegmentCount(); i++) {
Line2D segment = getSegment(i);
Point2D a = new Point2D.Double(pt.getX() - segment.getX1(), pt.getY() - segment.getY1());
Point2D b = new Point2D.Double(segment.getX2() - segment.getX1(), segment.getY2() - segment.getY1());
double magB = b.distance(0, 0);
double dist;
if (magB < 0.0000001) {
dist = pt.distance(segment.getP1());
} else {
b.setLocation(b.getX() / magB, b.getY() / magB);
double magAonB = a.getX() * b.getX() + a.getY() * b.getY();
if (magAonB < 0) {
magAonB = 0;
}
if (magAonB > magB) {
magAonB = magB;
}
a.setLocation(segment.getX1() + b.getX() * magAonB, segment.getY1() + b.getY() * magAonB);
dist = new Point2D.Double(pt.getX() - a.getX(), pt.getY() - a.getY()).distance(0, 0);
}
if (dist < min) {
min = dist;
if (outPointOnSegment != null) {
outPointOnSegment.setLocation(a);
}
nearest = i;
}
}
return nearest;
}
/**
* Calculates the anchor point for a label.
*
* @param line the line for the crosshair.
* @param anchor the anchor point.
* @param deltaX the x-offset.
* @param deltaY the y-offset.
*
* @return The anchor point.
*/
private Point2D calculateLabelPoint(Line2D line, RectangleAnchor anchor,
double deltaX, double deltaY) {
double x = 0.0;
double y = 0.0;
boolean left = (anchor == RectangleAnchor.BOTTOM_LEFT
|| anchor == RectangleAnchor.LEFT
|| anchor == RectangleAnchor.TOP_LEFT);
boolean right = (anchor == RectangleAnchor.BOTTOM_RIGHT
|| anchor == RectangleAnchor.RIGHT
|| anchor == RectangleAnchor.TOP_RIGHT);
boolean top = (anchor == RectangleAnchor.TOP_LEFT
|| anchor == RectangleAnchor.TOP
|| anchor == RectangleAnchor.TOP_RIGHT);
boolean bottom = (anchor == RectangleAnchor.BOTTOM_LEFT
|| anchor == RectangleAnchor.BOTTOM
|| anchor == RectangleAnchor.BOTTOM_RIGHT);
Rectangle rect = line.getBounds();
// we expect the line to be vertical or horizontal
if (line.getX1() == line.getX2()) { // vertical
x = line.getX1();
y = (line.getY1() + line.getY2()) / 2.0;
if (left) {
x = x - deltaX;
}
if (right) {
x = x + deltaX;
}
if (top) {
y = Math.min(line.getY1(), line.getY2()) + deltaY;
}
if (bottom) {
y = Math.max(line.getY1(), line.getY2()) - deltaY;
}
}
else { // horizontal
x = (line.getX1() + line.getX2()) / 2.0;
y = line.getY1();
if (left) {
x = Math.min(line.getX1(), line.getX2()) + deltaX;
}
if (right) {
x = Math.max(line.getX1(), line.getX2()) - deltaX;
}
if (top) {
y = y - deltaY;
}
if (bottom) {
y = y + deltaY;
}
}
return new Point2D.Double(x, y);
}
/**
* Calculates the anchor point for a label.
*
* @param line the line for the crosshair.
* @param anchor the anchor point.
* @param deltaX the x-offset.
* @param deltaY the y-offset.
*
* @return The anchor point.
*/
private Point2D calculateLabelPoint(Line2D line, RectangleAnchor anchor,
double deltaX, double deltaY) {
double x, y;
boolean left = (anchor == RectangleAnchor.BOTTOM_LEFT
|| anchor == RectangleAnchor.LEFT
|| anchor == RectangleAnchor.TOP_LEFT);
boolean right = (anchor == RectangleAnchor.BOTTOM_RIGHT
|| anchor == RectangleAnchor.RIGHT
|| anchor == RectangleAnchor.TOP_RIGHT);
boolean top = (anchor == RectangleAnchor.TOP_LEFT
|| anchor == RectangleAnchor.TOP
|| anchor == RectangleAnchor.TOP_RIGHT);
boolean bottom = (anchor == RectangleAnchor.BOTTOM_LEFT
|| anchor == RectangleAnchor.BOTTOM
|| anchor == RectangleAnchor.BOTTOM_RIGHT);
Rectangle rect = line.getBounds();
// we expect the line to be vertical or horizontal
if (line.getX1() == line.getX2()) { // vertical
x = line.getX1();
y = (line.getY1() + line.getY2()) / 2.0;
if (left) {
x = x - deltaX;
}
if (right) {
x = x + deltaX;
}
if (top) {
y = Math.min(line.getY1(), line.getY2()) + deltaY;
}
if (bottom) {
y = Math.max(line.getY1(), line.getY2()) - deltaY;
}
}
else { // horizontal
x = (line.getX1() + line.getX2()) / 2.0;
y = line.getY1();
if (left) {
x = Math.min(line.getX1(), line.getX2()) + deltaX;
}
if (right) {
x = Math.max(line.getX1(), line.getX2()) - deltaX;
}
if (top) {
y = y - deltaY;
}
if (bottom) {
y = y + deltaY;
}
}
return new Point2D.Double(x, y);
}
/**
* Try to extend the provided beam on the desired side to another beam within reach.
* The other beam must be compatible in terms of gap (abscissa and ordinate) and beam slope.
* <p>
* If such a compatible beam is found, but the middle area between them is not correctly filled,
* we must remember this information to avoid any other extension attempt on this side.
*
* @param beam the beam to extend
* @param side the horizontal side
* @param other the side beam found
* @return true if extension was done, false otherwise
*/
private boolean extendToBeam (AbstractBeamInter beam,
HorizontalSide side,
AbstractBeamInter other)
{
// Check black ratio in the middle area (if its width is significant)
final Line2D beamMedian = beam.getMedian();
final Line2D otherMedian = other.getMedian();
double gap = (beamMedian.getX1() < otherMedian.getX1()) ? (otherMedian.getX1() - beamMedian
.getX2()) : (beamMedian.getX1() - otherMedian.getX2());
if (gap >= params.minBeamsGapX) {
Area middleArea = middleArea(beam, other);
AreaMask coreMask = new AreaMask(middleArea);
WrappedInteger core = new WrappedInteger(0);
int coreCount = coreMask.fore(core, pixelFilter);
double coreRatio = (double) core.value / coreCount;
if (coreRatio < params.minExtBlackRatio) {
return false;
}
}
BeamInter newBeam = mergeOf(beam, other);
if (newBeam == null) {
return false;
}
registerBeam(newBeam);
rawSystemBeams.add(newBeam);
if (beam.isVip() || other.isVip()) {
newBeam.setVip(true);
}
beam.remove();
other.remove();
if (newBeam.isVip() || logger.isDebugEnabled()) {
logger.info("VIP Merged {} & {} into {}", beam, other, newBeam);
}
return true;
}
public static boolean isContent( final RenderBox element, final boolean ellipseAsBackground,
final boolean shapesAsContent ) {
// For legacy reasons: A single ReplacedContent in a paragraph means, we may have a old-style border and
// background definition.
if ( element.getNodeType() == LayoutNodeTypes.TYPE_BOX_CONTENT ) {
final RenderableReplacedContentBox contentBox = (RenderableReplacedContentBox) element;
final RenderableReplacedContent rpc = contentBox.getContent();
final Object rawContentObject = rpc.getRawObject();
if ( rawContentObject instanceof DrawableWrapper == false ) {
return true;
}
final DrawableWrapper wrapper = (DrawableWrapper) rawContentObject;
final Object rawbackend = wrapper.getBackend();
if ( rawbackend instanceof ShapeDrawable == false ) {
return true;
}
final ShapeDrawable drawable = (ShapeDrawable) rawbackend;
final Shape rawObject = drawable.getShape();
final StyleSheet styleSheet = element.getStyleSheet();
if ( shapesAsContent == false ) {
return false;
}
if ( rawObject instanceof Line2D ) {
if ( hasBorderEdge( styleSheet ) ) {
final Line2D line = (Line2D) rawObject;
if ( line.getY1() == line.getY2() ) {
return false;
} else if ( line.getX1() == line.getX2() ) {
return false;
}
}
} else if ( rawObject instanceof Rectangle2D ) {
return false;
} else if ( ellipseAsBackground && rawObject instanceof Ellipse2D ) {
return false;
} else if ( rawObject instanceof RoundRectangle2D ) {
return false;
}
return true;
}
RenderNode child = element.getFirstChild();
while ( child != null ) {
final int type = child.getNodeType();
if ( ( type & LayoutNodeTypes.MASK_BOX_INLINE ) == LayoutNodeTypes.MASK_BOX_INLINE ) {
return true;
}
if ( type == LayoutNodeTypes.TYPE_NODE_TEXT ) {
return true;
}
child = child.getNext();
}
return false;
}
/**
* Calculates the anchor point for a label.
*
* @param line the line for the crosshair.
* @param anchor the anchor point.
* @param deltaX the x-offset.
* @param deltaY the y-offset.
*
* @return The anchor point.
*/
private Point2D calculateLabelPoint(Line2D line, RectangleAnchor anchor,
double deltaX, double deltaY) {
double x, y;
boolean left = (anchor == RectangleAnchor.BOTTOM_LEFT
|| anchor == RectangleAnchor.LEFT
|| anchor == RectangleAnchor.TOP_LEFT);
boolean right = (anchor == RectangleAnchor.BOTTOM_RIGHT
|| anchor == RectangleAnchor.RIGHT
|| anchor == RectangleAnchor.TOP_RIGHT);
boolean top = (anchor == RectangleAnchor.TOP_LEFT
|| anchor == RectangleAnchor.TOP
|| anchor == RectangleAnchor.TOP_RIGHT);
boolean bottom = (anchor == RectangleAnchor.BOTTOM_LEFT
|| anchor == RectangleAnchor.BOTTOM
|| anchor == RectangleAnchor.BOTTOM_RIGHT);
Rectangle rect = line.getBounds();
// we expect the line to be vertical or horizontal
if (line.getX1() == line.getX2()) { // vertical
x = line.getX1();
y = (line.getY1() + line.getY2()) / 2.0;
if (left) {
x = x - deltaX;
}
if (right) {
x = x + deltaX;
}
if (top) {
y = Math.min(line.getY1(), line.getY2()) + deltaY;
}
if (bottom) {
y = Math.max(line.getY1(), line.getY2()) - deltaY;
}
}
else { // horizontal
x = (line.getX1() + line.getX2()) / 2.0;
y = line.getY1();
if (left) {
x = Math.min(line.getX1(), line.getX2()) + deltaX;
}
if (right) {
x = Math.max(line.getX1(), line.getX2()) - deltaX;
}
if (top) {
y = y - deltaY;
}
if (bottom) {
y = y + deltaY;
}
}
return new Point2D.Double(x, y);
}
/**
* Now that individual beams candidates have been extracted, try to improve beam
* geometry (merge, extension).
* Try to extend each beam to either another beam (merge) or a stem seed (extension) or in
* parallel with a sibling beam (extension) or to another spot (extension).
*/
private void extendBeams ()
{
// All stem seeds for this system, sorted by abscissa
sortedSystemSeeds = system.getGroupedGlyphs(GlyphGroup.VERTICAL_SEED);
// The beam & hook inters for this system, NOT sorted by abscissa.
// We may add to this list, but not remove elements (they are simply logically 'deleted').
// Later, buildHooks() will add hooks to this list.
rawSystemBeams = sig.inters(AbstractBeamInter.class);
// Extend each orphan beam as much as possible
for (Inter inter : new ArrayList<>(rawSystemBeams)) {
if (inter.isRemoved()) {
continue;
}
final AbstractBeamInter beam = (AbstractBeamInter) inter;
if (beam.isVip()) {
logger.info("VIP extendBeams for {}", beam);
}
for (HorizontalSide side : HorizontalSide.values()) {
// If successful, this appends a new beam instance to the list.
// The new beam will later be tested for further extension.
// Is there a compatible beam near by?
AbstractBeamInter sideBeam = getSideBeam(beam, side, null);
Integer maxDx = null;
if (sideBeam != null) {
// Try to merge the 2 beams (avoid double testing, so check on one side only)
if ((side == LEFT) && extendToBeam(beam, side, sideBeam)) {
break;
}
Line2D median = beam.getMedian();
Line2D sideMedian = sideBeam.getMedian();
double dx = (side == LEFT) ? (median.getX1() - sideMedian.getX2())
: (sideMedian.getX1() - median.getX2());
maxDx = (int) Math.rint(Math.max(0, dx - params.beamsXMargin));
}
// Try the other extension modes (limited by side beam if any)
if (extendToStem(beam, side, maxDx) || extendToSpot(beam, side, maxDx)) {
break;
}
// Try parallel extension (only when there is no side beam)
if ((sideBeam == null) && extendInParallel(beam, side)) {
break;
}
}
}
}
/**
* Check if a Beam-Stem link is possible between this beam and the provided stem.
*
* @param stem the provided stem
* @param headToBeam vertical direction (from head) to beam
* @param scale scaling information
* @return the link if OK, otherwise null
*/
public Link checkLink (StemInter stem,
VerticalSide headToBeam,
Scale scale)
{
if (isVip() && stem.isVip()) {
logger.info("VIP checkLink {} & {}", this, stem);
}
// Relation beam -> stem (if not yet present)
BeamStemRelation bRel;
final int yDir = (headToBeam == VerticalSide.TOP) ? (-1) : 1;
final Line2D beamBorder = getBorder(headToBeam.opposite());
bRel = new BeamStemRelation();
// Precise cross point
Point2D start = stem.getTop();
Point2D stop = stem.getBottom();
Point2D crossPt = LineUtil.intersection(stem.getMedian(), beamBorder);
// Extension point
bRel.setExtensionPoint(
new Point2D.Double(crossPt.getX(), crossPt.getY() + (yDir * (getHeight() - 1))));
// Abscissa -> beamPortion
// toLeft & toRight are >0 if within beam, <0 otherwise
double toLeft = crossPt.getX() - beamBorder.getX1();
double toRight = beamBorder.getX2() - crossPt.getX();
final double xGap;
final int maxBeamInDx = scale.toPixels(BeamStemRelation.getXInGapMaximum(manual));
if (this instanceof BeamInter && (Math.min(toLeft, toRight) > maxBeamInDx)) {
// It's a beam center connection
bRel.setBeamPortion(BeamPortion.CENTER);
xGap = 0;
} else if (toLeft < toRight) {
bRel.setBeamPortion(BeamPortion.LEFT);
xGap = Math.max(0, -toLeft);
} else {
bRel.setBeamPortion(BeamPortion.RIGHT);
xGap = Math.max(0, -toRight);
}
// Ordinate
final double yGap = (yDir > 0) ? Math.max(0, crossPt.getY() - stop.getY())
: Math.max(0, start.getY() - crossPt.getY());
bRel.setOutGaps(scale.pixelsToFrac(xGap), scale.pixelsToFrac(yGap), manual);
if (bRel.getGrade() >= bRel.getMinGrade()) {
logger.debug("{} {} {}", this, stem, bRel);
return new Link(stem, bRel, true);
} else {
return null;
}
}
/**
* Gets the distance and point along a Line2D at a specified x.
* If the Line2D is vertical this returns null.
*
* Based on a simplification of algorithm described by Paul Burke
* at http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ (April 1986)
*
* @param line the line
* @param x the value of x
* @return Object[] {fractional distance from line end, Point2D}
*/
private Object[] getDistanceAndPointAtX(Line2D line, double x) {
double dx = line.getX2()-line.getX1();
// if line is vertical, return null
if (dx==0) return null;
// parametric eqn of line: P = P1 + u(P2 - P1)
double u = (x-line.getX1())/dx;
double y = line.getY1() + u*(line.getY2()-line.getY1());
return new Object[] {u, new Point2D.Double(x, y)};
}
/**
* Gets the distance and point along a Line2D at a specified y.
* If the Line2D is horizontal this returns null.
*
* Based on a simplification of algorithm described by Paul Burke
* at http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ (April 1986)
*
* @param line the line
* @param y the value of y
* @return Object[] {fractional distance from line end, Point2D}
*/
private Object[] getDistanceAndPointAtY(Line2D line, double y) {
double dy = line.getY2()-line.getY1();
// if line is horizontal, return null
if (dy==0) return null;
// parametric eqn of line: P = P1 + u(P2 - P1)
double u = (y-line.getY1())/dy;
double x = line.getX1() + u*(line.getX2()-line.getX1());
return new Object[] {u, new Point2D.Double(x, y)};
}