Card game Sets in Processing [closed] - processing

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
i'm trying to make a card game called sets (Here a link to how it works). I need to create 27 cards (array) and then check each time take 12 cards out of it and get the pairs. Does anyone know the best way to search for pairs. Like to check which cards:
They all have the same number or have three different numbers.
They all have the same symbol or have three different symbols.
They all have the same color or have three different colors.
How can i use the wright datatype in the array and later check which is the good one in a function
I tried using a array with strings which contains the color, shape and amount. Like green triangle 3x times is: gt3. But i cant find out how to compare them for the good pairs

The short answer, that you can implement right away is using a 2D-array.
You learned that an array can hold values. An array can also hold other arrays. So you can use an array per card to hold the properties, and store all those arrays in a 'cardset' array. You can now access the individual card properties by using 2 indexes. The code below can help you understand:
String[] card_a = {"G", "T","3"};
String[] card_b = {"R", "S","2"};
String[] card_c = {"G", "S","1"};
String[][] cardset = {card_a, card_b, card_c};
void setup(){
//Print the number on card_a
print(cardset[0][2]);
//Compare the number on card_a with the number on card_b
if(cardset[0][2] == cardset[1][2]){
print("Equal!");
}
else{
print("Unequal!");
}
}
You can also instantiate a 2D-array directly like this:
String[][] cardset = { {"G", "T","3"},
{"R", "S","2"},
{"G", "S","1"}
};
The long answer is that you should learn about the power of objects.
I won't fully explain it, because that would be very lengthy and the internet is full of excellent explanations - better than mine would ever be.
I suggest you read this tutorial on the processing website. I can also advice this video series on the basics of both processing and programming, including objects.
The code below shows you what a basic implementation of an object can look like. This might not make a whole lot of sense to you yet. That's okay. Objects are a fundamental programming principle, but it takes some time - and a good explanation - to get your head around. Therefor I highly suggest you check out the tutorials I posted above. It will probably take some time before you fully master the concept, but when you do, you can harness its power.
class Card {
String shape;
int number;
color col;
Card(String s, int n, color c) {
shape = s;
number = n;
col = c;
}
}
void setup() {
color red = color(255, 0, 0);
color green = color(0, 255, 0);
color blue = color(0, 0, 255);
Card a = new Card("Circle", 1, red);
Card b = new Card("Square", 2, green);
Card c = new Card("Circle", 3, blue);
//Check for equal shapes
if (a.shape == b.shape && b.shape ==c.shape ) {
print("All shapes equal");
}
//Check for unequal shapes
if (a.shape != b.shape && a.shape != c.shape && b.shape !=c.shape ) {
print("All shapes unequal");
}
}

Related

Storing motion vectors from calculated optical flow in a practical way which enables reconstruction of subsequent frames from initial keyframes

