My initial attempt on even-odd got me in trouble with the outline, as given, being 1 unit wide, not zero-width. I had to compute normals to find out outline around the tiles. You write “on the line -> outside” but don’t many legal rectangle candidates sit on the edge?
- 9 Posts
- 218 Comments
C
Well this one got me stumped for a bit but after a few false starts, lots of debugging and some cleanup I’d say I have a pretty good solution now! The points being tiles rather than zero-width corners was the tricky bit here.
Basic working: it walks through the points, keeping track of normal vectors (the “outside” direction). With those, it generates the zero-width outline around the points, and from there on it’s pretty much old fashioned line intersection checks.
The initial nasty solve took 1.2 seconds on my Raspberry Pi 400, but some optimization (like sorting the edges list) brought that down to 0.08s on the Pi, and 0.02s on my 10-year old PC, and I’m quite happy with the code now.
Code
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <inttypes.h> #include <assert.h> #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define LEN(a) (sizeof(a)/sizeof(*(a))) #define MAXP 512 /* * There are two main problems with part 2: * 1. Deciding what is inside and what is outside of the polyline * 2. The points being _tiles_, not zero-width coordinates * * This solution walks the outline and calculates "normals" for each * point, which are angles pointing _out_ of the shape. Those are used * to derrive the outside boundary of the shape, the lines that go * around, not through, the corner tiles. Witth that we can do * more-or-less normal intersection checks. * * Angles are stored as 1/8ths of a circle. */ struct point { int x,y; }; struct edge { int off, lo,hi; }; static struct point pts[MAXP]; static struct edge hedges[MAXP/2]; static struct edge vedges[MAXP/2]; static int norms[MAXP]; static int np, nhe, nve; static int wrapa(int a) { return (a+8)%8; } static int cmp_edges(const void *a, const void *b) { return ((const struct edge *)a)->off - ((const struct edge *)b)->off; } static int line_dir(struct point a, struct point b) { return 4*(a.x>b.x || a.y<b.y) + 2*(a.x!=b.x); } static void calculate_normals(void) { int i, dir1,dir2, angle; int normal; /* relative to the current line */ dir1 = line_dir(pts[np-1], pts[0]); normal = wrapa(dir1 - 2); /* start left, assuming CCW order */ for (i=0; i<np; i++) { dir2 = line_dir(pts[i], pts[i==np-1 ? 0 : i+1]); angle = dir2 == dir1-2 || dir2 == dir1+6 ? -2 : 2; /* the point's normal is diagonal, halfway turned */ norms[i] = wrapa(normal + angle/2); dir1 = dir2; normal = wrapa(normal + angle); } } static void generate_edges(void) { struct point a,b; int i,j; for (i=0; i<np; i++) { a = pts[i]; b = pts[(j = i==np-1 ? 0 : i+1)]; /* shift the line to be _around_ point */ a.x += norms[i]<4; a.y += norms[i]>2 && norms[i]<6; b.x += norms[j]<4; b.y += norms[j]>2 && norms[j]<6; if (a.x == b.x) { assert(nve < (int)LEN(vedges)); vedges[nve].off = a.x; vedges[nve].lo = MIN(a.y, b.y); vedges[nve].hi = MAX(a.y, b.y); nve++; } else if (a.y == b.y) { assert(nhe < (int)LEN(hedges)); hedges[nhe].off = a.y; hedges[nhe].lo = MIN(a.x, b.x); hedges[nhe].hi = MAX(a.x, b.x); nhe++; } else assert(!"diagonal line"); } qsort(hedges, nhe, sizeof(*hedges), cmp_edges); qsort(vedges, nve, sizeof(*vedges), cmp_edges); } static bool rect_inside(struct point a, struct point b) { struct edge *e; int x0,y0,x1,y1; /* * Line intersection of the four rectangle edges against all * the polyline edges, with a caveat: the outline is 1 unit * thick, not zero-width! This is why some of the comparisons * are or-equals. */ x0 = MIN(a.x, b.x); y0 = MIN(a.y, b.y); x1 = MAX(a.x, b.x); y1 = MAX(a.y, b.y); for (e = vedges; e < vedges+nve; e++) { if (e->off <= x0) continue; if (e->off > x1) break; if (y0 >= e->lo && y0 < e->hi) return false; if (y1 >= e->lo && y1 < e->hi) return false; } for (e = hedges; e < hedges+nhe; e++) { if (e->off <= y0) continue; if (e->off > y1) break; if (x0 >= e->lo && x0 < e->hi) return false; if (x1 >= e->lo && x1 < e->hi) return false; } return true; } int main() { int64_t p1=0,p2=0, area, i,j; for (; scanf(" %d,%d", &pts[np].x, &pts[np].y)==2; np++) assert(np+1 < MAXP); assert(np >= 4); calculate_normals(); generate_edges(); for (i=0; i<np-1; i++) for (j=i+1; j<np; j++) { area = (int64_t)(abs(pts[i].x - pts[j].x) + 1) * (int64_t)(abs(pts[i].y - pts[j].y) + 1); if (area > p1) p1 = area; if (area > p2 && rect_inside(pts[i], pts[j])) p2 = area; } printf("09: %"PRIi64" %"PRIi64"\n", p1, p2); }
sjmulderto
Asklemmy@lemmy.ml•What are some loanwords (originated in another language and usually retains original spelling in equivalent english) for concepts, things, or experiences that English doesnt necessarily have yet?
2·2 months agoTurns out it’s from an old translation of James 4:15, here formulated as: “[If] so the Lord wills and we live”
sjmulderto
Asklemmy@lemmy.ml•What are some loanwords (originated in another language and usually retains original spelling in equivalent english) for concepts, things, or experiences that English doesnt necessarily have yet?
41·2 months agoThe English equivalent would be “God willing” and in Dutch, a lovely archaic phrase: “Zo de Heere wil en wij leven”
sjmulderto
Programming@programming.dev•The Original Sin of Computing...that no one can fix
1·2 months agoIt’s about the classic paper “Reflections on Trusting Trust”
sjmulderto
Gaming@beehaw.org•Weekly “What are you playing” Thread || Week of October 5th
1·2 months agoI started the Witcher 3 and immediately the world feels like a checklist and for some reason I can’t take Gerald seriously. He looks comical, like a teen’s drawing, and the movement feels completely ungrounded.
sjmulderto
Gaming@beehaw.org•Weekly “What are you playing” Thread || Week of October 5th
1·2 months ago- Circut Superstars. I’ll never become good at this but close to finishing it on Amateur
- Diablo 4. I dislike the MMOification and despite Blizzard, but got it with the Xbox so might as we’ll play it. The campaign and monster bashing are fine
- Sound Shapes. Sweet game, taking it one album at a time
- Trials Rising. Cleaning up the Hard tracks and that ain’t no lie
- Dirt 2.0 demo. I’m OK at CMR 2 and 05 but I have no idea how to control my car in this one. It’ll come with time
Programming. I don’t like where it’s heading and I don’t like the culture
sjmulderto
traingang@hexbear.net•I Built a 5 Acre Pond But Never Expected This to HappenEnglish
4·2 months agoClickbait title, tldw?
sjmulderto
Ask Lemmy@lemmy.world•Is there anything you're into that no one or basically nobody is into?
19·2 months agoI like retro programming, in particular Windows 2000.
Now I’m making a little 3D toy now that works with OpenGL on Windows with WGL and on X11 with GLX (also on Cygwin). No third party abstractions!
I want to keep adding backends, like DX 7, 9, Vulkan, WebGL, bare Linux KMS, and then stuff like screen space reflections, shadows, materials, ray tracing where possible, maybe get it running on a console or two too.
sjmulderto
Games@lemmy.world•Relooted - Game made by South Africans has been bombarded by right-wingersEnglish
5·3 months agoI was about to move on until I read someone asking if this was a Bit Trip Runner clone. NOW you have my attention
Netherlands: successive governments have been putting off actually addressing issues causing them to become a pile of confounding crises, such as nitrogen emissions and housing, which complicates migration, etc.
Note that ProtonMail actually supports automatic encryption to email accounts that publish their public keys in a Web Key Directory, which I’ve set up for mine. When you type such an email address in the To field, it’ll turn into a special color with a lock symbol.
Likewise, ProtonMail also exposed a WKD so people can send encrypted emails to ProtonMail accounts. I don’t know of any mail clients that support this though (I used the command line to pull keys)
Kéés (Texels Dutch, my wife’s home dialect)
Flikken Maastricht. Not because it’s so good but we always try to match the drum beats in the intro
sjmulderto
Ask Lemmy@lemmy.world•Have you ever been subjected to a search (both digital and physical spaces) by law enforcement? When, where, and what was searched? Did you consent or no? Was it lawfully conducted?
11·8 months agoA cop once asked me to shake my backpack to make sure there were no graffiti cans in there. Obviously there weren’t.
Now I’m involved a bit in activism get searched on the regular. It’s mostly procedural, I have the privilege of being not really considered a criminal.
iPhone SE2:
- Use until it turns off due to empty battery
- Put on charger, wait for it to boot.
- Unlock at the earliest opportunity.
Problem: after unlocking, the background disappears (goes black).
Only the home screen though, the lock screen wallpaper works. ‘Fix’ is to change the wallpaper.
sjmulderto
RetroGaming@lemmy.world•Are there really only a few New 3DS exclusive games?English
1·9 months agoNo it isn’t, just checked my copy to be sure. I played it on my regular 3DS XL.












How would you then distinguish between the situations in these two examples?