예제 #1
0
bool PolygonSplitter::testTracePolyOutline(int edge_start)
{
	int edge = edge_start;
	int v1, v2, next;
	unsigned a = 0;
	for (a = 0; a < 100000; a++)
	{
		v1 = edges[edge].v1;
		v2 = edges[edge].v2;
		next = -1;

		// Find the next convex edge with the lowest angle
		next = findNextEdge(edge, false, true);

		// Abort if no next edge was found
		if (next < 0)
			return false;

		// Stop if we're back at the start
		if (next == edge_start)
			break;

		// Continue loop
		edge = next;
	}

	if (a >= 99999)
	{
		if (verbose) wxLogMessage("Possible infinite loop in tracePolyOutline");
		return false;
	}

	return true;
}
예제 #2
0
void PolygonSplitter::detectConcavity()
{
	concave_edges.clear();

	// Go through all edges
	for (unsigned a = 0; a < edges.size(); a++)
	{
		if (!edges[a].ok)
			continue;

		// Find the next edge with the lowest angle (ignore edges with angle > 180)
		int next = findNextEdge(a, false);
		if (next < 0)
		{
			// If no edge with an angle < 180 was found, this edge is concave
			concave_edges.push_back(a);
		}
	}
}
예제 #3
0
bool PolygonSplitter::doSplitting(Polygon2D* poly)
{
	// Init
	split_edges_start = edges.size();

	// Trace polygon outlines
	for (unsigned a = 0; a < edges.size(); a++)
	{
		if (edges[a].inpoly || !edges[a].ok)
			continue;
		tracePolyOutline(a);
	}
	if (verbose) wxLogMessage("%d Polygon outlines detected", polygon_outlines.size());

	// Check if any edges are not part of a polygon outline
	for (unsigned a = 0; a < edges.size(); a++)
	{
		if (!edges[a].inpoly)
			edges[a].ok = false;	// Invalidate it
	}

	// Let's check for some cases where we can 'throw away' edges/vertices from further consideration
	for (unsigned a = 0; a < polygon_outlines.size(); a++)
	{
		// Check if this polygon intersects with any others
		bool separate = true;
		for (unsigned b = 0; b < polygon_outlines.size(); b++)
		{
			if (b == a) continue;
			bbox_t& bb1 = polygon_outlines[a].bbox;
			bbox_t& bb2 = polygon_outlines[b].bbox;
			if (!(bb2.min.x > bb1.max.x || bb2.max.x < bb1.min.x ||
			        bb2.min.y > bb1.max.y || bb2.max.y < bb1.min.y))
			{
				separate = false;
				break;
			}
		}

		// If the polygon didn't intersect, and is convex and clockwise ('outer')
		if (separate && polygon_outlines[a].clockwise && polygon_outlines[a].convex)
		{
			if (verbose) wxLogMessage("Separate, convex polygon exists, cutting (valid)");
			for (unsigned b = 0; b < polygon_outlines[a].edges.size(); b++)
			{
				// Set the edge to 'done' so it is ignored, but still used to build polygons
				edges[polygon_outlines[a].edges[b]].done = true;

				// If the edge's vertices aren't attached to anything else, also preclude these from later calculations
				int v1 = edges[polygon_outlines[a].edges[b]].v1;
				if (vertices[v1].edges_in.size() == 1 && vertices[v1].edges_out.size() == 1)
					vertices[v1].ok = false;

				int v2 = edges[polygon_outlines[a].edges[b]].v2;
				if (vertices[v2].edges_in.size() == 1 && vertices[v2].edges_out.size() == 1)
					vertices[v2].ok = false;
			}
		}

		// If the polygon didn't intersect, and is anticlockwise (inner), it is invalid
		else if (separate && !polygon_outlines[a].clockwise)
		{
			if (verbose) wxLogMessage("Separate, anticlockwise polygon exists, cutting (invalid)");
			for (unsigned b = 0; b < polygon_outlines[a].edges.size(); b++)
			{
				// Set the edge to 'done' so it is ignored, but still used to build polygons
				edges[polygon_outlines[a].edges[b]].ok = false;

				// If the edge's vertices aren't attached to anything else, also preclude these from later calculations
				int v1 = edges[polygon_outlines[a].edges[b]].v1;
				if (vertices[v1].edges_in.size() == 1 && vertices[v1].edges_out.size() == 1)
					vertices[v1].ok = false;

				int v2 = edges[polygon_outlines[a].edges[b]].v2;
				if (vertices[v2].edges_in.size() == 1 && vertices[v2].edges_out.size() == 1)
					vertices[v2].ok = false;
			}
		}
	}

	// Detect concave edges/vertices
	detectConcavity();

	// Keep splitting until we have no concave edges left
	// (we'll limit the number of rounds to 100 to avoid infinite loops, just in case)
	for (unsigned loop = 0; loop < 100; loop++)
	{
		for (unsigned a = 0; a < concave_edges.size(); a++)
			splitFromEdge(concave_edges[a]);

		detectConcavity();
		if (concave_edges.empty())
			break;
	}

	// Remove unnecessary splits
	for (unsigned a = split_edges_start; a < edges.size(); a++)
	{
		if (!edges[a].ok)
			continue;

		// Invalidate split
		edges[a].ok = false;
		edges[edges[a].sister].ok = false;

		// Check poly is still convex without split
		int next = findNextEdge(a, false, true);
		if (next >= 0)
		{
			if (testTracePolyOutline(next))
				continue;
		}

		// Not convex, split is needed
		edges[a].ok = true;
		edges[edges[a].sister].ok = true;
	}

	// Reset edge 'done' status
	for (unsigned a = 0; a < edges.size(); a++)
		edges[a].done = false;

	// Build polygons
	for (unsigned a = 0; a < edges.size(); a++)
	{
		if (edges[a].done || !edges[a].ok)
			continue;

		poly->addSubPoly();
		if (!buildSubPoly(a, poly->getSubPoly(poly->nSubPolys() - 1)))
			poly->removeSubPoly(poly->nSubPolys() - 1);
	}

	return true;
}
예제 #4
0
bool PolygonSplitter::buildSubPoly(int edge_start, gl_polygon_t* poly)
{
	// Check polygon was given
	if (!poly)
		return false;

	// Loop of death
	int edge = edge_start;
	//int v1 = edges[edge].v1;
	//int v = 0;
	vector<int> verts;
	for (unsigned a = 0; a < 1000; a++)
	{
		// Add vertex
		verts.push_back(edges[edge].v1);

		// Fill triangle
		// (doesn't seem to be any kind of performance increase using triangles over
		//	just rendering a GL_TRIANGLE_FAN polygon, not worth the memory usage increase)
		//v++;
		//if (v > 2) {
		//	verts.push_back(v1);
		//	verts.push_back(edges[edge].v1);
		//}

		// Add edge to 'valid' edges list, so it is ignored when building further polygons
		if (edge != edge_start) edges[edge].done = true;

		// Get 'next' edge
		edge = findNextEdge(edge);

		// If no next edge is found, something is wrong, so abort building the polygon
		if (edge < 0)
			return false;

		// If we're back at the start, finish
		if (edge == edge_start)
			break;
	}

	// Set starting edge to valid
	edges[edge_start].done = true;

	// Check if the polygon is valid
	if (verts.size() >= 3)
	{
		// Allocate polygon vertex data
		poly->n_vertices = verts.size();
		poly->vertices = new gl_vertex_t[poly->n_vertices];

		// Add vertex data to polygon
		for (unsigned a = 0; a < verts.size(); a++)
		{
			poly->vertices[a].x = vertices[verts[a]].x;
			poly->vertices[a].y = vertices[verts[a]].y;
		}

		return true;
	}
	else
		return false;
}
예제 #5
0
bool PolygonSplitter::tracePolyOutline(int edge_start)
{
	polygon_outlines.push_back(poly_outline_t());
	poly_outline_t& poly = polygon_outlines.back();
	poly.convex = true;
	double edge_sum = 0;

	int edge = edge_start;
	int v1, v2, next;
	//while (true) {
	unsigned a = 0;
	for (a = 0; a < 100000; a++)
	{
		v1 = edges[edge].v1;
		v2 = edges[edge].v2;
		next = -1;

		// Add current edge
		poly.edges.push_back(edge);
		if (edge == edge_start) poly.bbox.extend(vertices[v1].x, vertices[v1].y);
		else edges[edge].inpoly = true;
		poly.bbox.extend(vertices[v2].x, vertices[v2].y);
		edge_sum += vertices[v1].x*vertices[v2].y - vertices[v2].x*vertices[v1].y;

		// Find the next edge with the lowest angle
		next = findNextEdge(edge, true, false, true);

		// Abort if no next edge was found
		if (next < 0)
		{
			for (unsigned b = 0; b < poly.edges.size(); b++)
				edges[poly.edges[b]].inpoly = false;

			polygon_outlines.pop_back();
			return false;
		}

		// Check for concavity
		if (last_angle > PI)
			poly.convex = false;

		// Stop if we're back at the start
		if (next == edge_start)
			break;

		// Continue loop
		edge = next;
	}

	if (a >= 99999)
	{
		if (verbose) wxLogMessage("Possible infinite loop in tracePolyOutline");
		return false;
	}

	// Determine if this is an 'outer' (clockwise) or 'inner' (anti-clockwise) polygon
	poly.clockwise = (edge_sum < 0);

	// Set all polygon edges 'inpoly' to true (so they are ignored when tracing future polylines
	edges[edge_start].inpoly = true;
	//for (unsigned a = 0; a < poly.edges.size(); a++)
	//	edges[poly.edges[a]].inpoly = true;

	if (verbose)
	{
		string info = "Traced polygon outline: ";
		info += S_FMT("%d edges, ", poly.edges.size());
		if (poly.convex) info += "convex, ";
		else info += "concave, ";
		if (poly.clockwise) info += "clockwise";
		else info += "anticlockwise";
		wxLogMessage(info);
	}

	return true;
}
예제 #6
0
/*
 * This function is called straight from AbstractExecutor::execute,
 * which is called from executeExecutors, which is called from the
 * VoltDBEngine::executePlanFragments.  So, this is really the start
 * of execution for this executor.
 *
 * The executor will already have been initialized by p_init.
 */
