Retrieve new properties of an edited circle.

After changing size and position of an editable circle the Circle.Radius, Circle.Center.Latitude and Circle.Center.Longitude properties keep unchanged. Their values remain the same as when the circle was created.

How can I know the new Radius, Latitude and Longitude of an edited Circle?

 Same happens with the rectangle polygon type, bounds are kept unchanged after editing.

 

Thanks,

Aaron.

Hi,


Unfortunately it's currently not supported to retrieve updated values Circle and Polygon objects.
However, this is a good suggestion and we'll investigate if this feature can be added in a future version of the TMS WebGMaps.

Just a mention that our company is in the same boat, we need this feature: 

"Ability to retrieve updated values Circle and Polygon objects."

Can you provide an possible ETA?

Kind Regards,
Richard

At this moment we do not have an exact ETA. We need to plan-in such feature first in a next development cycle on TWebGMaps. The team is at this time fully allocated, so, it will be a matter of setting priorities when there is a first resource availability. Thanks for your understanding.

Thanks Bruno. I certainly understand the scheduling constraints a software development company deals with, but I noticed a similar feature request was asked more than 2 years ago (March 2013), so I am getting "worried" that this won't get done at all. 


http://www.tmssoftware.com/site/forum/forum_posts.asp?TID=2342&title=retrieving-the-paths-of-a-polyline

Any chance this could be bumped up the list?

Alternatively, could someone please describe how to use ExecJScript and/or provide some pointers so I could write my own routine that would make a Javascript call to the Google API?

I'd ratter have a TMS implementation but we certainly cannot wait 2 years, so if we have to, we'll attempt to write our own (with some guidance of course). 

Thanks in advance,
Richard

We'll try to schedule this in the Q1 planning.

Hi Bruno (Happy New Year).

We were in a situation were we kind of needed this sooner than later, so I took the liberty to make some changes to some of TMS source files and implemented that feature for you (please feel free to tear it apart and enhance it as you see fit, but at the moment, this works for us). So for whoever else would need this, here's how it goes:

I added a JavaScript function called printallpolygons. I also added a hidden input field where the result of the function is to be saved. 

So, in UWebGMapsConst.pas, I added the following:
(my Javascript changes are between <RD>MyChanges</RD>)


...
<script type="text/javascript">' + #13 +
                ' var map;' + #13 +
                ' var streetviewService;' + #13 +
                ' var streetviewPanorama;' + #13 +
                ' var allclusters = [];' + #13 +
                ' var clusterstyles = [];' + #13 +
                ' var allmarkers = [];' + #13 +
                ' var alllabels = [];' + #13 +
                ' var allpolylines = [];' + #13 +
                ' var allpolygons = [];' + #13 +
                ' var allkmllayers = [];' + #13 +
                ' var allinfowindows = [];' + #13 +
                ' var trafficLayer;' + #13 +
                ' var bicyclingLayer;' + #13 +
                ' var panoramioLayer;' + #13 +
                ' var cloudLayer;' + #13 +
                ' var weatherLayer;' + #13 +
                ' var directionsDisplay;' + #13 +
                ' var directionsService = new google.maps.DirectionsService();' + #13 +

                //<RD>
                ' function printallpolygons(){' + #13 +

                //'alert(" printallpolygons: " + allpolygons.length);'+

                '  var str = "";' + #13 +
                '  for (var i = 0; i < allpolygons.length; i++){' + #13 +

                // 'alert(" forloop: " + i);'+

                '     var polygonBounds = allpolygons.getPath();' + #13 +
                '     var xy;' + #13 +

                { Iterate over the polygonBounds vertices and build a string
                  that will contain the lat and long of all the polygons. Each
                  value (rows) will be delimited by a semi-colon ";".
                  Ex:
                  Polygone[0] Coordinate[0] LAT[44.1234567] LNG[103.123456887];
                  Polygone[0] Coordinate[1] LAT[44.1345566] LNG[103.231234567];
                  Polygone[0] Coordinate[2] LAT[44.4567889] LNG[103.451234567];
                  Polygone[0] Coordinate[3] LAT[44.5757567] LNG[103.671244567];
                  Polygone[1] Coordinate[0] LAT[44.1234567] LNG[103.89345367];
                  Polygone[1] Coordinate[1] LAT[44.7574565] LNG[103.103463567];
                  Polygone[1] Coordinate[2] LAT[44.0984233] LNG[103.118842567];

                }
                '     for (var j = 0; j < polygonBounds.length; j++) {' + #13 +
                '       xy = polygonBounds.getAt(j);' + #13 +
                '       str += "Polygon[" + i + "] Coordinate[" + j + "] LAT[" + xy.lat() + "] LNG[" + xy.lng() + "];";' + #13 +
                '     }' + #13 +
                '  }' + #13 +
                // Save the result string into our hidden input (i.e. "result")
                '  document.getElementById("result").value = str;' + #13 +
                '}' + #13 +
                //</RD>

                ' function setzoommap(newzoom) {' + #13 +
