SkylineGlobe 如何二次开发实现天际线分析功能

时间:2022-09-10 23:34:21

天际线效果:

SkylineGlobe 如何二次开发实现天际线分析功能

示例代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ToolTitle</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="StyleSheet" href="../Style.css" type="text/css">
<style>
</style>
</head>
<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" style="border: 0px" id="Body" class="hideUntillTranslated" onload="Init()">
<!--oncontextmenu="return false;"> onclick="bHide=true;HideOptionsNow()" > -->
<table border="0" width="100%" cellspacing="0" cellpadding="2">
<tr>
<td class="ToolTopArea" id="TopAreaTD" width="100%" valign="middle" >
<table border="0" width="100%" cellspacing="0" cellpadding="0">
<tr>
<td width="55px"><img style="margin-left:5px;" src="ToolIcon.png" alt="" /></td>
<td id="TitleTD" align="center" class="s12w i18n">ToolName</td>
<td align="right" id="CloseHelpTd"><img style="margin-right:5px;" alt="" src="../CommonImg/help.png" border="0" class="i18n" alt="help" title="help" onclick="DisplayHelpPopup6(SGLang.i18nFile('help.html'),SGLang.i18n('help'))" style="cursor: pointer;"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td class="ToolTopSeperator"></td>
</tr> <tr class="s8">
<td >
<table class="PropertiesSheet" cellspacing="0" cellpadding="2" >
<tr class='TableOtherLine'>
<td class="s8b">
<label class="i18n">Text7</label>
</td>
<td align="left">
&nbsp;<select id="OutputTypeID" onchange="TypeChanged();" >
<option class="i18n" value=0 selected="selected">Text8</option>
<option class="i18n" value=1 >Text9</option>
<option class="i18n" value=2 >Text10</option>
</select>
</td>
</tr> <tr >
<td class="s8b">
<label class="i18n">Text4</label>
</td>
<td align="left">
&nbsp;<select id="AccuracyID" >
<option class="i18n" value=0 selected="selected">Text5</option>
<option class="i18n" value=1 >Text6</option>
</select>
</td>
</tr> <tr class='TableOtherLine'> <!--Radius-->
<td class="s8b">
<label class="i18n">Text12</label>
</td>
<td align="left">
<input id="radiusID" type="text" value="1000" onchange="ValidateInput();" /> <span class="i18n">Text13</span>
</td>
</tr>
<tr> <!--Viewer Altitude-->
<td class="s8b">
<label class="i18n">Text16</label>
</td>
<td align="left">
<input id="ViewerAltitudeID" type="text" value="5" /> <span class="i18n">Text13</span>
</td>
</tr>
<tr class='TableOtherLine'> <!-- Elevation Angle-->
<td class="s8b">
<label class="i18n">Text22</label>
</td>
<td align="left">
<input id="ElevationAngleID" type="text" value="0" onchange="ValidateInput();" /> <span class="i18n">Text34</span>
</td>
</tr> </table>
</td>
</tr>
<tr >
<td colspan="2" align="center" class="ToolButtonsArea">
<button id="Draw" class="MenuButton" onclick="CreateObjects(1);"> <img src="img/SetPoint.png" /><br /> <span class="i18n">Text20</span></button>
<button id="groupButton" class="MenuButton" onclick="SelectGroupClipboard(0)"><img src="../commonimg/group.png" /><br /><span class="i18n">Text14</span></button>
<button id="clipboardButton" class="MenuButton" onclick="SelectGroupClipboard(1)"><img src="../commonimg/Clipboard.png" /><br /><span class="i18n">Text15</span></button>
<div id="ProfileID" style="display:none;"> <button class="MenuButton MenuButtonLast" onclick="ShowProfile();"><img src="img/profile.png" /><br /><span class="i18n">Text18</span></button> </div>
</td>
</tr>
</table> <object id="SGWorld" classid="CLSID:3a4f9199-65a8-11d5-85c1-0001023952c1"> </object> <script language="javascript" src="../ToolsCommon65.js"></script>
<script language="JavaScript"> var gCircle = null;
var gViewshed = null;
var gLayer;
var gType = 0;
//var gPositionsArray = [];
var gDomePoints=[];
var gLineArray = [];
var gRingArray = [];
var gRingList = [];
//var gElevationRingArray = [];
var gYawArray = [];
var gRingObj = null;
var gColorArray = ["#ff0000", "#00ff00", "#0000FF", "#FF00FF", "#C0FFFF", "#FFFF00", "#FFC119", "#B16CF8", "#D2FF01", "#AD8943"];
var gPopupCaption = ""; var gLineIndex = 0;
var gMainGroup = null;
var gGroup = null;
var gVisibilityDistance;
var gInEdit = 0;
var gOriginalPosition = null;
var yawStep ;
var pitchStep;
var gNumDome = 1; //--------------
// Init
function Init() {
if (GetParamValue("inSG", "") == "1") {
$("#TopAreaTD").attr("height", "57");
$("#TitleTD").attr("align", "left");
$("#CloseHelpTd").attr("display", "none");
}
} //------------------
// Reset
//------------------
function Reset(FirstTime, FromMouseInputMode) { try {
if (gCircle != null)
SGWorld.Creator.DeleteObject(gCircle.ID);
if (gViewshed != null)
SGWorld.Creator.DeleteObject(gViewshed.ID);
} catch (e) { } gType = 0;
gCircle = null;
gViewshed = null;
gLayer = null;
gGroup = null;
gOriginalPosition = null;
//gPositionsArray = [];
gLineArray = [];
gRingArray = [];
// gElevationRingArray = [];
gYawArray = [];
gLineIndex = 0; $("#Draw").removeClass("MenuButtonHighlight");
$("#groupButton").removeClass("MenuButtonHighlight");
$("#clipboardButton").removeClass("MenuButtonHighlight"); SGWorld.ProjectTree.EnableRedraw(1);
SGWorld.Window.HideMessageBarText(); if (gInEdit>0) {
SGWorld.DetachEvent("OnLButtonClicked", OnLButtonClicked);
SGWorld.DetachEvent("OnRButtonUp", OnRButtonUp);
SGWorld.DetachEvent("OnFrame", OnFrame);
SGWorld.DetachEvent("OnInputModeChanged", OnInputModeChanged);
}
gInEdit = 0; if (FirstTime != 1 && FromMouseInputMode == 0)
SGWorld.Window.SetInputMode(0);
} //--------------
// CreateObjects
//--------------
function CreateObjects(method) {
if (gInEdit==0) {
gInEdit = 1;
gNumDome = 1;
gRingArray = [];
gRingList = [];
SGWorld.AttachEvent("OnLButtonClicked", OnLButtonClicked);
SGWorld.AttachEvent("OnRButtonUp", OnRButtonUp);
SGWorld.AttachEvent("OnFrame", OnFrame);
SGWorld.AttachEvent("OnInputModeChanged", OnInputModeChanged);
SGWorld.Window.SetInputMode(1, abspath() + "/cursor_m.cur", true);
SGWorld.Window.ShowMessageBarText(SGLang.i18n("Text23"));
$(event.srcElement).addClass("MenuButtonHighlight"); try {
var a = SGWorld.ProjectTree.GetItemName(gMainGroup);
}
catch (e) { gMainGroup = SGWorld.ProjectTree.CreateGroup(SGLang.i18n("ToolName"), SGWorld.ProjectTree.RootID); } var pos = SGWorld.Creator.CreatePosition(0, 0, 0, 0, 0, 0, 0, 0);
gCircle = SGWorld.Creator.CreateCircle(pos, $("#radiusID").val(), SGWorld.Creator.CreateColor(255, 0, 0, 255), SGWorld.Creator.CreateColor(255, 255, 255, 100), gMainGroup, SGLang.i18n("Text24"));
gCircle.NumberOfSegments = 50;
gCircle.LineStyle.Width = -5;
}
else {
Reset (false,false);
}
}
//-----------
// SelectGroupClipboard
function SelectGroupClipboard(searchType) {
if (searchType == 0) {
var node = SGWorld.ProjectTree.GetNextItem("", 10);
if (node == 0 || !(SGWorld.ProjectTree.IsGroup(node) || SGWorld.ProjectTree.IsLayer(node))) {
alert(SGLang.i18n("Text32"));
return;
}
} $(event.srcElement).addClass("MenuButtonHighlight");
SGWorld.Window.ShowMessageBarText(SGLang.i18n("Text31"));
gNumDome = 1; gDomePoints = [];
gRingArray = [];
gRingList = []; if (searchType == 0)
searchGeometries2(node, AddDomeToList);
if (searchType == 1)
searchGeometriesClipboard(AddDomeToList); var CreateTheObjects = true;
if (gDomePoints.length > 10)
CreateTheObjects = confirm(SGLang.i18n("Text35") + gDomePoints.length + SGLang.i18n("Text36")); if (CreateTheObjects)
for (var i = 0; i < gDomePoints.length; i++)
CalculateDome (gDomePoints[i].pos, gDomePoints[i].objType, gDomePoints[i].AltitudeType); Reset(0, 0);
} //------------
// OnLButtonClicked
function OnLButtonClicked(Flags, X, Y) {
if (gInEdit == 0)
return;
var CursorCoord = SGWorld.Window.pixelToWorld(X, Y, 1 + 16 + 64 + 128 + 8192);
if (CursorCoord == null)
return false; if (gInEdit == 1) // First click, center point
{
var viewerAltitude = 1.0*$("#ViewerAltitudeID").val();
CursorCoord.Position.Altitude = CursorCoord.Position.Altitude + viewerAltitude;
gCircle.Position = CursorCoord.Position.Copy(); if (gCircle != null) { CalculateDome(gCircle.Position, 18, 3); //supported types: 18 = label, 24 = image label
}
}
}
//------------
// OnRButtonUp
function OnRButtonUp(Flags, X, Y) {
if (gInEdit == 0)
return; Reset(false, false);
}
//------------
// OnFrame
function OnFrame() {
if (gInEdit != 1)
return;
try {
var mouseInfo = SGWorld.Window.GetMouseInfo();
var CursorCoord = SGWorld.Window.pixelToWorld(mouseInfo.X, mouseInfo.Y, 1 + 16 + 64 + 128 + 8192);
if (CursorCoord == null)
return false;
var viewerAltitude = 1.0 * $("#ViewerAltitudeID").val();
CursorCoord.Position.Altitude = CursorCoord.Position.Altitude + viewerAltitude;
gCircle.Position = CursorCoord.Position.Copy(); gCircle.Radius = $("#radiusID").val();
}
catch (e) { }
}
//------------
// OnInputModeChanged
function OnInputModeChanged(NewMode) {
if (NewMode != 1)
if (gInEdit != 0)
Reset(0, 1);
} //---------
//AddDomeToList
function AddDomeToList(pos, objType, AltitudeType) {
gDomePoints.push({ pos: pos, objType: objType, AltitudeType: AltitudeType });
return true;
}
//---------
//CalculateDome
function CalculateDome(pos, objType, AltitudeType) { if (objType != 0 && objType != 18 && objType != 24)
return true; try {
ValidateInput();
// Houre glass cursor
SGWorld.Window.SetInputMode(1, abspath() + "/hourglass.cur", true); var position = pos.Copy(); // to make sure we do not change the position of an object
// Make sure the point altitude is not lower than the Viewer Altitude the user provided
var viewerAltitude = 1.0 * $("#ViewerAltitudeID").val();
position.ChangeAltitudeType(3);
var groundHeight = SGWorld.Terrain.GetGroundHeightInfo(position.X, position.Y, 1, true);
position.Altitude = Math.max(groundHeight.Position.Altitude + viewerAltitude, position.Altitude); if (AnalyzePoints(position))
DrawPoints(position);
if (gLayer != null) {
gLayer.Save();
}
Reset(false, false);
gNumDome++;
}
catch (e) {alert(e.description);} return true;
} //------------
// AnalyzePoints
function AnalyzePoints(position) {
var radius = $("#radiusID").val();
var ElevationAngle = 1.0 * $("#ElevationAngleID").val();
var pos = null;
var pointIndex = 0;
var lastVisiblePos; gType = $("#OutputTypeID").val(); gVisibilityDistance = radius*20; // Create the Viewshed
SGWorld.Window.ShowMessageBarText(SGLang.i18n("Text31") + " [" + gNumDome + "]", -1);
gViewshed = SGWorld.Analysis.Create3DViewshed(position, 360, 180, radius*1.01, SGWorld.ProjectTree.HiddenGroupID, SGLang.i18n("Text25")); // HiddenGroupID
gViewshed.Quality = 2;
gViewshed.SaveInFlyFile = false;
SGWorld.Analysis.StartViewshedVisibilityQuery(gViewshed.ID); // calculate ray accuracy
var raySteps = Math.floor((Math.log(radius) * 5) / Math.LN10) + 4; if ($("#AccuracyID").val() == 0) { // Normal
yawStep = 2;
pitchStep = 0.1;
}
else { // high
yawStep = 1;
pitchStep = 0.05;
} // dome or base
if (gType == 0 || gType == 1 ) { // Dome || Base for (var yaw = 0; yaw < 360; yaw += yawStep ) {
SGWorld.Window.ShowMessageBarText(SGLang.i18n("Text26") + " [" + gNumDome + "] " + Math.floor((yaw * 100) / (360)) + "%", -1);
pointIndex = 0;
var numVisiblePoint = 0;
gLineArray[gLineIndex] = [];
var bFoundVisible = true;
pointIndex = AddPoint(gLineIndex, pointIndex, position); // add point at the center
gYawArray[gLineIndex] = yaw; for (var pitch = ElevationAngle; pitch <= 90; pitch += pitchStep) {
pos = position.Move(radius, yaw, pitch);
var PointVisible = SGWorld.Analysis.QueryVisibilityDistance(pos); // Returns the radius of the visibility from the viewer to the position point
if (PointVisible >= radius ) { // visible
if (numVisiblePoint > 1 && numVisiblePoint % 20 != 0) // reduce number of point on the outer dome
pointIndex -= 1;
pointIndex = AddPoint(gLineIndex, pointIndex, pos);
if (bFoundVisible)
AddRing(gLineIndex, pos);
bFoundVisible = false;
if (gType == 1)
break;
numVisiblePoint++; }
else {
pos = position.Move(PointVisible, yaw, pitch);
pointIndex = AddPoint(gLineIndex, pointIndex, pos);
numVisiblePoint = 0;
}
}
gLineIndex++;
} // yaw
} // if dome|base
else if (gType == 2) { // Skyline
for (var yaw = 0; yaw < 360; yaw += yawStep/4 ) {
SGWorld.Window.ShowMessageBarText(SGLang.i18n("Text26") + " [" + gNumDome + "] " + Math.floor((yaw * 100) / (360)) + "%", -1);
var bAllVisible = true;
for (var pitch = 90; pitch >= -45; pitch -= pitchStep ) {
pos = position.Move(radius, yaw, pitch);
var PointVisible = SGWorld.Analysis.QueryVisibilityDistance(pos); // Returns the radius of the visibility from the viewer to the position point if (PointVisible < radius && PointVisible > -1) { // not visible
bAllVisible = false;
pos = position.Move(PointVisible, yaw, pitch);
AddRing(gLineIndex, pos);
break;
}
} // pitch if (bAllVisible) { // add point to the border line
AddRing(gLineIndex, pos);
}
gLineIndex++;
} // yaw
} // close the ring
var ringFirstPoint = SGWorld.Creator.CreatePosition(gRingArray[0], gRingArray[1], gRingArray[2], 0, 0, 0, 0, 0);
AddRing(gLineIndex, ringFirstPoint); SGWorld.Analysis.EndVisibilityQuery(); return true;
}
//------------
// AddPoint
function AddPoint(line, point, position) {
gLineArray[line][point * 3] = position.X;
gLineArray[line][point * 3 + 1] = position.Altitude;
gLineArray[line][point * 3 + 2] = position.Y;
point++;
return point;
} //-------------
// AddRing
function AddRing(point, position) {
gRingArray[point * 3] = position.X;
gRingArray[point * 3 + 1] = position.Y;
gRingArray[point * 3 + 2] = position.Altitude;
}
//------------
// DrawPoints
function DrawPoints(position) {
var radius = $("#radiusID").val();
try {
var a = SGWorld.ProjectTree.GetItemName(gMainGroup);
}
catch (e) { gMainGroup = SGWorld.ProjectTree.CreateGroup(SGLang.i18n("ToolName"), SGWorld.ProjectTree.RootID); } try {
var layerName = $("#OutputTypeID option:selected").text()+" ["+gNumDome+"]";
gGroup = SGWorld.ProjectTree.CreateGroup(layerName, gMainGroup); // Viewer label
var labelStyle = SGWorld.Creator.CreateLabelStyle(0);
var CenterLabel = SGWorld.Creator.CreateImageLabel(position, abspath() + "./img/image11.gif", labelStyle, gGroup, SGLang.i18n("Text11"));
CenterLabel.Action.Code = 11;
CenterLabel.Style.Scale = radius/100;
CenterLabel.Style.IconColor.FromHTMLColor (gColorArray[(gNumDome-1) % 10]); // Dome
if (gType == 0 || gType == 1 ) { // dome || Base || elevation rings
for (var i = 0; i < gLineIndex; i++) {
DrawObject(gLineArray[i], radius, gYawArray[i], gType);
}
}
/******
// Elevation Rings
if (gType == 3) { // dome or Base
for (var alt = -10; alt < 100; alt++)
gElevationRingArray[alt] = [];
for (var i = 0; i < gLineIndex; i++) {
for (var j = 0; j < gLineArray[i].length / 3 - 1; j++) {
var pointA = gLineArray[i][j * 3 + 1];
var pointB = gLineArray[i][(j + 1) * 3 + 1];
if (Math.floor(pointA / 100) != Math.floor(pointB / 100)) {
var positionA = SGWorld.Creator.CreatePosition(gLineArray[i][j * 3 ], gLineArray[i][j * 3 + 2], gLineArray[i][j * 3 + 1], 3, 0, 0, 0, 0);
var positionB = SGWorld.Creator.CreatePosition(gLineArray[i][(j + 1) * 3 ], gLineArray[i][(j + 1) * 3 + 2], gLineArray[i][(j + 1) * 3 + 1], 3, 0, 0, 0, 0);
var l = positionA.DistanceTo(positionB);
var l1 = (l * (Math.floor(pointB / 100) * 100 - pointA)) / (pointB - pointA);
var positionC = positionA.MoveToward(positionB, l1);
gElevationRingArray[Math.floor(pointB / 100)].push(positionC.X, positionC.Altitude, positionC.Y);
}
}
}
for (var alt = -10; alt < 100; alt++) {
if (gElevationRingArray[alt].length > 3) // at least two points
DrawObject(gElevationRingArray[alt], radius, alt);
}
}
******/
// Outer ring
gRingObj = SGWorld.Creator.CreatePolylineFromArray(gRingArray, gColorArray[(gNumDome - 1) % 10], 3, gGroup, SGLang.i18n("Text21"));
gRingObj.LineStyle.Width = -3;
gRingObj.Visibility.MaxVisibilityDistance = radius * 50; gRingList.push(gRingObj);
$("#ProfileID").show();
$("#ProfileID").css('display','inline');
}
catch (e) { alert(e.message); Reset(false, false); } return true;
} //---------
// DrawObject
function DrawObject(LineArray, range, Yaw, gType) {
var node;
var TEObj;
var scale = range * 50;
var ObjType; // = "ImageLabel"; if (gType == 0)
ObjType = "Polygon";
else
ObjType = "Polyline"; SGWorld.Window.ShowMessageBarText(SGLang.i18n("Text27")+" ["+gNumDome+"]"); if (gLayer == null)
{
CreateGroupOrLayer(ObjType); // style the feature group
if (featureLayerStyles[ObjType] != null)
{
var result = featureLayerStyles[ObjType](scale);
if (result === false)
return false;
}
} if (ObjType == "Polygon")
gLayer.FeatureGroups.Polygon.CreateFeature(LineArray, range + ";" + Yaw);
if (ObjType == "Polyline")
gLayer.FeatureGroups.Polyline.CreateFeature(LineArray, range + ";" + Yaw); return true; }
//----------
// CreateGroupOrLayer
function CreateGroupOrLayer(ObjType) { var radius = $("#radiusID").val(); if (gLayer == null) {
var postfix = new Date().getTime();
var layerName = $("#OutputTypeID option:selected").text() + postfix;
if (ObjType == "Polygon")
gLayer = SGWorld.Creator.CreateNewFeatureLayer(layerName, LayerGeometryType.LGT_POLYGON, "FileName=ThreatDome" + postfix + ".shp;TEPlugName=OGR;", gGroup);
if (ObjType == "Polyline")
gLayer = SGWorld.Creator.CreateNewFeatureLayer(layerName, LayerGeometryType.LGT_POLYLINE, "FileName=ThreatDome" + postfix + ".shp;TEPlugName=OGR;", gGroup); // gLayer = SGWorld.Creator.CreateNewFeatureLayer(layerName, LayerGeometryType.LGT_POINT, "FileName=ThreatDome" + postfix + ".shp;TEPlugName=OGR;", gGroup);
gLayer.Streaming = true;
gLayer.BlockWidth = radius /4;
gLayer.Refresh();
///gLayer.DataSourceInfo.Attributes.CreateAttribute(SGLang.i18n("Text29"), 1, 20, 0);
gLayer.DataSourceInfo.Attributes.CreateAttribute(SGLang.i18n("Text30"), 1, 20, 0);
gLayer.DataSourceInfo.Attributes.CreateAttribute(SGLang.i18n("Text33"), 2, 20, 1);
gLayer.DataSourceInfo.Attributes.ImportAll = true;
gLayer.Visibility.MaxVisibilityDistance = gVisibilityDistance; } }
var featureLayerStyles = { "Polygon": function (size) {
gLayer.FeatureGroups.Polygon.SetProperty("Line Color", "#ffffff");
gLayer.FeatureGroups.Polygon.SetProperty("Line Opacity", 0.5);
gLayer.FeatureGroups.Polygon.SetProperty("Fill Opacity", 0);
gLayer.FeatureGroups.Polygon.SetProperty("Altitude Method", 11);
gLayer.Visibility.MaxVisibilityDistance = size;
},
"Polyline": function (size) {
gLayer.FeatureGroups.Polyline.SetProperty("Line Color", "#ffffff");
gLayer.FeatureGroups.Polyline.SetProperty("Line Opacity", 0.5);
gLayer.FeatureGroups.Polyline.SetProperty("Altitude Method", 11);
gLayer.Visibility.MaxVisibilityDistance = size;
}
}
//---------------
// TypeChanged
function TypeChanged() {
gType = $("#OutputTypeID").val();
if (gType == 2) // Skyline
$("#ElevationAngleID").attr('disabled','disabled');
else
$("#ElevationAngleID").attr('disabled', '');
}
//---------------
// ValidateInput
function ValidateInput() {
var radius = $("#radiusID").val();
radius = Math.max(radius, 0.1);
$("#radiusID").val(radius); var ElevationAngle = $("#ElevationAngleID").val();
ElevationAngle = Math.max(Math.min(ElevationAngle, 80), -90);
$("#ElevationAngleID").val(ElevationAngle);
return;
}
//--------------
// ShoeProfile
function ShowProfile() {
var objList = ""; if (gRingList.length == 0)
return; try {
for (var i =0 ; i<gRingList.length ; i++)
objList += "&ObjID"+i+"=" + gRingList[i].ID ;
}
catch (e) { alert(SGLang.i18n("Text37")) ; return; } // Remove previos popup
SGWorld.Window.RemovePopupByCaption(gPopupCaption); var a = new Date();
gPopupCaption = SGLang.i18n("Text19") + Date().toString();
var url = abspath() + "/../TerrainProfile/TerrainProfilePopup.html?Type=3" + objList + "&Density=1&Compare=0&Caption=" + gPopupCaption;
var popupMsg = SGWorld.Creator.CreatePopupMessage(gPopupCaption, url, 1, -1000, 100, 100, -1); popupMsg.Flags = 2 + 32;
SGWorld.Window.ShowPopup(popupMsg); }
//--------------
// CheckNumberEx
function CheckNumberEx(field, defVal, MinNum, MaxNum) {
try {
field.value = validateNumber(field.value); if (field.value < MinNum)
field.value = MinNum;
if (field.value > MaxNum)
field.value = MaxNum;
}
catch (e) { field.value = defVal }
} </script> </body>
</html> <!--Sig:00000040mkMXNLI#5a52TFY#E1faqOyI2#t2mlbqFNlnWR51q3LTfVtdo4QjqwI2eWUFDXYNAnXSak1iWIC9XwWBaOUdMdJJ-->