public ISurface AdaptToCurves(IEnumerable <ICurve> curves) { BoundingRect domain = BoundingRect.EmptyBoundingRect; foreach (ICurve curve in curves) { ICurve2D c2d = periodicSurface.GetProjectedCurve(curve, 0.0); if (domain.IsEmpty()) { domain = c2d.GetExtent(); } else { SurfaceHelper.AdjustPeriodic(periodicSurface, domain, c2d); domain.MinMax(c2d.GetExtent()); } } return(new NonPeriodicSurface(periodicSurface, domain)); }
/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.Intersect (ICurve, BoundingRect, out GeoPoint[], out GeoPoint2D[], out double[])"/> /// </summary> /// <param name="curve"></param> /// <param name="uvExtent"></param> /// <param name="ips"></param> /// <param name="uvOnFaces"></param> /// <param name="uOnCurve3Ds"></param> public override void Intersect(ICurve curve, BoundingRect uvExtent, out GeoPoint[] ips, out GeoPoint2D[] uvOnFaces, out double[] uOnCurve3Ds) { if (curve is Line) { GeoPoint ip; if (Plane.Intersect(curve.StartPoint, curve.StartDirection, out ip)) { ips = new GeoPoint[] { ip }; uvOnFaces = new GeoPoint2D[] { PositionOf(ip) }; uOnCurve3Ds = new double[] { curve.PositionOf(ip) }; } else { ips = new GeoPoint[0]; uvOnFaces = new GeoPoint2D[0]; uOnCurve3Ds = new double[0]; } #if DEBUG //GeoPoint[] ipsdbg; //GeoPoint2D[] uvOnFacesdbg; //double[] uOnCurve3Dsdbg; //base.Intersect(curve, out ipsdbg, out uvOnFacesdbg, out uOnCurve3Dsdbg); #endif return; } //else if (curve is IExplicitPCurve3D) //{ // ExplicitPCurve3D epc3d = (curve as IExplicitPCurve3D).GetExplicitPCurve3D(); // double [] res = epc3d.GetPlaneIntersection(Location, DirectionX, DirectionY); // for (int i = 0; i < res.Length; i++) // { // double d = Plane.Distance(epc3d.PointAt(res[i])); // if (i>0) d = Plane.Distance(epc3d.PointAt((res[i]+res[i-1])/2.0)); // } // double dd = Plane.Distance(epc3d.PointAt(epc3d.knots[epc3d.knots.Length - 1])); // for (int i = 0; i < res.Length; i++) // { // res[i] = (res[i] - epc3d.knots[0]) / (epc3d.knots[epc3d.knots.Length - 1] - epc3d.knots[0]); // } //} else { if (curve.GetPlanarState() == PlanarState.Planar) { GeoPoint loc; GeoVector dir; Plane pln = curve.GetPlane(); if (Plane.Intersect(curve.GetPlane(), out loc, out dir)) { ICurve2D c2d = curve.GetProjectedCurve(pln); BoundingRect ext = c2d.GetExtent(); ext.Inflate(ext.Height + ext.Width); // sonst entstehen null-Linien ICurve2D ll = new Line2D(pln.Project(loc), pln.Project(dir), ext); #if DEBUG DebuggerContainer dc = new DebuggerContainer(); dc.Add(c2d); dc.Add(ll); #endif GeoPoint2DWithParameter[] gpp = ll.Intersect(c2d); ips = new GeoPoint[gpp.Length]; uvOnFaces = new GeoPoint2D[gpp.Length]; uOnCurve3Ds = new double[gpp.Length]; for (int i = 0; i < gpp.Length; ++i) { ips[i] = pln.ToGlobal(gpp[i].p); uvOnFaces[i] = PositionOf(ips[i]); uOnCurve3Ds[i] = curve.PositionOf(ips[i]); } } else { ips = new GeoPoint[0]; uvOnFaces = new GeoPoint2D[0]; uOnCurve3Ds = new double[0]; } #if DEBUG //GeoPoint[] ipsdbg; //GeoPoint2D[] uvOnFacesdbg; //double[] uOnCurve3Dsdbg; //base.Intersect(curve, out ipsdbg, out uvOnFacesdbg, out uOnCurve3Dsdbg); #endif return; } } TetraederHull th = new TetraederHull(curve); // alle Kurven müssten eine gemeinsame basis habe, auf die man sich hier beziehen kann // damit die TetraederHull nicht mehrfach berechnet werden muss th.PlaneIntersection(this, out ips, out uvOnFaces, out uOnCurve3Ds); // base.Intersect(curve, out ips, out uvOnFaces, out uOnCurve3Ds); }
static public CurveGraph CrackCurves(GeoObjectList l, Plane plane, double maxGap) { // alle Kurven in l werden in die Ebene plane projiziert. Das ist mal ein erster Ansatz // Man könnte auch gemeinsame Ebenen finden u.s.w. ArrayList curves = new ArrayList(); BoundingRect ext = BoundingRect.EmptyBoundingRect; foreach (IGeoObject go in l) { ICurve cv = go as ICurve; if (cv != null) { ICurve2D cv2 = cv.GetProjectedCurve(plane); if (cv2 != null) { // "3d" wird nur verwendet um hinterher aus den Originalkurven die Ebene zu bestimmen // in die alles zurücktranformiert wird. Besser würde man vermutlich mit "plane" arbeiten // so wie es hier reinkommt. if (cv2 is Path2D && (cv2 as Path2D).GetSelfIntersections().Length > 0) { // ein sich selbst überschneidender Pfad muss aufgelöst werden ICurve2D[] sub = (cv2 as Path2D).SubCurves; curves.AddRange(sub); for (int i = 0; i < sub.Length; ++i) { sub[i].UserData.Add("3d", cv); } ext.MinMax(cv2.GetExtent()); } else { cv2.UserData.Add("3d", cv); curves.Add(cv2); ext.MinMax(cv2.GetExtent()); } } } } if (curves.Count == 0) { return(null); } QuadTree qt = new QuadTree(ext); qt.MaxDeepth = 8; qt.MaxListLen = 3; for (int i = 0; i < curves.Count; ++i) { qt.AddObject(curves[i] as ICurve2D); } // jetzt alle mit allen schneiden und die Schnipsel in eine weitere Liste stecken ArrayList snippet = new ArrayList(); for (int i = 0; i < curves.Count; ++i) { ICurve2D cv1 = curves[i] as ICurve2D; ArrayList intersectionPoints = new ArrayList(); // double ICollection closecurves = qt.GetObjectsCloseTo(cv1); foreach (ICurve2D cv2 in closecurves) { if (cv2 != cv1) { //if ((cv1 is Line2D && (cv1 as Line2D).Length > 10 && (cv1 as Line2D).Length < 15) || // (cv2 is Line2D && (cv2 as Line2D).Length > 10 && (cv2 as Line2D).Length < 15)) //{ //} GeoPoint2DWithParameter[] isp = cv1.Intersect(cv2); for (int k = 0; k < isp.Length; ++k) { if (cv2.IsParameterOnCurve(isp[k].par2) && 0.0 < isp[k].par1 && isp[k].par1 < 1.0) { intersectionPoints.Add(isp[k].par1); } } } } if (intersectionPoints.Count == 0) { snippet.Add(cv1); } else { intersectionPoints.Add(0.0); intersectionPoints.Add(1.0); // damit sinds mindesten 3 double[] pps = (double[])intersectionPoints.ToArray(typeof(double)); Array.Sort(pps); for (int ii = 1; ii < pps.Length; ++ii) { if (pps[ii - 1] < pps[ii]) { ICurve2D cv3 = cv1.Trim(pps[ii - 1], pps[ii]); if (cv3 != null) { #if DEBUG GeoPoint2D dbg1 = cv1.PointAt(pps[ii - 1]); GeoPoint2D dbg2 = cv1.PointAt(pps[ii]); GeoPoint2D dbg3 = cv3.StartPoint; GeoPoint2D dbg4 = cv3.EndPoint; double d1 = dbg1 | dbg3; double d2 = dbg2 | dbg4; #endif cv3.UserData.Add("3d", cv1.UserData.GetData("3d")); snippet.Add(cv3); } } } } } // snippet ist jetzt die Liste aller Schnipsel return(new CurveGraph((ICurve2D[])snippet.ToArray(typeof(ICurve2D)), maxGap)); }
/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.Orientation (GeoPoint)"/> /// </summary> /// <param name="p"></param> /// <returns></returns> public override double Orientation(GeoPoint p) { // soll vermutlich feststellen ob außerhalb oder innerhalb der Fläche im Bezug auf die Achse // Richards code verwendet das aufwendige GetLineIntersection. // Hier die bessere Version, die das Problem ins zweidimensionale projiziert: GeoPoint up = fromSurface * p; double x = Math.Sqrt(up.z * up.z + up.x * up.x); double y = up.y; GeoPoint2D toCeck = new GeoPoint2D(x, y); BoundingRect ext = basisCurve2D.GetExtent(); GeoPoint2D sp, ep; if (ext.Left > 0) { sp = new GeoPoint2D(ext.Left, y); ep = new GeoPoint2D(ext.Right, y); } else { sp = new GeoPoint2D(ext.Right, y); ep = new GeoPoint2D(ext.Left, y); } GeoPoint2DWithParameter[] isp = basisCurve2D.Intersect(sp, ep); // muss die Kurve immer rechts von der Achse liegen? Durch sp und ep sid wir davon unabhängig, es sei denn die Kurve schneidet die Achse SortedList <double, GeoPoint2D> par = new SortedList <double, GeoPoint2D>(); for (int i = 0; i < isp.Length; ++i) { if (isp[i].par2 >= 0.0 && isp[i].par2 <= 1.0 && isp[i].par1 >= 0.0 && isp[i].par1 <= 1.0) { // nur wenn echter Schnitt par[isp[i].par2] = isp[i].p; // nach Position auf der horizontalen Linie } } if (par.Count == 0) { return(0.0); // Seite kann nicht bestimmt werden, da völlig außerhalb. Das Vorzeichen von 0.0 } // ist aber verschieden von +1 und von -1, so dass wenn es andere konkrete Punkte gibt also ein Test gemacht wird double ppar = Geometry.LinePar(sp, ep, toCeck); for (int i = 0; i < par.Count; ++i) { if (ppar < par.Keys[i]) { if ((i & 1) == 0) // gerade, also innerhalb { return(-(toCeck | par.Values[i])); // innerhalb ist negativ } else { return(toCeck | par.Values[i]); // außerhalb positiv } } } // größer als alle if ((par.Count & 1) == 1) // ungerade, also letzer Punkt innerhalb { return(toCeck | par.Values[par.Count - 1]); // außerhalb positiv } else { return(-(toCeck | par.Values[par.Count - 1])); // innerhalb ist negativ } // Richards code: //GeoPoint gp = fromSurface * p; //double d = gp.y; //double e = Math.Abs(d); //GeoPoint ac = new GeoPoint(0, d, 0); //GeoPoint2D[] sp = GetLineIntersection(p, toSurface * (ac - gp)); //int n = 0; //for (int i = 0; i < sp.Length; ++i) //{ // double ds = (sp[i] - GeoPoint2D.Origin).Length - e; // if (Math.Abs(ds) > Precision.eps) // { // if (ds < 0) // n++; // } // else return 0; //} //if (n % 4 == 2) // return (-e); //else // return e; }