下图说明了创建Manhattan图时遇到的问题:
该框围绕着与现有线重叠的大部分线[(tx,midy) - (sx,midy)](在下面的代码中由psegment
表示)。我已经删除了重叠的箭头(和尾部),并且对如何检查重叠感到有些困惑。
以下是有问题的代码:
Line2D.Double segment = new Line2D.Double( sx, midy, tx, midy );
// Associate the middle-y point with the bounds of the target object.
// On subsequent draws of targets with a similar mid-y, make sure that
// there are no overlapping lines.
//
if( midPointMap.put( midy, segment ) != null ) {
//if( midy == 90 ) {
// New Line.
//
System.err.printf( "NEW: (%3.2f, %3d)-(%3.2f, %3d)\n", sx, midy, tx,
midy );
for( Line2D.Double psegment : midPointMap.getValues( midy ) ) {
// Previous Line.
//
System.err.printf( "OLD: (%3.2f, %3d)-(%3.2f, %3d)\n",
psegment.getX1(), midy, psegment.getX2(), midy );
}
//}
}
// Line for the bus.
//
result.moveTo( sx, midy );
result.lineTo( tx, midy );
这是另一个示例图片,让您了解曼哈顿布局:
在上面的图中,Dialog和Window之间的线重叠(在此缩放时不太明显)。该图像说明了如何存在多个子类,因此检测重叠必须考虑沿同一y线的多个源(sx,sy)的多个目标(tx,ty)。
midPointMap
变量是一个哈希集,每个键可以包含多个值:
private MultiValueMap<Integer, Line2D.Double> midPointMap =
new MultiValueMap<Integer, Line2D.Double>();
这会将mid-y值映射到一组线段。
如果与现有线段重叠,如何不绘制线条?
更新#1
请注意,每个“总线”的线段没有特定的顺序。
答案 0 :(得分:1)
我可能会遗漏某些东西(例如,我不明白你为什么要这样做 - 也许你正在用不同颜色或其他东西画画?如果你只是想优化一些写操作,我我不确定你是否会真正获得任何收益。
但是,假设有充分的理由这样做,我认为以下算法可行:
我假设片段的布局是这样的,你不能有两个部分相互重叠的片段,像这样(片段是aA和bB):
一个===== b ===甲=========乙
如果你确实有这种可能性,那么你将不得不决定如何解决这个问题。
PS - 请务必添加为什么的简要说明,以消除这些细分。我很好奇!
答案 1 :(得分:0)
这是一个完整的解决方案:
// If line segments would overlap, this gets set to false.
//
boolean drawSegment = true;
Line2D.Double segment = new Line2D.Double( sx, midy, tx, midy );
// Associate the middle-y point with the bounds of the target object.
// On subsequent draws of targets with a similar mid-y, make sure that
// there are no overlapping lines.
//
if( midPointMap.put( midy, segment ) != null ) {
// Check previous lines for overlap. Each previous line segment has
// values in the form: (sx, mid-y)-(tx, mid-y), which map to
// (getX1(), midy)-(getX2(), midy).
//
for( Line2D.Double psegment : midPointMap.getValues( midy ) ) {
// If the lines have the same source point, and differ in their
// target point, then they might overlap
//
if( sx == psegment.getX1() && tx != psegment.getX2() ) {
double pdx = psegment.getX1() - psegment.getX2();
double cdx = sx - tx;
// At this juncture: the mid-y points are the same, the source
// points of the previous segment and the current segment are the
// same, and the target points of the segments differ.
//
// If both lines go in the same direction (relative to the same
// source point), then they overlap. The difference of the tx
// and X2 points is how much overlap exists.
//
// There are two actionable possibilities: (1) psegment is longer
// than the current segment; or (2) psegment is shorter.
//
// If psegment is longer, then no segment must be drawn. If
// psegment is shorter, the difference between psegment and the
// current segment must be drawn.
//
if( tx < sx && psegment.getX2() < sx ) {
// SEGMENT IS TO THE LEFT OF SOURCE
//
if( pdx > cdx ) {
// If the previous segment is longer, then draw nothing.
//
drawSegment = false;
}
else {
// If the previous segment is shorter, then draw the
// difference. That is, change the source point for
// this segment to the target point of the previous segment.
//
sx = psegment.getX2();
}
}
else if( tx > sx && psegment.getX2() > sx ) {
// SEGMENT IS TO THE RIGHT OF SOURCE
//
if( pdx < cdx ) {
// If the previous segment is longer, then draw nothing.
//
drawSegment = false;
}
else {
// If the previous segment is shorter, then draw the
// difference. That is, change the source point for
// this segment to the target point of the previous segment.
//
sx = psegment.getX2();
}
}
}
}
}
// Draw the line for the bus.
//
if( drawSegment ) {
result.moveTo( sx, midy );
result.lineTo( tx, midy );
}
如果可以优化(或简化),我真的很想知道。