I am trying to store the motion detected from optical flow for frames in a video sequence and then use these stored motion vectors in order to predict the already known frames using just the first frame as a reference. I am currently using two processing sketches - the first sketch draws a motion vector for every pixel grid (each of width and height 10 pixels). This is done for every frame in the video sequence. The vector is only drawn in a grid if there is sufficient motion detected. The second sketch aims to reconstruct the video frames crudely from just the initial frame of the video sequence combined with information about the motion vectors got from the first sketch.
My approach so far is as follows: I am able to determine the size, position and direction of each motion vector drawn in the first sketch from four variables. By creating four arrays (two for the motion vector's x and y coordinate and another two for its length in the x and y direction), every time a motion vector is drawn I can append each of the four variables to the arrays mentioned above. This is done for each pixel grid throughout an entire frame where the vector is drawn and for each frame in the sequence - via for loops. Once the arrays are full, I can then save them to a text file as a list of strings. I then load these strings from the text file into the second sketch, along with the first frame of the video sequence. I load the strings into variables within a while loop in the draw function and convert them back into floats. I increment a variable by one each time the draw function is called - this moves on to the next frame (I used a specific number as a separator in my text-files which appears at the end of every frame - the loop searches for this number and then increments the variable by one, thus breaking the while loop and the draw function is called again for the subsequent frame). For each frame, I can draw 10 by 10 pixel boxes and move then by the parameters got from the text files in the first sketch. My problem is simply this: How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
Apologies for the length and complexity of my question. Any tips would be very much appreciated! I will add the code for the second sketch. I can also add the first sketch if required, but it's rather long and a lot of it is not my own. Here is the second sketch:
import processing.video.*;
Movie video;
PImage [] naturalMovie = new PImage [0];
String xlengths [];
String ylengths [];
String xpositions [];
String ypositions [];
int a = 0;
int c = 0;
int d = 0;
int p;
int gs = 10;
void setup(){
size(640, 480, JAVA2D);
xlengths = loadStrings("xlengths.txt");
ylengths = loadStrings("ylengths.txt");
xpositions = loadStrings("xpositions.txt");
ypositions = loadStrings("ypositions.txt");
video = new Movie(this, "sample1.mov");
video.play();
rectMode(CENTER);
}
void movieEvent(Movie m) {
m.read();
PImage f = createImage(m.width, m.height, ARGB);
f.set(0, 0, m);
f.resize(width, height);
naturalMovie = (PImage []) append(naturalMovie, f);
println("naturalMovie length: " + naturalMovie.length);
p = naturalMovie.length - 1;
}
void draw() {
if(naturalMovie.length >= p && p > 0){
if (c == 0){
image(naturalMovie[0], 0, 0);
}
d = c;
while (c == d && c < xlengths.length){
float u, v, x0, y0;
u = float(xlengths[a]);
v = float(ylengths[a]);
x0 = float(xpositions[a]);
y0 = float(ypositions[a]);
if (u != 1.0E-19){
//stroke(255,255,255);
//line(x0,y0,x0+u,y0+v);
PImage box;
box = get(int(x0-gs/2), int(y0 - gs/2), gs, gs);
image(box, x0-gs/2 +u, y0 - gs/2 +v, gs, gs);
if (a < xlengths.length - 1){
a += 1;
}
}
else if (u == 1.0E-19){
if (a < xlengths.length - 1){
c += 1;
a += 1;
}
}
}
}
}
Word to the wise: most people aren't going to read that wall of text. Try to "dumb down" your posts so they get to the details right away, without any extra information. You'll also be better off if you post an MCVE instead of only giving us half your code. Note that this does not mean posting your entire project. Instead, start over with a blank sketch and only create the most basic code required to show the problem. Don't include any of your movie logic, and hardcode as much as possible. We should be able to copy and paste your code onto our own machines to run it and see the problem.
All of that being said, I think I understand what you're asking.
How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
Separate your program into a view and a model. Right now you're using the screen (the view) to store all of your information, which is going to cause you headaches. Instead, store the state of your program into a set of variables (the model). For you, this might just be a bunch of PVector instances.
Let's say I have an ArrayList<PVector> that holds the current position of all of my vectors:
ArrayList<PVector> currentPositions = new ArrayList<PVector>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
currentPositions.add(new PVector(random(width), random(height)));
}
}
void draw(){
background(0);
for(PVector vector : currentPositions){
ellipse(vector.x, vector.y, 10, 10);
}
}
Notice that I'm just hardcoding their positions to be random. This is what your MCVE should do as well. And then in the draw() function, I'm simply drawing each vector. This is like drawing a single frame for you.
Now that we have that, we can create a nextFrame() function that moves the vectors based on the ArrayList (our model) and not what's drawn on the screen!
void nextFrame(){
for(PVector vector : currentPositions){
vector.x += random(-2, 2);
vector.y += random(-2, 2);
}
}
Again, I'm just hardcoding a random movement, but you would be reading these from your file. Then we just call the nextFrame() function as the last line in the draw() function:
If you're still having trouble, I highly recommend posting an MCVE similar to mine and posting a new question. Good luck.

