/**
* pdfXtk - PDF Extraction Toolkit
* Copyright (c) by the authors/contributors. All rights reserved.
* This project includes code from PDFBox and TouchGraph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the names pdfXtk or PDF Extraction Toolkit; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://pdfxtk.sourceforge.net
*
*/
package at.ac.tuwien.dbai.pdfwrap.utils;
import at.ac.tuwien.dbai.pdfwrap.model.document.GenericSegment;
import at.ac.tuwien.dbai.pdfwrap.model.graph.AdjacencyEdge;
/**
* static intersection, etc. methods for segments
*
* @author Tamir Hassan, pdfanalyser@tamirhassan.com
* @version PDF Analyser 0.9
*/
public class SegmentUtils
{
/*
public static void mergeIntersectingCompositeSegs
(List<CompositeSegment<? extends GenericSegment>> segs)
{
List<CompositeSegment<? extends GenericSegment>> segsToRemove =
new ArrayList<CompositeSegment<? extends GenericSegment>>();
for (CompositeSegment<? extends GenericSegment> cs : segs)
{
for (CompositeSegment<? extends GenericSegment> cs1 : segs)
{
if (centresIntersect(cs, cs1))
{
segsToRemove.add(cs1);
cs.getItems().addAll(cs1.getItems());
cs.setCalculatedFields();
}
}
}
}
*/
public static boolean horizMinIntersect(GenericSegment seg1,
GenericSegment seg2, float percent)
{
// calculate intersectionWidth as the * of the
// smaller width dimension
float intersectionWidth = seg1.getWidth() * percent;
if (seg2.getWidth() < seg1.getWidth())
intersectionWidth = seg2.getWidth() * percent;
// seg1.getX1() lies within bounds of seg2
// ### #### seg1
// ####### #### seg2
if (seg1.getX1() >= seg2.getX1() && seg1.getX1() <= seg2.getX2())
{
// intersection between seg1.getX1() and min(seg1.getX2(), seg2.getX2())
return (Utils.minimum(seg1.getX2(), seg2.getX2()) - seg1.getX1()
>= intersectionWidth);
}
// seg2.getX1() lies within bounds of seg1
// ####### #### seg1
// ### #### seg2
else if (seg2.getX1() >= seg1.getX1() && seg2.getX1() <= seg1.getX2())
{
// intersection between seg2.getX1() and min(seg1.getX2(), seg2.getX2())
// System.out.println("actual: " + (Utils.minimum(seg1.getX2(), seg2.getX2()) - seg1.getX1()));
// System.out.println("required 0.2: " + intersectionWidth);
return (Utils.minimum(seg1.getX2(), seg2.getX2()) - seg2.getX1()
>= intersectionWidth);
}
return false;
}
public static boolean horizIntersect(GenericSegment seg1,
GenericSegment seg2)
{
return (seg1.getX1() >= seg2.getX1() && seg1.getX1() <= seg2.getX2()) //seg1.getX1() edge lies along seg2 boundary
|| (seg2.getX1() >= seg1.getX1() && seg2.getX1() <= seg1.getX2()); //or seg2.getX1() edge lies along seg1 boundary
// 13.07.10 seems sufficient
}
public static boolean horizIntersect(GenericSegment seg1, float sx1,
float sx2)
{
GenericSegment seg2 = new GenericSegment(sx1, sx2, -1, -1);
return (seg1.getX1() >= seg2.getX1() && seg1.getX1() <= seg2.getX2())
|| (seg2.getX1() >= seg1.getX1() && seg2.getX1() <= seg1.getX2());
}
public static boolean horizIntersect(GenericSegment seg, float val)
{
return (seg.getX1() <= val && seg.getX2() >= val)
|| (seg.getX1() >= val && seg.getX2() <= val);
}
public static boolean vertMinIntersect(GenericSegment seg1,
GenericSegment seg2, float percent)
{
// calculate intersectionWidth as the * of the
// smaller width dimension
float intersectionHeight = seg1.getHeight() * percent;
if (seg2.getHeight() < seg1.getHeight())
intersectionHeight = seg2.getHeight() * percent;
// System.out.println("intersection height limit: " + intersectionHeight);
// seg1.getY1() lies within bounds of seg2
if (seg1.getY1() >= seg2.getY1() && seg1.getY1() <= seg2.getY2())
{
// intersection between seg1.getY1() and min(seg1.getY2(), seg2.getY2())
// System.out.println("actual intersection height: "+(Utils.minimum(seg1.getY2(), seg2.getY2()) - seg1.getY1()));
return (Utils.minimum(seg1.getY2(), seg2.getY2()) - seg1.getY1()
>= intersectionHeight);
}
// seg2.getY1() lies within bounds of seg1
else if (seg2.getY1() >= seg1.getY1() && seg2.getY1() <= seg1.getY2())
{
// intersection between seg2.getX1() and min(seg1.getX2(), seg2.getX2())
// System.out.println("actual intersection height: "+(Utils.minimum(seg1.getY2(), seg2.getY2()) - seg1.getY1()));
return (Utils.minimum(seg1.getY2(), seg2.getY2()) - seg2.getY1()
>= intersectionHeight);
}
return false;
}
public static boolean vertIntersect(GenericSegment seg1, GenericSegment seg2)
{
return (seg1.getY1() >= seg2.getY1() && seg1.getY1() <= seg2.getY2())
|| (seg2.getY1() >= seg1.getY1() && seg2.getY1() <= seg1.getY2());
}
public static boolean vertIntersect(GenericSegment seg1, float sy1,
float sy2)
{
GenericSegment seg2 = new GenericSegment(-1, -1, sy1, sy2);
return (seg1.getY1() >= seg2.getY1() && seg1.getY1() <= seg2.getY2())
|| (seg2.getY1() >= seg1.getY1() && seg2.getY1() <= seg1.getY2());
}
public static boolean vertIntersect(GenericSegment seg, float val)
{
return (seg.getY1() <= val && seg.getY2() >= val)
|| (seg.getY1() >= val && seg.getY2() <= val);
}
public static boolean horizCentresIntersect(GenericSegment seg1, GenericSegment seg2)
{
return (horizIntersect(seg1, seg2.getXmid()) ||
horizIntersect(seg2, seg1.getXmid()));
}
public static boolean vertCentresIntersect(GenericSegment seg1, GenericSegment seg2)
{
return (vertIntersect(seg1, seg2.getYmid()) ||
vertIntersect(seg2, seg1.getYmid()));
}
public static boolean centresIntersect(GenericSegment seg1, GenericSegment seg2)
{
return (horizCentresIntersect(seg1, seg2) && vertCentresIntersect(seg1, seg2));
}
public static boolean intersects(GenericSegment seg1, GenericSegment seg2)
{
//System.out.println("seg1: " + seg1 + "\nseg2: " + seg2);
//System.out.println("H: " + horizIntersect(seg1, seg2) + " V: " + vertIntersect(seg1, seg2));
return horizIntersect(seg1, seg2) && vertIntersect(seg1, seg2);
}
public static boolean intersects(AdjacencyEdge<? extends GenericSegment> e1,
AdjacencyEdge<? extends GenericSegment> e2)
{
/* 2011-01-26 variables never read...
GenericSegment a1 = e1.getNodeFrom();
GenericSegment b1 = e1.getNodeTo();
GenericSegment a2 = e2.getNodeFrom();
GenericSegment b2 = e2.getNodeTo();
*/
// returns FALSE if a nonsensical comparison is requested
// TODO: throw exception if a horizontal edge
// is compared with a vertical?
if ((e1.isHorizontal() == false && e2.isHorizontal() == true) ||
(e1.isHorizontal() == true && e2.isHorizontal() == false))
return false;
float hi1, low1, hi2, low2;
switch(e1.getDirection())
{
case AdjacencyEdge.REL_LEFT:
hi1 = e1.getNodeFrom().getX1();
low1 = e1.getNodeTo().getX2();
break;
case AdjacencyEdge.REL_RIGHT:
hi1 = e1.getNodeTo().getX1();
low1 = e1.getNodeFrom().getX2();
break;
case AdjacencyEdge.REL_ABOVE:
hi1 = e1.getNodeTo().getY1();
low1 = e1.getNodeFrom().getY2();
break;
case AdjacencyEdge.REL_BELOW:
hi1 = e1.getNodeFrom().getY1();
low1 = e1.getNodeTo().getY2();
break;
default:
// yet another nonsensical comparison!
return false;
}
switch(e2.getDirection())
{
case AdjacencyEdge.REL_LEFT:
hi2 = e2.getNodeFrom().getX1();
low2 = e2.getNodeTo().getX2();
break;
case AdjacencyEdge.REL_RIGHT:
hi2 = e2.getNodeTo().getX1();
low2 = e2.getNodeFrom().getX2();
break;
case AdjacencyEdge.REL_ABOVE:
hi2 = e2.getNodeTo().getY1();
low2 = e2.getNodeFrom().getY2();
break;
case AdjacencyEdge.REL_BELOW:
hi2 = e2.getNodeFrom().getY1();
low2 = e2.getNodeTo().getY2();
break;
default:
// yet another nonsensical comparison!
return false;
}
return (low1 >= low2 && low1 <= hi2) ||
(hi1 >= low2 && hi1 <= hi2) ||
(low1 < low2 && hi1 > hi2);
}
}