I'm trying to extract the boundary facets of a periodic c3t3, i.e. all boundary facets including those at the periodic boundaries. My current approach is to try to iterate trough all the tetrahedra and test one by one its facets with "is_infinite" (see the code snipped bellow), but "is_infinite" is always returning false.
for(Cell_iterator cit = c3t3P.cells_begin(); cit !=c3t3P.cells_end(); ++cit) {
for(int l=0; l<4; ++l) {
const int id = V[cit->vertex(l)];
CGAL_assertion(1 <= id && id <= medit_number_of_vertices);
t[l] = id - 1;
if( tr.is_infinite(cit, l) )
std::cout << "is true!" << std::endl ;//Facet_boundary.push_back(points[t[l]]);
}
}
Here is a way you could go at your problem given the clarification in the comments above:
Start from a point on your surface
Use the locate() function of the periodic triangulation . This gives you a cell and an offset such that the point is in the tetrahedron of this cell translated by the offset parameter.
You can qualify whether a vertex of the periodic triangulation is contained in the interior, on the boundary, or in the exterior of the 3D closed shape using the class Side_of_triangle_mesh.
Walk from cell to cell (using cell->neighbor(0...3)). Note that as you walk, you will eventually reach the border of the internal representation and will need to shift offset when going to its neighboring cell: that's the purpose of the neighbor_offset() function that I mentioned in the comments.
For a given visited cell, qualify the position of its vertices as in (Side_of_triangle_mesh returns on boundary or on bounded side) or out (Side_of_triangle_mesh returns on unbounded side) of the shape. The position canonical position is given by Periodic_triangulation::point(Cell_handle, index) and you can shift it using Periodic_triangulation::construct_point(Point, Offset).
Do not explore the neighbors of a cell whose vertices are all out.
Cells whose vertices are all in are directly in your output.
For cells that have some vertices in and some vertices out, you could create a surface mesh from the tetrahedron (for example with make_tetrahedron) and compute the intersection with the shape using the corefine_and_compute_intersection.
In the glyf table, if a glyph is a composite glyph, I don't understand what it means if the flag ARGS_ARE_XY_VALUES is not set. The msdn docs say
the first point number indicates the point that is to be matched to the new glyph. The second number indicates the new glyph’s “matched” point. Once a glyph is added, its point numbers begin directly after the last glyphs (endpoint of first glyph + 1).
But I have NO idea what it means:
What is a "point number"? Is it an index into the glyph's points?
What does "matched to the new glyph" mean?
What is a "point number"? Is it an index into the glyph's points?
Yes. It’s an index into the array of pairs of coordinates that make up the glyph’s outline (as defined in the glyph’s contour data).
What does "matched to the new glyph" mean?
It means that the new component glyph of that composite/compound glyph is to be positioned so that the coordinates of its ‘match point’ are equal to those of the ‘match point’ of the base component glyph. In other words: so that the indicated points for the two components match. This is repeated for each new component glyph, with the point numbers/indices of the already matched components being treated as if it were a single, base component glyph.
Apple's TrueType spec is a bit clearer about the meaning of this flag. It says that if the ARGS_ARE_XY_VALUES flag is not set that:
1st short contains the index of matching point in compound being constructed
2nd short contains index of matching point in component
Source: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html
In other words, let m be the first short and n be the second, then the coordinates of point n of the new component should have the same coordinates as point m of the so far constructed compound glyph.
I'm trying to build a MKPolygon using the outer boundary of a set of coordinates.
From what I can tell, there is no delivered functionality to achieve this in Xcode (the MKPolygon methods would use all points to build the polygon, including interior points).
After some research I've found that a convex-hull solves this problem.
After looking into various algorithms, the one I can best wrap my head around to implement is QuickHull.
This takes the outer lat coords and draws a line between the two. From there, you split your points based on that line into two subsets and process distance between the outer lats to start building triangles and eliminating points within until you are left with the outer boundary.
I can find the outer points just by looking at min/max lat and can draw a line between the two (MKPolyline) - but how would I determine whether a point falls on one side or the other of this MKPolyline?
A follow up question is whether there is a hit test to determine whether points fall within an MKPolygon.
Thanks!
I ended up using a variation of the gift wrap algorithm. Certainly not a trivial task.
Having trouble with formatting of the full code so I'll have to just put my steps (probably better because I have some clean up to do!)
I started with an array of MKPointAnnotations
1) I got the lowest point that is furthest left. To do this, I looped through all of the points and compared lat/lng to get lowest point. This point will definitely be in the convex hull, so add it to a NSMutableArray that will store our convex hull points (cvp)
2) Get all points to the left of the lowest point and loop through them, calculating the angle of the cvp to the remaining points on the left. Whichever has the greatest angle, will be the point you need to add to the array.
atan(cos(lat1)sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2))
For each point found, create a triangle (by using lat from new point and long from previous point) and create a polygon. I used this code to do a hit test on my polygon:
BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);
If anything was found in the hit test, remove it from the comparison array (all those on the left of the original array minus the hull points)
Once you have at least 3 points in your cvp array, build another polygon with all of the cvp's in the array and remove anything within using the hit test.
3) Once you've worked through all of the left points, create a new comparison array of the remaining points that haven't been eliminated or added to the hull
4) Use the same calculations and polygon tests to remove points and add the cvp's found
At the end, you're left with a list of points in that make up your convex hull.
I'm starting on a native iPad app (we can assume iOS 4.3+ if necessary) where I need to have a series of curved regions that bump up against each other.
I'd love some advice about the best way to handle this.
One thought I had was to use a WebView and just have a JPG and an HTML image map but I'd really prefer to use some kind of native UI element that supports curves.
Any recommendations?
We had a problem something like this. To resolve it, we created a black and white mask in Adobe Illustrator. You'll need to do this for each and every distinct region that you want.
Next, we exported this file. I can't remember the file export option, but basically you get a text file that has a load of path data that includes lines, bezier curves, etc.
We then took this file and wrote an importer that parsed it and created a CGPath.
The final stage is the easy bit. You get your touch point from UITouch and do a CGPathContainsPoint call.
Here's some pseudo code for this:
Skip lines until we get to one with "1 XR". That's the
indication of something meaningful in the subsequent line.
Split the line into an array of components using a separator of " ".
The last component of the line is the action. If it's "m" it's a path move, if it's "C", it's a bezier curve, and if it's "L" it's a line.
If it's a "Y" or a "V" then you need to get the previous line's components and parse as follows:
(a) Component count includes action, so we need to reduce this. E.g. 274.5600 463.6800 m
(b) If this line has four coordinates and the previous one has two, then it's a point node to a bezier node. Figure your bezier curve points as follows:
cp1x = previous line's components object at index 0
cp1y = previous line's components object at index 1
cp2x = this line's components object at index 0
cp2y = this line's components object at index 1
x = this line's components object at index 2
y = this line's components object at index 3
(c) Otherwise if this line has four coordinates and the previous line has four or six coordinates, figure as follows:
cp1x = this line's components object at index 0
cp1y = this line's components object at index 1
cp2x = this line's components object at index 2
cp2y = this line's components object at index 3
x = this line's components object at index 2
y = this line's components object at index 3
Where cp is "control point". So you have control point one and control point two with their respective x and y coordinates.
Create bezier paths that each represent separate regions (by doing lineToPoint or similar functions).
UIBezierPath *p1 = [UIBezierPath bezierPath];
[path1 lineToPoint:somePoint];
[pointArray1 addObject:NSStringFromCGPoint(somePoint)];
// create lots of points and close p1 path
Then find some triangulation algorithm for concave shapes that would turn each bezier path to an array of triangles (i.e. instead of storing array of bezier path point coordinates you'd store array of triangles' coordinates (array of array of points). Algorithm and explanations can be found in any game development forum or even on GameDev of stack exchange.
Repeat the bezier path creation and triangulation for each region.
Then having these arrays it's just a matter of simple iterations to check if certain point of interest is in one of these triangles.
update seems that #omz comment renders my answer useless, hence it's just a matter of creating bezier paths and calling method on each of them .)
How could I, having a path defined by several points that are not in a uniform distance from each other, redefine along the same path the same number of points but with a uniform distance. I'm trying to do this in Objective-C with NSArrays of CGPoints but so far I haven't had any luck with this.
Thank you for any help.
EDIT
I was wondering if it would help to reduce the number of points, like when detecting if 3 points are collinear we could remove the middle one, but I'm not sure that would help.
EDIT
Illustrating:
Reds are the original points, blues the post processed points:
The new path defined by the blue dots does not correspond to the original one.
I don't think you can do what you state that you want to do. But that could be a misunderstanding on my part. For example, I have understood from your comment that the path is straight between successive points, not curved.
Take, for example, a simple path of 3 points (0,1,2) and 2 line segments (0-1,1-2) of different lengths. Leave points 0 and 2 where they are and introduce a new point 1' which is equidistant from points 0 and 2. If point 1' is on one of the line segments 0-1, 1-2, then one of the line segments 0-1', 1'-2 is not coincident with 0-1, 1-2. (Easier to draw this, which I suggest you do.) If point 1' is not on either of the original line segments then the entire path is new, apart from its endpoints.
So, what relationship between the new path and the old path do you want ?
EDIT: more of an extended comment really, like my 'answer' but the comment box is too small.
I'm still not clear how you want to define the new path and what relationship it has to the old path. First you wanted to keep the same number of points, but in your edit you say that this is not necessary. You agree that replacing points by new points will shift the path. Do you want, perhaps, a new path from point 0 to point N-1, defined by N points uniformly spaced on a path which minimises the area between the old and new paths when drawn on the Cartesian plane ?
Or, perhaps you could first define a polynomial (or spline or other simple curve) path through the original points, then move the points to and fro along the curve until they are uniformly spaced ?
I think the problem is simple and easily solvable actually :)
The basic idea is:
First check if the distance between your current point (P) and the end point of the line segment you are on is >= the distance between P and the next point (Q).
If it is, great, we use some simple trigonometry to figure it out.
Else, we move to the adjacent line segment (in your ordering) and deduct the distance between P and the endpoint of the line segment you are on and continue the process.
Pseudocode:
Defined previously
struct LineSegment
{
Point start,end;
int ID;
double len; // len = EuclideanDistance(start,end);
LineSegment *next_segment;
double theta; // theta = atan2(slope_of_line_segment);
}
Function [LineSegment nextseg] = FindNextLineSegment(LineSegment lineseg)
Input: LineSegment object of the current line segment
Output: LineSegment object of the adjacent line segment in your ordering.
nextseg.ID = -1 if there are no more segments
Function: Find the next point along your path
Function [Point Q, LineSegment Z] = FindNextPt(Point P, LineSegment lineseg, int dist):
Input: The current point P, the distance between this point and the next, and the LineSegment of the line segment which contains P.
Output: The next point Q, and the line segment it is on
Procedure:
distToEndpt = EuclideanDistance(P,lineseg->end);
if( distToEndpt >= d )
{
Point Q(lineseg->start.x + dist*cos(lineseg.theta), lineseg->start.y + dist*sin(lineseg.theta));
Z = lineseg;
}
else
{
nextseg = lineseg->next_segment;
if( nextseg.ID !=-1 )
{
[Q, Z] = FindNextPt(nextseg->start,nextseg->ID,dist-distToEndpt);
}
else
{
return [P,lineseg];
}
}
return [Q,Z]
Entry point
Function main()
Output: vector of points
Procedure:
vector<LineSegment> line_segments;
// Define it somehow giving it all the properties
// ....
vector<Point> equidistant_points;
const int d = DIST;
[Q Z] = FindNextPoint(line_segments[0].start,line_segments[0],DIST);
while( Z.ID != -1 )
{
equidistant_points.push_back(Q);
[Q Z] = FindNextPt(Q,Z,d);
}
My sense is that this is a very hard problem.
It basically amounts to a constrained optimization problem. The objective function measures how close the new line is from the old one. The constraints enforce that the new points are the same distance apart.
Finding a good objective function is the tricky bit, since it must be differentiable, and we don't know ahead of time on which segments each new point will lie: for instance, it's possible for two new points to lie on an extra-long old segment, and no new points lying on some extra-short old segment. If you somehow know a priori on which segments the new points will lie, you can sum the distances between points and their target segments and use that as your objective function (note that this distance function is nontrivial, since the segments are finite: it is composed of three pieces and its level-sets are "pill-shaped.")
Or you might forget about requiring the new points to lie on old segments, and just look for a new polyline that's "close" to the old one. For instance, you might try to write down an L2-like metric between polylines, and use that as your objective function. I don't expect this metric to be pleasant to write down, or differentiate.
I think a perturbative approach will work for this one.
I assume:
we know how to slide a point along the path and recalculate the distances (pretty trivial), and
the end points must remain fixed (otherwise the whole problem becomes trivial).
just iterate over the remaining (n-2) points: if point k is closer to point (k-1) than to point (k+1), move it a little forward along the path. Likewise if it's closer to point (k+1), move a little back along the path.
It's probably best to start with large step sizes (for speed) then make them smaller (for precision). Even if the points pass each other, I think this approach will sort them back into order.
This will use quite a bit of vector math but is quite simple really.
First you will need to find the total distance of the path. Depending on how the points of the path are stored is how you will do it. Here is a basic example on a 2 Dimensional Path in Pseudo-code.
// This would generally be done with vectors, however I'm not sure
// if you would like to make your own class for them as I do so I will use arrays.
// The collection of points
int Points[4][2] = { {0,0}, {1,2}, {5,4}, {6,5} };
int Points2 = Points;
// goes to 3 because there are 4 points
for(int i=0; i<3; i++) {
x = Points[i+1][0] - Points[i][0];
y = Points[i+1][1] - Points[i][1];
d += sqrt(( x * x ) + ( y * y ));
}
// divide distance by number of points to get uniform distance
dist = d/4;
// now that you have the new distance you must find the points
// on your path that are that far from your current point
// same deal here... goes to 3 because there are 4 points
for(int i=0; i<3; i++) {
// slope
m = ( Points[i+1][1] - Points[i][1] ) / ( Points[i+1][0] - Points[i][0] );
// y intercept
b = -(M * Points[i][0]) + Points[i][1];
// processor heavy which makes this problem difficult
// if some one knows a better way please say something
// check every degree grabbing the points till one matches
// if it doesn't then check next segment.
for(float j=0; j<360; j += 0.1) {
x = dist * sin(j);
y = sqrt((dist * dist) - ( x * x ));
if (y - (M * x + C)) {
// then the point is on the line so set it
Points2[i+1][0] = x;
Points2[i+1][1] = y;
}
}
}
The last step is what makes it unreasonable but this should work for you.
There may be a small math error somewhere I double checked this several times but there could be something I missed. So if anyone notices something please inform me and I will edit it.
Hope this helps,
Gale