//Map must be a local sceneboolcanCreateVoxel=(MapView.Active.ViewingMode == MapViewingMode.SceneLocal);if(canCreateVoxel){//TODO - use the voxel api methods}
Create Voxel Layer
//Must be on the QueuedTask.Run()//Must be a .NetCDF file for voxelsvarurl=@"C:\MyData\AirQuality_Redlands.nc";varcim_connection=new CIMVoxelDataConnection(){URI=url};//Create a VoxelLayerCreationParamsvarcreateParams= VoxelLayerCreationParams.Create(cim_connection);
createParams.IsVisible =true;//Can also just use the path directly...//var createParams = VoxelLayerCreationParams.Create(url);//Use VoxelLayerCreationParams to enumerate the variables within//the voxelvarvariables= createParams.Variables;foreach(var variable in variables){varline=$"{variable.Variable}: {variable.DataType}, "+$"{variable.Description}, {variable.IsDefault}, {variable.IsSelected}";
System.Diagnostics.Debug.WriteLine(line);}//Optional: set the default variable
createParams.SetDefaultVariable(variables.Last());//Create the layer - map must be a local sceneVoxelLayervoxelLayer= LayerFactory.Instance.CreateLayer<VoxelLayer>(createParams, map);
Voxel Layer settings and properties
Get a Voxel Layer from the TOC
//Get selected layer if a voxel layer is selectedvarvoxelLayer= MapView.Active.GetSelectedLayers().OfType<VoxelLayer>().FirstOrDefault();if(voxelLayer==null){//just get the first voxel layer in the TOCvoxelLayer= MapView.Active.Map.GetLayersAsFlattenedList().OfType<VoxelLayer>().FirstOrDefault();if(voxelLayer==null)return;}
Manipulate the Voxel Layer TOC Group
//var voxelLayer = ...//Must be on the QueuedTask.Run()//Toggle containers and visibility in the TOC
voxelLayer.SetExpanded(!voxelLayer.IsExpanded);
voxelLayer.SetVisibility(!voxelLayer.IsVisible);
voxelLayer.SetIsosurfaceContainerExpanded(!voxelLayer.IsIsosurfaceContainerExpanded);
voxelLayer.SetIsosurfaceContainerVisibility(!voxelLayer.IsIsosurfaceContainerVisible);
voxelLayer.SetSliceContainerExpanded(voxelLayer.IsSliceContainerExpanded);
voxelLayer.SetSliceContainerVisibility(!voxelLayer.IsSliceContainerVisible);
voxelLayer.SetSectionContainerExpanded(!voxelLayer.IsSectionContainerExpanded);
voxelLayer.SetSectionContainerVisibility(!voxelLayer.IsSectionContainerVisible);
voxelLayer.SetLockedSectionContainerExpanded(!voxelLayer.IsLockedSectionContainerExpanded);
voxelLayer.SetLockedSectionContainerVisibility(!voxelLayer.IsLockedSectionContainerVisible);
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Change the visualization to Volume//e.g. for creating slices
voxelLayer.SetVisualization(VoxelVisualization.Volume);//Change the visualization to Surface//e.g. to create isosurfaces and sections
voxelLayer.SetVisualization(VoxelVisualization.Surface);
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Offsetvaroffset= voxelLayer.CartographicOffset;//apply an offset
voxelLayer.SetCartographicOffset(offset+100.0);//VerticalExaggerationvarexaggeration= voxelLayer.VerticalExaggeration;//apply an exaggeration
voxelLayer.SetVerticalExaggeration(exaggeration+100.0);//Change the exaggeration mode to "ScaleZ" - corresponds to 'Z-coordinates' //on the Layer properties UI - must use the CIMvardef= voxelLayer.GetDefinition()as CIMVoxelLayer;
def.Layer3DProperties.ExaggerationMode = ExaggerationMode.ScaleZ;//can set vertical exaggeration via the CIM also//def.Layer3DProperties.VerticalExaggeration = exaggeration + 100.0;//apply the change
voxelLayer.SetDefinition(def);//Diffuse Lightingif(!voxelLayer.IsDiffuseLightingEnabled)
voxelLayer.SetDiffuseLightingEnabled(true);vardiffuse= voxelLayer.DiffuseLighting;//set Diffuse lighting to a value between 0 and 1
voxelLayer.SetDiffuseLighting(0.5);//50%//Specular Lightingif(!voxelLayer.IsSpecularLightingEnabled)
voxelLayer.SetSpecularLightingEnabled(true);varspecular= voxelLayer.SpecularLighting;//set Diffuse lighting to a value between 0 and 1
voxelLayer.SetSpecularLighting(0.5);//50%
Get the Voxel Volume Dimensions
//At 2.x - var volume = voxelLayer.GetVolumeSize();//var x_max = volume.Item1;//var y_max = volume.Item2;//var z_max = volume.Item3;varx_max= voxelLayer.GetVolumes().Max(v => v.GetVolumeSize().X);vary_max= voxelLayer.GetVolumes().Max(v => v.GetVolumeSize().Y);varz_max= voxelLayer.GetVolumes().Max(v => v.GetVolumeSize().Z);//Get the dimensions of just one volumevardimensions= voxelLayer.GetVolumes().FirstOrDefault();//Get the dimensions of the volume associated with the selected variablevardimensions2= voxelLayer.SelectedVariableProfile.Volume.GetVolumeSize();
Events
Subscribe for Changes to a Voxel Layer
ArcGIS.Desktop.Mapping.Events.MapMemberPropertiesChangedEvent.Subscribe((args)=>{varvoxel= args.MapMembers.OfType<VoxelLayer>().FirstOrDefault();if(voxel==null)return;//Anything changed on a voxel layer?//At 2.x - if (args.EventHints.Any(hint => hint == MapMemberEventHint.VoxelSelectedVariableProfileIndex))if(args.EventHints.Any(hint =>hint== MapMemberEventHint.VoxelSelectedVariable)){//Voxel variable profile selection changedvarchanged_variable_name= voxel.SelectedVariableProfile.Variable;//TODO respond to change, use QueuedTask if needed}elseif(args.EventHints.Any(hint =>hint== MapMemberEventHint.Renderer)){//This can fire when a renderer becomes ready on a new layer; the selected variable profile//is changed; visualization is changed, etc.varrenderer= voxel.SelectedVariableProfile.Renderer;//TODO respond to change, use QueuedTask if needed}});
ArcGIS.Desktop.Mapping.Voxel.Events.VoxelAssetChangedEvent.Subscribe((args)=>{//An asset changed on a voxel layer System.Diagnostics.Debug.WriteLine(""); System.Diagnostics.Debug.WriteLine("VoxelAssetChangedEvent"); System.Diagnostics.Debug.WriteLine($" AssetType: {args.AssetType}, ChangeType: {args.ChangeType}");if(args.ChangeType == VoxelAssetEventArgs.VoxelAssetChangeType.Remove)return;//Get "what"changed - add or update//eg IsoSurfaceVoxelLayervoxelLayer=null;if(args.AssetType == VoxelAssetEventArgs.VoxelAssetType.Isosurface){varsurface= MapView.Active.GetSelectedIsosurfaces().FirstOrDefault();//there will only be one selected...if(surface!=null){voxelLayer= surface.Layer;//TODO respond to change, use QueuedTask if needed}}//Repeat for Slices, Sections, LockedSections...//GetSelectedSlices(), GetSelectedSections(), GetSelectedLockedSections();});
Variable Profiles + Renderer
Get the Selected Variable Profile
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varsel_profile= voxelLayer.SelectedVariableProfile;//Get the variable profile namevarprofile_name= sel_profile.Variable;
Change the Selected Variable Profile
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varprofiles= voxelLayer.GetVariableProfiles();//Select any profile as long as it is not the current selected variablevarnot_selected= profiles.Where(p => p.Variable != sel_profile.Variable).ToList();if(not_selected.Count()>0){
voxelLayer.SetSelectedVariableProfile(not_selected.First());}
Get the Variable Profiles
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varvariable_profiles= voxelLayer.GetVariableProfiles();
Get the Variable Renderer
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varvariable= voxelLayer.GetVariableProfiles().First();varrenderer= variable.Renderer;if(variable.DataType == VoxelVariableDataType.Continuous){//Renderer will be stretchvarstretchRenderer= renderer as CIMVoxelStretchRenderer;//access the renderer}else//VoxelVariableDataType.Discrete{//Renderer will be unique valuevaruvr= renderer as CIMVoxelUniqueValueRenderer;//access the renderer}
Access Stats and Color Range for a Stretch Renderer
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Get the variable profile on which to access the datavarvariable= voxelLayer.SelectedVariableProfile;//or use ...voxelLayer.GetVariableProfiles()//Data range//At 2.x - //var min = variable.GetVariableStatistics().MinimumValue;//var max = variable.GetVariableStatistics().MaximumValue;varmin= variable.Statistics.MinimumValue;varmax= variable.Statistics.MaximumValue;//Color range (Continuous only)doublecolor_min,color_max;if(variable.DataType == VoxelVariableDataType.Continuous){varrenderer= variable.Renderer as CIMVoxelStretchRenderer;color_min= renderer.ColorRangeMin;color_max= renderer.ColorRangeMax;}
Change Stretch Renderer Color Range
//Typically, the default color range covers the most//commonly occuring voxel values. Usually, the data//range is much broader than the color range//Get the variable profile whose renderer will be changedvarvariable= voxelLayer.SelectedVariableProfile;//Check DataTypeif(variable.DataType != VoxelVariableDataType.Continuous)return;//must be continuous to have a Stretch Renderer...varrenderer= variable.Renderer as CIMVoxelStretchRenderer;varcolor_min= renderer.ColorRangeMin;varcolor_max= renderer.ColorRangeMax;//increase range by 10% of the current differencevardif=(color_max-color_min)*0.05;color_min-=dif;color_max+=dif;//make sure we do not exceed data range//At 2.x - //if (color_min < variable.GetVariableStatistics().MinimumValue)// color_min = variable.GetVariableStatistics().MinimumValue;//if (color_max > variable.GetVariableStatistics().MaximumValue)// color_max = variable.GetVariableStatistics().MaximumValue;if(color_min< variable.Statistics.MinimumValue)color_min= variable.Statistics.MinimumValue;if(color_max> variable.Statistics.MaximumValue)color_max= variable.Statistics.MaximumValue;//variable.Statistics.MinimumValue
renderer.ColorRangeMin =color_min;
renderer.ColorRangeMax =color_max;//apply changes
variable.SetRenderer(renderer);
Change The Visibility on a CIMVoxelColorUniqueValue class
//Get the variable profile whose renderer will be changedvarvariable= voxelLayer.SelectedVariableProfile;//Check DataTypeif(variable.DataType != VoxelVariableDataType.Discrete)return;//must be Discrete to have a UV Renderer...varrenderer= variable.Renderer as CIMVoxelUniqueValueRenderer;//A CIMVoxelUniqueValueRenderer consists of a collection of//CIMVoxelColorUniqueValue classes - one per discrete value//in the associated variable profile value array//Get the first classvarclasses= renderer.Classes.ToList();varunique_value_class= classes.First();//Set its visibility off
unique_value_class.Visible =false;//Apply the change to the renderer
renderer.Classes = classes.ToArray();//apply the changes
variable.SetRenderer(renderer);
IsoSurfaces
Check the MaxNumberofIsoSurfaces for a Variable
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varvariable= voxelLayer.GetVariableProfiles().First();varmax= variable.MaxNumberOfIsosurfaces;if(max >= variable.GetIsosurfaces().Count){//no more surfaces can be created on this variable}
Check a Variable's Datatype
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varvariable= voxelLayer.GetVariableProfiles().First();if(variable.DataType != VoxelVariableDataType.Continuous){//No iso surfaces//Iso surface can only be created for VoxelVariableDataType.Continuous}
Check CanCreateIsoSurface
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Visualization must be surface or CanCreateIsosurface will return//falseif(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);//Get the variable profile on which to create the iso surfacevarvariable= voxelLayer.SelectedVariableProfile;//or use ...voxelLayer.GetVariableProfiles().First(....// o Visualization must be Surface// o Variable profile must be continuous// o Variable MaxNumberofIsoSurfaces must not have been reached...if(variable.CanCreateIsosurface){//Do the create}
Create Isosurface
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Visualization must be surfaceif(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);//Get the variable profile on which to create the iso surfacevarvariable= voxelLayer.SelectedVariableProfile;// o Visualization must be Surface// o Variable profile must be continuous// o Variable MaxNumberofIsoSurfaces must not have been reached...if(variable.CanCreateIsosurface){//Note: calling create if variable.CanCreateIsosurface == false//will trigger an InvalidOperationException//Specify a voxel value for the iso surface//At 2.x - //var min = variable.GetVariableStatistics().MinimumValue;//var max = variable.GetVariableStatistics().MaximumValue;varmin= variable.Statistics.MinimumValue;varmax= variable.Statistics.MaximumValue;varmid=(max+min)/2;//color range (i.e. values that are being rendered)varrenderer= variable.Renderer as CIMVoxelStretchRenderer;varcolor_min= renderer.ColorRangeMin;varcolor_max= renderer.ColorRangeMax;//keep the surface within the current color range (or it//won't render)if(mid<color_min){mid= renderer.ColorRangeMin;}elseif(mid>color_max){mid= renderer.ColorRangeMax;}//Create the iso surfacevarsuffix= Math.Truncate(mid*100)/100;
variable.CreateIsosurface(new IsosurfaceDefinition(){Name=$"Surface {suffix}",Value=mid,IsVisible=true});}
How to Change Value and Color on an Isosurface
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varvariable= voxelLayer.SelectedVariableProfile;//Change the color of the first surface for the given profilevarsurface= variable.GetIsosurfaces().FirstOrDefault();if(surface!=null){if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);//Change the iso surface voxel value
surface.Value = surface.Value *0.9;//get a random colorvarcount=new Random().Next(0,100);varcolors= ColorFactory.Instance.GenerateColorsFromColorRamp(((CIMVoxelStretchRenderer)variable.Renderer).ColorRamp, count);varidx=new Random().Next(0,count-1);
surface.Color = colors[idx];//set the custom color flag true to lock the color//locking the color prevents it from being changed if the//renderer color range or color theme is updated
surface.IsCustomColor =true;//update the surface
variable.UpdateIsosurface(surface);}
Change Isourface Color Back to Default
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//var variable = ...;//var surface = ...;if(surface.IsCustomColor){
surface.Color = variable.GetIsosurfaceColor((double)surface.Value);
surface.IsCustomColor =false;//update the surface
variable.UpdateIsosurface(surface);}
Delete Isosurface- s
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varvariable= voxelLayer.SelectedVariableProfile;//delete the last surfacevarlast_surface= variable.GetIsosurfaces().LastOrDefault();if(last_surface!=null){
variable.DeleteIsosurface(last_surface);}//delete all the surfacesforeach(var surface in variable.GetIsosurfaces())
variable.DeleteIsosurface(surface);//Optional - set visualization back to Volumeif(variable.GetIsosurfaces().Count()==0){
voxelLayer.SetVisualization(VoxelVisualization.Volume);}
Slices
Get the Collection of Slices
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//At 2.x - var slices = voxelLayer.GetSlices();//Use the SelectedVariableProfile to get the slices currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varslices= volume.GetSlices();//Do something... e.g. make them visibleforeach(var slice in slices){
slice.IsVisible =true;//at 2.x - voxelLayer.UpdateSlice(slice);
volume.UpdateSlice(slice);}//expand the slice container and make sure container visibility is true
voxelLayer.SetSliceContainerExpanded(true);
voxelLayer.SetSliceContainerVisibility(true);
Get a Slice
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//At 2.x -//var slice = voxelLayer.GetSlices().FirstOrDefault();//var slice2 = voxelLayer.GetSlices().First(s => s.Id == my_slice_id);//Use the SelectedVariableProfile to get the slices currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varslice= volume.GetSlices().FirstOrDefault();varslice2= volume.GetSlices().First(s => s.Id ==my_slice_id);
Get Selected Slice in TOC
//Must be on the QueuedTask.Run()varslice= MapView.Active?.GetSelectedSlices()?.FirstOrDefault();if(slice!=null){}
Get Voxel Layer for the Selected Slice in TOC
//Must be on the QueuedTask.Run()VoxelLayervoxelLayer=null;varslice= MapView.Active?.GetSelectedSlices()?.FirstOrDefault();if(slice!=null){voxelLayer= slice.Layer;//TODO - use the layer}
Create a Slice
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Volume)
voxelLayer.SetVisualization(VoxelVisualization.Volume);
voxelLayer.SetSliceContainerExpanded(true);
voxelLayer.SetSliceContainerVisibility(true);//To stop the Voxel Exploration Dockpane activating use:
voxelLayer.AutoShowExploreDockPane =false;//This is useful if u have your own dockpane currently activated...//At 2.x - var volumeSize = voxelLayer.GetVolumeSize();//Use the SelectedVariableProfile to get the slices currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varvolumeSize= volume.GetVolumeSize();//Orientation 90 degrees (West), Tilt 0.0 (vertical)//Convert to a normalvarnormal= voxelLayer.GetNormal(90,0.0);//Create the slice at the voxel mid-point. VoxelPosition//is specified in voxel-space coordinates//At 2.x - //voxelLayer.CreateSlice(new SliceDefinition()//{// Name = "Middle Slice",// VoxelPosition = new Coordinate3D(volume.Item1 / 2, volume.Item2 / 2, volume.Item3 / 2),// Normal = normal,// IsVisible = true//});//Create the slice on the respective volume
volume.CreateSlice(new SliceDefinition(){Name="Middle Slice",VoxelPosition=new Coordinate3D(volumeSize.X /2, volumeSize.Y /2, volumeSize.Z /2),Normal=normal,IsVisible=true});//reset if needed...
voxelLayer.AutoShowExploreDockPane =true;
Change Tilt on a Slice
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//To stop the Voxel Exploration Dockpane activating use:
voxelLayer.AutoShowExploreDockPane =false;//This is useful if u have your own dockpane currently activated...//Normally, it would be set in your dockpaneif(voxelLayer.Visualization != VoxelVisualization.Volume)
voxelLayer.SetVisualization(VoxelVisualization.Volume);
voxelLayer.SetSliceContainerVisibility(true);//At 2.x - var slice = voxelLayer.GetSlices().First(s => s.Name == "Change Tilt Slice");//Use the SelectedVariableProfile to get the slices currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varslice= volume.GetSlices().First(s => s.Name =="Change Tilt Slice");(double orientation,double tilt)= voxelLayer.GetOrientationAndTilt(slice.Normal);//Convert orientation and tilt to a normal
slice.Normal = voxelLayer.GetNormal(orientation,45.0);//At 2.x - voxelLayer.UpdateSlice(slice);
volume.UpdateSlice(slice);//reset if needed...Normally this might be when your dockpane//was de-activated (ie "closed")
voxelLayer.AutoShowExploreDockPane =true;
Delete Slice
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//At 2.x//var last_slice = voxelLayer.GetSlices().LastOrDefault();// if (last_slice != null)// voxelLayer.DeleteSlice(last_slice);// //Delete all slices// var slices = voxelLayer.GetSlices();// foreach (var slice in slices)// voxelLayer.DeleteSlice(slice);//Use the SelectedVariableProfile to get the slices currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varlast_slice= volume.GetSlices().LastOrDefault();if(last_slice!=null)
volume.DeleteSlice(last_slice);//Delete all slicesvarslices= volume.GetSlices();foreach(var slice in slices)
volume.DeleteSlice(slice);
Sections
Get a Section
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//At 2.x -//var section = voxelLayer.GetSections().FirstOrDefault();//var section2 = voxelLayer.GetSections().First(sec => sec.Id == my_section_id);//Use the SelectedVariableProfile to get the sections currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varsection= volume.GetSections().FirstOrDefault();varsection2= volume.GetSections().First(sec => sec.ID ==my_section_id);
Get the Current Collection of Sections
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//At 2.x - var sections = voxelLayer.GetSections();//Use the SelectedVariableProfile to get the sections currently in the TOC//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varsections= volume.GetSections();
Get the Selected Section in TOC
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varsection= MapView.Active?.GetSelectedSections()?.FirstOrDefault();if(section!=null){}
Get Voxel Layer for the Selected Section in TOC
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()VoxelLayervoxelLayer=null;varsection= MapView.Active?.GetSelectedSections()?.FirstOrDefault();if(section!=null){voxelLayer= section.Layer;//TODO - use the layer}
Create a Section at the Voxel MidPoint
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//To stop the Voxel Exploration Dockpane activating use:
voxelLayer.AutoShowExploreDockPane =false;//This is useful if u have your own dockpane currently activated...//Normally, it would be set in your dockpane//Create a section that cuts the volume in two on the vertical plane//At 2.x - var volume = voxelLayer.GetVolumeSize();//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varvolumeSize= volume.GetVolumeSize();//Orientation 90 degrees (due West), Tilt 0 degreesvarnormal= voxelLayer.GetNormal(90,0.0);//Position must be specified in voxel space//At 2.x -//voxelLayer.CreateSection(new SectionDefinition()//{// Name = "Middle Section",// VoxelPosition = new Coordinate3D(volume.Item1 / 2, volume.Item2 / 2, volume.Item3 / 2),// Normal = normal,// IsVisible = true//});
volume.CreateSection(new SectionDefinition(){Name="Middle Section",VoxelPosition=new Coordinate3D(volumeSize.X /2, volumeSize.Y /2, volumeSize.Z /2),Normal=normal,IsVisible=true});//reset if needed...Normally this might be when your dockpane//was de-activated (ie "closed")
voxelLayer.AutoShowExploreDockPane =true;
Create a Horizontal Section
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//Create a section that cuts the volume in two on the horizontal plane//At 2.x - var volumeSize = voxelLayer.GetVolumeSize();//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varvolumeSize= volume.GetVolumeSize();//Or use normal (0, 0, 1) or (0, 0, -1)...varhorz_section= SectionDefinition.CreateHorizontalSectionDefinition();
horz_section.Name ="Horizontal Section";
horz_section.IsVisible =true;
horz_section.VoxelPosition =new Coordinate3D(volumeSize.X /2, volumeSize.Y /2, volumeSize.Z /2);//At 2.x - voxelLayer.CreateSection(horz_section);
volume.CreateSection(horz_section);
Create Sections in a Circle Pattern
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//At 2.x - var volumeSize = voxelLayer.GetVolumeSize();//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varvolumeSize= volume.GetVolumeSize();//180 degrees orientation is due South. 90 degrees orientation is due west.varsouth=180.0;varnum_sections=12;varspacing=1/(double)num_sections;//Create a section every nth degree of orientation. Each section//bisects the middle of the voxelfor(ints=0;s<num_sections;s++){varorientation=south*(s*spacing);//At 2.x -//voxelLayer.CreateSection(new SectionDefinition()//{// Name = $"Circle {s + 1}",// VoxelPosition = new Coordinate3D(volumeSize.Item1 / 2, volumeSize.Item2 / 2, volumeSize.Item3 / 2),// Normal = voxelLayer.GetNormal(orientation, 0.0),// IsVisible = true//});
volume.CreateSection(new SectionDefinition(){Name=$"Circle {s+1}",VoxelPosition=new Coordinate3D(volumeSize.X /2, volumeSize.Y /2, volumeSize.Z /2),Normal= voxelLayer.GetNormal(orientation,0.0),IsVisible=true});}
Create Sections that Bisect the Voxel
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//At 2.x - var volumeSize = voxelLayer.GetVolumeSize();//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varvolumeSize= volume.GetVolumeSize();//Make three Normals - each is a Unit Vector (x, y, z)varnorth_south=new Coordinate3D(1,0,0);vareast_west=new Coordinate3D(0,1,0);varhorizontal=new Coordinate3D(0,0,1);intn=0;//The two verticals bisect the x,y plane. The horizontal normal bisects//the Z plane.foreach(var normal innewList<Coordinate3D>{ north_south, east_west, horizontal }){//At 2.x -//voxelLayer.CreateSection(new SectionDefinition()//{// Name = $"Cross {++n}",// VoxelPosition = new Coordinate3D(volumeSize.Item1 / 2, volumeSize.Item2 / 2, volumeSize.Item3 / 2),// Normal = normal,// IsVisible = true//});
volume.CreateSection(new SectionDefinition(){Name=$"Cross {++n}",VoxelPosition=new Coordinate3D(volumeSize.X /2, volumeSize.Y /2, volumeSize.Z /2),Normal=normal,IsVisible=true});}
Create Sections Diagonally across the Voxel
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//At 2.x - var volumeSize = voxelLayer.GetVolumeSize();//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varvolumeSize= volume.GetVolumeSize();//make a diagonal across the voxelvarvoxel_pos=new Coordinate3D(0,0, volumeSize.Z);varvoxel_pos_ur=new Coordinate3D(volumeSize.X, volumeSize.Y, volumeSize.Z);varlineBuilder=new LineBuilderEx(voxel_pos, voxel_pos_ur,null);vardiagonal= PolylineBuilderEx.CreatePolyline(lineBuilder.ToSegment());varnum_sections=12;varspacing=1/(double)num_sections;//change as neededvarorientation=20.0;//(approx NNW)vartilt=-15.0;varnormal= voxelLayer.GetNormal(orientation, tilt);for(ints=0;s<num_sections;s++){Coordinate2Dend_pt=new Coordinate2D(0,0);if(s>0){//position each section evenly spaced along the diagonalvarsegments=newList<Segment>()asICollection<Segment>;varpart= GeometryEngine.Instance.GetSubCurve3D(
diagonal,0.0,s*spacing, AsRatioOrLength.AsRatio);
part.GetAllSegments(ref segments);end_pt= segments.First().EndCoordinate;}//At 2.x -//voxelLayer.CreateSection(new SectionDefinition()//{// Name = $"Diagonal {s + 1}",// VoxelPosition = new Coordinate3D(end_pt.X, end_pt.Y, volumeSize.Item3),// Normal = normal,// IsVisible = true//});
volume.CreateSection(new SectionDefinition(){Name=$"Diagonal {s+1}",VoxelPosition=new Coordinate3D(end_pt.X, end_pt.Y, volumeSize.Z),Normal=normal,IsVisible=true});}
Update Section Orientation and Tilt
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;//At 2.x - foreach (var section in voxelLayer.GetSections())foreach(var section in volume.GetSections()){//set each normal to 45.0 orientation and tilt
section.Normal = voxelLayer.GetNormal(45.0,45.0);//apply the change//At 2.x - voxelLayer.UpdateSection(section);
volume.UpdateSection(section);}
Update Section Visibility
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);//At 2.x - var sections = voxelLayer.GetSections().Where(s => !s.IsVisible);//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;varsections= volume.GetSections().Where(s =>!s.IsVisible);//Make them all visibleforeach(var section in sections){
section.IsVisible =true;//apply the change//At 2.x - voxelLayer.UpdateSection(section);
volume.UpdateSection(section);}
Delete Sections
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;//At 2.x - foreach (var section in voxelLayer.GetSections())// voxelLayer.DeleteSection(section);foreach(var section in volume.GetSections())
volume.DeleteSection(section);//optional...if(voxelLayer.Visualization != VoxelVisualization.Volume)
voxelLayer.SetVisualization(VoxelVisualization.Volume);
Locked Sections
Get the Current Collection of Locked Sections
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetLockedSectionContainerExpanded(true);
voxelLayer.SetLockedSectionContainerVisibility(true);varlocked_sections= voxelLayer.GetLockedSections();
Get a Locked Section
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varlocked_section= voxelLayer.GetLockedSections().FirstOrDefault();varlocked_section2= voxelLayer.GetLockedSections().First(lsec => lsec.ID ==my_locked_section_id);
Get Selected Locked Section in TOC
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()varlocked_section= MapView.Active?.GetSelectedLockedSections()?.FirstOrDefault();if(locked_section!=null){}
Get Voxel Layer for the Selected Locked Section in TOC
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()VoxelLayervoxelLayer=null;varlocked_section= MapView.Active?.GetSelectedLockedSections()?.FirstOrDefault();if(locked_section!=null){voxelLayer= locked_section.Layer;//TODO - use the layer}
Set the Variable Profile Active for Selected Locked Section
//Must be on the QueuedTask.Run()varlocked_section= MapView.Active?.GetSelectedLockedSections()?.FirstOrDefault();if(locked_section!=null){varvariable= locked_section.Layer.GetVariableProfile(locked_section.VariableName);
locked_section.Layer.SetSelectedVariableProfile(variable);}
Lock a Section/"Create" a Locked Section
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetLockedSectionContainerExpanded(true);
voxelLayer.SetLockedSectionContainerVisibility(true);//Use the SelectedVariableProfile to get the sections//via its associated volumevarvolume= voxelLayer.SelectedVariableProfile.Volume;//get the selected sectionvarsection= MapView.Active.GetSelectedSections().FirstOrDefault();if(section==null){//At 2.x - section = voxelLayer.GetSections().FirstOrDefault();section= volume.GetSections().FirstOrDefault();}if(section==null)return;//Lock the section (Creates a locked section, deletes//the section)//if (voxelLayer.CanLockSection(section))// voxelLayer.LockSection(section);if(volume.CanLockSection(section))
volume.LockSection(section);
Update Locked Section Visibility
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetLockedSectionContainerExpanded(true);
voxelLayer.SetLockedSectionContainerVisibility(true);varlocked_sections= voxelLayer.GetLockedSections().Where(ls =>!ls.IsVisible);//Make them visibleforeach(var locked_section in locked_sections){
locked_section.IsVisible =true;//apply change
voxelLayer.UpdateSection(locked_section);}
Unlock a Locked Section
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.Visualization != VoxelVisualization.Surface)
voxelLayer.SetVisualization(VoxelVisualization.Surface);
voxelLayer.SetSectionContainerExpanded(true);
voxelLayer.SetSectionContainerVisibility(true);
voxelLayer.SetLockedSectionContainerExpanded(true);//get the selected locked sectionvarlocked_section= MapView.Active.GetSelectedLockedSections().FirstOrDefault();if(locked_section==null)locked_section= voxelLayer.GetLockedSections().FirstOrDefault();if(locked_section==null)return;//Unlock the locked section (Deletes the locked section, creates//a section)if(voxelLayer.CanUnlockSection(locked_section))
voxelLayer.UnlockSection(locked_section);
Delete a Locked Section
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()if(voxelLayer.GetLockedSections().Count()==0)return;//Delete the last locked section from the collection of//locked sections
voxelLayer.DeleteSection(voxelLayer.GetLockedSections().Last());