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; }
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); } } }
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; }
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; }
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; }
/* * 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; }
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; }