/// <summary> /// Exact geometric check whether a point p lies inside the node. This is important for intersection calculation, among others. /// </summary> protected override bool IsInside(INode node, PointD location) { return(GeomUtilities.EllipseContains(node.Layout.ToRectD(), location, 0)); }
/// <summary> /// Hit test which considers HitTestRadius specified in CanvasContext /// </summary> /// <returns>True if p is inside node.</returns> protected override bool IsHit(IInputModeContext context, PointD location, INode node) { return(GeomUtilities.EllipseContains(node.Layout.ToRectD(), location, context.HitTestRadius)); }
/// <summary> /// Exact geometric check whether a point p lies inside the node. This is important for intersection calculation, among others. /// </summary> protected override bool IsInside(INode node, PointD point) { return GeomUtilities.EllipseContains(node.Layout.ToRectD(), point, 0); }
internal void NativeDrawString(string s, Font font, Color brush, RectangleF layoutRectangle, StringFormat stringFormat) { if (font == null) { throw new ArgumentNullException("font"); } if (s == null || s.Length == 0) { return; } var attributedString = buildAttributedString(s, font, brush); // Work out the geometry RectangleF insetBounds = layoutRectangle; bool layoutAvailable = true; if (insetBounds.Size == SizeF.Empty) { insetBounds.Size = new SizeF(8388608, 8388608); layoutAvailable = false; } PointF textPosition = new PointF(insetBounds.X, insetBounds.Y); float boundsWidth = insetBounds.Width; // Calculate the lines int start = 0; int length = attributedString.Length; var typesetter = new CTTypesetter(attributedString); float baselineOffset = 0; // First we need to calculate the offset for Vertical Alignment if we // are using anything but Top if (layoutAvailable && stringFormat.LineAlignment != StringAlignment.Near) { while (start < length) { int count = typesetter.SuggestLineBreak(start, boundsWidth); var line = typesetter.GetLine(new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; line.GetTypographicBounds(out ascent, out descent, out leading); baselineOffset += (float)Math.Ceiling(ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose(); start += count; } } start = 0; while (start < length && textPosition.Y < insetBounds.Bottom) { // Now we ask the typesetter to break off a line for us. // This also will take into account line feeds embedded in the text. // Example: "This is text \n with a line feed embedded inside it" int count = typesetter.SuggestLineBreak(start, boundsWidth); var line = typesetter.GetLine(new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading); if (!layoutAvailable) { insetBounds.Width = (float)lineWidth; insetBounds.Height = ascent + descent + leading; } // Calculate the string format if need be var penFlushness = 0.0f; if (stringFormat.Alignment == StringAlignment.Far) { penFlushness = (float)line.GetPenOffsetForFlush(1.0f, insetBounds.Width); } else if (stringFormat.Alignment == StringAlignment.Center) { penFlushness = (float)line.GetPenOffsetForFlush(0.5f, insetBounds.Width); } // initialize our Text Matrix or we could get trash in here var textMatrix = new CGAffineTransform( 1, 0, 0, -1, 0, ascent); if (stringFormat.LineAlignment == StringAlignment.Near) { textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y); //insetBounds.Height - textPosition.Y -(float)Math.Floor(ascent - 1)); } if (stringFormat.LineAlignment == StringAlignment.Center) { textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height / 2) - (baselineOffset / 2))); // -(float)Math.Floor(ascent) } if (stringFormat.LineAlignment == StringAlignment.Far) { textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height) - (baselineOffset))); } var glyphRuns = line.GetGlyphRuns(); for (int glyphRunIndex = 0; glyphRunIndex < glyphRuns.Length; glyphRunIndex++) { var glyphRun = glyphRuns [glyphRunIndex]; var glyphs = glyphRun.GetGlyphs(); var glyphPositions = glyphRun.GetPositions(); //var textMatrix = glyphRun.TextMatrix; // Create and initialize some values from the bounds. float glyphAscent; float glyphDescent; float glyphLeading; var elementPoints = new PointF[3]; for (int glyphIndex = 0; glyphIndex < glyphs.Length; glyphIndex++) { if (glyphIndex > 0) { textMatrix.x0 += glyphPositions [glyphIndex].X - glyphPositions[glyphIndex - 1].X; textMatrix.y0 += glyphPositions [glyphIndex].Y - glyphPositions[glyphIndex - 1].Y; } var glyphPath = font.nativeFont.GetPathForGlyph(glyphs [glyphIndex]); // glyphPath = null if it is a white space character if (glyphPath != null) { glyphPath.Apply( delegate(CGPathElement pathElement) { elementPoints[0] = textMatrix.TransformPoint(pathElement.Point1); elementPoints[1] = textMatrix.TransformPoint(pathElement.Point2); elementPoints[2] = textMatrix.TransformPoint(pathElement.Point3); //Console.WriteLine ("Applying {0} - {1}, {2}, {3}", pathElement.Type, elementPoints[0], elementPoints[1], elementPoints[2]); // now add position offsets switch (pathElement.Type) { case CGPathElementType.MoveToPoint: start_new_fig = true; Append(elementPoints[0].X, elementPoints[0].Y, PathPointType.Line, true); break; case CGPathElementType.AddLineToPoint: var lastPoint = points[points.Count - 1]; AppendPoint(lastPoint, PathPointType.Line, false); AppendPoint(elementPoints[0], PathPointType.Line, false); break; case CGPathElementType.AddCurveToPoint: case CGPathElementType.AddQuadCurveToPoint: // This is the only thing I can think of right now for the fonts that // I have tested. See the description of the quadraticToCubic method for // more information // Get the last point var pt1 = points[points.Count - 1]; var pt2 = PointF.Empty; var pt3 = PointF.Empty; var pt4 = elementPoints[1]; GeomUtilities.QuadraticToCubic(pt1, elementPoints[0], elementPoints[1], out pt2, out pt3); Append(pt1.X, pt1.Y, PathPointType.Line, true); AppendBezier(pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y); break; case CGPathElementType.CloseSubpath: CloseFigure(); break; } } ); } } } // Move the index beyond the line break. start += count; textPosition.Y += (float)Math.Ceiling(ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose(); } }
void setColorsUsingBlend() { int size = blend.Positions.Length; if (size == 1) { shadingColors = new nfloat[2, 4]; factors = new float[2]; positions = new float[2]; // check for default Blend to setup the shading colors // appropriately. if (blend.Factors[0] == 1 && blend.Positions[0] == 1) { factors[0] = 0f; positions[0] = 0; } else { // This is a special case where a blend was set // with a factor. It still does not give exact // results with windows. Need to look at this as // still not sure what it should do. // Example: // float[] myFactors = { 0.2f }; // float[] myPositions = { 0.0f }; // Blend myBlend = new Blend(); // myBlend.Factors = myFactors; // myBlend.Positions = myPositions; // lgBrush2.Blend = myBlend; factors[0] = blend.Factors[0]; positions[0] = 1.0f; } // Close off the color shadings factors[1] = 1.0f; positions[1] = 1.0f; } else { shadingColors = new nfloat[size, 4]; factors = blend.Factors; positions = blend.Positions; } float[] sc = colors[0].ElementsCGRGBA(); float[] ec = colors[1].ElementsCGRGBA(); float factor = 0; for (int s = 0; s < positions.Length; s++) { factor = factors[s]; //Console.WriteLine("shadingIndex {0} position {1} factor {2}",s, positions[s], factor); for (int c = 0; c < 4; c++) { shadingColors[s, c] = GeomUtilities.Lerp(sc[c], ec[c], factor); } } }
unsafe public void GradientLerp(nfloat *data, nfloat *outData) { nfloat lerpDist = *(nfloat *)data; int i = 0; int numPositions = positions.Length; // Make sure we put the linear distance value back into the 0.0 .. 1.0 range // depending on the wrap mode if (wrapMode == WrapMode.Tile || wrapMode == WrapMode.TileFlipY) { // Repeat lerpDist = lerpDist - (nfloat)NMath.Floor(lerpDist); } else { // Reflect lerpDist = (nfloat)NMath.Abs(lerpDist) % 2.0f; if (lerpDist > 1.0f) { lerpDist = 2.0f - lerpDist; } } for (i = 0; i < numPositions; i++) { if (positions[i] > lerpDist) { break; } } nfloat prevPosition = 0; nfloat dist = 0; nfloat normalized = 0; if (i == 0 || i == numPositions) { if (i == numPositions) { --i; } // When we have multiple positions we need to interpolate the colors // between the two positions. // normalized will be the normalized [0,1] amount // of the gradiant area between the two positions. // // The shading colors have already // been setup with the color factors taken into account. // Get the distance between current position and last position dist = factors[i] - prevPosition; // normalized value between the two shading colors normalized = (nfloat)((lerpDist - prevPosition) / dist); // Console.WriteLine("prev {0} dist {1} normal {2} i {3} t {4}", // prevPosition, dist, normalized, i, t); for (ushort ctr = 0; ctr < 4; ctr++) { outData[ctr] = GeomUtilities.Lerp(shadingColors[0, ctr], shadingColors[1, ctr], normalized); } } else { // When we have multiple positions we need to interpolate the colors // between the two positions. // normalized will be the normalized [0,1] amount // of the gradiant area between the two positions. // // The shading colors have already // been setup with the color factors taken into account. prevPosition = positions[i - 1]; // Get the distance between current position and last position dist = positions[i] - prevPosition; // normalized value between the two shading colors normalized = (nfloat)((lerpDist - prevPosition) / dist); for (ushort ctr = 0; ctr < 4; ctr++) { outData[ctr] = GeomUtilities.Lerp(shadingColors[i - 1, ctr], shadingColors[i, ctr], normalized); } } if (gammaCorrection) { // * NOTE * Here I am only computing the gamma correction for RGB values not alpha // I am really not sure if this is correct or not but from my reading on this topic // it is really never mentioned that alpha is included. for (ushort ctr = 0; ctr < 3; ctr++) { outData[ctr] = (nfloat)Math.Pow(outData[ctr], gamma); } } // Console.WriteLine("R: {0}, G: {1}, B: {2}, A: {3}", // outData[0], // outData[1], // outData[2], // outData[3]); }
public XAMachPostion(double x, double aDegrees) { _geometry = MachineGeometry.XA; _aRad = GeomUtilities.ToRadians(aDegrees); _x = x; }
/// <summary> /// parse string line from nc file into path LINE entity /// </summary> /// <param name="ncLine">line from NC file</param> /// <param name="blockT">Block type</param> /// <returns>LinePathEntity</returns> private LinePathEntity parseLine(string ncLine, BlockType blockT, bool jeton, bool invertedF) { LinePathEntity ent = new LinePathEntity(blockT); string[] splitLine = ncLine.Split(splitters, StringSplitOptions.None); ent.JetOn = jeton; ent.Feedrate.Inverted = invertedF; ent.InputString = ncLine; foreach (string str in splitLine) { if (str.Contains(n)) { ent.LineNumber = parseInt(str, n); } if (str.Contains(x)) { ent.Position.X = parseDouble(str, x); ent.ContainsX = true; } if (str.Contains(y)) { ent.Position.Y = parseDouble(str, y); ent.ContainsY = true; } if (str.Contains(z)) { ent.Position.Z = parseDouble(str, z); ent.ContainsZ = true; } if (str.Contains(b)) { ent.Position.Bdeg = parseDouble(str, b); ent.Type = BlockType.FiveAxis; } if (str.Contains(c)) { ent.Position.Cdeg = parseDouble(str, c); ent.Type = BlockType.FiveAxis; } if (str.Contains(f)) { ent.Feedrate.Value = parseDouble(str, f); ent.ContainsF = true; } } if (ent.Type == BlockType.FiveAxis) { Vector3 pt = new Vector3(0, 0, 1); Vector3 origin = new Vector3(0, 0, 0); pt.RotateY(origin, GeomUtilities.ToRadians(ent.Position.Bdeg)); pt.RotateZ(origin, GeomUtilities.ToRadians(ent.Position.Cdeg)); ent.JetVector = pt; } else { ent.JetVector = GeometryLib.Vector3.ZAxis; } ent.Type = blockT; return(ent); }
public void Run(CancellationToken ct, IProgress <int> progress) { try { double searchRadius = jetRadius + surface.MeshSize; int pcount = path.Count * runInfo.Runs * runInfo.Iterations; int count = 0; List <string> pointlist = new List <string>(); pointlist.Add("run,Nx,Ny,Nz,x,z,pointradius,jetfactor,incidentangle,slopefactor"); double spFactor = spacingFactor(); double testJetRadius = jetRadius + surface.MeshSize; for (int iteration = 1; iteration <= runInfo.Iterations; iteration++) { runInfo.CurrentIteration = iteration; for (int run = 1; run <= runInfo.Runs; run++) { runInfo.CurrentRun = run; int pathCount = 0; foreach (ModelPathEntity mpe in path) { if (!ct.IsCancellationRequested) { double feedFactor = currentRemovalRate.DepthPerPass * spFactor * feedrateFactor(mpe.Feedrate.Value, currentRemovalRate); pathCount++; if (mpe.JetOn && feedFactor != 0) { BoundingBox searchBox = BoundingBoxBuilder.GetSearchCylinder(surface.BoundingBox, mpe.PositionAsVector3, mpe.JetVector, searchRadius); List <AbmachPoint> jetIntersectList = surface.GetPointsInsideBox(searchBox); Octree <AbmachPoint> localSurface = OctreeBuilder <AbmachPoint> .Build(jetIntersectList, surface.MeshSize);// OctreeBuilder<AbmachPoint>.Build(jetIntersectList, searchBox, surface.MeshSize); var newPts = new List <AbmachPoint>(); var mpeV = new Vector3(mpe.Position.X, mpe.Position.Y, 0); var jetRay = new Ray(mpe.PositionAsVector3, mpe.JetVector); foreach (AbmachPoint jetPt in localSurface.GetAllPoints()) { if (jetPt != null) { //var jetV = new Vector3(jetPt.Position.X, jetPt.Position.Y, 0); //double pointRadius = jetV.DistanceTo(mpeV); double pointRadius = GeomUtilities.RayPointDistance(jetRay, jetPt.Position); if (pointRadius <= testJetRadius) { double jFactor = jetFactor(pointRadius); if (jFactor > 0) { Vector3 localNormal = new Vector3(0, 0, 1); // localSurface.GetNormalAt(jetPt.Position); if (localNormal.Length == 0) { localNormal = new Vector3(mpe.JetVector); } double angle = incidentAngle(mpe.JetVector, localNormal); double slFactor = slopeFactor(angle); //debug if (jetPt.Position.X > 0.006 && jetPt.Position.X < .1 && jetPt.Position.Y > .072 && jetPt.Position.Y < .102) { pointlist.Add(run.ToString() + "," + jetPt.Position.X.ToString("f5") + "," + jetPt.Position.Y.ToString("f5") + "," + jetPt.Position.Z.ToString("f5") + "," + pointRadius.ToString("f5") + "," + jFactor.ToString("F5") + "," + angle.ToString("F5") + "," + slFactor.ToString("F5")); } //debug Vector3 materialRemoved = (feedFactor * slFactor * jFactor) * mpe.JetVector; Vector3 newPosition = jetPt.Position - materialRemoved; jetPt.Position = newPosition; jetPt.Normal = localNormal; jetPt.OriginalPosition = jetPt.OriginalPosition; jetPt.JetHit = true; newPts.Add(jetPt); } } else { newPts.Add(jetPt); } } //end foreach jetPt } surface.Insert(newPts); }//endif jeton } progress.Report(100 * ++count / pcount); }//next path entity if (runInfo.RunType == ModelRunType.NewMRR) { currentRemovalRate = newRemovalRate(path, runInfo, currentRemovalRate, depthInfo); } } //next run if (runInfo.RunType == ModelRunType.NewFeedrates && runInfo.CurrentIteration < runInfo.Iterations) { path = newFeedrates(path, depthInfo); resetSurface(); } }//next iteration FileIOLib.FileIO.Save(pointlist, "slopefactor.csv"); } catch (Exception) { throw; } }