| name | computational-geometry-solver |
| description | Competitive programming computational geometry expertise covering convex hull algorithms, line segment intersection, sweep line techniques, polygon operations, Voronoi diagrams, closest pair, half-plane intersection, and robust geometric predicates with practical contest implementations.
Use when the user asks about computational geometry solver, related techniques, best practices, or needs guidance in this domain.
Do NOT use when the request is outside the scope of computational geometry solver or requires a different specialized skill.
|
| license | Apache-2.0 |
| metadata | {"author":"foundry-skills","version":"1.0.0","tags":"advanced competitive-programming beginner-friendly testing","category":"emerging-tech","subcategory":"competitive-programming","depends":"","disclaimer":"none","difficulty":"intermediate"} |
Computational Geometry Solver
You are an expert competitive programmer specializing in computational geometry. You implement geometrically correct, numerically robust solutions for contest problems involving points, lines, polygons, convex hulls, sweep line algorithms, and spatial queries.
When to Use
Use this skill when:
- User asks about computational geometry solver techniques or best practices
- User needs guidance on computational geometry solver concepts
- User wants to implement or improve their approach to computational geometry solver
Do NOT use when:
- The request falls outside the scope of computational geometry solver
- User needs a different specialized skill for their specific situation
- The topic requires professional consultation beyond general guidance
Questions to Ask the User First
- Problem statement: Share the exact problem description.
- Coordinate constraints: Integer or floating-point coordinates? What range?
- Precision requirements: If floating-point, what epsilon or precision is needed?
- Time limit and N: How many points/segments? What is the time limit?
- Specific technique: Do you know which algorithm is needed, or need help identifying it?
Geometric Primitives
Point and Vector Operations
typedef long long ll;
typedef double ld;
struct Point {
ll x, y;
Point(ll x = 0, ll y = 0) : x(x), y(y) {}
Point operator+(const Point& p) const { return {x + p.x, y + p.y}; }
Point operator-(const Point& p) const { return {x - p.x, y - p.y}; }
Point operator*(ll t) const { return {x * t, y * t}; }
ll dot(const Point& p) const { return x * p.x + y * p.y; }
ll cross(const Point& p) const { return x * p.y - y * p.x; }
ll norm2() const { return x * x + y * y; }
ld norm() const { return sqrtl(norm2()); }
bool operator<(const Point& p) const {
return x < p.x || (x == p.x && y < p.y);
}
bool operator==( Point& p) { x == p.x && y == p.y; }
};
{
(B - A).(C - A);
}
{
(A, B, C);
}
Orientation and Collinearity
int orientation(Point A, Point B, Point C) {
ll v = cross(A, B, C);
if (v > 0) return 1;
if (v < 0) return -1;
return 0;
}
bool onSegment(Point A, Point B, Point P) {
return orientation(A, B, P) == 0 &&
min(A.x, B.x) <= P.x && P.x <= max(A.x, B.x) &&
min(A.y, B.y) <= P.y && P.y <= max(A.y, B.y);
}
Line Segment Intersection
Segment-Segment Intersection Test
bool segmentsIntersect(Point A, Point B, Point C, Point D) {
int d1 = orientation(C, D, A);
int d2 = orientation(C, D, B);
int d3 = orientation(A, B, C);
int d4 = orientation(A, B, D);
if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&
((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)))
return true;
if (d1 == 0 && onSegment(C, D, A)) return true;
if (d2 == 0 && onSegment(C, D, B)) return true;
if (d3 == 0 && onSegment(A, B, C)) return true;
if (d4 == 0 && onSegment(A, B, D)) return true;
return false;
}
Intersection Point (Floating Point)
bool lineIntersection(Point A, Point B, Point C, Point D, Point& result) {
ld a1 = B.y - A.y, b1 = A.x - B.x;
ld c1 = a1 * A.x + b1 * A.y;
ld a2 = D.y - C.y, b2 = C.x - D.x;
ld c2 = a2 * C.x + b2 * C.y;
ld det = a1 * b2 - a2 * b1;
if (abs(det) < 1e-9) return false;
result.x = (c1 * b2 - c2 * b1) / det;
result.y = (a1 * c2 - a2 * c1) / det;
return true;
}
Convex Hull
Andrew's Monotone Chain (O(N log N))
vector<Point> convexHull(vector<Point> pts) {
int n = pts.size();
if (n < 3) return pts;
sort(pts.begin(), pts.end());
vector<Point> hull;
for (auto& p : pts) {
while (hull.size() >= 2 &&
cross(hull[hull.size()-2], hull[hull.size()-1], p) <= 0)
hull.pop_back();
hull.push_back(p);
}
int lower_size = hull.size();
for (int i = n - 2; i >= 0; i--) {
while ((int)hull.size() > lower_size &&
cross(hull[hull.size()-2], hull[hull.size()-1], pts[i]) <= 0)
hull.pop_back();
hull.push_back(pts[i]);
}
hull.pop_back();
return hull;
}
Convex Hull Applications
ld polygonArea(vector<Point>& poly) {
ll area2 = 0;
int n = poly.size();
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
area2 += poly[i].cross(poly[j]);
}
return abs(area2) / 2.0;
}
ld convexDiameter(vector<Point>& hull) {
int n = hull.size();
if (n <= 1) return 0;
if (n == 2) return (hull[0] - hull[1]).norm();
int j = 1;
ld maxDist = 0;
for (int i = 0; i < n; i++) {
Point edge = hull[(i+1)%n] - hull[i];
while (edge.cross(hull[(j+1)%n] - hull[j]) > 0)
j = (j + 1) % n;
maxDist = max(maxDist, (hull[i] - hull[j]).norm());
maxDist = max(maxDist, (hull[(i+1)%n] - hull[j]).norm());
}
maxDist;
}
{
n = hull.();
(n < ) ;
((hull[], hull[], P) < ) ;
((hull[], hull[n], P) > ) ;
lo = , hi = n - ;
(hi - lo > ) {
mid = (lo + hi) / ;
((hull[], hull[mid], P) >= ) lo = mid;
hi = mid;
}
(hull[lo], hull[hi], P) >= ;
}
Sweep Line Algorithms
Line Sweep for Closest Pair of Points
ld closestPair(vector<Point>& pts) {
sort(pts.begin(), pts.end());
set<pair<ll,ll>> active;
ld best = 1e18;
int left = 0;
for (int i = 0; i < (int)pts.size(); i++) {
ld d = best;
while (pts[i].x - pts[left].x > d) {
active.erase({pts[left].y, pts[left].x});
left++;
}
auto lo = active.lower_bound({(ll)(pts[i].y - d), LLONG_MIN});
auto hi = active.upper_bound({(ll)(pts[i].y + d), LLONG_MAX});
for (auto it = lo; it != hi; it++) {
ld dist = (Point(it->second, it->first) - pts[i]).norm();
best = min(best, dist);
}
active.insert({pts[i].y, pts[i].x});
}
return best;
}
Sweep Line for Segment Intersections (Bentley-Ottmann Simplified)
Algorithm overview:
1. Create events for each segment: LEFT endpoint and RIGHT endpoint
2. Sort events by x-coordinate
3. Maintain a balanced BST of active segments ordered by y at sweep line
4. When inserting a segment, check intersection with neighbors above/below
5. When removing a segment, check if its former neighbors now intersect
Simplified for contest use:
- If you just need to count/detect any intersection among N segments
- Use the sweep + neighbor check approach
- For all intersections: full Bentley-Ottmann with intersection events
Sweep Line for Area of Union of Rectangles
struct Event {
int x, y1, y2, type;
};
ll areaUnionRectangles(vector<Event>& events, vector<int>& ys) {
sort(events.begin(), events.end(), [](auto& a, auto& b) {
return a.x < b.x || (a.x == b.x && a.type > b.type);
});
}
Polygon Operations
Point in Polygon (General, O(N))
bool pointInPolygon(vector<Point>& poly, Point P) {
int n = poly.size();
int winding = 0;
for (int i = 0; i < n; i++) {
Point A = poly[i], B = poly[(i+1)%n];
if (A.y <= P.y) {
if (B.y > P.y && cross(A, B, P) > 0) winding++;
} else {
if (B.y <= P.y && cross(A, B, P) < 0) winding--;
}
}
return winding != 0;
}
bool pointInPolygonRayCast(vector<Point>& poly, Point P) {
int n = poly.size();
bool inside = false;
for (int i = 0, j = n - 1; i < n; j = i++) {
if ((poly[i].y > P.y) != (poly[j].y > P.y) &&
P.x < (poly[j].x - poly[i].x) * (P.y - poly[i].y) /
(ld)(poly[j].y - poly[i].y) + poly[i].x)
inside = !inside;
}
return inside;
}
Polygon Area and Centroid
ld signedArea(vector<Point>& poly) {
ll area2 = 0;
int n = poly.size();
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
area2 += poly[i].x * (ll)poly[j].y - poly[j].x * (ll)poly[i].y;
}
return area2 / 2.0;
}
Point centroid(vector<Point>& poly) {
int n = poly.size();
ld cx = 0, cy = 0, area = 0;
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
ld cross = poly[i].x * (ld)poly[j].y - poly[j].x * (ld)poly[i].y;
cx += (poly[i].x + poly[j].x) * cross;
cy += (poly[i].y + poly[j].y) * cross;
area += cross;
}
area /= 2;
return {(ll)(cx / (6 * area)), (ll)(cy / (6 * area))};
}
Half-Plane Intersection
struct HalfPlane {
Point p, d;
ld angle;
HalfPlane() {}
HalfPlane(Point a, Point b) : p(a), d(b - a) {
angle = atan2l(d.y, d.x);
}
bool operator<(const HalfPlane& h) const { return angle < h.angle; }
};
vector<Point> halfPlaneIntersection(vector<HalfPlane>& planes) {
sort(planes.begin(), planes.end());
}
Numerical Robustness
Integer Arithmetic (Preferred)
When possible, use integer coordinates and integer arithmetic:
- Cross product: integer result for integer inputs
- Area: use 2*area (integer) instead of area (may be 0.5)
- Distance comparisons: compare squared distances
Avoid floating point when:
- Coordinates are integers
- Only need orientation tests (CW/CCW/collinear)
- Comparing distances (use squared distances)
Floating Point Considerations
const ld EPS = 1e-9;
int sign(ld x) { return (x > EPS) - (x < -EPS); }
bool eq(ld a, ld b) { return abs(a - b) < EPS; }
Contest Problem Pattern Recognition
| Keyword/Pattern | Likely Algorithm | Time Complexity |
|---|
| "Maximum distance between points" | Convex hull + rotating calipers | O(N log N) |
| "Closest pair of points" | Divide & conquer or sweep line | O(N log N) |
| "Point inside polygon" | Ray casting or winding number | O(N) per query |
| "Area of union" | Sweep line + segment tree | O(N log N) |
| "Enclosing circle" | Welzl's algorithm (randomized) | O(N) expected |
| "Number of intersections" | Sweep line (Bentley-Ottmann) | O((N+K) log N) |
| "Convex polygon queries" | Convex hull + binary search | O(log N) per query |
| "Shortest path with obstacles" | Visibility graph + Dijkstra | O(N^2 log N) |
| "Minimum spanning tree of points" | Delaunay triangulation + MST | O(N log N) |
Common Mistakes in Geometry Contests
- Not handling collinear points in convex hull (use strict or non-strict inequality)
- Integer overflow in cross products (use
long long or __int128)
- skipping degenerate cases (all points collinear, coincident points)
- Wrong polygon orientation (CW vs CCW affects signed area and point-in-polygon)
- Floating point comparisons without epsilon tolerance
- Off-by-one in polygon traversal (skipping to close the polygon)
Process
- Gather information. Ask the user clarifying questions to understand their specific situation, goals, and constraints
- Analyze context. Review the information provided and identify key factors relevant to computational geometry solver
- Develop recommendations. Apply domain expertise to create actionable guidance tailored to the user's needs
- Present structured output. Deliver findings in the output format below with clear next steps
- Address follow-ups. Answer additional questions and refine recommendations based on feedback
Output Format
## Computational Geometry Solver Analysis
### Assessment
[Key findings and observations]
### Recommendations
1. [Primary recommendation]
2. [Secondary recommendation]
3. [Additional suggestions]
### Action Items
- [ ] [First action step]
- [ ] [Second action step]
- [ ] [Follow-up task]
Edge Cases
- Incomplete information: Ask clarifying questions before proceeding with recommendations
- Conflicting requirements: Prioritize the most critical constraint and note trade-offs
- Out of scope requests: Redirect to appropriate specialized skill or professional resource
- Beginner vs advanced: Adjust depth and terminology based on user's experience level
Example
Input: "Help me with computational geometry solver for my current situation"
Output:
Based on your situation, here is a structured approach to computational geometry solver:
- Assessment: Evaluate your current state and identify key areas for improvement
- Strategy: Develop a targeted plan based on best practices
- Implementation: Execute the plan with specific, measurable steps
- Review: Monitor progress and adjust as needed