private static EdgeTable build_lmt( LmtTable lmt_table, ScanBeamTreeEntries sbte, IPoly p, int type, //poly type SUBJ/CLIP OperationType op) { /* Create the entire input polygon edge table in one go */ EdgeTable edge_table = new EdgeTable(); for ( int c= 0; c < p.InnerPolygonCount; c++) { IPoly ip = p.GetInnerPoly(c); if( !ip.IsContributing(0) ) { /* Ignore the non-contributing contour */ ip.SetContributing(0, true); } else { /* Perform contour optimisation */ int num_vertices= 0; int e_index = 0 ; edge_table = new EdgeTable(); for ( int i= 0; i < ip.PointCount; i++) { if( OPTIMAL(ip, i) ) { double x = ip.GetX(i); double y = ip.GetY(i); edge_table.addNode( x, y ); /* Record vertex in the scanbeam table */ add_to_sbtree( sbte, ip.GetY(i) ); num_vertices++; } } /* Do the contour forward pass */ for ( int min= 0; min < num_vertices; min++) { /* If a forward local minimum... */ if( edge_table.FWD_MIN( min ) ) { /* Search for the next local maximum... */ int num_edges = 1; int max = NEXT_INDEX( min, num_vertices ); while( edge_table.NOT_FMAX( max ) ) { num_edges++; max = NEXT_INDEX( max, num_vertices ); } /* Build the next edge list */ int v = min; EdgeNode e = edge_table.getNode( e_index ); e.bstate[BELOW] = BundleState.UNBUNDLED; e.bundle[BELOW, CLIP] = 0; e.bundle[BELOW, SUBJ] = 0; for ( int i= 0; i < num_edges; i++) { EdgeNode ei = edge_table.getNode( e_index+i ); EdgeNode ev = edge_table.getNode( v ); ei.xb = ev.vertex.X; ei.bot.X = ev.vertex.X; ei.bot.Y = ev.vertex.Y; v = NEXT_INDEX(v, num_vertices); ev = edge_table.getNode( v ); ei.top.X= ev.vertex.X; ei.top.Y= ev.vertex.Y; ei.dx= (ev.vertex.X - ei.bot.X) / (ei.top.Y - ei.bot.Y); ei.type = type; ei.outp[ABOVE] = null ; ei.outp[BELOW] = null; ei.next = null; ei.prev = null; ei.succ = ((num_edges > 1) && (i < (num_edges - 1))) ? edge_table.getNode(e_index+i+1) : null; ei.pred = ((num_edges > 1) && (i > 0)) ? edge_table.getNode(e_index+i-1) : null ; ei.next_bound = null ; ei.bside[CLIP] = (op == OperationType.GPC_DIFF) ? RIGHT : LEFT; ei.bside[SUBJ] = LEFT ; } insert_bound( bound_list(lmt_table, edge_table.getNode(min).vertex.Y), e); #if DEBUG Console.WriteLine("fwd"); lmt_table.print(); #endif e_index += num_edges; } } /* Do the contour reverse pass */ for ( int min= 0; min < num_vertices; min++) { /* If a reverse local minimum... */ if ( edge_table.REV_MIN( min ) ) { /* Search for the previous local maximum... */ int num_edges= 1; int max = PREV_INDEX(min, num_vertices); while( edge_table.NOT_RMAX( max ) ) { num_edges++; max = PREV_INDEX(max, num_vertices); } /* Build the previous edge list */ int v = min; EdgeNode e = edge_table.getNode( e_index ); e.bstate[BELOW] = BundleState.UNBUNDLED; e.bundle[BELOW, CLIP] = 0; e.bundle[BELOW, SUBJ] = 0; for (int i= 0; i < num_edges; i++) { EdgeNode ei = edge_table.getNode( e_index+i ); EdgeNode ev = edge_table.getNode( v ); ei.xb = ev.vertex.X; ei.bot.X = ev.vertex.X; ei.bot.Y = ev.vertex.Y; v= PREV_INDEX(v, num_vertices); ev = edge_table.getNode( v ); ei.top.X = ev.vertex.X; ei.top.Y = ev.vertex.Y; ei.dx = (ev.vertex.X - ei.bot.X) / (ei.top.Y - ei.bot.Y); ei.type = type; ei.outp[ABOVE] = null; ei.outp[BELOW] = null; ei.next = null ; ei.prev = null; ei.succ = ((num_edges > 1) && (i < (num_edges - 1))) ? edge_table.getNode(e_index+i+1) : null; ei.pred = ((num_edges > 1) && (i > 0)) ? edge_table.getNode(e_index+i-1) : null ; ei.next_bound = null ; ei.bside[CLIP] = (op == OperationType.GPC_DIFF) ? RIGHT : LEFT; ei.bside[SUBJ] = LEFT; } insert_bound( bound_list(lmt_table, edge_table.getNode(min).vertex.Y), e); #if DEBUG Console.WriteLine("rev"); lmt_table.print(); #endif e_index+= num_edges; } } } } return edge_table; }
private static RectangleF[] create_contour_bboxes( IPoly p ) { RectangleF[] box = new RectangleF[p.InnerPolygonCount] ; /* Construct contour bounding boxes */ for ( int c= 0; c < p.InnerPolygonCount; c++) { IPoly inner_poly = p.GetInnerPoly(c); box[c] = inner_poly.Bounds; } return box; }