public void AddRowSpan(TableCell cell, int firstCol, int numCols, int cellHeight, int rowsSpanned) { spanInfo[firstCol - 1] = new SpanInfo(cell, cellHeight, rowsSpanned); for (int i = 0; i < numCols - 1; i++) { spanInfo[firstCol + i] = new SpanInfo(null, cellHeight, rowsSpanned); } }
/// <summary> /// Initializes a new instance of the <see cref="LegFace"/> class that has undefined spans, and /// no sequence number. /// </summary> internal LegFace(Leg leg, int nspan) { this.Leg = leg; // Allocate an array of spans (always at least ONE). m_Spans = new SpanInfo[Math.Max(1, nspan)]; for (int i = 0; i < m_Spans.Length; i++) m_Spans[i] = new SpanInfo(); }
/// <summary> /// Initializes a new instance of the <see cref="LegFace"/> class. /// <param name="leg">The leg this face relates to.</param> /// <param name="dists">The observed distances for this face.</param> /// </summary> internal LegFace(Leg leg, Distance[] dists) { this.Leg = leg; m_Spans = new SpanInfo[dists.Length]; for (int i=0; i<m_Spans.Length; i++) { m_Spans[i] = new SpanInfo(); m_Spans[i].ObservedDistance = dists[i]; } }
private Dictionary <int, SpanInfo> SpanRows = new Dictionary <int, SpanInfo>(); //需要2维表头的列 /// <summary> /// 合并列 /// </summary> /// <param name="ColIndex">列的索引</param> /// <param name="ColCount">需要合并的列数</param> /// <param name="Text">合并列后的文本</param> public void AddSpanHeader(int ColIndex, int ColCount, string Text) { if (ColCount < 2) { throw new Exception("行宽应大于等于2,合并1列无意义。"); } //将这些列加入列表 int Right = ColIndex + ColCount - 1; //同一大标题下的最后一列的索引 SpanRows[ColIndex] = new SpanInfo(Text, 1, ColIndex, Right); //添加标题下的最左列 SpanRows[Right] = new SpanInfo(Text, 3, ColIndex, Right); //添加该标题下的最右列 for (int i = ColIndex + 1; i < Right; i++) //中间的列 { SpanRows[i] = new SpanInfo(Text, 2, ColIndex, Right); } }
/// <summary> /// Apply BoxBlur to the destinationBitmap /// </summary> /// <param name="destinationBitmap">Bitmap to blur</param> /// <param name="range">Must be ODD, if not +1 is used</param> public static void ApplyBoxBlurSpan(this Bitmap destinationBitmap, int range) { var bitmapData = destinationBitmap.LockBits(new Rectangle(Point.Empty, destinationBitmap.Size), ImageLockMode.ReadWrite, destinationBitmap.PixelFormat); try { var pixelStride = destinationBitmap.Width; bool isAlpha = false; switch (bitmapData.PixelFormat) { case PixelFormat.Format24bppRgb: pixelStride = bitmapData.Stride / 3; break; case PixelFormat.Format32bppRgb: case PixelFormat.Format32bppArgb: pixelStride = bitmapData.Stride / 4; isAlpha = true; break; } var spanInfo = new SpanInfo { Width = destinationBitmap.Width, Height = destinationBitmap.Height, Left = 0, Right = destinationBitmap.Width, Top = 0, Bottom = destinationBitmap.Height, Pointer = bitmapData.Scan0, PixelStride = pixelStride, BitmapSize = destinationBitmap.Height * pixelStride }; if (isAlpha) { ApplyBoxBlurSpanAlpha(spanInfo, range); } else { ApplyBoxBlurSpan(spanInfo, range); } } finally { destinationBitmap.UnlockBits(bitmapData); } }
#pragma warning restore 67 public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan processedSpan) { var currentSnapshot = processedSpan.Snapshot; var result = new List <ClassificationSpan>(); for (int i = 0; i < _spanInfos.Length; i++) { var snapshot = _snapshots[i]; var spanInfos = _spanInfos[i]; var translatesSnapshot = processedSpan.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive); var processedSpanInfo = new SpanInfo(new NSpan(translatesSnapshot.Span.Start, translatesSnapshot.Span.End), -1); var index = spanInfos.BinarySearch(processedSpanInfo, SpanInfo.Comparer); if (index < 0) { index = ~index; } var oldSpan = default(NSpan); for (int k = index; k < spanInfos.Length; k++) { var spanInfo = spanInfos[k]; var span = spanInfo.Span; if (oldSpan == span) { continue; } oldSpan = span; var newSpan = new SnapshotSpan(snapshot, new Span(span.StartPos, span.Length)) .TranslateTo(currentSnapshot, SpanTrackingMode.EdgeExclusive); if (!newSpan.IntersectsWith(processedSpan)) { break; } if (ClassificationMap.TryGetValue(spanInfo.SpanClassId, out var classificationType)) { result.Add(new ClassificationSpan(newSpan, classificationType)); } else { } } } return(result); }
private bool LoadSpans(string row) { Match match = _spanRegex.Match(row); if (match.Success) { SpanInfo span = new SpanInfo() { ID = Int32.Parse(match.Groups[1].Value), SegmentID = Int32.Parse(match.Groups[2].Value), Offset = Int32.Parse(match.Groups[3].Value) }; _spans.Add(span.ID, span); return(true); } return(false); }
/// <summary> /// Apply BoxBlur to the fastBitmap /// </summary> /// <param name="spanInfo">SpanInfo</param> /// <param name="range">Must be even!</param> private static void ApplyBoxBlurSpan(SpanInfo spanInfo, int range) { // Range must be odd! if ((range & 1) == 0) { range++; } if (range <= 1) { return; } // Box blurs are frequently used to approximate a Gaussian blur. // By the central limit theorem, if applied 3 times on the same image, a box blur approximates the Gaussian kernel to within about 3%, yielding the same result as a quadratic convolution kernel. // This might be true, but the GDI+ BlurEffect doesn't look the same, a 2x blur is more simular and we only make 2x Box-Blur. // (Might also be a mistake in our blur, but for now it looks great) BoxBlurHorizontalSpan(spanInfo, range); BoxBlurVerticalSpan(spanInfo, range); BoxBlurHorizontalSpan(spanInfo, range); BoxBlurVerticalSpan(spanInfo, range); }
/// <summary> /// Ths callback is invoked by AsyncLocal each time the values changed for an underlying physical managed tread. /// The tracer must use a collback timilar to this. /// </summary> /// <param name="changeInfo"></param> private static void OnAsyncLocalValueChanged(AsyncLocalValueChangedArgs <MockSpan> changeInfo) { MockSpan currenActiveSpan = changeInfo.CurrentValue; Console.WriteLine($"\n* AsyncLocalValueChanged." + $" PrevVal=\"{changeInfo.PreviousValue}\"," + $" CurrVal=\"{currenActiveSpan}\"," + $" CtxChange={changeInfo.ThreadContextChanged}," + $" ThreadId={Thread.CurrentThread.ManagedThreadId}."); if (TraceContextTrackerFactory.SingletonInstance.TryGetOrCreateTraceContextTrackerForCurrentThread(out TraceContextTracker tracker)) { if (currenActiveSpan != null) { tracker.TrySetTraceContextInfoForCurrentThread(SpanInfo.ForSpan(currenActiveSpan.TraceId, currenActiveSpan.SpanId)); } else { tracker.TrySetTraceContextInfoForCurrentThread(SpanInfo.ForNoSpan()); } } }
private SymbolInfo GetMatchingSymbol(SymbolInfo symbol, int rangeStart, int rangeEnd) { AddressTypeInfo symbolAddress = GetSymbolAddressInfo(symbol); if (symbolAddress != null && symbolAddress.Type == AddressType.PrgRom && symbolAddress.Address >= rangeStart && symbolAddress.Address <= rangeEnd) { //If the range start/end matches the symbol's definition, return it return(symbol); } foreach (int reference in symbol.References) { LineInfo line = _lines[reference]; foreach (int spanID in line.SpanIDs) { SpanInfo span = _spans[spanID]; SegmentInfo seg = _segments[span.SegmentID]; if (!seg.IsRam) { int spanPrgOffset = seg.FileOffset - _headerSize + span.Offset; if (rangeStart < spanPrgOffset + span.Size && rangeEnd >= spanPrgOffset) { if (symbol.ExportSymbolID != null && symbol.Address == null) { return(_symbols[symbol.ExportSymbolID.Value]); } else { return(symbol); } } } } } return(null); }
private Dictionary<int, SpanInfo> SpanRows = new Dictionary<int, SpanInfo>();//需要2维表头的列 /// <summary> /// 增加表头 /// </summary> /// <param name="ColIndex">开始的列索引</param> /// <param name="ColCount">合并的列数</param> /// <param name="Text">增加的表头的内容</param> public void AddSpanHeader(int ColIndex, int ColCount, string Text) { if (ColCount < 2) //throw new Exception("行宽应大于等于2,合并1列无意义。"); { MessageBox.Show("行宽应大于等于2,合并1列无意义。"); return; } //检查范围 //for (int i = 0; i < ColCount; i++) //{ // if (SpanRows.ContainsKey(ColIndex + i)) // throw new Exception("单元格范围重叠!"); //} //将这些列加入列表 int Right = ColIndex + ColCount - 1; //同一大标题下的最后一列的索引 SpanRows[ColIndex] = new SpanInfo(Text, 1, ColIndex, Right); //添加标题下的最左列 SpanRows[Right] = new SpanInfo(Text, 3, ColIndex, Right); //添加该标题下的最右列 for (int i = ColIndex + 1; i < Right; i++) //中间的列 { SpanRows[i] = new SpanInfo(Text, 2, ColIndex, Right); } }
/// <summary> /// Attaches geometry to the spans along a leg. /// </summary> /// <param name="ctx">The context in which the geometry is being defined.</param> /// <param name="spans">Information about each observed span</param> /// <param name="sections">The geometry that corresponds to each span</param> void AttachGeometry(EditingContext ctx, SpanInfo[] spans, ILineGeometry[] sections) { Debug.Assert(spans.Length == sections.Length); for (int i = 0; i < spans.Length; i++) { SpanInfo data = spans[i]; Feature feat = data.CreatedFeature; PointFeature endPoint = null; if (feat is PointFeature) endPoint = (PointFeature)feat; else if (feat is LineFeature) endPoint = (feat as LineFeature).EndPoint; if (endPoint != null && endPoint.PointGeometry == null) { PointGeometry pg = PointGeometry.Create(sections[i].End); endPoint.ApplyPointGeometry(ctx, pg); } } }
private void BuildCdlData() { int prgSize = InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom); if (prgSize <= 0) { return; } byte[] cdlFile = new byte[prgSize]; //Mark data/code regions foreach (SpanInfo span in _spans.Values) { int prgAddress = GetPrgAddress(span); if (prgAddress >= 0 && prgAddress < prgSize) { for (int i = 0; i < span.Size; i++) { if (cdlFile[prgAddress + i] != (byte)CdlPrgFlags.Data && !span.IsData && span.Size <= 3) { cdlFile[prgAddress + i] = (byte)CdlPrgFlags.Code; } else if (span.IsData) { cdlFile[prgAddress + i] = (byte)CdlPrgFlags.Data; } else if (cdlFile[prgAddress + i] == 0) { //Mark bytes as tentative data, until we know that the bytes are actually code cdlFile[prgAddress + i] = 0x04; } } } } for (int i = 0; i < cdlFile.Length; i++) { if (cdlFile[i] == 0x04) { //Mark all bytes marked as tentative data as data cdlFile[i] = (byte)CdlPrgFlags.Data; } } //Find/identify functions and jump targets byte[] prgRomContent = InteropEmu.DebugGetMemoryState(DebugMemoryType.PrgRom); foreach (SymbolInfo symbol in _symbols.Values) { LineInfo line; if (!symbol.SegmentID.HasValue) { //This is a constant, ignore it continue; } foreach (int reference in symbol.References) { if (_lines.TryGetValue(reference, out line) && line.SpanIDs.Count > 0) { SpanInfo span; if (_spans.TryGetValue(line.SpanIDs[0], out span) && !span.IsData && span.Size <= 3) { int referencePrgAddr = GetPrgAddress(span); if (referencePrgAddr >= 0 && referencePrgAddr < prgRomContent.Length) { byte opCode = prgRomContent[referencePrgAddr]; if (opCode == 0x20 || opCode == 0x10 || opCode == 0x30 || opCode == 0x50 || opCode == 0x70 || opCode == 0x90 || opCode == 0xB0 || opCode == 0xD0 || opCode == 0xF0 || opCode == 0x4C || opCode == 0x20 || opCode == 0x4C || opCode == 0x6C) { //This symbol is used with a JSR/jump instruction, so it's either a function or jump target bool isJsr = opCode == 0x20; SpanInfo definitionSpan = GetSymbolDefinitionSpan(symbol); if (definitionSpan != null) { int definitionPrgAddr = GetPrgAddress(definitionSpan); if (definitionPrgAddr >= 0 && definitionPrgAddr < prgRomContent.Length) { cdlFile[definitionPrgAddr] |= (byte)(isJsr ? CdlPrgFlags.SubEntryPoint : CdlPrgFlags.JumpTarget); break; } } } } } } } } InteropEmu.DebugSetCdlData(cdlFile); }
#pragma warning restore 67 public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan processedSpan) { var currentSnapshot = processedSpan.Snapshot; var result = new List<ClassificationSpan>(); for (int i = 0; i < _spanInfos.Length; i++) { var snapshot = _snapshots[i]; var spanInfos = _spanInfos[i]; var translatesSnapshot = processedSpan.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive); var processedSpanInfo = new SpanInfo(new NSpan(translatesSnapshot.Span.Start, translatesSnapshot.Span.End), -1); var index = spanInfos.BinarySearch(processedSpanInfo, SpanInfo.Comparer); if (index < 0) index = ~index; for (int k = index; k < spanInfos.Length; k++) { var spanInfo = spanInfos[k]; var span = spanInfo.Span; var newSpan = new SnapshotSpan(snapshot, new Span(span.StartPos, span.Length)) .TranslateTo(currentSnapshot, SpanTrackingMode.EdgeExclusive); if (!newSpan.IntersectsWith(processedSpan)) break; var classificationType = ClassificationMap[spanInfo.SpanClassId]; result.Add(new ClassificationSpan(newSpan, classificationType)); } } return result; }
/// <summary> /// 画标题文字 /// </summary> /// <param name="e"></param> /// <param name="span"></param> /// <param name="left"></param> /// <param name="right"></param> /// <param name="top"></param> /// <param name="bottom"></param> private void DrawString(DataGridViewCellPaintingEventArgs e, SpanInfo span, ref int left, ref int right, ref int top, ref int bottom) { var g = e.Graphics; var rect = e.CellBounds; // 网格画笔 var gridPen = new Pen(GridColor); // 填充笔刷 var fillBrush = new SolidBrush(DefaultCellStyle.BackColor); // 标题文字格式 var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; // 二级标题矩形 rect = new Rectangle(left, (top + bottom) / 2 + 1, rect.Width, rect.Height / 2); // 标题笔刷 var headerBrush = new SolidBrush(ColumnHeadersDefaultCellStyle.ForeColor); g.FillRectangle(fillBrush, left, rect.Top, rect.Width, rect.Height - 2); // 一级标题和二级标题不同时,需要画二级标题 if (span.HeaderText != e.Value?.ToString()) { g.DrawString(e.Value?.ToString(), e.CellStyle.Font, headerBrush, rect, sf); } // 画分割线 g.DrawLine(gridPen, right - 1, top, right - 1, bottom); left = GetColumnDisplayRectangle(span.LeftIndex, true).Left; if (left < 0) { left = GetCellDisplayRectangle(-1, -1, true).Width; } right = GetColumnDisplayRectangle(span.RightIndex, true).Right; if (right < 0) { right = rect.Width; } // 一级标题矩形 rect = new Rectangle(left, top, right - left, (bottom - top) / 2); // 画上半部分底色 g.FillRectangle(fillBrush, left, top, rect.Width, rect.Height); if (span.HeaderText == e.Value?.ToString()) { rect = new Rectangle(left, top, right - left, bottom - top); } // 始终都需要画一级标题 g.DrawString(span.HeaderText, e.CellStyle.Font, headerBrush, rect, sf); }
private void LoadComments() { SortedDictionary <string, int> constants = GetConstants(); foreach (KeyValuePair <int, LineInfo> kvp in _lines) { try { LineInfo line = kvp.Value; if (line.SpanIDs.Count == 0) { continue; } SpanInfo span = _spans[line.SpanIDs[0]]; SegmentInfo segment = _segments[span.SegmentID]; if (_files[line.FileID].Data == null) { //File was not found. if (_filesNotFound.Add(_files[line.FileID].Name)) { _errorCount++; } continue; } bool isAsm = _files[line.FileID].IsAssembly; string comment = ""; for (int i = line.LineNumber; i >= 0; i--) { string sourceCodeLine = _files[line.FileID].Data[i]; if (sourceCodeLine.Trim().Length == 0) { //Ignore empty lines continue; } Regex regex; if (i == line.LineNumber) { regex = isAsm ? _asmFirstLineRegex : _cFirstLineRegex; } else { regex = isAsm ? _asmPreviousLinesRegex : _cPreviousLinesRegex; } Match match = regex.Match(sourceCodeLine); if (match.Success) { string matchedComment = match.Groups[1].Value.Replace("\t", " "); if (string.IsNullOrWhiteSpace(comment)) { comment = matchedComment; } else { comment = matchedComment + Environment.NewLine + comment; } } else if (i != line.LineNumber) { break; } } if (comment.Length > 0) { int address = -1; AddressType?addressType; if (segment.IsRam) { GetRamLabelAddressAndType(span.Offset + segment.Start, out address, out addressType); } else { address = GetPrgAddress(span); addressType = AddressType.PrgRom; } if (address >= 0 && addressType != null) { CodeLabel label = this.CreateLabel(address, addressType.Value, 1); if (label != null) { //Parse and replace content of asserts as needed string[] commentLines = comment.Split(_splitOnNewLine, StringSplitOptions.None); for (int i = 0; i < commentLines.Length; i++) { Match m = LabelManager.AssertRegex.Match(commentLines[i]); if (m.Success) { foreach (KeyValuePair <string, int> entry in constants) { commentLines[i] = commentLines[i].Replace(entry.Key, entry.Value.ToString()); } } } label.Comment = string.Join(Environment.NewLine, commentLines); } } } } catch { _errorCount++; } } }
/// <summary> /// 合并列 /// </summary> /// <param name="ColIndex">列的索引</param> /// <param name="ColCount">需要合并的列数</param> /// <param name="Text">合并列后的文本</param> public void AddSpanHeader(int ColIndex, int ColCount, string Text) { if (ColCount < 2) { throw new Exception("行宽应大于等于2,合并1列无意义。"); } //将这些列加入列表 int Right = ColIndex + ColCount - 1; //同一大标题下的最后一列的索引 SpanRows[ColIndex] = new SpanInfo(Text, 1, ColIndex, Right); //添加标题下的最左列 SpanRows[Right] = new SpanInfo(Text, 3, ColIndex, Right); //添加该标题下的最右列 for (int i = ColIndex + 1; i < Right; i++) //中间的列 { SpanRows[i] = new SpanInfo(Text, 2, ColIndex, Right); } }
private void LoadComments() { DbgIntegrationConfig config = ConfigManager.Config.Debug.DbgIntegration; foreach (KeyValuePair <int, LineInfo> kvp in _lines) { try { LineInfo line = kvp.Value; if (line.SpanIDs.Count == 0) { continue; } SpanInfo span = _spans[line.SpanIDs[0]]; SegmentInfo segment = _segments[span.SegmentID]; if (_files[line.FileID].Data == null) { //File was not found. if (_filesNotFound.Add(_files[line.FileID].Name)) { _errorCount++; } continue; } bool isAsm = _files[line.FileID].IsAssembly; string comment = ""; for (int i = line.LineNumber; i >= 0; i--) { string sourceCodeLine = _files[line.FileID].Data[i]; if (sourceCodeLine.Trim().Length == 0) { //Ignore empty lines continue; } Regex regex; if (i == line.LineNumber) { regex = isAsm ? _asmFirstLineRegex : _cFirstLineRegex; } else { regex = isAsm ? _asmPreviousLinesRegex : _cPreviousLinesRegex; } Match match = regex.Match(sourceCodeLine); if (match.Success) { string matchedComment = match.Groups[1].Value.Replace("\t", " "); if (string.IsNullOrWhiteSpace(comment)) { comment = matchedComment; } else { comment = matchedComment + Environment.NewLine + comment; } } else if (i != line.LineNumber) { break; } } if (comment.Length > 0) { int address = -1; SnesMemoryType?memoryType; if (segment.IsRam) { if (segment.IsSpc) { address = span.Offset + segment.Start; memoryType = SnesMemoryType.SpcRam; } else { GetRamLabelAddressAndType(span.Offset + segment.Start, out address, out memoryType); } } else { address = GetPrgAddress(span); memoryType = SnesMemoryType.PrgRom; } if (memoryType == SnesMemoryType.SpcRam && !config.ImportSpcComments) { continue; } else if (memoryType != SnesMemoryType.SpcRam && !config.ImportCpuComments) { continue; } if (address >= 0 && memoryType != null) { CodeLabel label = this.CreateLabel(address, memoryType.Value, 1); if (label != null) { label.Comment = comment; } } } } catch { _errorCount++; } } }
/// <summary> /// Obtains the geometry for spans along an alternate face attached to this leg. /// </summary> /// <param name="start">The position for the start of the leg. /// <param name="end">The position for the end of the leg.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition start, IPosition end, SpanInfo[] spans) { Debug.Assert(AlternateFace != null); // Get the desired length (in meters on the ground) double len = Geom.Distance(start, end); // Get the observed length (in meters on the ground) double obs = AlternateFace.GetTotal(); // Get the adjustment factor for stretching-compressing the observed distances. double factor = len / obs; // Get the bearing of the line. double bearing = Geom.BearingInRadians(start, end); return GetSpanSections(start, bearing, factor, spans); }
/// <summary> /// Obtains the geometry for spans along this leg. /// </summary> /// <param name="pos">The position for the start of the leg. /// <param name="bearing">The bearing of the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition pos, double bearing, double sfac, SpanInfo[] spans) { var result = new ILineGeometry[spans.Length]; // A leg with just one span, but no observed distance is due to the fact that the Leg constructor // that accepts a span count will always produce an array with at least one span (this covers cul-de-sacs // defined only with a central angle). May be better to handle it there. if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = new LineSegmentGeometry(pos, pos); return result; } double sinBearing = Math.Sin(bearing); double cosBearing = Math.Cos(bearing); IPosition sPos = pos; IPosition ePos = null; double edist = 0.0; for (int i = 0; i < result.Length; i++, sPos=ePos) { edist += (spans[i].ObservedDistance.Meters * sfac); ePos = new Position(pos.X + (edist * sinBearing), pos.Y + (edist * cosBearing)); result[i] = new LineSegmentGeometry(sPos, ePos); } return result; }
/// <summary> /// Obtains the geometry for spans along an alternate face attached to this leg. /// </summary> /// <param name="legStart">The position for the start of the leg. /// <param name="legEnd">The position for the end of the leg.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition legStart, IPosition legEnd, SpanInfo[] spans) { var result = new ILineGeometry[spans.Length]; Debug.Assert(AlternateFace != null); // Define the arc that corresponds to the complete leg (the circle should have been // already defined when we processed the primary face_. Debug.Assert(Circle != null); var arc = new CircularArcGeometry(Circle, legStart, legEnd, m_Metrics.IsClockwise); // Handle case where the leg is a cul-de-sac with no observed spans on the alternate face if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = arc; return result; } // Get the required arc length (in meters on the ground) double len = arc.Length.Meters; // Get the observed arc length (in meters on the ground) double obs = AlternateFace.GetTotal(); // Get the adjustment factor for stretching-compressing the observed distances. double factor = len / obs; // Define start of first arc. IPosition sPos = legStart; IPosition ePos = null; // Haven't got anywhere yet. double totobs = 0.0; // Figure out the location of each span for (int i = 0; i < result.Length; i++, sPos = ePos) { if (i == result.Length - 1) { ePos = legEnd; } else { // Add on the unscaled distance totobs += spans[i].ObservedDistance.Meters; // Scale to the required length for the overall leg double elen = totobs * factor; // Define the end position. arc.GetPosition(new Length(elen), out ePos); } result[i] = new CircularArcGeometry(Circle, sPos, ePos, m_Metrics.IsClockwise); } return result; }
public void Process(ReadOnlySpan <char> line) { SpanInfo[] pieces = new SpanInfo[10]; SpanInfo[] slashSplit = new SpanInfo[10]; _currentLine++; SplitBy(pieces, line, ' ', out int numItemsSplit); if (numItemsSplit == 0 || pieces[0].Get(line).IsEmpty || pieces[0].Get(line)[0] == '#') { return; } if (pieces[0].Get(line).SequenceEqual(_span_v)) { ExpectExactly(numItemsSplit, 3, "v", line); DiscoverPosition(ParseVector3(pieces[1].Get(line), pieces[2].Get(line), pieces[3].Get(line), "position data", line)); } else if (pieces[0].Get(line).SequenceEqual(_span_vn)) { ExpectExactly(numItemsSplit, 3, "vn", line); DiscoverNormal(ParseVector3(pieces[1].Get(line), pieces[2].Get(line), pieces[3].Get(line), "normal data", line)); } else if (pieces[0].Get(line).SequenceEqual(_span_vt)) { ExpectAtLeast(numItemsSplit, 1, "vt", line); Vector2 texCoord = ParseVector2(pieces[1].Get(line), pieces[2].Get(line), "texture coordinate data", line); // Flip v coordinate texCoord.Y = 1f - texCoord.Y; DiscoverTexCoord(texCoord); } else if (pieces[0].Get(line).SequenceEqual(_span_g)) { ExpectAtLeast(numItemsSplit, 1, "g", line); FinalizeGroup(); _currentGroupName = GetString(line.Slice(1, line.Length - 1)); } else if (pieces[0].Get(line).SequenceEqual(_span_usemtl)) { ExpectExactly(numItemsSplit, 1, "usematl", line); if (!string.IsNullOrEmpty(_currentMaterial)) { string nextGroupName = _currentGroupName + "_Next"; FinalizeGroup(); _currentGroupName = nextGroupName; } _currentMaterial = GetString(pieces[1].Get(line)); } else if (pieces[0].Get(line).SequenceEqual(_span_s)) { ExpectExactly(numItemsSplit, 1, "s", line); if (pieces[1].Get(line).SequenceEqual(_span_off)) { _currentSmoothingGroup = 0; } else { _currentSmoothingGroup = ParseInt(pieces[1].Get(line), "smoothing group"); } } else if (pieces[0].Get(line).SequenceEqual(_span_f)) { ExpectAtLeast(numItemsSplit, 3, "f", line); ProcessFaceLine(slashSplit, pieces, numItemsSplit, line); } else if (pieces[0].Get(line).SequenceEqual(_span_mtllib)) { ExpectExactly(numItemsSplit, 1, "mtllib", line); DiscoverMaterialLib(pieces[1].Get(line), line); } else { throw new ObjParseException( string.Format("An unsupported line-type specifier, '{0}', was used on line {1}, \"{2}\"", GetString(pieces[0].Get(line)), _currentLine, GetString(line))); } }
private void LoadComments() { foreach (KeyValuePair <int, LineInfo> kvp in _lines) { try { LineInfo line = kvp.Value; if (line.SpanID == null) { continue; } SpanInfo span = _spans[line.SpanID.Value]; SegmentInfo segment = _segments[span.SegmentID]; if (_files[line.FileID].Data == null) { //File was not found. if (_filesNotFound.Add(_files[line.FileID].Name)) { _errorCount++; } continue; } string ext = Path.GetExtension(_files[line.FileID].Name).ToLower(); bool isAsm = ext != ".c" && ext != ".h"; string comment = ""; for (int i = line.LineNumber; i >= 0; i--) { string sourceCodeLine = _files[line.FileID].Data[i]; if (sourceCodeLine.Trim().Length == 0) { //Ignore empty lines continue; } Regex regex; if (i == line.LineNumber) { regex = isAsm ? _asmFirstLineRegex : _cFirstLineRegex; } else { regex = isAsm ? _asmPreviousLinesRegex : _cPreviousLinesRegex; } Match match = regex.Match(sourceCodeLine); if (match.Success) { string matchedComment = match.Groups[1].Value.Replace("\t", " "); if (string.IsNullOrWhiteSpace(comment)) { comment = matchedComment; } else { comment = matchedComment + Environment.NewLine + comment; } } else if (i != line.LineNumber) { break; } } if (comment.Length > 0) { CodeLabel label; if (segment.IsRam) { int address = span.Offset + segment.Start; if (!_ramLabels.TryGetValue(address, out label)) { label = new CodeLabel() { Address = (UInt32)address, AddressType = AddressType.InternalRam, Label = string.Empty }; _ramLabels[span.Offset] = label; } } else { int address = span.Offset + segment.FileOffset - iNesHeaderSize; if (!_romLabels.TryGetValue(address, out label)) { label = new CodeLabel() { Address = (UInt32)address, AddressType = AddressType.PrgRom, Label = string.Empty }; _romLabels[span.Offset] = label; } } label.Comment = comment; } } catch { _errorCount++; } } }
/// <summary> /// Obtains the geometry for spans along this leg (to be called only via implementations of <see cref="GetSections"/>). /// </summary> /// <param name="start">The position for the start of the leg. /// <param name="bearing">The bearing of the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal abstract ILineGeometry[] GetSpanSections(IPosition start, double bearing, double sfac, SpanInfo[] spans);
/// <summary> /// Obtains the geometry for spans along an alternate face attached to this leg. /// </summary> /// <param name="start">The position for the start of the leg. /// <param name="end">The position for the end of the leg.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal abstract ILineGeometry[] GetSpanSections(IPosition start, IPosition end, SpanInfo[] spans);
/// <summary> /// Initializes a new instance of the <see cref="LegFace"/> class /// using the data read from persistent storage. /// </summary> /// <param name="editDeserializer">The mechanism for reading back content.</param> internal LegFace(EditDeserializer editDeserializer) { // Only connection paths should generate LegFace instances PathOperation op = (editDeserializer.CurrentEdit as PathOperation); if (op == null) throw new ApplicationException("Unexpected creating edit for a leg face"); this.Sequence = editDeserializer.ReadInternalId(DataField.Id); if (editDeserializer.IsNextField(DataField.PrimaryFaceId)) { InternalIdValue primaryFaceId = editDeserializer.ReadInternalId(DataField.PrimaryFaceId); LegFace face = op.FindFace(primaryFaceId); if (face == null) throw new ApplicationException("Cannot locate primary face " + primaryFaceId); Leg = face.Leg; Leg.AlternateFace = this; } else { // This should never happen. Primary faces are not serialized using the LegFace // class (we only use LegFace as part of a PathOperation to simplify import of // extra legs from old CEdit files). throw new ApplicationException(); } // Convert the data entry string into observed spans string entryString = editDeserializer.ReadString(DataField.EntryString); DistanceUnit defaultEntryUnit = EditingController.Current.EntryUnit; Distance[] dists = LineSubdivisionFace.GetDistances(entryString, defaultEntryUnit, false); m_Spans = new SpanInfo[dists.Length]; for (int i=0; i<m_Spans.Length; i++) { m_Spans[i] = new SpanInfo() { ObservedDistance = dists[i] }; } }
private void BuildCdlData() { int prgSize = DebugApi.GetMemorySize(SnesMemoryType.PrgRom); if (prgSize <= 0) { return; } byte[] cdlFile = new byte[prgSize]; byte[] prgRomContent = DebugApi.GetMemoryState(SnesMemoryType.PrgRom); //Mark data/code regions foreach (SpanInfo span in _spans.Values) { if (_scopeSpans.Contains(span.ID)) { //Skip any span used by a scope, they don't correspond to an actual line of code continue; } int prgAddress = GetPrgAddress(span); if (prgAddress >= 0 && prgAddress < prgSize) { for (int i = 0; i < span.Size; i++) { if (cdlFile[prgAddress + i] != (byte)CdlFlags.Data && !span.IsData && span.Size <= 4) { cdlFile[prgAddress + i] = (byte)CdlFlags.Code; byte opCode = prgRomContent[prgAddress]; if (span.Size == 2) { if (IsVarWidthMemoryInstruction(opCode)) { //8-bit immediate memory operation, set M flag cdlFile[prgAddress + i] |= (byte)CdlFlags.MemoryMode8; } else if (IsVarWidthIndexInstruction(opCode)) { //8-bit immediate index operation, set X flag cdlFile[prgAddress + i] |= (byte)CdlFlags.IndexMode8; } } } else if (span.IsData) { cdlFile[prgAddress + i] = (byte)CdlFlags.Data; } else if (cdlFile[prgAddress + i] == 0) { //Mark bytes as tentative data, until we know that the bytes are actually code cdlFile[prgAddress + i] = 0x04; } } } } for (int i = 0; i < cdlFile.Length; i++) { if (cdlFile[i] == 0x04) { //Mark all bytes marked as tentative data as data cdlFile[i] = (byte)CdlFlags.Data; } } //Find/identify functions and jump targets foreach (SymbolInfo symbol in _symbols.Values) { LineInfo line; if (!symbol.SegmentID.HasValue) { //This is a constant, ignore it continue; } foreach (int reference in symbol.References) { if (_lines.TryGetValue(reference, out line) && line.SpanIDs.Count > 0) { SpanInfo span; if (_spans.TryGetValue(line.SpanIDs[0], out span) && !span.IsData && span.Size <= 4) { int referencePrgAddr = GetPrgAddress(span); if (referencePrgAddr >= 0 && referencePrgAddr < prgRomContent.Length) { byte opCode = prgRomContent[referencePrgAddr]; if (IsBranchInstruction(opCode)) { //This symbol is used with a JSR/jump instruction, so it's either a function or jump target bool isJsr = opCode == 0x20 || opCode == 0x22; //JSR/JSL SpanInfo definitionSpan = GetSymbolDefinitionSpan(symbol); if (definitionSpan != null) { int definitionPrgAddr = GetPrgAddress(definitionSpan); if (definitionPrgAddr >= 0 && definitionPrgAddr < prgRomContent.Length) { cdlFile[definitionPrgAddr] |= (byte)(isJsr ? CdlFlags.SubEntryPoint : CdlFlags.JumpTarget); break; } } } } } } } } DebugApi.SetCdlData(CpuType.Cpu, cdlFile, cdlFile.Length); }
public void DiskBufferChanged(object sender, TextContentChangedEventArgs e) { foreach (var change in e.Changes) { int closest; if (TryGetSingleStartSpan(e, change, out closest)) { var closestSpan = _spans[closest]; int recalcPosition = -1; bool recalc = false; if (closestSpan.Kind == TemplateTokenKind.Text) { // we're in a section of HTML or whatever language the actual template is being applied to. // First, check and see if the user has just pasted some code which includes a template, // in which case we'll recalculate everything. if (!(recalc = ContainsTemplateMarkup(change))) { // Then see if they inserted/deleted text creates a template tag by being merged // with the text around us. if (change.NewSpan.Start != 0 && change.NewSpan.End < e.After.Length) { // Check if the character before us plus the inserted character(s) makes a template tag var newText = e.After.GetText(new Span(change.NewSpan.Start - 1, 2)); if (Array.IndexOf(_templateTags, newText) != -1) { if (closest != 0) { recalcPosition = _spans[--closest].DiskBufferSpan.GetStartPoint(e.After); } else { recalcPosition = _spans[closest].DiskBufferSpan.GetStartPoint(e.After); } recalc = true; } } if (!recalc && change.NewSpan.End >= 2) { // check if we inserted template tags at the end var newText = e.After.GetText(new Span(change.NewSpan.End - 2, 2)); if (Array.IndexOf(_templateTags, newText) != -1) { if (closest != 0) { recalcPosition = _spans[--closest].DiskBufferSpan.GetStartPoint(e.After); } else { recalcPosition = _spans[closest].DiskBufferSpan.GetStartPoint(e.After); } recalc = true; } } if (!recalc && change.NewSpan.Start + 2 <= e.After.Length) { // check if the inserted char plus the char after us makes a template tag var newText = e.After.GetText(new Span(change.NewSpan.Start, 2)); if (Array.IndexOf(_templateTags, newText) != -1) { if (closest != 0) { recalcPosition = _spans[--closest].DiskBufferSpan.GetStartPoint(e.After); } else { recalcPosition = _spans[closest].DiskBufferSpan.GetStartPoint(e.After); } recalc = true; } } } if (!recalc && change.NewSpan.Start == closestSpan.DiskBufferSpan.GetStartPoint(e.After) && change.NewSpan.Length == 0) { // finally, if we are just deleting code (change.NewSpan.Length == 0 indicates there's no insertions) from // the start of the buffer then we are definitely deleting a } which means we need to re-calc. We know // we're deleting the } because it's the last char in the buffer before us because it has // to be the end of a template. closestSpan = _spans[0]; closest = 0; recalc = true; } } else { // check if the newly inserted text makes a tag, we include the character before // our span and the character after. Span changeBounds = change.NewSpan; if (changeBounds.Start > 0) { changeBounds = new Span(changeBounds.Start - 1, changeBounds.Length + 1); } if (changeBounds.End < e.After.Length) { changeBounds = new Span(changeBounds.Start, changeBounds.Length + 1); } var newText = e.After.GetText(changeBounds); foreach (var tag in _templateTags) { if (newText.Contains(tag)) { recalc = true; break; } } if (!recalc) { var templateStart = closestSpan.DiskBufferSpan.GetStartPoint(e.After); if (change.NewSpan.Start <= templateStart + 1 || change.NewSpan.End == closestSpan.DiskBufferSpan.GetEndPoint(e.After) - 1) { // we are altering one of the 1st two characters or the last character. // Because we're a template that could be messing us up. // We recalcuate from the previous text buffer // because the act of deleting this character could have turned us into a text // buffer, and we need to replace and extend the previous text buffer. recalcPosition = _spans[--closest].DiskBufferSpan.GetStartPoint(e.After); recalc = true; } } } if (recalc) { var start = recalcPosition != -1 ? recalcPosition : closestSpan.DiskBufferSpan.GetStartPoint(e.After).Position; var reader = new SnapshotSpanSourceCodeReader(new SnapshotSpan(e.After, Span.FromBounds(start, e.After.Length))); UpdateTemplateSpans(reader, closest, start); } else if (closestSpan.Kind == TemplateTokenKind.Block) { // re-parse the block _spans[closest] = new SpanInfo( closestSpan.DiskBufferSpan, closestSpan.Kind, DjangoBlock.Parse(closestSpan.DiskBufferSpan.GetText(closestSpan.DiskBufferSpan.TextBuffer.CurrentSnapshot)) ); } } else { UpdateTemplateSpans(new StringReader(e.After.GetText())); } } }
/// <summary> /// Renders the geometry for the spans along a leg. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="spans">Information about each observed span</param> /// <param name="sections">The geometry that corresponds to each span</param> void DrawSpans(ISpatialDisplay display, SpanInfo[] spans, ILineGeometry[] sections) { Debug.Assert(spans.Length == sections.Length); IDrawStyle solidStyle = EditingController.Current.Style(Color.Magenta); IDrawStyle dottedStyle = new DottedStyle(Color.Magenta); for (int i = 0; i < spans.Length; i++) { ILineGeometry geom = sections[i]; IDrawStyle style = (spans[i].HasLine ? solidStyle : dottedStyle); if (geom is IClockwiseCircularArcGeometry) style.Render(display, (IClockwiseCircularArcGeometry)geom); else style.Render(display, new IPosition[] { geom.Start, geom.End }); if (spans[i].HasEndPoint) solidStyle.Render(display, geom.End); } }
/// <summary> /// Inserts a new distance into this face. /// </summary> /// <param name="index">The index where the new distance should go.</param> /// <param name="newdist">The distance to insert.</param> /// <param name="wantLine">Should a new line be created (it won't happen until rollforward /// occurs, but it will get marked to happen).</param> void InsertAt(int index, Distance newdist, bool wantLine) { // Expand the array of span data int numSpan = NumSpan; SpanInfo[] newSpans = new SpanInfo[numSpan + 1]; // Copy over stuff prior to the new distance for (int i = 0; i < index; i++) newSpans[i] = m_Spans[i]; // Stick in the new guy with miss-connect flag SpanInfo extraSpan = new SpanInfo(); extraSpan.ObservedDistance = newdist; extraSpan.Flags = LegItemFlag.MissConnect; newSpans[index] = extraSpan; // If a line is required, flag it for creation when rollforward runs (we can't do // it right now, since the end positions are currently coincident). if (wantLine) extraSpan.Flags |= LegItemFlag.NewLine; // Copy over the rest. for (int i = index; i < numSpan; i++) newSpans[i + 1] = m_Spans[i]; // Replace original arrays with the new ones m_Spans = newSpans; /* // If we inserted at the very start, ensure that any // deflection angle switch is still with the very first span. if (index==0 && (m_Spans[1].Flags & LegItemFlag.Deflection)!=0) { m_Spans[0].Flags |= LegItemFlag.Deflection; m_Spans[1].Flags &= (~LegItemFlag.Deflection); } */ }
bool PushSpan(Stack <SpanInfo> formatStack, string markup, int textIndex, ref int i) { // <span kk="jj"> int k = i; k++; // Skip the < string tag; if (!ReadId(markup, ref k, out tag)) { return(false); } SpanInfo span = new SpanInfo(); span.Tag = tag; switch (tag) { case "b": span.Add(new FontWeightTextAttribute() { Weight = FontWeight.Bold }); break; case "i": span.Add(new FontStyleTextAttribute() { Style = FontStyle.Italic }); break; case "s": span.Add(new StrikethroughTextAttribute()); break; case "u": span.Add(new UnderlineTextAttribute()); break; case "span": ParseAttributes(span, markup, ref k); break; // case "small": // case "big": // case "tt": } if (span.Count == 0) { return(false); } if (!ReadCharToken(markup, '>', ref k)) { return(false); } foreach (var att in span) { att.StartIndex = textIndex; } formatStack.Push(span); i = k; return(true); }
public void Import(string path, bool silent = false) { string[] fileRows = File.ReadAllLines(path); string basePath = Path.GetDirectoryName(path); foreach (string row in fileRows) { try { if (LoadLines(row) || LoadSpans(row) || LoadSymbols(row) || LoadCSymbols(row) || LoadFiles(row, basePath) || LoadSegments(row)) { continue; } } catch { _errorCount++; } } LoadFileData(basePath); int prgSize = InteropEmu.DebugGetMemorySize(DebugMemoryType.PrgRom); if (prgSize > 0) { byte[] cdlFile = new byte[prgSize]; foreach (KeyValuePair <int, SpanInfo> kvp in _spans) { SegmentInfo segment; if (_segments.TryGetValue(kvp.Value.SegmentID, out segment)) { if (!segment.IsRam && kvp.Value.Size != segment.Size) { int prgAddress = kvp.Value.Offset + segment.FileOffset - iNesHeaderSize; if (prgAddress >= 0 && prgAddress < prgSize) { for (int i = 0; i < kvp.Value.Size; i++) { if (cdlFile[prgAddress + i] == 0 && !kvp.Value.IsData && kvp.Value.Size <= 3) { cdlFile[prgAddress + i] = (byte)0x01; } else if (kvp.Value.IsData) { cdlFile[prgAddress + i] = (byte)0x02; } } } } } } InteropEmu.DebugSetCdlData(cdlFile); } foreach (LineInfo line in _lines.Values) { if (line.SpanID == null) { continue; } FileInfo file = _files[line.FileID]; SpanInfo span = _spans[line.SpanID.Value]; SegmentInfo segment = _segments[span.SegmentID]; if (!segment.IsRam) { for (int i = 0; i < span.Size; i++) { int prgAddress = segment.FileOffset - iNesHeaderSize + span.Offset + i; LineInfo existingLine; if (_linesByPrgAddress.TryGetValue(prgAddress, out existingLine) && existingLine.Type == LineType.External) { //Give priority to lines that come from C files continue; } _linesByPrgAddress[prgAddress] = line; if (i == 0) { _prgAddressByLine[file.ID.ToString() + "_" + line.LineNumber.ToString()] = prgAddress; } } } } LoadLabels(); int labelCount = 0; DebugImportConfig config = ConfigManager.Config.DebugInfo.ImportConfig; if (config.DbgImportComments) { LoadComments(); } if (config.DbgImportPrgRomLabels) { LabelManager.SetLabels(_romLabels.Values); labelCount += _romLabels.Count; } if (config.DbgImportRamLabels) { LabelManager.SetLabels(_ramLabels.Values); labelCount += _ramLabels.Count; } if (!silent) { if (_errorCount > 0) { _errorCount -= _filesNotFound.Count; string message = $"Import completed with {labelCount} labels imported"; if (_errorCount > 0) { message += $"and {_errorCount} errors - please file a bug report and attach the DBG file you tried to import."; } if (_filesNotFound.Count > 0) { message += Environment.NewLine + Environment.NewLine + "The following files could not be found:"; foreach (string file in _filesNotFound) { message += Environment.NewLine + file; } } MessageBox.Show(message, "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { MessageBox.Show($"Import completed with {labelCount} labels imported.", "Mesen", MessageBoxButtons.OK, MessageBoxIcon.Information); } } }
/// <summary> /// Obtains the geometry for spans along this leg. /// </summary> /// <param name="bc">The position for the start of the leg. /// <param name="bcBearing">The bearing on entry into the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition bc, double bcBearing, double sfac, SpanInfo[] spans) { // Can't do anything if the leg radius isn't defined if (m_Metrics.ObservedRadius == null) throw new InvalidOperationException("Cannot create sections for circular leg with undefined radius"); var result = new ILineGeometry[spans.Length]; // Use supplied stuff to derive info on the center and EC. IPosition center; IPosition ec; double bearingToBC; double ecBearing; GetPositions(bc, bcBearing, sfac, out center, out bearingToBC, out ec, out ecBearing); // Define the underlying circle ICircleGeometry circle = new CircleGeometry(PointGeometry.Create(center), BasicGeom.Distance(center, bc)); // Handle case where the leg is a cul-de-sac with no observed spans if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = new CircularArcGeometry(circle, bc, ec, m_Metrics.IsClockwise); return result; } /// Initialize scaling factor for distances in cul-de-sacs (ratio of the length calculated from /// the CA & Radius, versus the observed distances that were actually specified). For curves that /// are not cul-de-sacs, this will be 1.0 double culFactor = 1.0; if (m_Metrics.IsCulDeSac) { double obsv = PrimaryFace.GetTotal(); if (obsv > MathConstants.TINY) culFactor = Length.Meters / obsv; } IPosition sPos = bc; IPosition ePos = null; bool isClockwise = m_Metrics.IsClockwise; double radius = RadiusInMeters; double edist = 0.0; for (int i = 0; i < result.Length; i++, sPos = ePos) { // Add on the unscaled distance edist += spans[i].ObservedDistance.Meters; // Get the angle subtended at the center of the circle. We use // unscaled values here, since the scale factors would cancel out. // However, we DO apply any cul-de-sac scaling factor, to account // for the fact that the distance may be inconsistent with the // curve length derived from the CA and radius. For example, it // is possible that the calculated curve length=200, although the // total of the observed spans is somehow only 100. In that case, // if the supplied distance is 50, we actually want to use a // value of 50 * (200/100) = 100. double angle = (edist * culFactor) / radius; // Get the bearing of the point with respect to the center of the circle. double bearing; if (isClockwise) bearing = bearingToBC + angle; else bearing = bearingToBC - angle; // Calculate the position using the scaled radius. ePos = Geom.Polar(center, bearing, radius * sfac); result[i] = new CircularArcGeometry(circle, sPos, ePos, isClockwise); } return result; }