Esempio n. 1
0
 Real BondFunctions::convexity(const Bond& bond,
                               Rate yield,
                               const DayCounter& dayCounter,
                               Compounding compounding,
                               Frequency frequency,
                               Date settlement) {
     InterestRate y(yield, dayCounter, compounding, frequency);
     return convexity(bond, y, settlement);
 }
Esempio n. 2
0
bool triangulate_simple_polygon_naive( const std::vector<double> &coords, const int *facet, std::vector<int> &tris ){
	// get the number of facet vertices
	int num_verts = facet[0];
	
	// store some vectors of next and previous vertices, as well
	// as pointers to the xyz coordinates, original vertex id and
	// a convexity flag indicating which vertices can be clipped.
	std::vector<int>			vert( num_verts );		// stores the input vertex id 
	std::vector<int>			next( num_verts );		// stores the index of the next vertex in the contour
	std::vector<int>			prev( num_verts );		// stores the index of the previous vertex in the contour
	std::vector<const double*>	xyz( num_verts );		// stores pointers to the xyz coordinates of each vertex
	std::vector<double>			convexity( num_verts ); // stores the convexity status of each vertex, >0 == convex
	double normal[3];
	
	// compute the facet normal
	triangulate_estimate_facet_normal( coords, facet, normal );
	
	// set up the linked list pointers, vertex indices and coordinates
	for( int i=0; i<num_verts; i++ ){
		vert[i] = facet[i+1];
		xyz[i] = &coords[vert[i]*3];
		prev[i] = (i-1+num_verts)%num_verts;
		next[i] = (i+1)%num_verts;
	}
	
	// compute the convexity of each vertex
	for( int i=0; i<num_verts; i++ ){
		convexity[i] = compute_convexity( normal, xyz[prev[i]], xyz[i], xyz[next[i]] );
	}
	
	// Main loop.  A stopping criteria has been aded so that the 
	// algorithm does not stall on bad inputs where no progress can be made.
	// For simple polygons in the worst case, the algorithm will remove
	// one vertex for every full traversal of the polygon.  This gives an
	// upper bound of (num_verts^2)/2 that the main loop should execute,
	// although in practice it will typically do much better. A bound of
	// num_verts^2 will consequently be more than sufficient for the 
	// algorithm to complete on valid inputs, failure to finish in that
	// many iterations indicates either improper input, or input that
	// cannot be tesselated due to precision of the non-exact tests.
	bool okay;
	int test, tmp_next, tmp_prev, max_tries=num_verts*num_verts, tries=0, curr = 0;
	while( num_verts > 2 && tries++ < max_tries ){
		
		// if the current vertex is (strictly) convex
		if( convexity[curr] > TRIANGULATE_EPSILON ){
			
			// then check the other vertices in the polygon to see if 
			// they fall within the triangle that would be clipped. 
			// All vertices except those that are in the clipped triangle
			// are checked.  This section could (should) be replaced
			// with spatial partitioning searches for very large inputs
			okay = true;
			test = next[curr];
			while( okay && test != curr ){
				// This conditional is necessary, since we may have bridges connecting two contours to form
				// a simple polygon. This test prevents incorrectly failing when a vertex that will be on 
				// the clipped triangle appears later in the polydon due to one of these bridges
				if( vert[test] != vert[prev[curr]] && vert[test] != vert[curr] && vert[test] != vert[next[curr]] ){
					okay &= !point_in_triangle( normal, xyz[prev[curr]], xyz[curr], xyz[next[curr]], xyz[test] );
				}
				test = next[test];
			}
			
			// no vertices fell within the clipped triangle, so 
			// the triangle can be added to the output and the 
			// current vertex removed from the contour
			if( okay ){
				// decrement the number of vertices
				num_verts--;
				
				// store the next and previous vertices for convenience, it
				// avoids unnecessary nesting like next[prev[curr]] that happens
				// otherwise to avoid using vertex curr which gets removed.
				tmp_prev = prev[curr];
				tmp_next = next[curr];
				
				// add the triangle to the output
				tris.push_back( 3 );
				tris.push_back( vert[tmp_prev] );
				tris.push_back( vert[curr] );
				tris.push_back( vert[tmp_next] );
				
				// update the linked list indices
				next[tmp_prev] = tmp_next;
				prev[tmp_next] = tmp_prev;
				
				// update the convexity status of the next
				// and previous vertices, since it may
				// have changed after clipping
				convexity[tmp_prev] = compute_convexity( normal, xyz[prev[tmp_prev]], xyz[tmp_prev], xyz[next[tmp_prev]] );
				convexity[tmp_next] = compute_convexity( normal, xyz[prev[tmp_next]], xyz[tmp_next], xyz[next[tmp_next]] );
			}
		}
		
		// advance one point around the boundary, we do this regardless of whether
		// the vertex was clipped. It is always valid since we never invalidate
		// the current vertex, just clip it out of the loop (i.e. next[curr] will
		// point to a valid vertex in the contour, even though curr will never 
		// be reached again).
		curr = next[curr];
	}
	
	//std::cout << "took " << tries << " out of a maximum of " << max_tries << std::endl;
		
	// should always end up with num_verts-2 triangles when
	// tesselating a simple polygon. Failure to do so indicates
	// non-simple input, or input that cannot be resolved with 
	// the current TRIANGULATE_EPSILON setting
	return num_verts == 2;
}
Esempio n. 3
0
/**
 @brief Triangulates a simple polygon using an ear-clipping algorithm and heuristic to (hopefully) reduce the time-complexity.  Always tries to clip the ear with minimal area first, under the assumption that this will have the least probability of enclosing an unrelated polygon vertex.  Worst-case complexity of O(N^3 log(N)), with a best-case complexity of O(N^2 log(N)), which the algorithm appears to achieve often in practice. Note that this explicitly checks every vertex in the polygon for inclusion in a clipped ear, spatial partitioning should reduce the the complexity to O(N log(N)).
 @param[in] coords input array of polygon vertices, stored [x, y, z, x, y, z, ...]
 @param[in] facet input pointer to facet contour vertex indices, stored [nverts, v_0, v_1, ... v_(n_verts-1}]
 @param[out] tris output vector of triangles, stored as [ 3, v0, v1, v2, 3, v0, v1, v2, ... ]
 @return true if the triangulation succeeded, false otherwise
*/
bool triangulate_simple_polygon_set( const std::vector<double> &coords, const int *facet, std::vector<int> &tris ){
	// get the number of facet vertices
	int num_verts = facet[0];
	
	// store some vectors of next and previous vertices, as well
	// as pointers to the xyz coordinates, original vertex id and
	// a convexity flag indicating which vertices can be clipped.
	std::vector<int>			vert( num_verts );		// stores the input vertex id 
	std::vector<int>			next( num_verts );		// stores the index of the next vertex in the contour
	std::vector<int>			prev( num_verts );		// stores the index of the previous vertex in the contour
	std::vector<const double*>	xyz( num_verts );		// stores pointers to the xyz coordinates of each vertex
	std::vector<double>			convexity( num_verts ); // stores the convexity status of each vertex, >0 == convex
	double normal[3];
	
	triangulate_compare comp( convexity );
	std::set< int, triangulate_compare > best_vert( comp );
	std::set< int, triangulate_compare >::iterator iter;
	
	// compute the facet normal
	triangulate_estimate_facet_normal( coords, facet, normal );
	
	// set up the linked list pointers, vertex indices and coordinates
	for( int i=0; i<num_verts; i++ ){
		vert[i] = facet[i+1];
		xyz[i] = &coords[vert[i]*3];
		prev[i] = (i-1+num_verts)%num_verts;
		next[i] = (i+1)%num_verts;
	}
	
	// compute the convexity of each vertex
	for( int i=0; i<num_verts; i++ ){
		convexity[i] = compute_convexity( normal, xyz[prev[i]], xyz[i], xyz[next[i]] );
		if( convexity[i] > TRIANGULATE_EPSILON ){
			best_vert.insert( i );
		}
	}
	
	// Main loop.  A stopping criteria has been aded so that the 
	// algorithm does not stall on bad inputs where no progress can be made.
	// For simple polygons in the worst case, the algorithm will remove
	// one vertex for every full traversal of the polygon.  This gives an
	// upper bound of (num_verts^2)/2 that the main loop should execute,
	// although in practice it will typically do much better. A bound of
	// num_verts^2 will consequently be more than sufficient for the 
	// algorithm to complete on valid inputs, failure to finish in that
	// many iterations indicates either improper input, or input that
	// cannot be tesselated due to precision of the non-exact tests.
	bool okay;
	int test, curr, tmp_next, tmp_prev, init_verts=num_verts, tries=0, max_tries=num_verts*num_verts;
	for( int i=0; i<init_verts-2; i++ ){
		
		// Grab the first vertex from the sorted list of vertices. This should
		// be the 'best' vertex to clip according to the criteria in the 
		// triangulate_compare class, which could be the smallest area triangle,
		// or a randomized metric.  We have to iterate over these in order
		// to make sure that we actually find one that can be clipped, since the
		// first might produce a triangle that encloses another vertex
		for( iter=best_vert.begin(); iter!=best_vert.end(); iter++ ){
			curr = *iter;
			tries++;
			
			okay = true;
			test = next[curr];
			while( okay && test != curr ){
				// This conditional is necessary, since we may have bridges connecting two contours to form
				// a simple polygon. This test prevents incorrectly failing when a vertex that will be on 
				// the clipped triangle appears later in the polydon due to one of these bridges
				if( vert[test] != vert[prev[curr]] && vert[test] != vert[curr] && vert[test] != vert[next[curr]] ){
					okay &= !point_in_triangle( normal, xyz[prev[curr]], xyz[curr], xyz[next[curr]], xyz[test] );
				}
				test = next[test];
			}
			if( okay ){
				if( okay ){
					// decrement the number of vertices
					num_verts--;
					
					// remove the clipped vertex from consideration
					best_vert.erase( curr );
					
					// store the next and previous vertices for convenience, it
					// avoids unnecessary nesting like next[prev[curr]] that happens
					// otherwise to avoid using vertex curr which gets removed.
					tmp_prev = prev[curr];
					tmp_next = next[curr];
					
					// add the triangle to the output
					tris.push_back( 3 );
					tris.push_back( vert[tmp_prev] );
					tris.push_back( vert[curr] );
					tris.push_back( vert[tmp_next] );
					
					// update the linked list indices
					next[tmp_prev] = tmp_next;
					prev[tmp_next] = tmp_prev;
					
					// update the convexity status of the next
					// and previous vertices, since it may
					// have changed after clipping
					best_vert.erase( tmp_prev );
					best_vert.erase( tmp_next );
					convexity[tmp_prev] = compute_convexity( normal, xyz[prev[tmp_prev]], xyz[tmp_prev], xyz[next[tmp_prev]] );
					convexity[tmp_next] = compute_convexity( normal, xyz[prev[tmp_next]], xyz[tmp_next], xyz[next[tmp_next]] );
					if( convexity[tmp_prev] > TRIANGULATE_EPSILON ) best_vert.insert( tmp_prev );
					if( convexity[tmp_next] > TRIANGULATE_EPSILON ) best_vert.insert( tmp_next );
					break;
				}				
			}
		}		
	}
	
	//std::cout << "took " << tries << " out of a maximum of " << max_tries << std::endl;
	
	// should always end up with num_verts-2 triangles when
	// tesselating a simple polygon. Failure to do so indicates
	// non-simple input, or input that cannot be resolved with 
	// the current TRIANGULATE_EPSILON setting
	return num_verts == 2;
}