private com.epl.geometry.SimpleRasterizer.Edge SortAET_(com.epl.geometry.SimpleRasterizer.Edge aet) { int num = 0; for (com.epl.geometry.SimpleRasterizer.Edge e = aet; e != null; e = e.next) { num++; } sortedNum_ = num; if (num == 1) { return(aet); } if (sortBuffer_ == null) { sortBuffer_ = new com.epl.geometry.SimpleRasterizer.Edge[System.Math.Max(num, 16)]; } else { if (sortBuffer_.Length < num) { sortBuffer_ = new com.epl.geometry.SimpleRasterizer.Edge[System.Math.Max(num, sortBuffer_.Length * 2)]; } } { int i = 0; for (com.epl.geometry.SimpleRasterizer.Edge e_1 = aet; e_1 != null; e_1 = e_1.next) { sortBuffer_[i++] = e_1; } } if (num == 2) { if (sortBuffer_[0].x > sortBuffer_[1].x) { com.epl.geometry.SimpleRasterizer.Edge tmp = sortBuffer_[0]; sortBuffer_[0] = sortBuffer_[1]; sortBuffer_[1] = tmp; } } else { System.Array.Sort(sortBuffer_, 0, num, edgeCompare_); } aet = sortBuffer_[0]; sortBuffer_[0] = null; com.epl.geometry.SimpleRasterizer.Edge prev = aet; for (int i_1 = 1; i_1 < num; i_1++) { prev.next = sortBuffer_[i_1]; prev = sortBuffer_[i_1]; sortBuffer_[i_1] = null; } prev.next = null; return(aet); }
private void AddNewEdgesToAET_(int y) { if (y >= height_) { return; } com.epl.geometry.SimpleRasterizer.Edge edgesOnLine = ySortedEdges_[y]; if (edgesOnLine != null) { ySortedEdges_[y] = null; edgesOnLine = SortAET_(edgesOnLine); //sort new edges numEdges_ -= sortedNum_; //set in the sortAET // merge the edges with sorted AET - O(n) operation com.epl.geometry.SimpleRasterizer.Edge aet = activeEdgesTable_; bool first = true; com.epl.geometry.SimpleRasterizer.Edge newEdge = edgesOnLine; com.epl.geometry.SimpleRasterizer.Edge prev_aet = null; while (aet != null && newEdge != null) { if (aet.x > newEdge.x) { if (first) { activeEdgesTable_ = newEdge; } com.epl.geometry.SimpleRasterizer.Edge p = newEdge.next; newEdge.next = aet; if (prev_aet != null) { prev_aet.next = newEdge; } prev_aet = newEdge; newEdge = p; } else { // aet.x <= newEdges.x com.epl.geometry.SimpleRasterizer.Edge p = aet.next; aet.next = newEdge; if (prev_aet != null) { prev_aet.next = aet; } prev_aet = aet; aet = p; } first = false; } if (activeEdgesTable_ == null) { activeEdgesTable_ = edgesOnLine; } } }
private void EmitScans_() { if (activeEdgesTable_ == null) { return; } int w = 0; com.epl.geometry.SimpleRasterizer.Edge e0 = activeEdgesTable_; int x0 = (int)(e0.x >> 32); for (com.epl.geometry.SimpleRasterizer.Edge e = e0.next; e != null; e = e.next) { if (evenOdd_) { w ^= 1; } else { w += e.dir; } if (e.x > e0.x) { int x = (int)(e.x >> 32); if (w != 0) { int xx0 = Snap_(x0, 0, width_); int xx = Snap_(x, 0, width_); if (xx > xx0 && xx0 < width_) { scanBuffer_[scanPtr_++] = xx0; scanBuffer_[scanPtr_++] = xx; scanBuffer_[scanPtr_++] = e.y; if (scanPtr_ == scanBuffer_.Length) { callback_.DrawScan(scanBuffer_, scanPtr_); scanPtr_ = 0; } } } e0 = e; x0 = x; } } }
/// <summary>Call before starting the edges.</summary> /// <remarks> /// Call before starting the edges. /// For example to render two polygons that consist of a single ring: /// startAddingEdges(); /// addRing(...); /// renderEdges(Rasterizer.EVEN_ODD); /// addRing(...); /// renderEdges(Rasterizer.EVEN_ODD); /// For example to render a polygon consisting of three rings: /// startAddingEdges(); /// addRing(...); /// addRing(...); /// addRing(...); /// renderEdges(Rasterizer.EVEN_ODD); /// </remarks> public void StartAddingEdges() { if (numEdges_ > 0) { for (int i = 0; i < height_; i++) { for (com.epl.geometry.SimpleRasterizer.Edge e = ySortedEdges_[i]; e != null;) { com.epl.geometry.SimpleRasterizer.Edge p = e; e = e.next; p.next = null; } ySortedEdges_[i] = null; } activeEdgesTable_ = null; } minY_ = height_; maxY_ = -1; numEdges_ = 0; }
private void AdvanceAET_() { if (activeEdgesTable_ == null) { return; } bool needSort = false; com.epl.geometry.SimpleRasterizer.Edge prev = null; for (com.epl.geometry.SimpleRasterizer.Edge e = activeEdgesTable_; e != null;) { e.y++; if (e.y == e.ymax) { com.epl.geometry.SimpleRasterizer.Edge p = e; e = e.next; if (prev != null) { prev.next = e; } else { activeEdgesTable_ = e; } p.next = null; continue; } e.x += e.dxdy; if (prev != null && prev.x > e.x) { needSort = true; } prev = e; e = e.next; } if (needSort) { //resort to fix the order activeEdgesTable_ = SortAET_(activeEdgesTable_); } }
//reset for new edges /// <summary>Add a single edge.</summary> /// <param name="x1"/> /// <param name="y1"/> /// <param name="x2"/> /// <param name="y2"/> public void AddEdge(double x1, double y1, double x2, double y2) { if (y1 == y2) { return; } int dir = 1; if (y1 > y2) { double temp; temp = x1; x1 = x2; x2 = temp; temp = y1; y1 = y2; y2 = temp; dir = -1; } if (y2 < 0 || y1 >= height_) { return; } if (x1 < 0 && x2 < 0) { x1 = -1; x2 = -1; } else { if (x1 >= width_ && x2 >= width_) { x1 = width_; x2 = width_; } } //clip to extent double dxdy = (x2 - x1) / (y2 - y1); if (y2 > height_) { y2 = height_; x2 = dxdy * (y2 - y1) + x1; } if (y1 < 0) { x1 = dxdy * (0 - y1) + x1; y1 = 0; } //do not clip x unless it is too small or too big int bigX = System.Math.Max(width_ + 1, unchecked ((int)(0x7fffff))); if (x1 < -unchecked ((int)(0x7fffff))) { //from earlier logic, x2 >= -1, therefore dxdy is not 0 y1 = (0 - x1) / dxdy + y1; x1 = 0; } else { if (x1 > bigX) { //from earlier logic, x2 <= width_, therefore dxdy is not 0 y1 = (width_ - x1) / dxdy + y1; x1 = width_; } } if (x2 < -unchecked ((int)(0x7fffff))) { //from earlier logic, x1 >= -1, therefore dxdy is not 0 y2 = (0 - x1) / dxdy + y1; x2 = 0; } else { if (x2 > bigX) { //from earlier logic, x1 <= width_, therefore dxdy is not 0 y2 = (width_ - x1) / dxdy + y1; x2 = width_; } } int ystart = (int)y1; int yend = (int)y2; if (ystart == yend) { return; } com.epl.geometry.SimpleRasterizer.Edge e = new com.epl.geometry.SimpleRasterizer.Edge(); e.x = (long)(x1 * 4294967296.0); e.y = ystart; e.ymax = yend; e.dxdy = (long)(dxdy * 4294967296.0); e.dir = dir; if (ySortedEdges_ == null) { ySortedEdges_ = new com.epl.geometry.SimpleRasterizer.Edge[height_]; } e.next = ySortedEdges_[e.y]; ySortedEdges_[e.y] = e; if (e.y < minY_) { minY_ = e.y; } if (e.ymax > maxY_) { maxY_ = e.ymax; } numEdges_++; }