bool WindowFunctionExecutor::p_execute(const NValueArray& params) {
    VOLT_TRACE("windowFunctionExecutor::p_execute(start)\n");
    // Input table
    Table * input_table = m_abstractNode->getInputTable();
    assert(input_table);
    VOLT_TRACE("WindowFunctionExecutor: input table\n%s", input_table->debug().c_str());
    m_inputSchema = input_table->schema();
    assert(m_inputSchema);

    /*
     * Do this after setting the m_inputSchema.
     */
    initWorkingTupleStorage();
    TableWindow tableWindow(input_table);
    ProgressMonitorProxy pmp(m_engine->getExecutorContext(), this);
    m_pmp = &pmp;

    m_aggregateRow
        = new (m_memoryPool, m_aggTypes.size())
        WindowAggregateRow(m_inputSchema, m_memoryPool);

    initAggInstances();

    VOLT_TRACE("Beginning: %s", tableWindow.debug().c_str());

    TableTuple nextTuple(m_inputSchema);

    /*
     * Force a call p_execute_finish when this is all over.
     */
    EnsureCleanupOnExit finishCleanup(this);
    for (EdgeType etype = START_OF_INPUT,
                  nextEtype = INVALID_EDGE_TYPE;
         etype != END_OF_INPUT;
         etype = nextEtype) {
        // Reset the aggregates if this is the
        // start of a partition group.  The start of
        // input is a special form of this.
        if (etype == START_OF_INPUT || etype == START_OF_PARTITION_GROUP) {
            m_aggregateRow->resetAggs();
        }
        // Find the next edge.  This will
        // give the aggs a crack at each row
        // if they want it.
        nextEtype = findNextEdge(etype, tableWindow);
        // Let the aggs know the results
        // of the lookahead.
        lookaheadNextGroupForAggs(tableWindow);
        // Advance to the end of the current group.
        for (int idx = 0; idx < tableWindow.m_orderByGroupSize; idx += 1) {
            VOLT_TRACE("MiddleEdge: Window = %s", m_tableWindow->debug().c_str());
            tableWindow.m_middleEdge.next(nextTuple);
            m_pmp->countdownProgress();
            m_aggregateRow->recordPassThroughTuple(nextTuple);
            insertOutputTuple();
        }
        endGroupForAggs(tableWindow, etype);
        VOLT_TRACE("FirstEdge: %s", m_tableWindow->debug().c_str());
    }
    VOLT_TRACE("WindowFunctionExecutor: finalizing..");

    cleanupInputTempTable(input_table);
    VOLT_TRACE("WindowFunctionExecutor::p_execute(end)\n");
    return true;
}
예제 #7
0
bool tm_polygon_selectloop::calculate( MIntArray &edgesArray, const int &selIndex, const int &mode, const double &angle_deg, const int &maxCount)
{
	if(!objectIsSet)
	{
		MGlobal::displayError("tm_polygon_selectloop::calculate - Object is not set.");
		return false;
	}

	double angle = angle_deg*M_PI/180;
	MStatus stat;
	pMesh = new MFnMesh( meshObject, &stat);				if (!stat) return false;
	int meshEdgesCount = pMesh->numEdges( &stat);		if (!stat) return false;
	int *pVisitedEdges = new int[meshEdgesCount];
	for( int i = 0; i < meshEdgesCount; i++) pVisitedEdges[i] = 0;

	pVtxIt = new MItMeshVertex( meshObject, &stat);			if (!stat) return false;
	pEdgeIt = new MItMeshEdge( meshObject, &stat);			if (!stat) return false;
	pFaceIt = new MItMeshPolygon( meshObject, &stat);		if (!stat) return false;

	int edgeVtx[2];
	int edge, vtx;
	stat = pMesh->getEdgeVertices( selIndex, edgeVtx);	if (!stat) return false;
	std::list <int> edgesList;
	edgesList.push_front( selIndex);

	int count = 1;
	edge = selIndex;
	pVisitedEdges[selIndex] = 1;
	vtx = edgeVtx[0];
	while( findNextEdge( edge, vtx, mode, angle))
	{
		if (pVisitedEdges[edge]) break;
		if ((++count) > maxCount) break;
		edgesList.push_front( edge);
		pVisitedEdges[edge] = 1;
	}
	edge = selIndex;
	vtx = edgeVtx[1];
	while( findNextEdge( edge, vtx, mode, angle))
	{
		if (pVisitedEdges[edge]) break;
		if ((++count) > maxCount) break;
		edgesList.push_back( edge);
		pVisitedEdges[edge] = 1;
	}

	int len = (int)edgesList.size();
	edgesArray.setLength( len);
	for( int i = 0; i < len; i++)
	{
		edgesArray[i] = *edgesList.begin();
		edgesList.pop_front();
	}

	if( pMesh != NULL) delete pMesh;
	if( pVtxIt != NULL) delete pVtxIt;
	if( pEdgeIt != NULL) delete pEdgeIt;
	if( pFaceIt != NULL) delete pFaceIt;
	if( pVisitedEdges != NULL) delete [] pVisitedEdges;

	return true;
}