PMR QuadTree data structure and algorithm [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 8 years ago.
Improve this question
I want to implement PMR Quadtree which can process points and random polygons instead of point only as traditional QuadTree in below demo
http://donar.umiacs.umd.edu/quadtree/lines/pmr.html
However, I could not find any pages describe the PMR QuadTree algorithm or any sample code about it. If someone know about the PMR QuadTree material, please share me.
Note: The above Webpage mentions two materials but they are not free to download online.
The PMR Quadtree is typically used to store edges of a polygon but can easily be extended to include points as well. There is a C++ implementation of it at http://czep.net/quicksilver/ (quadtree.cpp & quadtree.hpp). Below is pseudocode explaining the algorithm:
class Box
double CenterX
double CenterY
double Size
// a SpatialItem must implement Intersects against a Box (i.e. a rectangle)
class SpatialItem
abstract bool Intersects(Box box)
class PMRQuadTreeNode
int level // the level of this node
int maxDepth // the maximum number of levels of the quadtree
int splittingThreshold // determines when to split the node
Box bounds
PMRQuadTreeNode[] childNodes
SpatialItemCollection items
// Determines if the Leaf Node is overflowing and should be split
// NOTE: Leaves at the maximum depth never overflow
bool IsOverflowing()
if (level == maxDepth)
return false
return items.Count > splittingThreshold
// Insert adds the SpatialItem to items if it intersets against bounds
// If this Node IsOverflowing, then it is Split and becomes an internal
// Node with 4 Leaf Nodes
void Insert(SpatialItem item)
if (item.Intersects(bounds))
if (IsLeaf)
items.Add(item)
if (IsOverflowing())
Split()
else
foreach (Node child in childNodes)
child.Insert(item)
// When a Node is Split, each SpatialItem is added to each Child Node it
// intersects. Split is *NOT* called again for each child - items are
// merely added directly to each Child's items collection.
void Split()
CreateChildNodes() // create and initialize 4 child nodes
foreach (var item in items)
foreach (var child in childNodes)
// don't call Insert() here, as Split should only be called once
if (item.Intersects(child.bounds))
child.items.Add(item)
items.Clear()
IsLeaf = false
void CreateChildNodes()
static double[] XOffsets = new double[] { -0.25, 0.25, 0.25, -0.25 }
static double[] YOffsets = new double[] { -0.25, -0.25, 0.25, 0.25 }
childNodes = new PMRQuadTreeNode[4]
for (int i = 0..3)
childNodes[i] = new PMRQuadTreeNode {
level = level + 1
maxDepth = maxDepth
splittingThreshold = splittingThreshold
bounds = new Box {
CenterX = bounds.center.X + XOffsets[i] * bounds.size,
CenterY = bounds.center.Y + YOffsets[i] * bounds.size,
Size = bounds.size / 2
}
}

What is the method to detect whether a given picture is human face or not?

Is there any simple algorithm to judge whether a given image is face or something else (without training hopefully)?
My thought is to construct the eigenvectors of each image, then apply some clustering method (for example k-means with k = 2). But I'm not sure what will be the best criteria to distinguish face/non-face even if a good clustering result is obtained?
Eigen decomposition reduces dimensionality in continues domain by finding directions in data space with high variance. K-means finds clusters in space with high density of points. You kind of mixing them together while completely ignoring how would you arrive at the face features on the first place (how would you scale, rotate and crop whatever you want to inspect either).
You don’t need to train Haar detectors since they are already trained for faces. They detect a face, not recognize its identity. ALl you need is to port the code together with a little file with parameters obtained after training (that was already performed) as Shiva suggested above.
Thoughtless copy-pasting of the code doesn’t make much sense though. Read a bit about Haar. Try to understand
Why they work - faces have features most pronounced on the intermediate spatial scale such as eyes, nose, brows. Too small (size of the pupil) or too large (size of the whole face) features are less useful.
why Haars are preferred to wavelets or Gabors - Haars are just raw (boxy) approximations of Gabors but since they can be quickly calculated with Integral images they are preferred to more precise but slower counterparts;
what are the restrictions - Haars have their own spatial scale and orientation but can be quickly recalculated for another scale.
How to train Haar classifier (the most exciting topic you are trying to avoid). Ada boost is the one way to train a more complex classifier consisting of several Haars. Finally to speed up processing you can ask a slightly different question instead of find me a face. Namely, you can try to quickly eliminate the areas in the image that cannot be a face. This is called a cascade classification. Study these aspects in a systematic way and you will learn more about face detection than you’d do from the code pasting.
You can use Haar classifier method for face detection in an image/video frame.
A sample code for finding faces in an images will be like this
int main(int argc, _TCHAR* argv[])
{
IplImage* img;
img = cvLoadImage( "dasl_hubo.jpg" );
CvMemStorage* storage = cvCreateMemStorage(0);
// Note that you must copy C:\Program Files\OpenCV\data\haarcascades\haarcascade_frontalface_alt2.xml or where opencv is installed
// to your working directory
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt2.xml" );
double scale = 1.3;
static CvScalar colors[] = { {{0,0,255}}, {{0,128,255}}, {{0,255,255}},
{{0,255,0}}, {{255,128,0}}, {{255,255,0}}, {{255,0,0}}, {{255,0,255}} };// this will draw rectangles of these colors around the detected faces.
// Detect objects
cvClearMemStorage( storage );
CvSeq* objects = cvHaarDetectObjects( img, cascade, storage, 1.1, 4, 0, cvSize( 40, 50 ));
CvRect* r;
// Loop through objects and draw boxes
for( int i = 0; i < (objects ? objects->total : 0 ); i++ ){
r = ( CvRect* )cvGetSeqElem( objects, i );
cvRectangle( img, cvPoint( r->x, r->y ), cvPoint( r->x + r->width, r->y + r->height ),
colors[i%8]);
}
cvNamedWindow( "Output" );
cvShowImage( "Output", img );
cvWaitKey();
cvReleaseImage( &img );
return 0;
}
visit these links to find more about face detection using harr cascades
drexel.edu
opencv documentation
presentation on Harr training and usages
Here is my opencv code in C++, it is simple to detect faces in an image with the help of Opencv haar-like feature, you may refer to the documents for the usage of some methods in it. I hope it helps.
CascadeClassifier face_cascade; //for read in haar-like faces database in opencv
std::vector<Rect> faces; //for storing detected faces
vector<Point2d> FaceCenter; //for storing centres of faces
Mat frame_gray = imread(“/Users/xxx/Desktop/xxx.jpg”, CV_8UC1); //read the image in gray-scale;
equalizeHist( frame_gray, frame_gray ); //histogram to extract the contrast
String face_cascade_name = "/Users/xxx/opencv-2.4.7/data/haarcascades/haarcascade_frontalface_alt.xml"; //path of the trained faces .xml file
if(!face_cascade.load(face_cascade_name)) //load the .xml
{
cout << "face_casacade.xml load error" << endl;
}
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0, Size(50, 50) ); //Detect faces in the image
for(size_t i = 0; i < faces.size(); i++)
{
Point2d center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5); //store centres of faces
FaceCenter.push_back(center);
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 ); //circle the faces in the image, optional
ellipse( frame_gray, center, Size( eyes[j].width*0.5, eyes[j].height*0.25), 0, 0, 360, Scalar( 255, 0, 0 ), 2, 8, 0 );
}
imshow(“Faces Detection”, frame_gray); //show the result

