public Body2 CreateOffset(IEnumerable <ISketchSegment> segs, double offset, double innerRadius, double outerRadius, bool reverse) { if (!segs.Any()) { throw new UserException("No segments provided"); } var curves = new List <ICurve>(); var transform = segs.First().GetSketch().ModelToSketchTransform.IInverse(); foreach (var skSeg in segs) { if (!skSeg.ConstructionGeometry) { var curve = skSeg.GetTrimmedCurve(); curve.ApplyTransform(transform); curves.Add(curve); } } var wireBody = m_Modeler.CreateWireBody(curves.ToArray(), (int)swCreateWireBodyOptions_e.swCreateWireBodyByDefault); if (wireBody == null) { throw new UserException("Segments must be connected and form chain"); } var offsetNormal = m_MathUtils.CreateVector(new double[] { 0, 0, reverse ? -1 : 1 }) as MathVector; offsetNormal = offsetNormal.MultiplyTransform(transform) as MathVector; var offsetBody = wireBody.OffsetPlanarWireBody(offset, offsetNormal, (int)swOffsetPlanarWireBodyOptions_e.swOffsetPlanarWireBodyOptions_GapFillRound); if (offsetBody == null) { throw new UserException("Failed to offset the body. Try change the parameters"); } var offsetCurves = new List <ICurve>(); var linearEdges = (offsetBody.GetEdges() as object[]).Cast <IEdge>() .Where(e => e.IGetCurve().IsLine()).ToArray(); var findFarMostPointFunc = new Func <IEdge, double[], double[]>( (edge, startPt) => { var startVert = edge.IGetStartVertex().GetPoint() as double[]; var endVert = edge.IGetEndVertex().GetPoint() as double[]; var startDist = MathUtils.GetDistanceBetweenPoints(startVert, startPt); var endDist = MathUtils.GetDistanceBetweenPoints(endVert, startPt); if (startDist > endDist) { return(startVert); } else { return(endVert); } }); double[] prevEndPt = null; for (int i = 0; i < linearEdges.Length - 1; i++) { var firstEdge = linearEdges[i]; var secondEdge = linearEdges[i + 1]; var interPt = firstEdge.IGetCurve().GetIntersectionWithLinearCurve(secondEdge.IGetCurve()); //TODO: check parallel curves var firstStartPt = findFarMostPointFunc.Invoke(firstEdge, interPt); var secondStartPt = findFarMostPointFunc.Invoke(secondEdge, interPt); var firstDir = new double[] { firstStartPt[0] - interPt[0], firstStartPt[1] - interPt[1], firstStartPt[2] - interPt[2] }; var secondDir = new double[] { secondStartPt[0] - interPt[0], secondStartPt[1] - interPt[1], secondStartPt[2] - interPt[2] }; var radius = outerRadius; if (i % 2 == 0) { radius = innerRadius; } var firstVec = m_MathUtils.CreateVector(firstDir) as IMathVector; var secondVec = m_MathUtils.CreateVector(secondDir) as IMathVector; var ang = firstVec.GetAngle(secondVec); var dist = radius / Math.Sin(ang / 2); var bisecVec = firstVec.Normalise().Add(secondVec.Normalise()) as IMathVector; var centerPt = m_MathUtils.CreatePoint(interPt) as IMathPoint; centerPt = centerPt.MoveAlongVector(bisecVec, dist); var centrPtCoord = centerPt.ArrayData as double[]; var createLineFunc = new Func <double[], double[], Curve>( (s, e) => { var line = m_Modeler.CreateLine(s, new double[] { e[0] - s[0], e[1] - s[1], e[2] - s[2] }) as Curve; line = line.CreateTrimmedCurve2(s[0], s[1], s[2], e[0], e[1], e[2]); return(line); }); var firstCurve = firstEdge.IGetCurve().GetBaseCurve(); var firstEndPt = firstCurve.GetClosestPointOn( centrPtCoord[0], centrPtCoord[1], centrPtCoord[2]) as double[]; firstEndPt = new double[] { firstEndPt[0], firstEndPt[1], firstEndPt[2] }; if (prevEndPt != null) { firstStartPt = prevEndPt; } firstCurve = createLineFunc.Invoke(firstStartPt, firstEndPt); offsetCurves.Add(firstCurve); var secondCurve = secondEdge.IGetCurve().GetBaseCurve(); var secondEndPt = secondCurve.GetClosestPointOn(centrPtCoord[0], centrPtCoord[1], centrPtCoord[2]) as double[]; secondEndPt = new double[] { secondEndPt[0], secondEndPt[1], secondEndPt[2] }; var isLast = i == linearEdges.Length - 2; if (isLast) { secondCurve = createLineFunc.Invoke(secondStartPt, secondEndPt); offsetCurves.Add(secondCurve); } ICurve filletCurve = null; var arcDir = (secondVec.Cross(firstVec) as IMathVector).ArrayData as double[]; filletCurve = m_Modeler.CreateArc(centrPtCoord, arcDir, radius, firstEndPt, secondEndPt) as ICurve; filletCurve = filletCurve.CreateTrimmedCurve2(firstEndPt[0], firstEndPt[1], firstEndPt[2], secondEndPt[0], secondEndPt[1], secondEndPt[2]); prevEndPt = secondEndPt; offsetCurves.Add(filletCurve); } var offsetFilletBody = m_Modeler.CreateWireBody(offsetCurves.ToArray(), (int)swCreateWireBodyOptions_e.swCreateWireBodyByDefault); if (offsetFilletBody == null) { throw new UserException("Failed to generate the chain from offset result"); } offsetBody = null; GC.Collect(); return(offsetFilletBody); }
public static ICurve CreateTrimmedCurve(this ICurve curve, double[] start, double[] end) { return(curve.CreateTrimmedCurve2(start[0], start[1], start[2], end[0], end[1], end[2])); }