...

Then at the very bottom of the unit, the hidden input field:

...
<body>' + #13 +
                '  <div id="map_canvas"></div>' + #13 +

                //<RD>
                // Hidden input that will be used to get the result from Javascript
                // See the printAllPolygons Javascript function defined above.)
                '  <input type="hidden" name="result" id="result" value="" />' + #13 +
                //</RD>

                '</body>' + #13 +
                '</html>';
...

In WebGMaps.pas:

...
interface

public
  //<RD>
  function InvokeScript(const AScript: String): String;
  procedure GetAllPolygonsFromJavascript( var AllPolygons: TStringlist );
  //</RD>
...

implementation

//<RD>
function TWebGMaps.InvokeScript(const AScript: String): String;
{Use InvokeScript when you need the result from a JavaScript function.
 It first calls/uses ExecJScript to execute the function, then saves the result
 into a hidden input (i.e. "result") that has been declared in
 UWebGMapsConst.pas (see const HTML_FILE_1). }

  function GetElementIdValue(AWebBrowser: TWebBrowser;
    TagName, TagId, TagAttrib: string):string;
  var
    Document: IHTMLDocument2;
    Body: IHTMLElement2;
    Tags: IHTMLElementCollection;
    Tag: IHTMLElement;
    I: Integer;
  begin
    Result:='';
    if not Supports(AWebBrowser.Document, IHTMLDocument2, Document) then
      raise Exception.Create('Invalid HTML document');
    if not Supports(document.body, IHTMLElement2, Body) then
      raise Exception.Create('Can''t find <body> element');
    Tags := body.getElementsByTagName(UpperCase(TagName));
    for I := 0 to Pred(Tags.length) do begin
      Tag:=Tags.item(I, EmptyParam) as IHTMLElement;
      if Tag.id=TagId then Result := Tag.getAttribute(TagAttrib, 0);
    end;
  end;

begin
  Result := '';

  // Run the script
  if ExecJScript( AScript { 'Ex: printallpolygons();' } ) then
  begin
    // Get the result
    Result := GetElementIdValue(FWebBrowser, 'input', 'result', 'value')
  end;
end;


procedure TWebGMaps.GetAllPolygonsFromJavascript(var AllPolygons: TStringlist);
begin
  AllPolygons.Clear;
  AllPolygons.Delimiter := ';';
  AllPolygons.StrictDelimiter := True;
  AllPolygons.DelimitedText := Trim( InvokeScript( 'printallpolygons();' ) );
end;
//</RD>


I also created a couple utility methods:

function GetPolygonItemById( AWebGMaps: TWebGMaps; AId: Integer): TPolygonItem;
{Iterates through the Polygons of given WebGMaps (AWebGMaps) and returns the
 PolygonItem with the specified AId.
 Returns nil if the itenm cannot be found. }
var
  Index: Integer;