3D Rotation Matrix deforms over time in Processing/Java

Im working on a project where i want to generate a 3D mesh to represent a certain amount of data.
To create this mesh i want to use transformation Matrixes, so i created a class based upon the mathematical algorithms found on a couple of websites.
Everything seems to work, scale/translation but as soon as im rotating a mesh on its x-axis its starts to deform after 2 to 3 complete rotations. It feels like my scale values are increasing which transforms my mesh. I'm struggling with this problem for a couple of days but i can't figure out what's going wrong.
To make things more clear you can download my complete setup here.
I defined the coordinates of a box and put them through the transformation matrix before writing them to the screen
This is the formula for rotating my object
void appendRotation(float inXAngle, float inYAngle, float inZAngle, PVector inPivot ) {
boolean setPivot = false;
if (inPivot.x != 0 || inPivot.y != 0 || inPivot.z != 0) {
setPivot = true;
}
// If a setPivot = true, translate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,inPivot.z); }
}
// Create a rotationmatrix
Matrix3D rotationMatrix = new Matrix3D();
// xsin en xcos
float xSinCal = sin(radians(inXAngle));
float xCosCal = cos(radians(inXAngle));
// ysin en ycos
float ySinCal = sin(radians(inYAngle));
float yCosCal = cos(radians(inYAngle));
// zsin en zcos
float zSinCal = sin(radians(inZAngle));
float zCosCal = cos(radians(inZAngle));
// Rotate around x
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[1][1] = xCosCal;
rotationMatrix.matrix[1][2] = xSinCal;
rotationMatrix.matrix[2][1] = -xSinCal;
rotationMatrix.matrix[2][2] = xCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around y
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = yCosCal;
rotationMatrix.matrix[0][2] = -ySinCal;
rotationMatrix.matrix[2][0] = ySinCal;
rotationMatrix.matrix[2][2] = yCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around z
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = zCosCal;
rotationMatrix.matrix[0][1] = zSinCal;
rotationMatrix.matrix[1][0] = -zSinCal;
rotationMatrix.matrix[1][1] = zCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Untranslate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(-inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,-inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,-inPivot.z); }
}
}
Does anyone have a clue?
You never want to cumulatively transform matrices. This will introduce error into your matrices and cause problems such as scaling or skewing the orthographic components.
The correct method would be to keep track of the cumulative pitch, yaw, roll angles. Then reconstruct the transformation matrix from those angles every update.
If there is any chance: avoid multiplying rotation matrices. Keep track of the cumulative rotation and compute a new rotation matrix at each step.
If it is impossible to avoid multiplying the rotation matrices then renormalize them (starts on page 16). It works for me just fine for more than 10 thousand multiplications.
However, I suspect that it will not help you, numerical errors usually requires more than 2 steps to manifest themselves. It seems to me the reason for your problem is somewhere else.
Yaw, pitch and roll are not good for arbitrary rotations. Euler angles suffer from singularities and instability. Look at 38:25 (presentation of David Sachs)
http://www.youtube.com/watch?v=C7JQ7Rpwn2k
Good luck!
As #don mentions, try to avoid cumulative transformations, as you can run into all sort of problems. Rotating by one axis at a time might lead you to Gimbal Lock issues. Try to do all rotations in one go.
Also, bare in mind that Processing comes with it's own Matrix3D class called PMatrix3D which has a rotate() method which takes an angle(in radians) and x,y,z values for the rotation axis.
Here is an example function that would rotate a bunch of PVectors:
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
int vl = verts.length;
PVector[] clone = new PVector[vl];
for(int i = 0; i<vl;i++) clone[i] = verts[i].get();
//rotate using a matrix
PMatrix3D rMat = new PMatrix3D();
rMat.rotate(angle,axis.x,axis.y,axis.z);
PVector[] dst = new PVector[vl];
for(int i = 0; i<vl;i++) {
dst[i] = new PVector();
rMat.mult(clone[i],dst[i]);
}
return dst;
}
and here is an example using it.
HTH
A shot in the dark: I don't know the rules or the name of the programming language you are using, but this procedure looks suspicious:
void setIdentity() {
this.matrix = identityMatrix;
}
Are you sure your are taking a copy of identityMatrix? If it is just a reference you are copying, then identityMatrix will be modified by later operations, and soon nothing makes sense.
Though the matrix renormalization suggested probably works fine in practice, it is a bit ad-hoc from a mathematical point of view. A better way of doing it is to represent the cumulative rotations using quaternions, which are only converted to a rotation matrix upon application. The quaternions will also drift slowly from orthogonality (though slower), but the important thing is that they have a well-defined renormalization.
Good starting information for implementing this can be:
http://www.cprogramming.com/tutorial/3d/quaternions.html
http://www.scheib.net/school/library/quaternions.pdf
A useful academic reference can be:
K. Shoemake, “Animating rotation with quaternion curves,” ACM
SIGGRAPH Comput. Graph., vol. 19, no. 3, pp. 245–254, 1985. DOI:10.1145/325165.325242

