use of com.itextpdf.kernel.geom.Point in project i7j-pdfsweep by itext.
the class PdfCleanUpFilter method checkIfRectanglesIntersect.
/**
* Return true if two given rectangles (specified by an array of points) intersect.
*
* @param rect1 the first rectangle, considered as a subject of intersection. Even if it's width is zero,
* it still can be intersected by second rectangle.
* @param rect2 the second rectangle, considered as intersecting rectangle. If it has zero width rectangles
* are never considered as intersecting.
* @return true if the rectangles intersect, false otherwise
*/
static boolean checkIfRectanglesIntersect(Point[] rect1, Point[] rect2) {
IClipper clipper = new DefaultClipper();
// If the redaction area is degenerate, the result will be false
if (!ClipperBridge.addPolygonToClipper(clipper, rect2, PolyType.CLIP)) {
// If the content area is degenerate, let's process this case specifically
if (!ClipperBridge.addPolygonToClipper(clipper, rect1, PolyType.SUBJECT)) {
// because the redaction line corresponds to the descent line of the content.
if (!ClipperBridge.addPolylineSubjectToClipper(clipper, rect2)) {
return false;
}
if (rect1.length != rect2.length) {
return false;
}
Point startPoint = rect2[0];
Point endPoint = rect2[0];
for (int i = 1; i < rect2.length; i++) {
if (rect2[i].distance(startPoint) > EPS) {
endPoint = rect2[i];
break;
}
}
for (int i = 0; i < rect1.length; i++) {
if (isPointOnALineSegment(rect1[i], startPoint, endPoint, true)) {
return true;
}
}
}
return false;
}
// According to clipper documentation:
// The function will return false if the path is invalid for clipping. A path is invalid for clipping when:
// - it has less than 2 vertices;
// - it has 2 vertices but is not an open path;
// - the vertices are all co-linear and it is not an open path.
// Reference: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperBase/Methods/AddPath.htm
// If addition returns false, this means that there are less than 3 distinct points, because of rectangle zero width.
// Let's in this case specify the path as polyline, because we still want to know if redaction area
// intersects even with zero-width rectangles.
boolean intersectionSubjectAdded = ClipperBridge.addPolygonToClipper(clipper, rect1, PolyType.SUBJECT);
if (intersectionSubjectAdded) {
// working with paths is considered to be a bit faster in terms of performance.
Paths paths = new Paths();
clipper.execute(ClipType.INTERSECTION, paths, PolyFillType.NON_ZERO, PolyFillType.NON_ZERO);
return !checkIfIntersectionRectangleDegenerate(paths.getBounds(), false) && !paths.isEmpty();
} else {
int rect1Size = rect1.length;
intersectionSubjectAdded = ClipperBridge.addPolylineSubjectToClipper(clipper, rect1);
if (!intersectionSubjectAdded) {
// According to the comment above,
// this could have happened only if all four passed points are actually the same point.
// Adding here a point really close to the original point, to make sure it's not covered by the
// intersecting rectangle.
double smallDiff = 0.01;
List<Point> rect1List = new ArrayList<Point>(Arrays.asList(rect1));
rect1List.add(new Point(rect1[0].getX() + smallDiff, rect1[0].getY()));
rect1 = rect1List.toArray(new Point[rect1Size]);
intersectionSubjectAdded = ClipperBridge.addPolylineSubjectToClipper(clipper, rect1);
assert intersectionSubjectAdded;
}
PolyTree polyTree = new PolyTree();
clipper.execute(ClipType.INTERSECTION, polyTree, PolyFillType.NON_ZERO, PolyFillType.NON_ZERO);
Paths paths = Paths.makePolyTreeToPaths(polyTree);
return !checkIfIntersectionRectangleDegenerate(paths.getBounds(), true) && !paths.isEmpty();
}
}
use of com.itextpdf.kernel.geom.Point in project i7j-pdfsweep by itext.
the class PdfCleanUpFilter method approximateCircle.
/**
* Approximate a circle with 4 Bezier curves (one for each 90 degrees sector).
*
* @param center center of the circle
* @param radius radius of the circle
*/
private static BezierCurve[] approximateCircle(Point center, double radius) {
// The circle is split into 4 sectors. Arc of each sector
// is approximated with bezier curve separately.
BezierCurve[] approximation = new BezierCurve[4];
double x = center.getX();
double y = center.getY();
approximation[0] = new BezierCurve(Arrays.asList(new Point(x, y + radius), new Point(x + radius * CIRCLE_APPROXIMATION_CONST, y + radius), new Point(x + radius, y + radius * CIRCLE_APPROXIMATION_CONST), new Point(x + radius, y)));
approximation[1] = new BezierCurve(Arrays.asList(new Point(x + radius, y), new Point(x + radius, y - radius * CIRCLE_APPROXIMATION_CONST), new Point(x + radius * CIRCLE_APPROXIMATION_CONST, y - radius), new Point(x, y - radius)));
approximation[2] = new BezierCurve(Arrays.asList(new Point(x, y - radius), new Point(x - radius * CIRCLE_APPROXIMATION_CONST, y - radius), new Point(x - radius, y - radius * CIRCLE_APPROXIMATION_CONST), new Point(x - radius, y)));
approximation[3] = new BezierCurve(Arrays.asList(new Point(x - radius, y), new Point(x - radius, y + radius * CIRCLE_APPROXIMATION_CONST), new Point(x - radius * CIRCLE_APPROXIMATION_CONST, y + radius), new Point(x, y + radius)));
return approximation;
}
use of com.itextpdf.kernel.geom.Point in project i7j-pdfsweep by itext.
the class PdfCleanUpFilter method filterFillPath.
/**
* Note: this method will close all unclosed subpaths of the passed path.
*
* @param path the PathRenderInfo object to be filtered.
* @param ctm a {@link com.itextpdf.kernel.geom.Path} transformation matrix.
* @param fillingRule If the subpath is contour, pass any value.
* @return a filtered {@link com.itextpdf.kernel.geom.Path} object.
*/
private com.itextpdf.kernel.geom.Path filterFillPath(com.itextpdf.kernel.geom.Path path, Matrix ctm, int fillingRule) {
path.closeAllSubpaths();
IClipper clipper = new DefaultClipper();
ClipperBridge.addPath(clipper, path, PolyType.SUBJECT);
for (Rectangle rectangle : regions) {
try {
Point[] transfRectVertices = transformPoints(ctm, true, getRectangleVertices(rectangle));
ClipperBridge.addPolygonToClipper(clipper, transfRectVertices, PolyType.CLIP);
} catch (PdfException e) {
if (!(e.getCause() instanceof NoninvertibleTransformException)) {
throw e;
} else {
logger.error(MessageFormatUtil.format(CleanUpLogMessageConstant.FAILED_TO_PROCESS_A_TRANSFORMATION_MATRIX));
}
}
}
PolyFillType fillType = PolyFillType.NON_ZERO;
if (fillingRule == PdfCanvasConstants.FillingRule.EVEN_ODD) {
fillType = PolyFillType.EVEN_ODD;
}
PolyTree resultTree = new PolyTree();
clipper.execute(ClipType.DIFFERENCE, resultTree, fillType, PolyFillType.NON_ZERO);
return ClipperBridge.convertToPath(resultTree);
}
use of com.itextpdf.kernel.geom.Point in project i7j-pdfsweep by itext.
the class PdfCleanUpFilter method transformPoints.
private static Point[] transformPoints(Matrix transformationMatrix, boolean inverse, Point... points) {
AffineTransform t = new AffineTransform(transformationMatrix.get(Matrix.I11), transformationMatrix.get(Matrix.I12), transformationMatrix.get(Matrix.I21), transformationMatrix.get(Matrix.I22), transformationMatrix.get(Matrix.I31), transformationMatrix.get(Matrix.I32));
Point[] transformed = new Point[points.length];
if (inverse) {
try {
t = t.createInverse();
} catch (NoninvertibleTransformException e) {
throw new PdfException(CleanupExceptionMessageConstant.NONINVERTIBLE_MATRIX_CANNOT_BE_PROCESSED, e);
}
}
t.transform(points, 0, transformed, 0, points.length);
return transformed;
}
use of com.itextpdf.kernel.geom.Point in project i7j-pdfsweep by itext.
the class PdfCleanUpFilter method constructSquare.
private static Subpath constructSquare(Point squareCenter, double widthHalf, double rotationAngle) {
// Orthogonal square is the square with sides parallel to one of the axes.
Point[] ortogonalSquareVertices = { new Point(-widthHalf, -widthHalf), new Point(-widthHalf, widthHalf), new Point(widthHalf, widthHalf), new Point(widthHalf, -widthHalf) };
Point[] rotatedSquareVertices = getRotatedSquareVertices(ortogonalSquareVertices, rotationAngle, squareCenter);
Subpath square = new Subpath();
square.addSegment(new Line(rotatedSquareVertices[0], rotatedSquareVertices[1]));
square.addSegment(new Line(rotatedSquareVertices[1], rotatedSquareVertices[2]));
square.addSegment(new Line(rotatedSquareVertices[2], rotatedSquareVertices[3]));
square.addSegment(new Line(rotatedSquareVertices[3], rotatedSquareVertices[0]));
return square;
}
Aggregations