|
IDEA
|
I'd like to see both wizards and tools in Pro as well. ArcMap's "Extract Data" wizard is especially handy for creating sample datasets to send to Esri tech support.
... View more
02-14-2020
08:00 AM
|
1
|
0
|
861
|
|
POST
|
Looks like 100.7 finally fixed the problem. It's interesting that ToJSON returns the full CIM definition; nonetheless, I was able to update the colors successfully. I notice I can still substitute the simpler style JSON used in the Guide as well. private static void UpdateTextSymbol(Dictionary<string, object>labelDef, string sLayerName)
{
Dictionary<string, object> txtSymbol = labelDef["symbol"] as Dictionary<string, object>;
Dictionary<string, object> txtSym = txtSymbol["symbol"] as Dictionary<string, object>;
Dictionary<string, object> polySymbol = txtSym["symbol"] as Dictionary<string, object>;
object[] symbolLayers = polySymbol["symbolLayers"] as object[];
Dictionary<string, object> lyr = symbolLayers[0] as Dictionary<string, object>;
switch (sLayerName)
{
// Landbase labels
case "Street Name":
case "Street Centerline":
lyr["color"] = new object[] { 255, 0, 0, 255 };
break;
case "Lot Number":
lyr["color"] = new object[] { 170, 255, 0, 255 };
break;
// Gas labels
case "Meter Setting":
lyr["color"] = new object[] { 255, 0, 0, 255 };
break;
case "Distribution Main":
case "High Pressure Distribution Main":
case "Transmission Main":
lyr["color"] = new object[] { 255, 255, 0, 255 };
break;
}
}
... View more
02-11-2020
02:32 PM
|
0
|
0
|
1951
|
|
POST
|
I took a quick look, and symbols look good without the workaround. Thanks!
... View more
02-07-2020
06:07 AM
|
1
|
0
|
782
|
|
POST
|
I've been busy on other projects, but I hope to check out all of my reported issues this month.
... View more
02-05-2020
12:34 PM
|
0
|
0
|
782
|
|
BLOG
|
Being a user of Microsoft Visual Studio since version 6.0, I prefer it as a one-stop shop for as many kinds of development as possible, including C++, VB, C#, Python, and HTML5/TypeScript projects. One feature of VS that I really like is the ability to create project templates. VS2015 included a project template for TypeScript, but it was ugly as sin. VS2017 dropped it, but failed to provide a viable alternative; being lazy, I continued to use the same version available online: This must stop! Sometimes, you just have to get your hands dirty, so I decided to create my own project template from scratch. Fortunately, the TypeScript documentation has sections on Integrating with Build Tools, and Compiler Options in MSBuild, which provided valuable assistance. Also, see the MSBuild documentation and How to: Create project templates for more information. Prerequisites: The TypeScript website has download links to install the latest version for a number of IDEs, including VS2017. In addition, since the TypeScript folks now prefer you to use npm to install typings; you should install Node. Warning! If you are behind a corporate firewall, you may run into this error when you try to use npm to install typings: npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY If you see that, try setting this configuration at the command prompt: npm config set strict-ssl false Create a generic TypeScript project: While, formally, the best approach would be to create a new project type, my lazy approach recycles the C# project type and redefines the build targets (but there is a disadvantage – see below). The first step is to create a blank solution in VS2017 named “TypeScriptProjectTemplates.” In Explorer or the Command Prompt, navigate to the solution folder and create a subfolder named “BasicTypeScriptTemplate.” In that folder, create a file named “BasicTypeScriptTemplate.csproj,” containing the following text: <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<OutputType>Library</OutputType>
<StartupObject />
<OutputPath>.\</OutputPath>
<IntermediateOutputPath>vs\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
</PropertyGroup>
<PropertyGroup>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<TypeScriptModuleKind>amd</TypeScriptModuleKind>
<TypeScriptNoImplicitAny>true</TypeScriptNoImplicitAny>
<TypeScriptESModuleInterop>true</TypeScriptESModuleInterop>
<TypeScriptJSXEmit>react</TypeScriptJSXEmit>
<TypeScriptJSXFactory>tsx</TypeScriptJSXFactory>
<TypeScriptTarget>es5</TypeScriptTarget>
<TypeScriptExperimentalDecorators>true</TypeScriptExperimentalDecorators>
<TypeScriptPreserveConstEnums>true</TypeScriptPreserveConstEnums>
<TypeScriptSuppressImplicitAnyIndexErrors>true</TypeScriptSuppressImplicitAnyIndexErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<TypeScriptRemoveComments>false</TypeScriptRemoveComments>
<TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptRemoveComments>true</TypeScriptRemoveComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets')" />
<Target Name="Build" DependsOnTargets="CompileTypeScript">
</Target>
<Target Name="Rebuild" DependsOnTargets="CompileTypeScript">
</Target>
<Target Name="Clean" Condition="Exists('$(TSDefaultOutputLog)')">
<ItemGroup>
<TSOutputLogsToDelete Include="$(TSDefaultOutputLog)" />
</ItemGroup>
<ReadLinesFromFile File="@(TSOutputLogsToDelete)">
<Output TaskParameter="Lines" ItemName="TSCompilerOutput" />
</ReadLinesFromFile>
<Delete Files="@(TSCompilerOutput)" Condition=" '@(TSCompilerOutput)' != '' " />
<Delete Files="@(TSOutputLogsToDelete)" />
<!-- <RemoveDir Directories="$(IntermediateOutputPath)" /> -->
</Target>
</Project>
In VS2017, add the existing project to the solution. Within the project, create an “app” subfolder, and add a new TypeScript file named “main.ts,” containing the following text: class Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
interface Person {
firstName: string;
lastName: string;
}
function greeter(person: Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
let user = new Student("Jane", "M.", "User");
document.body.textContent = greeter(user);
In the project folder, add an HTML Page file named “index.html,” containing the following text: <!DOCTYPE html>
<html>
<head>
<title>TypeScript Greeter</title>
</head>
<body>
<script src="./app/main.js"></script>
</body>
</html> At this point, the project should look like this in Solution Explorer: Building or rebuilding the project will generate TypeScript compiler output, and a file named “Tsc.out” will be created in a subfolder named “vs”. The “Tsc.out” file defines the compiler output to delete when cleaning the project; cleaning the project will also delete that file. [Note that if you build and clean “Release” without cleaning “Debug” beforehand, the source map files will still remain.] Export the project template: At this point, if you export the project to a template, you have a generic TypeScript project template. However, it will be displayed under the “Visual C#” category. If you want it to appear under the “TypeScript” category, there are additional steps to take. First, unzip the template to a new folder and edit “MyTemplate.vstemplate:” Change the “ProjectType” value from “CSharp” to “TypeScript”. Zip the contents of the folder to a new zip file, and the template is ready to use. Building a JSAPI project template: Now that we have a basic TypeScript project template, the next step is to use it to create a template for a simple JavaScript API project. First, create a new project, called “ArcGIS4xTypeScriptTemplate,” using the template created above. Open a Command Prompt, navigate to the project folder, and enter the following commands: npm init --yes
npm install --save @types/arcgis-js-api Back in Solution Explorer, select the project and click the “Show All Files” button. Select the “node_modules” folder, “package.json,” and “package-lock.json,” right-click, and select “Include In Project.” Finally, replace the contents of “main.ts” and “index.html” with the text given at the JSAPI TypeScript walk-through. Your project should now look like this: You may notice that the “import” statements in “main.ts” are marked as errors, even though the esModuleInterop flag is set in the project: This appears to be a defect in the Visual Studio extension. The project will build without errors, and the resulting page will load correctly. If it annoys you, you can always revert to the older AMD style statements: At this point, you’re ready to export the template. On a final note: The JavaScript API is updated frequently, which means that you may also want to keep your project templates up to date. Rather than updating the source project and repeating the export steps, you might want to consider keeping the unzipped template folders in a standard location, and updating those directly. Then, all you have to do is zip them to create the updated template.
... View more
01-10-2020
09:34 AM
|
2
|
0
|
1802
|
|
BLOG
|
While the "Failed to create Worker" warnings occur at 4.12, they don't occur at 4.14, so whatever issue was causing them appears to have been fixed.
... View more
01-06-2020
02:46 PM
|
0
|
0
|
4749
|
|
POST
|
This affects cookies sent by server-side code only, so this is something that concerns Esri. These warnings are temporary and will go away with the stable Chrome 80 release, because at that point any deprecated cookies will simply be blocked. In the meantime, if you're debugging and these warnings annoy you, you can disable them using chrome://flags ("Cookie deprecation messages"). Should client side developers be concerned? That shouldn't affect your app at all, as far as I can tell, EXCEPT for one situation: if you're developing a Chrome extension that uses chrome.cookies. If your extension's logic relies on monitoring a cookie that becomes deprecated, then you have cause for concern, but there's nothing you can do unless you're also the server-side developer (or have the developer's ear!). Then, the Stack Overflow link given above is pertinent.
... View more
01-06-2020
01:05 PM
|
0
|
0
|
6883
|
|
BLOG
|
Recently, I found myself painted into a corner. Some time ago, I'd created custom tile caches for use with Runtime .NET, which had one scale level defined. They worked just fine in 10.2.7, but on preparing to upgrade to 100.x, I discovered that they caused 100.6 to hang up. The workaround was simple enough, namely to define additional scale levels, even if they weren't populated. However, the task of modifying the caches for nearly 150 users proved so daunting, that I decided to let the app itself make the modification. Updates to the app are automatically detected and downloaded, which provides a simpler mechanism than deploying a script to everyone's machine. It's not a perceptible performance hit as it is, and later on, as part of another update, I can simply deactivate it. So here's the code: using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace NavAddin
{
/*
* Runtime 100.6 BUG: Tile caches that have only one scale level level defined will hang up on loading.
* WORKAROUND: Define additional scale levels
* [Assumes that 100 < scale level < 24000]
*/
public static class TileCacheHelper
{
public const string L0Scale = "24000";
public const string L0Resolution = "20.833375000083333";
public const string L2Scale = "100";
public const string L2Resolution = "0.086805729167013887";
public static bool CheckTileCache(string sPath)
{
// Check if tile cache (i.e. a folder)
if (!Directory.Exists(sPath))
return true; // Not a tile cache
// Check if one scale level defined
string sConfigPath = Path.Combine(sPath, "conf.xml");
StreamReader sr = new StreamReader(sConfigPath);
XDocument xDoc = XDocument.Load(sr);
sr.Close();
XElement xRoot = xDoc.Root;
XElement xTCInfo = xRoot.Element("TileCacheInfo");
XElement xLODInfos = xTCInfo.Element("LODInfos");
int iLevelCount = xLODInfos.Elements("LODInfo").Count();
if (iLevelCount > 1)
return true; // Not a problem
if (iLevelCount < 1)
return false; // This should never happen?
// Check if scale level is between 100 (L2) and 24000 (L0)
XElement xLODInfo, xLevelID, xScale, xResolution;
xLODInfo = xLODInfos.Element("LODInfo");
xScale = xLODInfo.Element("Scale");
string sScale = xScale.Value;
double dScale = Convert.ToDouble(sScale);
double dL0Scale = Convert.ToDouble(L0Scale);
double dL2Scale = Convert.ToDouble(L2Scale);
if (dScale >= dL0Scale)
return false;
if (dScale <= dL2Scale)
return false;
// Redefine scale levels
xLevelID = xLODInfo.Element("LevelID");
xLevelID.Value = "1";
XElement xLOD0 = new XElement(xLODInfo);
xLevelID = xLOD0.Element("LevelID");
xLevelID.Value = "0";
xScale = xLOD0.Element("Scale");
xScale.Value = L0Scale;
xResolution = xLOD0.Element("Resolution");
xResolution.Value = L0Resolution;
xLODInfos.AddFirst(xLOD0);
XElement xLOD2 = new XElement(xLODInfo);
xLevelID = xLOD2.Element("LevelID");
xLevelID.Value = "2";
xScale = xLOD2.Element("Scale");
xScale.Value = L2Scale;
xResolution = xLOD2.Element("Resolution");
xResolution.Value = L2Resolution;
xLODInfos.Add(xLOD2);
// Write config file
StreamWriter sw = new StreamWriter(sConfigPath);
xDoc.Save(sw);
sw.Close();
// Rename L00 folder to L01
string sLayersPath = Path.Combine(sPath, "_alllayers");
string sL00Path = Path.Combine(sLayersPath, "L00");
string sL01Path = Path.Combine(sLayersPath, "L01");
Directory.Move(sL00Path, sL01Path);
return true;
}
}
}
... View more
11-13-2019
12:53 PM
|
0
|
0
|
779
|
|
POST
|
It seems to be working now (sort of -- it doesn't let me modify my contact information). It did not work for me at all last week.
... View more
11-12-2019
05:43 AM
|
0
|
0
|
1678
|
|
BLOG
|
At some point in the 100.x lifespan of ArcGIS Runtime SDK for .NET, the old tried-and-true method of treating a MapView as just another WPF Visual went sailing out the window. Granted, the ExportImageAsync method should have been a simple workaround, but for one drawback: overlay items are not included! Now I don't know about you, but I find the OverlayItemsControl to be a great way to add interactive text to a map. You can have it respond to a mouse-over: Bring up a context menu: Modify properties: And so on. In the old days, when you created an image of the MapView, the overlays would just come right along: private RenderTargetBitmap GetMapImage(MapView mv)
{
// Save map transform
System.Windows.Media.Transform t = mv.LayoutTransform;
Rect r = System.Windows.Controls.Primitives.LayoutInformation.GetLayoutSlot(mv);
mv.LayoutTransform = null;
Size sz = new Size(mv.ActualWidth, mv.ActualHeight);
mv.Measure(sz);
mv.Arrange(new Rect(sz));
// Output map
RenderTargetBitmap rtBitmap = new RenderTargetBitmap(
(int)sz.Width, (int)sz.Height, 96d, 96d,
System.Windows.Media.PixelFormats.Pbgra32);
rtBitmap.Render(mv);
// Restore map transform
mv.Arrange(r);
mv.LayoutTransform = t;
return rtBitmap;
}
Not so today! Try that approach in 100.6 and you just get a black box. My workaround: Create a Canvas Create an Image for the Mapview and add it to the Canvas Create an Image for every overlay and add it to the Canvas Create a bitmap from the Canvas Step 3 is trickier than you would think, however, because of two issues: 1) relating the anchor point to the overlay, and 2) taking any RenderTransform into account. As far as I can tell, this is the rule for determining the relationship between the overlay and the anchor point: HorizontalAlignment: Center or Stretch, anchor point is at the center; Left, anchor point is at the right; Right, anchor point is at the left. VerticalAlignment: Center or Stretch, anchor point is at the center; Top, anchor point is at the bottom; Bottom, anchor point is at the top. For a Canvas element, the anchor point is at 0,0 -- however, I have not found a good way to create an Image from a Canvas [if the actual width and height are unknown]. To create an Image from the element, any RenderTransform must be removed before generating the RenderTargetBitmap. Then, the Transform must be reapplied to the Image. Also, you need to preserve HorizontalAlignment and VerticalAlignment if you're creating a page layout using a copy of the MapView, so that the anchor point placement is correct. So here it is, the code for my workaround: using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.UI.Controls;
namespace Workarounds
{
public struct MapOverlayExport
{
public Image OverlayImage;
public MapPoint Anchor;
public MapPoint TopLeft;
}
public static class MapExportHelper
{
// Export bitmap from map with XAML graphics overlays
public static async Task<ImageSource> GetMapImage(MapView mv)
{
RuntimeImage ri = await mv.ExportImageAsync();
ImageSource src=await ri.ToImageSourceAsync();
if (mv.Overlays.Items.Count == 0)
return src; // No XAML overlays
// Create canvas
double dWidth = mv.ActualWidth;
double dHeight = mv.ActualHeight;
Rect rMap = new Rect(0, 0, dWidth, dHeight);
Size szMap = new Size(dWidth, dHeight);
Canvas c = new Canvas();
// Add map image
Image imgMap = new Image()
{
Height = dHeight,
Width = dWidth,
Source = src
};
imgMap.Measure(szMap);
imgMap.Arrange(rMap);
imgMap.UpdateLayout();
Canvas.SetTop(imgMap, 0);
Canvas.SetLeft(imgMap, 0);
c.Children.Add(imgMap);
// Add map overlays
List<MapOverlayExport> Overlays = GetMapOverlays(mv);
foreach (MapOverlayExport overlay in Overlays)
{
// Get Image and location
Image img = overlay.OverlayImage;
MapPoint ptMap = overlay.TopLeft;
Point ptScreen = mv.LocationToScreen(ptMap);
// Create and place image of element
Canvas.SetTop(img, ptScreen.Y);
Canvas.SetLeft(img, ptScreen.X);
c.Children.Add(img);
img.UpdateLayout();
}
c.Measure(szMap);
c.Arrange(rMap);
c.UpdateLayout();
// Create RenderTargetBitmap
RenderTargetBitmap rtBitmap = new RenderTargetBitmap(
(int)dWidth, (int)dHeight, 96d, 96d, PixelFormats.Pbgra32);
rtBitmap.Render(c);
return rtBitmap;
}
public static List<MapOverlayExport> GetMapOverlays(MapView mv)
{
List<MapOverlayExport> Overlays = new List<MapOverlayExport>();
foreach (object obj in mv.Overlays.Items)
{
// Get element and location
if (!(obj is FrameworkElement elem))
{
Debug.Print("MapExportHelper: Non-FrameworkElement encountered.");
continue;
}
double dW = elem.ActualWidth;
double dH = elem.ActualHeight;
if ((dH == 0) || (dW == 0))
{
Debug.Print("MapExportHelper: Unsupported FrameworkElement encountered.");
continue;
}
// Remove RenderTransform and RenderTransformOrigin
Transform tRender = elem.RenderTransform;
Point ptOrigin = elem.RenderTransformOrigin;
elem.RenderTransform = null;
elem.RenderTransformOrigin = new Point(0,0);
elem.Measure(new Size(dW, dH));
elem.Arrange(new Rect(0, 0, dW, dH));
elem.UpdateLayout();
// Create image of element
ImageSource src=null;
if (elem is Image imgSrc)
src=imgSrc.Source;
else
{
RenderTargetBitmap bmp = new RenderTargetBitmap(
(int)dW, (int)dH, 96d, 96d, PixelFormats.Pbgra32);
bmp.Render(elem);
src=bmp;
}
Image img = new Image()
{
Height = dH,
Width = dW,
Source = src,
HorizontalAlignment = elem.HorizontalAlignment,
VerticalAlignment = elem.VerticalAlignment,
RenderTransform = tRender,
RenderTransformOrigin = ptOrigin
};
// Restore RenderTransform and RenderTransformOrigin
elem.RenderTransform = tRender;
elem.RenderTransformOrigin = ptOrigin;
// Find top left location in map coordinates
MapPoint ptMap = MapView.GetViewOverlayAnchor(elem);
Point ptScreen = mv.LocationToScreen(ptMap);
double dY = 0;
double dX = 0;
switch (elem.VerticalAlignment)
{
case VerticalAlignment.Center:
case VerticalAlignment.Stretch:
dY = -dH / 2;
break;
case VerticalAlignment.Top:
dY = -dH;
break;
}
switch (elem.HorizontalAlignment)
{
case HorizontalAlignment.Center:
case HorizontalAlignment.Stretch:
dX = -dW / 2;
break;
case HorizontalAlignment.Left:
dX = -dW;
break;
}
Point ptTopLeftScreen = new Point(ptScreen.X + dX, ptScreen.Y + dY);
MapPoint ptTopLeftMap = mv.ScreenToLocation(ptTopLeftScreen);
// Add exported overlay to list
Overlays.Add(new MapOverlayExport()
{
OverlayImage = img,
Anchor = ptMap,
TopLeft = ptTopLeftMap
});
}
return Overlays;
}
}
}
P.S. -- If you want ExportImageAsync to include overlays, vote up this idea: https://community.esri.com/ideas/17558
... View more
11-06-2019
11:30 AM
|
0
|
0
|
1332
|
|
POST
|
Is the "Session Proposals" site fully up yet? I may be blind (no news to me) but I see no path to submit a presentation.
... View more
11-06-2019
08:44 AM
|
0
|
3
|
1828
|
|
IDEA
|
In Runtime .NET 100.x, GeoView.ExportImageAsync should include overlays. Or else, OverlayItemsControl should at least inherit System.Windows.Media.Visual, or provide access to a Visual.
... View more
11-04-2019
10:28 AM
|
1
|
0
|
1446
|
|
POST
|
Is there a timeline for full curve support in Runtime? Right now, when I create MMPKs, I have to densify lines and polygons in order to get spatial queries to work with the data.
... View more
10-11-2019
09:45 AM
|
1
|
1
|
914
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 01-04-2012 06:42 AM | |
| 1 | 09-23-2021 10:42 AM | |
| 2 | 09-28-2021 07:07 AM | |
| 1 | 04-07-2021 10:31 PM | |
| 3 | 03-21-2021 01:14 PM |
| Online Status |
Offline
|
| Date Last Visited |
01-07-2022
08:31 AM
|