private static double SolveLineFactorT(double[] N, double[] pe, double[] p0, double[] pdiff, out LineClipType type) { double dominator = N[0] * pdiff[0] + N[1] * pdiff[1]; if (dominator < 0.0) { type = LineClipType.entering; } else { type = LineClipType.leaving; } if (dominator == 0.0) { return(1e10); // paralell lines... } return((N[0] * (pe[0] - p0[0]) + N[1] * (pe[1] - p0[1])) / dominator); }
private static IPoint[] LiamBarsky(IEnvelope envelope, IPoint p1, IPoint p2, out LineClipType type) { IPoint[] points = new Point[2]; int code1 = CalculateLRBT(envelope, p1); int code2 = CalculateLRBT(envelope, p2); type = LineClipType.inside; if (code1 == 0 && code2 == 0) { points[0] = p1; points[1] = p2; return(points); } if ((code1 & code2) != 0) { type = LineClipType.outside; return(null); } double[] pdiff = { p2.X - p1.X, p2.Y - p1.Y }; double[] p0 = { p1.X, p1.Y }; double tpe = 1e10; //0.0; double tpl = 1e10; //1.0; for (int edge = 0; edge < 4; edge++) { double[] N = new double[2]; double[] pe = new double[2]; switch (edge) { case 0: N[0] = -1.0; N[1] = 0.0; pe[0] = envelope.minx; pe[1] = 0.0; break; case 1: N[0] = 0.0; N[1] = -1.0; pe[0] = 0.0; pe[1] = envelope.miny; break; case 2: N[0] = 1.0; N[1] = 0.0; pe[0] = envelope.maxx; pe[1] = 0.0; break; case 3: N[0] = 0.0; N[1] = 1.0; pe[0] = 0.0; pe[1] = envelope.maxy; break; } double t = SolveLineFactorT(N, pe, p0, pdiff, out type); if (t >= 0 && t <= 1.0) { if (type == LineClipType.entering && (t > tpe || tpe == 1e10)) { tpe = t; } else if (type == LineClipType.leaving && (t < tpl || tpl == 1e10)) { tpl = t; } } } if (tpe == 1e10 && tpl == 1e10) { type = LineClipType.outside; return(null); } double tpe_ = (tpe != 1e10) ? tpe : 0.0; double tpl_ = (tpl != 1e10) ? tpl : 1.0; points[0] = new Point(p1.X + tpe_ * pdiff[0], p1.Y + tpe_ * pdiff[1]); points[1] = new Point(p1.X + tpl_ * pdiff[0], p1.Y + tpl_ * pdiff[1]); code1 = CalculateLRBT(envelope, points[0]); code2 = CalculateLRBT(envelope, points[0]); if (code1 != 0 || code2 != 0) { type = LineClipType.outside; return(null); } if (tpl_ < 1.0) { type = LineClipType.leaving; return(points); } else if (tpe_ > 0.0) { type = LineClipType.entering; return(points); } return(null); }