Related
I am trying to implement boost trees in a c++ code. Currently I'm doing the following: given a vector of bounding boxes v_bboxes, I build a tree out of it.
LinearPointRtree built_tree(v_bboxes.begin(), v_bboxes.end());
Then, given a point, I'd like to know in which of the bounding boxes from v_bboxes the point lies (it might be one or more). Currently I'm making the following query:
built_tree.query(bgi::intersects(point), std::back_inserter(result));
The result is a vector containing the bounding boxes which contain the point, while I'm interested in indexes referring to the original vector v_bboxes.
I could compare "result" with the original vector and find which bounding boxes were returned, but this would be inefficient and I believe there is a better way of doing this directly with boost, I just cannot find anything in the documentation.
Currently what I am also trying to do is to build a tree starting from a vector of tuples (bounding boxes, index), but it is throwing a very long and bad looking compilation error:
error: no matching function for call to
‘boost::geometry::index::detail::varray >,
17>::push_back(std::tuple >, unsigned int>&)’
Does someone know what I should change or has suggestions?
Unless a better idea is presented, the thing I was trying is correct (the problem was I didn't define the tree properly). So, define the tree
template<int spacedim, int leaf_number>
using LinearPointRtree = bgi::rtree<std::tuple<bgBox<spacedim>,unsigned int>, bgi::linear<leaf_number>>;
Now create the object:
std::vector< std::tuple<bgBox<spacedim>, unsigned int> > boxes_and_indices;
Where for each entry there's a bounding box and the desired index. Finally simply build the tree (as boost handles automatically pairs and tuples):
LinearPointRtree<spacedim,leaf_number> rstar_tree(flat_global_bboxes.begin(), flat_global_bboxes.end());
Then, when querying, you can use the second entry to get the index.
The idea came to me just after posting the question here...anyway, maybe it will help someone else...
Thanks everyone!
I'm using the getclosest command to find a vertex.
ForceVertex1 = hatInstance.vertices.getClosest(coordinates=((x,y,z,))
This is a dictionary object with Key 0 and two values (hatInstance.vertices[1] and the coordinates of the vertex) The specific output:
{0: (mdb.models['EXP-100'].rootAssembly.instances['hatInstance-100'].vertices[1], (62.5242172081597, 101.192447407436, 325.0))}
Whenever I try to create a set, the vertex isn't accepted
mainAssembly.Set(vertices=ForceVertex1[0][0],name='LoadSet1')
I also tried a different way:
tolerance = 1.0e-3
vertex = []
for vertex in hatInstance.vertices:
x = vertex.pointOn[0][0]
print x
y = vertex.pointOn[0][1]
print y
z = vertex.pointOn[0][2]
print z
break
if (abs(x-xTarget)) < tolerance and abs(y-yTarget) < tolerance and abs(z-zTarget) < tolerance):
vertex.append(hatInstance.vertices[vertex.index:vertex.index+1])
xTarget etc being my coordinates, despite this I still don't get a vertex object
For those struggeling with this, I solved it.
Don't use the getClosest command as it returns a dictionary object despite the manual recommending this. I couldn't convert this dictionary object, specifically a key and a value within to a standalone object (vertex)
Instead use Instance.vertices.getByBoundingSphere(center=,radius=)
The center is basically a tuple of the coordinates and the radius is the tolerance. This returns an array of vertices
If you want the geometrical object you just have to access the dictionary.
One way to do it is:
ForceVertex1 = hatInstance.vertices.getClosest(coordinates=((x,y,z,))[0][0]
This will return the vertices object only, which you can assign to a set or whatever.
Edit: Found a solution to actually address the original question:
part=mdb.models[modelName].parts[partName]
v=part.vertices.getClosest(coordinates=(((x,y,z)),))
Note the formatting requirement for coordinates ((( )),), three sets of parenthesis with a comma. This will find the vertex closest to the specified point. In order to use this to create a set, I found you need to massage the Abaqus Python interface to return the vertex in a format that uses their "getSequenceFromMask" method. In order to create a set, the edges, faces, and/or vertices need to be of type "Sequence", which is internal to Abaqus. To do this, I then use the following code:
v2=part.verticies.findAt((((v[0][1])),))
part.Set(name='setName', vertices=v2)
Note, v[0][1] will give you the point at which the vertex lies on. Note again the format of the specified point using the findAt method (((point)),) with three sets of parenthesis and a comma. This will return a vertex that uses the getSequenceFromMask method in Abaqus (you can check by typing v2 then enter in the python box at the bottom of CAE, works with Abaqus 2020). This is type "Sequence" (you can check by typing type(V2)) and this can be used to create a set. If you do not format the point in findAt correctly (e.g., findAt(v[0][1]), without the parenthesis and comma), it will return an identical vertex as you get by accessing the dictionary returned using getClosest (e.g., v[0][0]). This is type 'Vertex' and cannot be used to create a set, even though it asks for a vertex. If you know the exact point where the vertex is, then you do not need the first step. You can simply use the findAt method with the correct formatting. However, the tolerance for findAt is very small (1e-6) and will return an empty sequence if nothing is found within the tolerance. If you only have a ballpark idea of where the vertex is located, then you need to use the getClosest method first. This indeed gets the closest vertex to the specified point, which may or may not be the one you are interested in.
Original post:
None of these answers work for a similar problem I am having while trying to create a set of faces within some range near a point. If I use getClosest as follows
f=mdb.models['Model-1'].parts['Part-1'].faces.getClosest(coordinates=((0,0,0),), searchTolerance=1)
mdb.models['Model-1'].parts['Part-1'].Set(faces=f, name='faceSet')
I get an error "TypeError: Keyword error on faces".
If I access the dictionary via face=f[0], I get error "Feature Creation Failed". If I access the tuple within the dictionary via f[0][0], I get the error "TypeError: keyword error on faces" again.
The option to use .getByBoundingSphere doesn't work either, because the faces in my model are massive, and the faces have to be completely contained within the sphere for Abaqus to "get" them, basically requiring me to create a sphere that encompasses the entire model.
My solution was to create my own script as follows:
import numpy as np
model=mdb.models['Model-1']
part=model.parts['Part-1']
faceSave=[]
faceSave2=[]
x=np.arange(-1,1,0.1)
y=np.arange(-1,1,0.1)
z=np.arange(-1,1,0.1)
for x1 in x:
for y1 in y:
for z1 in z:
f=part.faces.findAt(((x1,y1,z1),))
if len(f)>0:
if f[0] in faceSave2:
None
else:
faceSave.append(f)
faceSave2.append(f[0])
part.Set(faces=faceSave,name='faceSet')
This works, but it's extraordinarily slow, in part because "findAt" will throw a warning to the console whenever it doesn't find a face, and it usually doesn't find a face with this approach. The code above basically looks within a small cube for any faces, and puts them in the list "faceSave". faceSave2 is setup to ensure that duplicate faces aren't added to the list. Accessing the tuple (e.g, f[0] in the code above) contains the unique information about the face, whereas 'f' is just a pointer to the 'findAt' command. Strangely, you can use the pointer 'f' to create a Set, but you cannot use the actual face object 'f[0]' to create a set. The problem with this approach for general use is, the tolerance for "findAt" is super small, so, you either have to be confident where things are located in your model, or have the step size be 1e-6 in np.arange() to ensure you don't miss a face that's in the cube. With a tiny step size, expect the code to take forever.
At any rate, I can use a tuple (or a list of tuples) obtained via "findAt" to create a Set in Abaqus. However, I cannot use the tuple obtained via "getClosest" to make a set, even though I see no difference between the two objects. It's unfortunate, because getClosest gives me the exact info I need effectively immediately without my jumbled mess of for-loops.
#anarchoNobody:
Thank you so much for your edited answer!
This workaround works great, also with faces. I spent a lot of hours trying to figure out why .getClosest does not provide a working result for creating a set, but with the workaround and the number of brackets it works.
If applied with several faces, the code has to be slightly modified:
faces=((mdb.models['Model-1'].rootAssembly.instances['TT-1'].faces.getClosest(
coordinates=(((10.0, 10.0, 10.0)),), searchTolerance=2)),
(mdb.models['Model-1'].rootAssembly.instances['TT-1'].faces.getClosest(
coordinates=((-10.0, 10.0, 10.0),), searchTolerance=2)),)
faces1=(mdb.models['Model-1'].rootAssembly.instances['Tube-1'].faces.findAt((((
faces[0][0][1])),)),
mdb.models['Model-1'].rootAssembly.instances['Tube-1'].faces.findAt((((
faces[1][0][1])),)),)
mdb.models['Model-1'].rootAssembly.Surface(name='TT-inner-surf', side1Faces=faces1)
```
I am writing a game in Prolog. The game has a "board" of the form shown below and it has two lists of "pawns". The size of the board is fixed to 16 positions. I want to make the board "dynamic" so when the game starts the user will define the size.
I have thought of a way but the problem is that my way is more on a procedural way which for Prolog is not that correct.
I thought of creating a predicate size/1 which will be initialized by the user in the beginning and then all the lists will be initialized according to that predicate using repeats and cuts and assert...
Could someone propose any better implementation?
/*--------------------------------------------------------------------------
Initial armies (lists of 1 to 8)
--------------------------------------------------------------------------*/
black_army([1,2,3,4,5,6,7,8]).
white_army([1,2,3,4,5,6,7,8]).
/*--------------------------------------------------------------------------
Initial Board (all positions empty)
--------------------------------------------------------------------------*/
board([
(1,-,-),(2,-,-),(3,-,-),(4,-,-),
(5,-,-),(6,-,-),(7,-,-),(8,-,-),
(9,-,-),(10,-,-),(11,-,-),
(13,-,-),(14,-,-),(15,-,-),(16,-,-),(12,-,-)
]).
I think I would keep board size implicit in data declaration, just make it dynamic, and initialize when user request to change: so, keep your code as is, just add in front (note: untested code)
:- dynamic(black_army/1).
:- dynamic(white_army/1).
:- dynamic(board/1).
initialize_data(Size) :-
Size > 1, % this should be a sensible value, of course
retract(black_army(_)),
retract(white_army(_)),
retract(board(_)),
numlist(1,Size,B),
assertz(black_army(B)),
numlist(1,Size,W),
assertz(white_army(W)),
D is Size*2, findall((I,-,-), between(1,D,I), Board),
assertz(board(Board)).
Let me start off with saying that I have very basic knowledge of nodes and graphs.
My goal is to make a solver for a maze which is stored as an array. I know exactly how to implement the algorithm for solving (I'm actually implementing a couple of them) but what my problem is, is that I am very confused on how to implement the nodes that the solver will use in each empty cell.
Here is an example array:
char maze[5][9] =
"#########",
"# # #",
"# ## ## #",
"# # #",
"#########"
My solver starts at the top left and the solution (exit) is at the bottom right.
I've read up on how nodes work and how graphs are implemented, so here is how I think I need to make this:
Starting point will become a node
Each node will have as property the column and the row number
Each node will also have as property the visited state
Visited state can be visited, visited and leads to dead end, not visited
Every time a node gets visited, every directly adjacent, empty and not visited cell becomes the visited node's child
Every visited node gets put on top of the solutionPath stack (and marked on the map as '*')
Every node that led to a dead end is removed from the stack (and marked on the map as '~')
Example of finished maze:
"#########",
"#*~#****#",
"#*##*##*#",
"#****~#*#",
"#########"
Basically my question is, am I doing something really stupid here with my way of thinking (since I am really inexperienced with nodes) and if it is could you please explain to me why? Also if possible provide me other websites to check which implement examples of graphs on real world applications so I can get a better grasp of it.
The answer really depends on what you find most important in the problem. If you're searching for efficiency and speed - you're adding way too many nodes. There's no need for so many.
The efficient method
Your solver only needs nodes at the start and end of the path, and at every possible corner on the map. Like this:
"#########",
"#oo#o o#",
"# ## ## #",
"#o oo#o#",
"#########"
There's no real need to test the other places on the map - you'll either HAVE TO walk thru them, or won't have need to even bother testing.
If it helps you - I got a template digraph class that I designed for simple graph representation. It's not very well written, but it's perfect for showing the possible solution.
#include <set>
#include <map>
template <class _nodeType, class _edgeType>
class digraph
{
public:
set<_nodeType> _nodes;
map<pair<unsigned int,unsigned int>,_edgeType> _edges;
};
I use this class to find a path in a tower defence game using the Dijkstra's algorithm. The representation should be sufficient for any other algorithm tho.
Nodes can be of any given type - you'll probably end up using pair<unsigned int, unsigned int>. The _edges connect two _nodes by their position in the set.
The easy to code method
On the other hand - if you're looking for an easy to implement method - you just need to treat every free space in the array as a possible node. And if that's what you're looking for - there's no need for designing a graph, because the array represents the problem in a perfect way.
You don't need dedicated classes to solve it this way.
bool myMap[9][5]; //the array containing the map info. 0 = impassable, 1 = passable
vector<pair<int,int>> route; //the way you need to go
pair<int,int> start = pair<int,int>(1,1); //The route starts at (1,1)
pair<int,int> end = pair<int,int>(7,3); //The road ends at (7,3)
route = findWay(myMap,start,end); //Finding the way with the algorithm you code
Where findWay has a prototype of vector<pair<int,int>> findWay(int[][] map, pair<int,int> begin, pair<int,int> end), and implements the algorithm you desire. Inside the function you'll probably need another two dimensional array of type bool, that indicates which places were tested.
When the algorithm finds a route, you usually have to read it in reverse, but I guess it depends on the algorithm.
In your particular example, myMap would contain:
bool myMap[9][5] = {0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,1,1,0,
0,1,0,0,1,0,0,1,0,
0,1,1,1,1,1,0,1,0,
0,0,0,0,0,0,0,0,0};
And findWay would return a vector containing (1,1),(1,2),(1,3),(2,3),(3,3),(4,3),(4,2),(4,1),(5,1),(6,1),(7,1),(7,2),(7,3)
I am in trouble choosing the most pertinent structure for my data, here are the explanations:
I am actually working on a game project for school, a Bomberman like game in c++.
I am designing the Map object, who contain Bombs, Boxes, Players and Walls.
The map is 2D, I have already 2 containers of type:
std::unordered_map<int, std::unordered_map<int, AEntity*> > *UMap;
One contain Walls, the other contain destructible objects (Bombs, Boxes).
I have already discussed this choice here -> Choice of unsorted_map.
It's mainly for fast access time and because there can only be one element per map's box.
Now as the title suggest I'am in trouble choosing a data container for my players, because there can be multiple players on a single map's box, unordered_maps can't be used.
In a first time I was going to use a std::list<AEntity*> sorted with std::sorted, AEntity containing the entity information (coords), but while coding my
playerOn(const int x, const int y);
function I found it was a poor choice. I can't retrieve fast enough which player(s) is on the given box using dichotomies, and if there is no player of this box it's a waste of time.
How should I store my (AEntity)Players in order to be able to retrieve them fast
(On of the itchy thing is that there can be more than 500 player at the single time, on big map, that's why I am looking for optimization)
I am running out of brain juice. Thanks for your future answers.
Edit about my probleme
It's mainly because I want to know if there is another solution to go trough my whole std::list of player to find if there is someone on box(x, y). Looks slow and not optimized, but i can't figure another way to do this.
(I can change container type if needed)
First of all, before trying any optimization, you should profile your code to detect where is the bottleneck. You will be surprised. Once that said :
1) Your unordered_maps seem like a lot of over-engineering. The answers provided in your previous post are true but I think it is useless in your case. You absolutely do not care of a O(log(n)) cost when n = 500. Just make a vector of Entities*. It is much enough.
2) You seem to be falling in the god object anti-design pattern. A bomberman game is an excellent project for studying OOP, as it teaches you to avoid the God Object design pattern. Make sure each class does its own business and no class handles all the logic (I suspect your class Map or Game has too much power).
a) Create a vector of players, a vector of bombs, a vector of walls, a vector of fires, etc.
b) Map should be a 2-dimensionnal array storing list of pointers to the entities that are present on each Map's box. (Each Map[i][j] holds pointers to all the elements that are on the box of index (i,j)).
c) Bombs should create fire elements.
d) Your central routine should be something like :
while(gameContinued)
{
for each entity in the game
{
entity.Update(map);
}
game.Render();
}
Bomb update consists in making the bomb's texture rendering dynamic and create fires if delay is over-due (and update the Map with the fires pointers accordingly).
Fire update consists in nothing except vanishing if delay is over-due (and update the Map).
Player update consists in moving through keyboard event handling (and updating their current internal x and y values ), creating bomb if needed, dying if for their position (x,y), there is a fire in the Map[i][j] list of entities.
3) In most of my students implementation of bomberman, the only issue they can get is with textures and deep copy of objects. Make sure you have a Texture Loader (using Singleton Pattern) to avoid loading multiple times the same textures, and you should be fine.