What are the indicator functions and constraints for complex grid drawing problems?

If you're looking at an array of pixels, in either 0,1,2,3, or even N dimensions, it's easy to tell if a certain pixel falls on a square or rectangular grid line within it by using an indicator function like so (I'll use imperative pseudocode to make what I'm talking about clear but I'm really only interested in the constraints and the conditionals in the indicator functions for the more general types of grids):
/* define the array of pixels in however many dimensions you want */
//define the dimensions of the array
int x-dimension-length = <some positive integer>;
int y-dimension-length = <some positive integer>;
int z-dimension-length = <some positive integer>;
[...] //you could keep gong for even higher dimensions
/* define CONSTRAINTS (for the square or rectangular case) */
//define the height and width of the grid boxes within the grid (contstraints on a square/rectangular grid)
int horizontalSpacingBetweenGridlines = <non-negative integer>;
int verticalSpacingBetweenGridlines = <non-negative integer>;
/* end definition of CONSTRAINTS */
/* define the arrays to draw the grids on */
// -- assumes that the arrays here are intialised to contain all zeros:
//0-dimensional (degenerate) example:
int point = 0;
//1d example:
int [] OneDimensionalArray = int[x-dimension-length];
//(2d example)
int [] TwoDimensionalArray = int[x-dimension-length][y-dimension-length];
//(3d example)
int [] ThreeDimensionalArray = int[x-dimension-length][y-dimension-length][z-dimension-length];
/* Indicator functions */
/* zero-dimensional (degenerate) case */
//if a point falls on a gridline, degenerate example
boolean doesAPointFallOnAGridLine0D() {
if (point % horizontalSpacingBetweenGridlines == 0) {
return true;
}
/* one-dimensional case */
//decide if a point in the 1D array at index <x-coordinateFrom1DArray> falls on a gridline
boolean doesAPointFallOnAGridLine1D(int x-coordinateFrom1DArray) {
if (x-coordinate % horizontalSpacingBetweenGridlines == 0) {
return true;
}
}
/* two-dimensional case */
//decide if a point in the 2D array at index <x-coordinateFrom2DArray>,<y-coordinateFrom2DArray> falls on a gridline
boolean doesAPointFallOnAGridLine2D(int x-coordinateFrom2DArray, int y-coordinateFrom2DArray) {
if((x-coordinateFrom2DArray % horizontalSpacingBetweenGridlines == 0) && (y-coordinateFrom2DArray % verticalSpacingBetweenGridlines == 0)) {
return true;
}
}
/* [and so on for higher-and-higher-dimensional spaces...] */
My question is, in general what do the indicator function and constraints look like for the different types of non-square and non-rectangular-grids (e.g., triangular, hexagonal, octagonal, whatever), and is there a canonical reference work that talks about constructing that sort of indicator function and the constraints it requires for the different shapes of grid?
Knuth seems out on this one.
This is a very general mathematical problem so it probably has a name/canonical solution.
As an aside, I'm most interested in hexagonal grids in n-dimensions, but I don't want to write a kludgy one-off implementation that only works for those using linear algebra instead of a proper boolean indicator function, and would rather like to know how to solve these problems in general the right way.

Resources