//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=newCIMVoxelDataConnection(){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(varvariableinvariables){varline=$"{variable.Variable}: {variable.DataType}, "+$"{variable.Description}, {variable.IsDefault}, {variable.IsSelected}";System.Diagnostics.Debug.WriteLine(line);}//Optional: set the default variablecreateParams.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 TOCvoxelLayer.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 slicesvoxelLayer.SetVisualization(VoxelVisualization.Volume);//Change the visualization to Surface//e.g. to create isosurfaces and sectionsvoxelLayer.SetVisualization(VoxelVisualization.Surface);
//var voxelLayer = ... ;//Must be on the QueuedTask.Run()//Offsetvaroffset=voxelLayer.CartographicOffset;//apply an offsetvoxelLayer.SetCartographicOffset(offset+100.0);//VerticalExaggerationvarexaggeration=voxelLayer.VerticalExaggeration;//apply an exaggerationvoxelLayer.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()asCIMVoxelLayer;def.Layer3DProperties.ExaggerationMode=ExaggerationMode.ScaleZ;//can set vertical exaggeration via the CIM also//def.Layer3DProperties.VerticalExaggeration = exaggeration + 100.0;//apply the changevoxelLayer.SetDefinition(def);//Diffuse Lightingif(!voxelLayer.IsDiffuseLightingEnabled)voxelLayer.SetDiffuseLightingEnabled(true);vardiffuse=voxelLayer.DiffuseLighting;//set Diffuse lighting to a value between 0 and 1voxelLayer.SetDiffuseLighting(0.5);//50%//Specular Lightingif(!voxelLayer.IsSpecularLightingEnabled)voxelLayer.SetSpecularLightingEnabled(true);varspecular=voxelLayer.SpecularLighting;//set Diffuse lighting to a value between 0 and 1voxelLayer.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 layerSystem.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=rendererasCIMVoxelStretchRenderer;//access the renderer}else//VoxelVariableDataType.Discrete{//Renderer will be unique valuevaruvr=rendererasCIMVoxelUniqueValueRenderer;//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.RendererasCIMVoxelStretchRenderer;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.RendererasCIMVoxelStretchRenderer;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.MinimumValuerenderer.ColorRangeMin=color_min;renderer.ColorRangeMax=color_max;//apply changesvariable.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.RendererasCIMVoxelUniqueValueRenderer;//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 offunique_value_class.Visible=false;//Apply the change to the rendererrenderer.Classes=classes.ToArray();//apply the changesvariable.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.RendererasCIMVoxelStretchRenderer;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(newIsosurfaceDefinition(){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 valuesurface.Value=surface.Value*0.9;//get a random colorvarcount=newRandom().Next(0,100);varcolors=ColorFactory.Instance.GenerateColorsFromColorRamp(((CIMVoxelStretchRenderer)variable.Renderer).ColorRamp,count);varidx=newRandom().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 updatedsurface.IsCustomColor=true;//update the surfacevariable.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 surfacevariable.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(varsurfaceinvariable.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(varsliceinslices){slice.IsVisible=true;//at 2.x - voxelLayer.UpdateSlice(slice);volume.UpdateSlice(slice);}//expand the slice container and make sure container visibility is truevoxelLayer.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 volumevolume.CreateSlice(newSliceDefinition(){Name="Middle Slice",VoxelPosition=newCoordinate3D(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");(doubleorientation,doubletilt)=voxelLayer.GetOrientationAndTilt(slice.Normal);//Convert orientation and tilt to a normalslice.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(varsliceinslices)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(newSectionDefinition(){Name="Middle Section",VoxelPosition=newCoordinate3D(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=newCoordinate3D(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(newSectionDefinition(){Name=$"Circle {s+1}",VoxelPosition=newCoordinate3D(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=newCoordinate3D(1,0,0);vareast_west=newCoordinate3D(0,1,0);varhorizontal=newCoordinate3D(0,0,1);intn=0;//The two verticals bisect the x,y plane. The horizontal normal bisects//the Z plane.foreach(varnormalinnewList<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(newSectionDefinition(){Name=$"Cross {++n}",VoxelPosition=newCoordinate3D(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=newCoordinate3D(0,0,volumeSize.Z);varvoxel_pos_ur=newCoordinate3D(volumeSize.X,volumeSize.Y,volumeSize.Z);varlineBuilder=newLineBuilderEx(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=newCoordinate2D(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(refsegments);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(newSectionDefinition(){Name=$"Diagonal {s+1}",VoxelPosition=newCoordinate3D(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(varsectioninvolume.GetSections()){//set each normal to 45.0 orientation and tiltsection.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(varsectioninsections){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(varsectioninvolume.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(varlocked_sectioninlocked_sections){locked_section.IsVisible=true;//apply changevoxelLayer.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 sectionsvoxelLayer.DeleteSection(voxelLayer.GetLockedSections().Last());