begin
  Result := nil;
  if Assigned( AWebGMaps ) then
  begin
    Index := -1;
    while ( Result = nil ) and ( Index < AWebGMaps.Polygons.Count -1 ) do
    begin
      Inc( Index );
      // WebGMapsPolygonClickEvent has an "AId" parameter which can lead to some
      // confusion. Although they named it "AId", I think they really meant "AIndex"
      // (they are really referring to the Index of the Collection Item in it's
      // natural order, not the "Id" of the Collection.
      if Index = AId then
        Result := AWebGMaps.Polygons[ Index ];
    end;
  end;
end;


procedure LoadPolygonFromAllPolygons( var APolygonItem: TPolygonItem;
                                      const AllPolygons: TStringList );
var
  Index: Integer;
  TempStr: String;
  PolyGonIndex: String;
  Latitude, Longitude: Double;
begin
  APolygonItem.Polygon.Path.Clear;

  for Index := 0 to AllPolygons.Count -1 do
  begin
    //TempStr will be like: "Polygon[0] Coordinate[0] LAT[44.123456] LNG[103.123456];"
    TempStr := AllPolygons[ Index ];

    // Get the PolygonIndex
    Delete( TempStr, 1, Pos( 'Polygon[', TempStr ) +7 );
    PolyGonIndex := Copy( TempStr, 1, Pos( ']', TempStr ) -1 );
    Delete( TempStr, 1, Pos( ']', TempStr ) );

    // If this is the Polygon we are interested in...
    if ( StrToIntDef( PolyGonIndex, -1 ) = APolygonItem.Index ) then
    begin
      // Get the Latitude
      Delete( TempStr, 1, Pos( 'LAT[', TempStr ) +3 );
      Latitude := StrToFloatDef( Copy( TempStr, 1, Pos( ']', TempStr ) -1 ), -1 );
      Delete( TempStr, 1, Pos( ']', TempStr ) );

      // Get the Longitude
      Delete( TempStr, 1, Pos( 'LNG[', TempStr ) +3 );
      Longitude := StrToFloatDef( Copy( TempStr, 1, Pos( ']', TempStr ) -1 ), -1 );
      Delete( TempStr, 1, Pos( ']', TempStr ) );

      if ( Latitude <> -1 ) and ( Longitude <> -1 ) then
        APolygonItem.Polygon.Path.Add( Latitude, Longitude );

      // Do not be tempted to break out of the loop as we have to identify all
      // the coordinates that belong to this one polygon. Keep looping.
    end;
  end;
end;

Now let's use it, all you have to do is to add some code in the PolygonMouseExit event( or where ever you need it: for example I have a right click popup where the user can edit the specific lats and longs):

procedure TMapViewer.WebGMapsPolygonMouseExitEvent(Sender: TObject;
  IdPolygon: Integer);
var
  AllPolygons: TStringList;
  PolygonItem: TPolygonItem;
begin
  PolygonItem := GetPolygonItemById( FWebGMaps, IdPolygon );
  if Assigned( PolygonItem ) then
  begin
    AllPolygons := TStringList.Create;
    try
      WebGMaps.GetAllPolygonsFromJavascript( AllPolygons );

      // Refresh our Polygon from the StringList we got back from
      // the call to GetAllPolygonsFromJavascript.
      LoadPolygonFromAllPolygons( PolygonItem, AllPolygons );
    finally
     FreeAndNil( AllPolygons );
    end;
  end;
end;

I hope that helps.
Richard

Hi Richard,


Thank you for your suggestion.
The functionality to retrieve modified coordinates from Polygons, Polylines, Circles and Rectangles has now been implemented for TWebGMaps.
The update will be available with the next release of TMS WebGMaps.

Hi everyone,

Is this feature is now implements in the current version 2.7.0 ?

Have a good day!

Charly

Yes, it is in v2.7.0.0

Thanks for your quickly response.

The method GetModifiedMapPolygon is the best one to do this feature ?

Kind regards,

Charly

Yes, that is correct.

Thanks,

Have a nice day