Created
April 3, 2025 04:15
-
-
Save chausen/b154b1563c63285ad78ad4e64d1807f4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.*; | |
import java.awt.image.BufferedImage; | |
import java.util.List; | |
public class CrosshatchExample { | |
// A simple data structure to hold a region’s pixel coordinates plus a “density” value | |
public static class Region { | |
private List<Point> pixelCoordinates; | |
private float density; // e.g. 0.1 = sparse, 0.9 = dense | |
public Region(List<Point> pixelCoordinates, float density) { | |
this.pixelCoordinates = pixelCoordinates; | |
this.density = density; | |
} | |
public List<Point> getPixelCoordinates() { | |
return pixelCoordinates; | |
} | |
public float getDensity() { | |
return density; | |
} | |
} | |
public static void main(String[] args) { | |
int width = 400; | |
int height = 400; | |
// Create a BufferedImage where we will draw everything | |
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); | |
// Get a Graphics2D context so we can render shapes, lines, etc. | |
Graphics2D g = image.createGraphics(); | |
try { | |
// White background | |
g.setColor(Color.WHITE); | |
g.fillRect(0, 0, width, height); | |
// Example: Suppose we have a few Region objects | |
// (In a real scenario, these would come from your API or somewhere else) | |
Region regionA = new Region( | |
List.of( // some pixel coordinates for region A | |
new Point(50, 50), | |
new Point(50, 51), | |
new Point(51, 50), | |
new Point(51, 51), | |
// ... etc ... | |
new Point(100, 100) | |
), | |
0.3f // A fairly sparse crosshatch | |
); | |
Region regionB = new Region( | |
List.of( // some pixel coordinates for region B | |
new Point(150, 150), | |
new Point(150, 151), | |
new Point(151, 150), | |
// ... etc ... | |
new Point(200, 200) | |
), | |
0.8f // A dense crosshatch | |
); | |
// We’ll gather these in a list | |
List<Region> regions = List.of(regionA, regionB); | |
// Define a single color for all crosshatches | |
Color hatchColor = Color.BLACK; | |
// For each region, draw crosshatches | |
for (Region region : regions) { | |
drawCrossHatch(g, region, hatchColor); | |
} | |
// (You would now write the image to disk, or return it in a response, etc.) | |
// ImageIO.write(image, "PNG", new File("output.png")); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} finally { | |
// Dispose of the Graphics2D context | |
g.dispose(); | |
} | |
} | |
/** | |
* Draws crosshatches in the given region using the specified color. | |
* The region’s density determines how close the lines are. | |
*/ | |
private static void drawCrossHatch(Graphics2D g, Region region, Color hatchColor) { | |
float density = region.getDensity(); | |
// Map density [0.0, 1.0] to a spacing range (smaller spacing => higher density) | |
// For example, let’s say spacing can go from 3 pixels (dense) up to 20 pixels (sparse). | |
// You can tweak the numbers based on your needs. | |
int minSpacing = 3; | |
int maxSpacing = 20; | |
int spacing = (int) ((1 - density) * (maxSpacing - minSpacing) + minSpacing); | |
// Optional: get the bounding rectangle of the region so we can iterate systematically | |
Rectangle bounds = getBounds(region.getPixelCoordinates()); | |
// Set the color for the crosshatches | |
g.setColor(hatchColor); | |
// First diagonal (/) | |
for (int y = bounds.y; y <= bounds.y + bounds.height; y += spacing) { | |
// We'll draw a line from left to right across the bounding region | |
// We'll only draw where it intersects the region's pixels. | |
drawDiagonalLine(g, region, bounds.x, y, +1, spacing); | |
} | |
// Second diagonal (\) | |
for (int y = bounds.y; y <= bounds.y + bounds.height; y += spacing) { | |
// We'll draw in the opposite direction | |
drawDiagonalLine(g, region, bounds.x + bounds.width, y, -1, spacing); | |
} | |
} | |
/** | |
* Helper method: draws a diagonal line across the region if the region’s pixels are present. | |
* direction = +1 for one diagonal (/), -1 for the other diagonal (\). | |
*/ | |
private static void drawDiagonalLine(Graphics2D g, | |
Region region, | |
int startX, | |
int startY, | |
int direction, | |
int spacing) { | |
// We can step in increments until we’re out of the bounding box. | |
// direction +1 means x++ each step, direction -1 means x-- each step. | |
// We'll move along the diagonal until we exit the region’s bounding area. | |
// For simplicity, let's define a maximum length for a single diagonal | |
int maxLength = 1000; // or compute from bounding rectangle if you want | |
// We'll collect line segments that are valid (within region’s pixel set). | |
// This is just a demonstration approach. | |
int x = startX; | |
int y = startY; | |
// For quick membership checking, store region pixels in a HashSet | |
// (You could do it outside and pass in to avoid repeated creation). | |
// This is optional but helps if you want to only draw lines on real region pixels. | |
java.util.Set<Point> pixelSet = new java.util.HashSet<>(region.getPixelCoordinates()); | |
Point prev = null; | |
for (int i = 0; i < maxLength; i++) { | |
if (!pixelSet.contains(new Point(x, y))) { | |
// If we’re out of region pixels, break or skip | |
// In a real scenario, you might want to “continue” until we jump back in region | |
// This is just a simplistic approach that stops if we leave the region. | |
if (prev != null) { | |
// We can finalize the line segment if we had started one | |
// g.drawLine(prev.x, prev.y, x, y); | |
} | |
break; | |
} | |
if (prev == null) { | |
// Start a new line segment | |
prev = new Point(x, y); | |
} else { | |
// Extend the line segment | |
g.drawLine(prev.x, prev.y, x, y); | |
prev = new Point(x, y); | |
} | |
// Move to the next diagonal pixel | |
x += direction; | |
y -= 1; // for slope -1 or +1 diagonal | |
} | |
} | |
/** | |
* Returns the bounding rectangle that encloses all pixel coordinates in the region. | |
*/ | |
private static Rectangle getBounds(List<Point> points) { | |
if (points.isEmpty()) return new Rectangle(0,0,0,0); | |
int minX = points.stream().mapToInt(p -> p.x).min().orElse(0); | |
int maxX = points.stream().mapToInt(p -> p.x).max().orElse(0); | |
int minY = points.stream().mapToInt(p -> p.y).min().orElse(0); | |
int maxY = points.stream().mapToInt(p -> p.y).max().orElse(0); | |
return new Rectangle(minX, minY, (maxX - minX), (maxY - minY)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment