public void Add(Segment s) { // j iterates through the openPolygon chains. for (int j=0; j<openPolygons.Count; j++) { PointChain chain = openPolygons [j]; if (!chain.LinkSegment (s)) continue; if (chain.closed) { if (chain.pointList.Count == 2) { // We tried linking the same segment (but flipped end and start) to // a chain. (i.e. chain was <p0, p1>, we tried linking Segment(p1, p0) // so the chain was closed illegally. chain.closed = false; return; } closedPolygons.Add (chain); openPolygons.RemoveAt (j); return; } int k = openPolygons.Count; for (int i=j+1; i<k; i++) { // Try to connect this open link to the rest of the chains. // We won't be able to connect this to any of the chains preceding this one // because we know that linkSegment failed on those. if (chain.LinkPointChain (openPolygons [i])) { openPolygons.RemoveAt (i); return; } } return; } PointChain newChain = new PointChain (s); openPolygons.Add (newChain); }
void SurfaceSegmentForSurface(Segment s, Connector connector) { // trace the line until roughness is exceeded double dist = s.magnitude; // (float)Math.Sqrt ( (p1.x-p0.x)*(p1.x-p0.x) + (p1.y-p0.y)*(p1.y-p0.y)); Point direction = s.end - s.start; int numSteps = (int)(dist / MIN_VERTEX_DISTANCE); Point t0 = s.start; float h0 = _terrain.SampleHeight(transform.TransformPoint(t0.vector3)); Point ta = t0; float h1; for (int i=1;i<numSteps;i++) { Point t1 = s.start + direction * i / numSteps; h1 = _terrain.SampleHeight(transform.TransformPoint(t1.vector3)); if (h0 < h1 || h0-h1 > effectiveRoughness) { //-effectiveRoughness) { if (t0!=ta) { Segment s0 = new Segment(t0, ta, s.border); connector.Add (s0); Segment s1 = new Segment(ta, t1, s.border); connector.Add (s1); } else { Segment s0 = new Segment(t0, t1, s.border); connector.Add (s0); } t0 = t1; h0 = h1; } ta = t1; } // Add last point Segment finalSeg = new Segment(t0, s.end, s.border); connector.Add (finalSeg); }
void SetupHexagonalGrid() { // Make cell regions: we assume cells have only 1 region but that can change in the future int l = _numCells; int qx, qy; int q = (int)(Math.Sqrt (l)); q = q * 12 / 13; if (q<1) q= 1; qx=qy=q; int qx2 = qx * 4 / 3; double stepX = (transform.localScale.y / transform.localScale.x) / qx; double stepY = (transform.localScale.x / transform.localScale.y) / qy; double halfStepX = stepX*0.5; double halfStepY = stepY*0.5; Segment [,,] sides = new Segment[qx2,qy,6]; // 0 = left-up, 1 = top, 2 = right-up, 3 = right-down, 4 = down, 5 = left-down int c = -1; int subdivisions = goodGridCurvature > 0 ? 3: 1; for (int j=0;j<qy;j++) { for (int k=0;k<qx2;k++) { Point center = new Point((double)k/qx-0.5+halfStepX,(double)j/qy-0.5+halfStepY); center.x -= k * halfStepX/2; Cell cell = new Cell( (++c).ToString(), new Vector2((float)center.x, (float)center.y)); double offsetY = (k % 2==0) ? 0: -halfStepY; Segment leftUp = (k>0 && offsetY<0) ? sides[k-1, j, 3]: new Segment(center.Offset(-halfStepX, offsetY), center.Offset(-halfStepX/2, halfStepY + offsetY), k==0 || (j==qy-1 && offsetY==0)); sides[k, j, 0] = leftUp; Segment top = new Segment(center.Offset(-halfStepX/2, halfStepY + offsetY), center.Offset(halfStepX/2, halfStepY + offsetY), j==qy-1); sides[k, j, 1] = top; Segment rightUp = new Segment(center.Offset(halfStepX/2, halfStepY + offsetY), center.Offset(halfStepX, offsetY), k==qx2-1 || (j==qy-1 && offsetY==0)); sides[k, j, 2] = rightUp; Segment rightDown = (j > 0 && k<qx2-1 && offsetY<0) ? sides[k+1,j-1,0]: new Segment(center.Offset(halfStepX, offsetY), center.Offset(halfStepX/2, -halfStepY + offsetY), (j==0 && offsetY<0)|| k==qx2-1); sides[k, j, 3] = rightDown; Segment bottom = j>0 ? sides[k, j-1, 1] : new Segment(center.Offset(halfStepX/2, -halfStepY + offsetY), center.Offset(-halfStepX/2, -halfStepY +offsetY), true); sides[k, j, 4] = bottom; Segment leftDown; if (offsetY<0 && j>0) { leftDown = sides[k-1, j-1, 2]; } else if (offsetY==0 && k>0) { leftDown = sides[k-1, j, 2]; } else { leftDown = new Segment(center.Offset(-halfStepX/2, -halfStepY+offsetY), center.Offset(-halfStepX, offsetY), true); } sides[k, j, 5] = leftDown; if (j==0) { // leftDown.CropBottom(); // bottom.CropBottom(); // rightDown.CropBottom(); } if (k==qx2-1) { top.CropRight(); rightUp.CropRight(); rightDown.CropRight(); bottom.CropRight(); } Region cr = new Region (cell); if (subdivisions>1) { if (!top.deleted) cr.segments.AddRange (top.Subdivide(subdivisions, _gridCurvature)); if (!rightUp.deleted) cr.segments.AddRange (rightUp.Subdivide(subdivisions, _gridCurvature)); if (!rightDown.deleted) cr.segments.AddRange (rightDown.Subdivide(subdivisions, _gridCurvature)); if (!bottom.deleted) cr.segments.AddRange (bottom.Subdivide(subdivisions, _gridCurvature)); if (!leftDown.deleted) cr.segments.AddRange (leftDown.Subdivide(subdivisions, _gridCurvature)); if (!leftUp.deleted) cr.segments.AddRange (leftUp.Subdivide(subdivisions, _gridCurvature)); } else { if (!top.deleted) cr.segments.Add (top); if (!rightUp.deleted) cr.segments.Add (rightUp); if (!rightDown.deleted) cr.segments.Add (rightDown); if (!bottom.deleted) cr.segments.Add (bottom); if (!leftDown.deleted) cr.segments.Add (leftDown); if (!leftUp.deleted) cr.segments.Add (leftUp); } Connector connector = new Connector(); connector.AddRange(cr.segments); cr.polygon = connector.ToPolygon(); // FromLargestLineStrip(); if (cr.polygon!=null) { cell.region = cr; cells.Add (cell); } } } }
void SetupBoxGrid(bool strictQuads) { // Make cell regions: we assume cells have only 1 region but that can change in the future int l = _numCells; int qx, qy; int q = (int)(Math.Sqrt (l)); if (strictQuads) { qx=qy=q; } else { qx=l; qy=1; if (q<1) q=1; if ( (int)(q*q) != l) { // not squared if (!GetTwoFactors(l, out qx, out qy)) { // if number > 10 and it's prime, reduce by one so we can avoid ugly accordian grids if (l>10) GetTwoFactors(l-1, out qx, out qy); } } else { qx = qy = q; } } double stepX = (transform.localScale.y / transform.localScale.x) / qx; double stepY = (transform.localScale.x / transform.localScale.y) / qy; double halfStepX = stepX*0.5; double halfStepY = stepY*0.5; Segment [,,] sides = new Segment[qx,qy,4]; // 0 = left, 1 = top, 2 = right, 3 = bottom int c = -1; int subdivisions = goodGridCurvature > 0 ? 3: 1; for (int k=0;k<qx;k++) { for (int j=0;j<qy;j++) { Point center = new Point((double)k/qx-0.5+halfStepX,(double)j/qy-0.5+halfStepY); Cell cell = new Cell( (++c).ToString(), new Vector2((float)center.x, (float)center.y)); Segment left = k>0 ? sides[k-1, j, 2] : new Segment(center.Offset(-halfStepX, -halfStepY), center.Offset(-halfStepX, halfStepY), true); sides[k, j, 0] = left; Segment top = new Segment(center.Offset(-halfStepX, halfStepY), center.Offset(halfStepX, halfStepY), j==qy-1); sides[k, j, 1] = top; Segment right = new Segment(center.Offset(halfStepX, halfStepY), center.Offset(halfStepX, -halfStepY), k==qx-1); sides[k, j, 2] = right; Segment bottom = j>0 ? sides[k, j-1, 1] : new Segment(center.Offset(halfStepX, -halfStepY), center.Offset(-halfStepX, -halfStepY), true); sides[k, j, 3] = bottom; Region cr = new Region (cell); if (subdivisions>1) { cr.segments.AddRange (top.Subdivide(subdivisions, _gridCurvature)); cr.segments.AddRange (right.Subdivide(subdivisions, _gridCurvature)); cr.segments.AddRange (bottom.Subdivide(subdivisions, _gridCurvature)); cr.segments.AddRange (left.Subdivide(subdivisions, _gridCurvature)); } else { cr.segments.Add (top); cr.segments.Add (right); cr.segments.Add (bottom); cr.segments.Add (left); } Connector connector = new Connector(); connector.AddRange(cr.segments); cr.polygon = connector.ToPolygon(); // FromLargestLineStrip(); if (cr.polygon!=null) { cell.region = cr; cells.Add (cell); } } } }
void ProcessSegment(Segment segment, PolygonType polygonType) { if (Point.EqualsBoth(segment.start, segment.end)) return; SweepEvent e1 = new SweepEvent(segment.start, true, polygonType); SweepEvent e2 = new SweepEvent(segment.end, true, polygonType, e1); e1.otherSE = e2; if (e1.p.x < e2.p.x - Point.PRECISION ) { e2.isLeft = false; } else if (e1.p.x > e2.p.x + Point.PRECISION) { e1.isLeft = false; } else if (e1.p.y < e2.p.y - Point.PRECISION) { // the segment is vertical. The bottom endpoint is processed before the top endpoint e2.isLeft = false; } else { e1.isLeft = false; } // Pushing it so the que is sorted from left to right, with object on the left // having the highest priority. eventQueue.Enqueue(e1); eventQueue.Enqueue(e2); }
IntersectResult FindIntersection(Segment seg0, Segment seg1) { Point pi0 = Point.zero; Point pi1 = Point.zero; Point p0 = seg0.start; double d0x = seg0.end.x - p0.x; double d0y = seg0.end.y - p0.y; Point p1 = seg1.start; double d1x = seg1.end.x - p1.x; double d1y = seg1.end.y - p1.y; double Ex = p1.x - p0.x; double Ey = p1.y - p0.y; double kross = d0x * d1y - d0y * d1x; if (kross > Point.PRECISION || kross < -Point.PRECISION) { //sqrEpsilon) { // * sqrLen0 * sqrLen1) { // lines of the segments are not parallel double s = (Ex * d1y - Ey * d1x) / kross; if (s < 0 || s > 1) { return new IntersectResult (max: 0, point1: pi0, point2: pi1); } double t = (Ex * d0y - Ey * d0x) / kross; if (t < 0 || t > 1) { return new IntersectResult (max: 0, point1: pi0, point2: pi1); } // intersection of lines is a point an each segment pi0.x = p0.x + s * d0x; pi0.y = p0.y + s * d0y; return new IntersectResult ( max: 1, point1: pi0, point2: pi1 ); } // lines of the segments are parallel kross = Ex * d0y - Ey * d0x; if (kross > Point.PRECISION || kross < -Point.PRECISION) { // sqrEpsilon ) { //* sqrLen0 * sqrLenE) { // lines of the segment are different return new IntersectResult ( max: 0, point1: pi0, point2: pi1 ); } // Lines of the segments are the same. Need to test for overlap of segments. double sqrLen0 = Math.Sqrt (d0x*d0x+d0y*d0y); // d0.magnitude; double s0 = (d0x * Ex + d0y * Ey) / sqrLen0; // so = Dot (D0, E) * sqrLen0 double s1 = s0 + (d0x * d1x + d0y * d1y) / sqrLen0; // s1 = s0 + Dot (D0, D1) * sqrLen0 double smin = Math.Min(s0, s1); double smax = Math.Max(s0, s1); double[] w = new double[2]; int imax = FindIntersection2(0, 1, smin, smax, w); if (imax > 0) { pi0.x = p0.x + w[0] * d0x; pi0.y = p0.y + w[0] * d0y; if (imax > 1) { pi1.x = p0.x + w[1] * d0x; pi1.y = p0.y + w[1] * d0y; } } return new IntersectResult (max: imax, point1: pi0, point2: pi1); }