private void AddSampleDataToLinesTable(LinesLayer layer, SpatialDataTable dt) { int nplines = 15 / Layers.CountAll((l) => l.Visible && l is LinesLayer); var rnd = new Random(Layers.IndexOf(layer)); // this ensures same data for same layer but different points for different layers for (int i = 0; i < nplines; ++i) { LinesDataRow row = (LinesDataRow)dt.NewRow(); var lineStyle = layer.LineStyle; row.Latitude0 = rnd.Next(SampleLatMin, SampleLatMax); row.Longitude0 = rnd.Next(SampleLonMin, SampleLonMax); row.Latitude1 = rnd.Next(SampleLatMin, SampleLatMax); row.Longitude1 = rnd.Next(SampleLonMin, SampleLonMax); row.LineStroke = lineStyle.StrokeColor; row.DashStyle = lineStyle.DashStyle; dt.Add(row); } }
private Image BuildMap(List <SpatialDataTable> datas, bool designTime) { if (designTime) { foreach (KmlLayer layer in Layers.FindAll((l) => l is KmlLayer)) { layer.RemoveFromOwner(); } } else { var calcLayers = GetCalculatedKmlLayers(); calcLayers.ForEach((l) => l.RemoveFromOwner()); } _c1mapper.ClearMarks(); _c1mapper.ResetBoundingPoints(); _c1mapper.Width = (this.Width * ScreenDpiX) / TwipsIn; _c1mapper.Height = (this.Height * ScreenDpiY) / TwipsIn; // 1st pass: add KML layers, retrieve coordinates from other layers for auto-zoom/center: foreach (LayerBase layer in Layers.FindAll((l) => l.Visible && (l is KmlLayer || l.Track))) { if (layer is KmlLayer) { ((KmlLayer)layer).SetKmlOnOwner(); } else // layer.Track { SpatialDataTable dt = datas.Find((t) => t.LayerKey == layer.Key); dt.ForEach((row) => row.ForAllPoints((lon, lat) => _c1mapper.AddBoundingPoint(lon, lat))); } } // now we can auto zoom/center as all relevant spatial data has been given to the mapper: _c1mapper.DoCenterAndZoom(); // 2nd pass: add points/lines layers: foreach (LayerBase layer in Layers.FindAll((l) => l.Visible && !(l is KmlLayer))) { // considering that no of layers should not be large, this is ok: SpatialDataTable dt = datas.Find((t) => t.LayerKey == layer.Key); if (dt.RowType == typeof(PointsDataRow)) { var l = (PointsLayer)layer; // clustering: var clusterDist = l.ClusterDistance; var maxClusterSize = 0; if (clusterDist > 0) { for (int i = 0; i < dt.Count; ++i) { var r = (PointsDataRow)dt[i]; for (int j = dt.Count - 1; j > i; --j) { var r2 = (PointsDataRow)dt[j]; if (_c1mapper.DistancePix(r.Longitude, r.Latitude, r2.Longitude, r2.Latitude) < clusterDist) { maxClusterSize = Math.Max(maxClusterSize, ++r.Count); dt.RemoveAt(j); } } } } // spread styles among clusters: var styleCount = l.ClusterStyles != null ? l.ClusterStyles.Count : 0; var q = l.ClusterDistribution == ScaleType.Linear ? ((styleCount - 1f) / (maxClusterSize - 2f)) : 1f; // add clustered points to the map: dt.ForEach((row) => { PointsDataRow r = (PointsDataRow)row; if (r.Count > 1) { r.Caption = r.Count.ToString(CultureInfo.InvariantCulture); if (styleCount > 0) { // we have a style to apply: int idx; if (l.ClusterDistribution == ScaleType.Linear) { idx = (int)Math.Round((r.Count - 2) * q); } else { var t = Math.Log(r.Count - 1, maxClusterSize - 1); if (double.IsNaN(t)) { t = 0; } idx = (int)Math.Round(t * (styleCount - 1d)); } var s = l.ClusterStyles[idx]; r.Font = s.Font; r.TextColor = s.TextColor; r.MarkerShape = s.Shape; // todo: eval expr here, allow to use Count? r.MarkerSize = Maps.Util.GetDouble(s.SizeExpr, MarkerStyle.c_SizeValue); r.MarkerStroke = s.StrokeColor; r.MarkerFill = s.FillColor; } } _c1mapper.DrawPoint(layer.Key, r.Longitude, r.Latitude, r.Caption, r.Font, r.TextColor, r.MarkerShape, r.MarkerSize, r.MarkerStroke, r.MarkerFill); } ); } else if (dt.RowType == typeof(LinesDataRow)) { // add lines to the map: dt.ForEach((row) => { LinesDataRow r = (LinesDataRow)row; _c1mapper.DrawLine(layer.Key, r.Longitude0, r.Latitude0, r.Longitude1, r.Latitude1, r.LineStroke, r.DashStyle, r.LineThickness); } ); } } // done: return(_c1mapper.GetImage(TargetDpi, TargetDpi)); }