bool GetArrowHead(On2dVector dir, On2dPoint tip, double scale, ref On3dPointArray triangle) { double arrow_size = m_default_arrow_size * scale; On2dPointArray corners = new On2dPointArray(); corners.Reserve(3); corners.SetCount(3); On2dVector up = new On2dVector(-dir.y, dir.x); corners[0].Set(tip.x, tip.y); corners[1].x = tip.x + arrow_size * (0.25 * up.x - dir.x); corners[1].y = tip.y + arrow_size * (0.25 * up.y - dir.y); corners[2].x = corners[1].x - 0.5 * arrow_size * up.x; corners[2].y = corners[1].y - 0.5 * arrow_size * up.y; triangle.Reserve(corners.Count()); triangle.SetCount(corners.Count()); for (int i = 0; i < corners.Count(); i++) { triangle[i] = m_plane.PointAt(corners[i].x, corners[i].y); } return(true); }
private static OnCurve CreateOuterTrimmingCurve( OnSurface s, int side // 0 = SW to SE // 1 = SE to NE // 2 = NE to NW // 3 = NW to SW ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An outer trimming loop consists of a simple closed curve running // counter-clockwise around the region it trims. //In cases when trim curve is not easily defined in surface domain, //use ON_Surface::Pullback only be careful about curve direction to ensure //loop trims run anti-clockwise for outer loop and clockwise for inner loop. //In this case, trim curves lie on the four edges of the surface On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = double.NaN, u1 = double.NaN, v0 = double.NaN, v1 = double.NaN; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); switch (side) { case 0: // SW to SE from.x = u0; from.y = v0; to.x = u1; to.y = v0; break; case 1: // SE to NE from.x = u1; from.y = v0; to.x = u1; to.y = v1; break; case 2: // NE to NW from.x = u1; from.y = v1; to.x = u0; to.y = v1; break; case 3: // NW to SW from.x = u0; from.y = v1; to.x = u0; to.y = v0; break; default: return(null); } OnCurve c2d = new OnLineCurve(from, to); if (c2d != null) { c2d.SetDomain(0.0, 1.0); } return(c2d); }
/// <summary> /// TwistedCubeTrimmingCurve /// </summary> static OnCurve TwistedCubeTrimmingCurve( IOnSurface s, int side // 0 = SW to SE // 1 = SE to NE // 2 = NE to NW // 3 = NW to SW ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An outer trimming loop consists of a simple closed curve running // counter-clockwise around the region it trims. On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = 0.0, u1 = 0.0, v0 = 0.0, v1 = 0.0; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); switch (side) { case 0: // SW to SE from.x = u0; from.y = v0; to.x = u1; to.y = v0; break; case 1: // SE to NE from.x = u1; from.y = v0; to.x = u1; to.y = v1; break; case 2: // NE to NW from.x = u1; from.y = v1; to.x = u0; to.y = v1; break; case 3: // NW to SW from.x = u0; from.y = v1; to.x = u0; to.y = v0; break; default: return(null); } OnLineCurve c2d = new OnLineCurve(from, to); c2d.SetDomain(0.0, 1.0); return(c2d); }
private static OnCurve CreateTrimmingCurve( OnSurface s, int side // 0 = SW to SE // 1 = SE to NE // 2 = NE to NW // 3 = NW to SW ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An outer trimming loop consists of a simple closed curve running // counter-clockwise around the region it trims. // An inner trimming loop consists of a simple closed curve running // clockwise around the region the hole. On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = double.NaN, u1 = double.NaN, v0 = double.NaN, v1 = double.NaN; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); switch (side) { case 0: // SW to SE from.x = u0; from.y = v0; to.x = u1; to.y = v0; break; case 1: // diagonal from.x = u1; from.y = v0; to.x = (u0 + u1) / 2; to.y = v1; break; case 2: // diagonal from.x = (u0 + u1) / 2; from.y = v1; to.x = u0; to.y = v0; break; default: return(null); } OnCurve c2d = new OnLineCurve(from, to); if (c2d != null) { c2d.SetDomain(0.0, 1.0); } return(c2d); }
/// <summary> /// Public constructor /// </summary> public SampleCsDrawArrowheadConduit(OnPlane plane, OnLine line, double scale) : base(new MSupportChannels(MSupportChannels.SC_CALCBOUNDINGBOX | MSupportChannels.SC_DRAWOVERLAY), false) { m_bDraw = false; m_plane = plane; m_line = line; m_arrowhead = new On3dPointArray(); double x = 0, y = 0; m_plane.ClosestPointTo(line.from, ref x, ref y); On2dPoint from = new On2dPoint(x, y); m_plane.ClosestPointTo(line.to, ref x, ref y); On2dPoint to = new On2dPoint(x, y); On2dVector dir = new On2dVector(from - to); dir.Unitize(); m_bDraw = GetArrowHead(dir, from, scale, ref m_arrowhead); }
bool GetArrowHead(On2dVector dir, On2dPoint tip, double scale, ref On3dPointArray triangle) { double arrow_size = m_default_arrow_size * scale; On2dPointArray corners = new On2dPointArray(); corners.Reserve(3); corners.SetCount(3); On2dVector up = new On2dVector(-dir.y, dir.x); corners[0].Set(tip.x, tip.y); corners[1].x = tip.x + arrow_size * (0.25 * up.x - dir.x); corners[1].y = tip.y + arrow_size * (0.25 * up.y - dir.y); corners[2].x = corners[1].x - 0.5 * arrow_size * up.x; corners[2].y = corners[1].y - 0.5 * arrow_size * up.y; triangle.Reserve(corners.Count()); triangle.SetCount(corners.Count()); for (int i = 0; i < corners.Count(); i++) triangle[i] = m_plane.PointAt(corners[i].x, corners[i].y); return true; }
/// <summary> /// TwistedCubeTrimmingCurve /// </summary> static OnCurve TwistedCubeTrimmingCurve( IOnSurface s, int side // 0 = SW to SE // 1 = SE to NE // 2 = NE to NW // 3 = NW to SW ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An outer trimming loop consists of a simple closed curve running // counter-clockwise around the region it trims. On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = 0.0, u1 = 0.0, v0 = 0.0, v1 = 0.0; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); switch (side) { case 0: // SW to SE from.x = u0; from.y = v0; to.x = u1; to.y = v0; break; case 1: // SE to NE from.x = u1; from.y = v0; to.x = u1; to.y = v1; break; case 2: // NE to NW from.x = u1; from.y = v1; to.x = u0; to.y = v1; break; case 3: // NW to SW from.x = u0; from.y = v1; to.x = u0; to.y = v0; break; default: return null; } OnLineCurve c2d = new OnLineCurve(from, to); c2d.SetDomain(0.0, 1.0); return c2d; }
private static OnCurve CreateOuterTrimmingCurve( OnSurface s, int side // 0 = SW to SE // 1 = SE to NE // 2 = NE to NW // 3 = NW to SW ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An outer trimming loop consists of a simple closed curve running // counter-clockwise around the region it trims. //In cases when trim curve is not easily defined in surface domain, //use ON_Surface::Pullback only be careful about curve direction to ensure //loop trims run anti-clockwise for outer loop and clockwise for inner loop. //In this case, trim curves lie on the four edges of the surface On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = double.NaN, u1 = double.NaN, v0 = double.NaN, v1 = double.NaN; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); switch (side) { case 0: // SW to SE from.x = u0; from.y = v0; to.x = u1; to.y = v0; break; case 1: // SE to NE from.x = u1; from.y = v0; to.x = u1; to.y = v1; break; case 2: // NE to NW from.x = u1; from.y = v1; to.x = u0; to.y = v1; break; case 3: // NW to SW from.x = u0; from.y = v1; to.x = u0; to.y = v0; break; default: return null; } OnCurve c2d = new OnLineCurve(from, to); if (c2d != null) c2d.SetDomain(0.0, 1.0); return c2d; }
//Trim curves must run is clockwise direction private static OnCurve CreateInnerTrimmingCurve( OnSurface s, int side // 0 = near SE to SW // 1 = near SW to NW // 2 = near NW to NE // 3 = near NE to SE ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An inner trimming loop consists of a simple closed curve running // clockwise around the region the hole. //In this case, trim curves lie with 0.2 domain distance from surface edge On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = double.NaN, u1 = double.NaN, v0 = double.NaN, v1 = double.NaN; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); double udis = 0.2 * (u1 - u0); double vdis = 0.2 * (v1 - v0); u0 += udis; u1 -= udis; v0 += vdis; v1 -= vdis; switch (side) { case 0: // near SE to SW from.x = u1; from.y = v0; to.x = u0; to.y = v0; break; case 1: // near SW to NW from.x = u0; from.y = v0; to.x = u0; to.y = v1; break; case 2: // near NW to NE from.x = u0; from.y = v1; to.x = u1; to.y = v1; break; case 3: // near NE to SE from.x = u1; from.y = v1; to.x = u1; to.y = v0; break; default: return null; } OnCurve c2d = new OnLineCurve(from, to); if (c2d != null) c2d.SetDomain(0.0, 1.0); return c2d; }
/// <summary> /// The one and only MakeBox /// </summary> static OnBrep MakeBox() { /* This example demonstrates how to construct a OnBrep with the topology shown below. v7_______e6_____v6 |\ |\ | e7 | e5 | \ ______e4_____\ e11 v4 | v5 | | e10 | | | | | v3---|---e2----v2 e9 \ e8 \ | e3 | e1 | \ | \ | \v0_____e0_____\v1 */ On3dPoint[] points = new On3dPoint[8]; points[0] = new On3dPoint(0.0, 0.0, 0.0); points[1] = new On3dPoint(10.0, 0.0, 0.0); points[2] = new On3dPoint(10.0, 10.0, 0.0); points[3] = new On3dPoint(0.0, 10.0, 0.0); points[4] = new On3dPoint(0.0, 0.0, 10.0); points[5] = new On3dPoint(10.0, 0.0, 10.0); points[6] = new On3dPoint(10.0, 10.0, 10.0); points[7] = new On3dPoint(0.0, 10.0, 10.0); OnBrep brep = new OnBrep(); int vi = 0, ei = 0, fi = 0, si = 0, c2i = 0; for (vi = 0; vi < 8; vi++) brep.NewVertex(points[vi], 0.0); for (ei = 0; ei < 4; ei++) { OnBrepVertex v0 = brep.m_V[ei]; OnBrepVertex v1 = brep.m_V[(ei + 1) % 4]; brep.m_C3.Append(new OnLineCurve(v0.point, v1.point)); brep.NewEdge(ref v0, ref v1, ei, null, 0.0); } for (ei = 4; ei < 8; ei++) { OnBrepVertex v0 = brep.m_V[ei]; OnBrepVertex v1 = brep.m_V[ei == 7 ? 4 : (ei + 1)]; brep.m_C3.Append(new OnLineCurve(v0.point, v1.point)); brep.NewEdge(ref v0, ref v1, ei, null, 0.0); } for (ei = 8; ei < 12; ei++) { OnBrepVertex v0 = brep.m_V[ei - 8]; OnBrepVertex v1 = brep.m_V[ei - 4]; brep.m_C3.Append(new OnLineCurve(v0.point, v1.point)); brep.NewEdge(ref v0, ref v1, ei, null, 0.0); } OnBrepBoxFaceInfo[] f = new OnBrepBoxFaceInfo[6]; f[0] = new OnBrepBoxFaceInfo(0, 9, 4, 8, false, false, true, true); f[1] = new OnBrepBoxFaceInfo(1, 10, 5, 9, false, false, true, true); f[2] = new OnBrepBoxFaceInfo(2, 11, 6, 10, false, false, true, true); f[3] = new OnBrepBoxFaceInfo(3, 8, 7, 11, false, false, true, true); f[4] = new OnBrepBoxFaceInfo(3, 2, 1, 0, true, true, true, true); f[5] = new OnBrepBoxFaceInfo(4, 5, 6, 7, false, false, false, false); for (fi = 0; fi < 6; fi++ ) { OnBrepEdge e0 = brep.m_E[f[fi].e[0]]; OnBrepEdge e1 = brep.m_E[f[fi].e[1]]; OnBrepEdge e2 = brep.m_E[f[fi].e[2]]; OnBrepEdge e3 = brep.m_E[f[fi].e[3]]; OnBrepVertex v0 = brep.m_V[e0.get_m_vi(f[fi].bRev[0] ? 1 : 0)]; OnBrepVertex v1 = brep.m_V[e1.get_m_vi(f[fi].bRev[1] ? 1 : 0)]; OnBrepVertex v2 = brep.m_V[e2.get_m_vi(f[fi].bRev[2] ? 1 : 0)]; OnBrepVertex v3 = brep.m_V[e3.get_m_vi(f[fi].bRev[3] ? 1 : 0)]; si = brep.AddSurface(OnUtil.ON_NurbsSurfaceQuadrilateral(v0.point, v1.point, v2.point, v3.point)); OnInterval s = brep.m_S[si].Domain(0); OnInterval t = brep.m_S[si].Domain(1); On2dPoint p0 = new On2dPoint(s[0], t[0]); On2dPoint p1 = new On2dPoint(s[1], t[0]); On2dPoint p2 = new On2dPoint(s[1], t[1]); On2dPoint p3 = new On2dPoint(s[0], t[1]); OnBrepFace face = brep.NewFace(si); OnBrepLoop loop = brep.NewLoop(IOnBrepLoop.TYPE.outer, ref face); loop.m_pbox.m_min.x = s[0]; loop.m_pbox.m_min.y = t[0]; loop.m_pbox.m_min.z = 0.0; loop.m_pbox.m_max.x = s[1]; loop.m_pbox.m_max.y = t[1]; loop.m_pbox.m_max.z = 0.0; // south side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p0, p1)); OnBrepTrim trim0 = brep.NewTrim(ref e0, f[fi].bRev[0], ref loop, c2i); trim0.set_m_tolerance(0, 0.0); trim0.set_m_tolerance(1, 0.0); trim0.m_type = (trim0.get_m_vi(0) != trim0.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim0.m_iso = IOnSurface.ISO.S_iso; // east side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p1, p2)); OnBrepTrim trim1 = brep.NewTrim(ref e1, f[fi].bRev[1], ref loop, c2i); trim1.set_m_tolerance(0, 0.0); trim1.set_m_tolerance(1, 0.0); trim1.m_type = (trim1.get_m_vi(0) != trim1.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim1.m_iso = IOnSurface.ISO.E_iso; // north side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p2, p3)); OnBrepTrim trim2 = brep.NewTrim(ref e2, f[fi].bRev[2], ref loop, c2i); trim2.set_m_tolerance(0, 0.0); trim2.set_m_tolerance(1, 0.0); trim2.m_type = (trim2.get_m_vi(0) != trim2.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim2.m_iso = IOnSurface.ISO.N_iso; // west side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p3, p0)); OnBrepTrim trim3 = brep.NewTrim(ref e3, f[fi].bRev[3], ref loop, c2i); trim3.set_m_tolerance(0, 0.0); trim3.set_m_tolerance(1, 0.0); trim3.m_type = (trim3.get_m_vi(0) != trim3.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim3.m_iso = IOnSurface.ISO.W_iso; } if (!brep.IsValid()) return null; return brep; }
/// <summary> /// The one and only MakeBox /// </summary> static OnBrep MakeBox() { /* * This example demonstrates how to construct a OnBrep * with the topology shown below. * * v7_______e6_____v6 |\ |\ | e7 | e5 | \ ______e4_____\ | e11 v4 | v5 | | e10 | | | | | | v3---|---e2----v2 e9 \ e8 \ | \ e3 | e1 | \ | \ | \ \v0_____e0_____\v1 \ */ On3dPoint[] points = new On3dPoint[8]; points[0] = new On3dPoint(0.0, 0.0, 0.0); points[1] = new On3dPoint(10.0, 0.0, 0.0); points[2] = new On3dPoint(10.0, 10.0, 0.0); points[3] = new On3dPoint(0.0, 10.0, 0.0); points[4] = new On3dPoint(0.0, 0.0, 10.0); points[5] = new On3dPoint(10.0, 0.0, 10.0); points[6] = new On3dPoint(10.0, 10.0, 10.0); points[7] = new On3dPoint(0.0, 10.0, 10.0); OnBrep brep = new OnBrep(); int vi = 0, ei = 0, fi = 0, si = 0, c2i = 0; for (vi = 0; vi < 8; vi++) { brep.NewVertex(points[vi], 0.0); } for (ei = 0; ei < 4; ei++) { OnBrepVertex v0 = brep.m_V[ei]; OnBrepVertex v1 = brep.m_V[(ei + 1) % 4]; brep.m_C3.Append(new OnLineCurve(v0.point, v1.point)); brep.NewEdge(ref v0, ref v1, ei, null, 0.0); } for (ei = 4; ei < 8; ei++) { OnBrepVertex v0 = brep.m_V[ei]; OnBrepVertex v1 = brep.m_V[ei == 7 ? 4 : (ei + 1)]; brep.m_C3.Append(new OnLineCurve(v0.point, v1.point)); brep.NewEdge(ref v0, ref v1, ei, null, 0.0); } for (ei = 8; ei < 12; ei++) { OnBrepVertex v0 = brep.m_V[ei - 8]; OnBrepVertex v1 = brep.m_V[ei - 4]; brep.m_C3.Append(new OnLineCurve(v0.point, v1.point)); brep.NewEdge(ref v0, ref v1, ei, null, 0.0); } OnBrepBoxFaceInfo[] f = new OnBrepBoxFaceInfo[6]; f[0] = new OnBrepBoxFaceInfo(0, 9, 4, 8, false, false, true, true); f[1] = new OnBrepBoxFaceInfo(1, 10, 5, 9, false, false, true, true); f[2] = new OnBrepBoxFaceInfo(2, 11, 6, 10, false, false, true, true); f[3] = new OnBrepBoxFaceInfo(3, 8, 7, 11, false, false, true, true); f[4] = new OnBrepBoxFaceInfo(3, 2, 1, 0, true, true, true, true); f[5] = new OnBrepBoxFaceInfo(4, 5, 6, 7, false, false, false, false); for (fi = 0; fi < 6; fi++) { OnBrepEdge e0 = brep.m_E[f[fi].e[0]]; OnBrepEdge e1 = brep.m_E[f[fi].e[1]]; OnBrepEdge e2 = brep.m_E[f[fi].e[2]]; OnBrepEdge e3 = brep.m_E[f[fi].e[3]]; OnBrepVertex v0 = brep.m_V[e0.get_m_vi(f[fi].bRev[0] ? 1 : 0)]; OnBrepVertex v1 = brep.m_V[e1.get_m_vi(f[fi].bRev[1] ? 1 : 0)]; OnBrepVertex v2 = brep.m_V[e2.get_m_vi(f[fi].bRev[2] ? 1 : 0)]; OnBrepVertex v3 = brep.m_V[e3.get_m_vi(f[fi].bRev[3] ? 1 : 0)]; si = brep.AddSurface(OnUtil.ON_NurbsSurfaceQuadrilateral(v0.point, v1.point, v2.point, v3.point)); OnInterval s = brep.m_S[si].Domain(0); OnInterval t = brep.m_S[si].Domain(1); On2dPoint p0 = new On2dPoint(s[0], t[0]); On2dPoint p1 = new On2dPoint(s[1], t[0]); On2dPoint p2 = new On2dPoint(s[1], t[1]); On2dPoint p3 = new On2dPoint(s[0], t[1]); OnBrepFace face = brep.NewFace(si); OnBrepLoop loop = brep.NewLoop(IOnBrepLoop.TYPE.outer, ref face); loop.m_pbox.m_min.x = s[0]; loop.m_pbox.m_min.y = t[0]; loop.m_pbox.m_min.z = 0.0; loop.m_pbox.m_max.x = s[1]; loop.m_pbox.m_max.y = t[1]; loop.m_pbox.m_max.z = 0.0; // south side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p0, p1)); OnBrepTrim trim0 = brep.NewTrim(ref e0, f[fi].bRev[0], ref loop, c2i); trim0.set_m_tolerance(0, 0.0); trim0.set_m_tolerance(1, 0.0); trim0.m_type = (trim0.get_m_vi(0) != trim0.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim0.m_iso = IOnSurface.ISO.S_iso; // east side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p1, p2)); OnBrepTrim trim1 = brep.NewTrim(ref e1, f[fi].bRev[1], ref loop, c2i); trim1.set_m_tolerance(0, 0.0); trim1.set_m_tolerance(1, 0.0); trim1.m_type = (trim1.get_m_vi(0) != trim1.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim1.m_iso = IOnSurface.ISO.E_iso; // north side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p2, p3)); OnBrepTrim trim2 = brep.NewTrim(ref e2, f[fi].bRev[2], ref loop, c2i); trim2.set_m_tolerance(0, 0.0); trim2.set_m_tolerance(1, 0.0); trim2.m_type = (trim2.get_m_vi(0) != trim2.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim2.m_iso = IOnSurface.ISO.N_iso; // west side of surface c2i = brep.AddTrimCurve(new OnLineCurve(p3, p0)); OnBrepTrim trim3 = brep.NewTrim(ref e3, f[fi].bRev[3], ref loop, c2i); trim3.set_m_tolerance(0, 0.0); trim3.set_m_tolerance(1, 0.0); trim3.m_type = (trim3.get_m_vi(0) != trim3.get_m_vi(1)) ? IOnBrepTrim.TYPE.mated : IOnBrepTrim.TYPE.singular; trim3.m_iso = IOnSurface.ISO.W_iso; } if (!brep.IsValid()) { return(null); } return(brep); }
//Trim curves must run is clockwise direction private static OnCurve CreateInnerTrimmingCurve( OnSurface s, int side // 0 = near SE to SW // 1 = near SW to NW // 2 = near NW to NE // 3 = near NE to SE ) { // A trimming curve is a 2d curve whose image lies in the surface's domain. // The "active" portion of the surface is to the left of the trimming curve. // An inner trimming loop consists of a simple closed curve running // clockwise around the region the hole. //In this case, trim curves lie with 0.2 domain distance from surface edge On2dPoint from = new On2dPoint(); On2dPoint to = new On2dPoint(); double u0 = double.NaN, u1 = double.NaN, v0 = double.NaN, v1 = double.NaN; s.GetDomain(0, ref u0, ref u1); s.GetDomain(1, ref v0, ref v1); double udis = 0.2 * (u1 - u0); double vdis = 0.2 * (v1 - v0); u0 += udis; u1 -= udis; v0 += vdis; v1 -= vdis; switch (side) { case 0: // near SE to SW from.x = u1; from.y = v0; to.x = u0; to.y = v0; break; case 1: // near SW to NW from.x = u0; from.y = v0; to.x = u0; to.y = v1; break; case 2: // near NW to NE from.x = u0; from.y = v1; to.x = u1; to.y = v1; break; case 3: // near NE to SE from.x = u1; from.y = v1; to.x = u1; to.y = v0; break; default: return(null); } OnCurve c2d = new OnLineCurve(from, to); if (c2d != null) { c2d.SetDomain(0.0, 1.0); } return(c2d); }