Stereonet 3D Demo#

Comprehensive demonstration of Stereonet3D functionality in Dips Python API.

This script demonstrates Stereonet3D services including: - View Management: Create, Get, Close views - Entity Visibility: Poles, Intersections, Contours, Global Planes, Overlay - Entity Options: Pole options, Intersection options, Contour settings - Group Visibility: Sets, Planes, Traverses, Folds - Legend and Display Settings: Weighted, VectorMode - Entity References: Get and set individual entity visibility/options - Data Filters: Get and set active filter

Note: Stereonet3D does not have Kinematic Analysis or Projection Mode settings.

Code Snippet: Stereonet3DDemo.py#
"""
Comprehensive demonstration of Stereonet3D functionality in Dips Python API.

This script demonstrates Stereonet3D services including:
- View Management: Create, Get, Close views
- Entity Visibility: Poles, Intersections, Contours, Global Planes, Overlay
- Entity Options: Pole options, Intersection options, Contour settings
- Group Visibility: Sets, Planes, Traverses, Folds
- Legend and Display Settings: Weighted, VectorMode
- Entity References: Get and set individual entity visibility/options
- Data Filters: Get and set active filter

Note: Stereonet3D does not have Kinematic Analysis or Projection Mode settings.
"""

import math
from dips import DipsApp
from dips import BuiltInDataFormatters
from dips import DipsAPI_pb2

# Helper value wrappers
import dips.TrendPlungeVal
import dips.AngleDataVal
import dips.ColorSurrogateVal

# Entity options and visibility wrappers
import dips.PoleEntityOptionsVal
import dips.IntersectionOptionsVal
import dips.ContourEntityVisibilityVal
import dips.ContourOptionsVal
import dips.GlobalPlaneEntityVisibilityVal
import dips.StereonetOverlayEntityVisibilityVal
import dips.StereonetOverlaySettingsVal
import dips.VectorDensityContourSettingsVal
import dips.QuantitativeContourSettingsVal
import dips.SetVersusSetVal

# Data wrappers
import dips.DiscontinuityDataVal
import dips.OrientationDataSetVal


# =============================================================================
# HELPER FUNCTIONS
# =============================================================================

def create_trend_plunge(trend_deg: float, plunge_deg: float):
    """Create a TrendPlunge from degrees."""
    tp = dips.TrendPlungeVal.TrendPlungeVal()
    tp.trend = dips.AngleDataVal.AngleDataVal()
    tp.trend.angle_radians = math.radians(trend_deg)
    tp.plunge = dips.AngleDataVal.AngleDataVal()
    tp.plunge.angle_radians = math.radians(plunge_deg)
    return tp


def create_color(r: int, g: int, b: int, a: int = 255):
    """Create a Color from RGBA values."""
    color = dips.ColorSurrogateVal.ColorSurrogateVal()
    color.r = r
    color.g = g
    color.b = b
    color.a = a
    return color


# =============================================================================
# SAMPLE DATA CREATION
# =============================================================================

def create_sample_traverse_with_poles(model):
    """Create a sample traverse with discontinuities (poles) for demonstration."""
    ods = model.GetDefaultOrientationDataSet()
    ods.name = "Sample Traverse for Stereonet3D Demo"
    ods.orientation_convention = DipsAPI_pb2.eOrientationConvention.TrendPlungeOrientation
    ods.orientation_data_type = DipsAPI_pb2.eOrientationDataType.SpotMapping
    ods.discontinuity_orientation_convention = DipsAPI_pb2.eOrientationConvention.TrendPlungeOrientation
    
    # Use built-in unit formatters
    ods.traverse_elevation_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    ods.traverse_xyz_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    ods.traverse_depth_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    ods.survey_distance_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    ods.discontinuity_distance_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    ods.discontinuity_xyz_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    ods.discontinuity_persistence_unit = BuiltInDataFormatters.LengthMeterDataFormatter
    
    # Create sample poles with different orientations
    sample_poles = [
        (45, 30), (90, 45), (135, 60), (180, 30),
        (225, 45), (270, 60), (315, 30), (0, 45),
        (60, 75), (120, 25), (240, 50), (300, 40),
    ]
    
    for trend_deg, plunge_deg in sample_poles:
        discontinuity = dips.DiscontinuityDataVal.DiscontinuityDataVal()
        discontinuity.orientation1.angle_radians = math.radians(trend_deg)
        discontinuity.orientation2.angle_radians = math.radians(plunge_deg)
        discontinuity.quantity = 1.0
        ods.discontinuity_list.append(discontinuity)
    
    return ods


# =============================================================================
# VIEW MANAGEMENT DEMONSTRATIONS
# =============================================================================

def demonstrate_view_management(model):
    """Demonstrate view creation and listing."""
    print("\n" + "=" * 60)
    print("VIEW MANAGEMENT")
    print("=" * 60)
    
    # Get existing views
    views = model.GetStereonet3DViewList()
    print(f"  Found {len(views)} existing Stereonet3D view(s)")
    
    # Create a new view
    print("  Creating new Stereonet3D view...")
    new_view = model.CreateStereonet3DView()
    view_value = new_view.GetValue()
    print(f"  ✓ Created view: '{view_value.view_name}'")
    
    return new_view


# =============================================================================
# ENTITY VISIBILITY DEMONSTRATIONS
# =============================================================================

def demonstrate_entity_visibility(view):
    """Demonstrate all entity visibility settings."""
    print("\n" + "=" * 60)
    print("ENTITY VISIBILITY")
    print("=" * 60)
    
    try:
        view.SetPoleEntityVisibility(True)
        print("  ✓ SetPoleEntityVisibility: True")
    except Exception as e:
        print(f"  ✗ SetPoleEntityVisibility: {e}")
    
    try:
        view.SetIntersectionEntityVisibility(True)
        print("  ✓ SetIntersectionEntityVisibility: True")
    except Exception as e:
        print(f"  ✗ SetIntersectionEntityVisibility: {e}")
    
    try:
        view.SetContourEntityVisibility(True)
        print("  ✓ SetContourEntityVisibility: True")
    except Exception as e:
        print(f"  ✗ SetContourEntityVisibility: {e}")
    
    try:
        view.SetGlobalMeanPlaneEntityVisibility(True)
        print("  ✓ SetGlobalMeanPlaneEntityVisibility: True")
    except Exception as e:
        print(f"  ✗ SetGlobalMeanPlaneEntityVisibility: {e}")
    
    try:
        view.SetGlobalBestFitPlaneEntityVisibility(True)
        print("  ✓ SetGlobalBestFitPlaneEntityVisibility: True")
    except Exception as e:
        print(f"  ✗ SetGlobalBestFitPlaneEntityVisibility: {e}")
    
    try:
        view.SetStereonetOverlayEntityVisibility(True)
        print("  ✓ SetStereonetOverlayEntityVisibility: True")
    except Exception as e:
        print(f"  ✗ SetStereonetOverlayEntityVisibility: {e}")


# =============================================================================
# ENTITY OPTIONS DEMONSTRATIONS
# =============================================================================

def demonstrate_pole_options(view, model):
    """Demonstrate pole entity options."""
    print("\n" + "=" * 60)
    print("POLE OPTIONS")
    print("=" * 60)
    
    try:
        pole_options = dips.PoleEntityOptionsVal.PoleEntityOptionsVal()
        pole_options.pole_mode = DipsAPI_pb2.ePoleMode.Vector
        pole_options.show_pole_planes = False
        pole_options.show_pole_vector_lines = True
        view.SetPoleEntityOptions(pole_options)
        print("  ✓ SetPoleEntityOptions (Vector mode)")
    except Exception as e:
        print(f"  ✗ SetPoleEntityOptions: {e}")


def demonstrate_intersection_options(view, model):
    """Demonstrate intersection entity options."""
    print("\n" + "=" * 60)
    print("INTERSECTION OPTIONS")
    print("=" * 60)
    
    try:
        intersection_options = model.GetDefaultIntersectionOptions()
        view.SetIntersectionEntityOptions(intersection_options)
        print("  ✓ SetIntersectionEntityOptions")
    except Exception as e:
        print(f"  ✗ SetIntersectionEntityOptions: {e}")
    
    try:
        view.SetIntersectionType(DipsAPI_pb2.eIntersectionType.AllPoleIntersections)
        print("  ✓ SetIntersectionType (AllPoleIntersections)")
    except Exception as e:
        print(f"  ✗ SetIntersectionType: {e}")
    
    try:
        sets = model.GetSetList()
        if len(sets) >= 2:
            set_vs_set = dips.SetVersusSetVal.SetVersusSetVal()
            set_vs_set.set_a = sets[0]
            set_vs_set.set_b = sets[1]
            view.SetSetVersusSet(set_vs_set)
            print("  ✓ SetSetVersusSet")
        else:
            print("  - SetSetVersusSet (needs 2+ sets)")
    except Exception as e:
        print(f"  ✗ SetSetVersusSet: {e}")


def demonstrate_contour_options(view, model):
    """Demonstrate contour entity options and settings."""
    print("\n" + "=" * 60)
    print("CONTOUR OPTIONS")
    print("=" * 60)
    
    try:
        contour_visibility = dips.ContourEntityVisibilityVal.ContourEntityVisibilityVal()
        contour_visibility.is_visible = True
        view.SetContourEntityOptions(contour_visibility)
        print("  ✓ SetContourEntityOptions")
    except Exception as e:
        print(f"  ✗ SetContourEntityOptions: {e}")
    
    try:
        view.SetContourType(DipsAPI_pb2.eContourType.PoleVectorDensity)
        print("  ✓ SetContourType (PoleVectorDensity)")
    except Exception as e:
        print(f"  ✗ SetContourType: {e}")
    
    try:
        density_settings = model.GetDefaultVectorDensityContourSettings()
        view.SetPoleVectorDensityContourSettings(density_settings)
        print("  ✓ SetPoleVectorDensityContourSettings")
    except Exception as e:
        print(f"  ✗ SetPoleVectorDensityContourSettings: {e}")
    
    try:
        density_settings = model.GetDefaultVectorDensityContourSettings()
        view.SetIntersectionVectorDensityContourSettings(density_settings)
        print("  ✓ SetIntersectionVectorDensityContourSettings")
    except Exception as e:
        print(f"  ✗ SetIntersectionVectorDensityContourSettings: {e}")
    
    try:
        quant_settings = model.GetDefaultQuantitativeContourSettings()
        view.SetQuantitativeContourSettings(quant_settings)
        print("  ✓ SetQuantitativeContourSettings")
    except Exception as e:
        print(f"  ✗ SetQuantitativeContourSettings: {e}")
    
    try:
        contour_options = model.GetDefaultContourOptions()
        view.SetPoleVectorContourOptions(contour_options)
        print("  ✓ SetPoleVectorContourOptions")
    except Exception as e:
        print(f"  ✗ SetPoleVectorContourOptions: {e}")
    
    try:
        contour_options = model.GetDefaultContourOptions()
        view.SetIntersectionVectorContourOptions(contour_options)
        print("  ✓ SetIntersectionVectorContourOptions")
    except Exception as e:
        print(f"  ✗ SetIntersectionVectorContourOptions: {e}")
    
    try:
        contour_options = model.GetDefaultContourOptions()
        view.SetQuantitativeContourOptions(contour_options)
        print("  ✓ SetQuantitativeContourOptions")
    except Exception as e:
        print(f"  ✗ SetQuantitativeContourOptions: {e}")


def demonstrate_global_plane_options(view):
    """Demonstrate global plane options."""
    print("\n" + "=" * 60)
    print("GLOBAL PLANE OPTIONS")
    print("=" * 60)
    
    try:
        global_mean = dips.GlobalPlaneEntityVisibilityVal.GlobalPlaneEntityVisibilityVal()
        global_mean.is_visible = True
        view.SetGlobalMeanPlaneEntityOptions(global_mean)
        print("  ✓ SetGlobalMeanPlaneEntityOptions")
    except Exception as e:
        print(f"  ✗ SetGlobalMeanPlaneEntityOptions: {e}")
    
    try:
        global_best_fit = dips.GlobalPlaneEntityVisibilityVal.GlobalPlaneEntityVisibilityVal()
        global_best_fit.is_visible = True
        view.SetGlobalBestFitPlaneEntityOptions(global_best_fit)
        print("  ✓ SetGlobalBestFitPlaneEntityOptions")
    except Exception as e:
        print(f"  ✗ SetGlobalBestFitPlaneEntityOptions: {e}")


def demonstrate_stereonet_overlay(view):
    """Demonstrate stereonet overlay options."""
    print("\n" + "=" * 60)
    print("STEREONET OVERLAY")
    print("=" * 60)
    
    try:
        overlay_visibility = dips.StereonetOverlayEntityVisibilityVal.StereonetOverlayEntityVisibilityVal()
        overlay_visibility.is_visible = True
        overlay_settings = dips.StereonetOverlaySettingsVal.StereonetOverlaySettingsVal()
        overlay_settings.option = DipsAPI_pb2.eStereonetOverlayOption.Polar
        overlay_settings.color = create_color(128, 128, 128, 180)
        overlay_visibility.stereonet_overlay_settings = overlay_settings
        view.SetStereonetOverlayEntityOptions(overlay_visibility)
        print("  ✓ SetStereonetOverlayEntityOptions (Polar)")
    except Exception as e:
        print(f"  ✗ SetStereonetOverlayEntityOptions (Polar): {e}")
    
    try:
        overlay_visibility = dips.StereonetOverlayEntityVisibilityVal.StereonetOverlayEntityVisibilityVal()
        overlay_visibility.is_visible = True
        overlay_settings = dips.StereonetOverlaySettingsVal.StereonetOverlaySettingsVal()
        overlay_settings.option = DipsAPI_pb2.eStereonetOverlayOption.Equatorial
        overlay_settings.color = create_color(0, 0, 255, 180)
        overlay_visibility.stereonet_overlay_settings = overlay_settings
        view.SetStereonetOverlayEntityOptions(overlay_visibility)
        print("  ✓ SetStereonetOverlayEntityOptions (Equatorial)")
    except Exception as e:
        print(f"  ✗ SetStereonetOverlayEntityOptions (Equatorial): {e}")
    
    try:
        overlay_visibility = dips.StereonetOverlayEntityVisibilityVal.StereonetOverlayEntityVisibilityVal()
        overlay_visibility.is_visible = True
        overlay_settings = dips.StereonetOverlaySettingsVal.StereonetOverlaySettingsVal()
        overlay_settings.option = DipsAPI_pb2.eStereonetOverlayOption.CustomOverlay
        overlay_settings.color = create_color(255, 0, 0, 180)
        overlay_settings.custom_orientation = create_trend_plunge(45, 60)
        overlay_visibility.stereonet_overlay_settings = overlay_settings
        view.SetStereonetOverlayEntityOptions(overlay_visibility)
        print("  ✓ SetStereonetOverlayEntityOptions (Custom)")
    except Exception as e:
        print(f"  ✗ SetStereonetOverlayEntityOptions (Custom): {e}")


# =============================================================================
# GROUP VISIBILITY DEMONSTRATIONS
# =============================================================================

def demonstrate_group_visibility(view):
    """Demonstrate all group visibility settings."""
    print("\n" + "=" * 60)
    print("GROUP VISIBILITY")
    print("=" * 60)
    
    try:
        view.SetSetWindowEntityGroupVisibility(True)
        print("  ✓ SetSetWindowEntityGroupVisibility: True")
    except Exception as e:
        print(f"  ✗ SetSetWindowEntityGroupVisibility: {e}")
    
    try:
        view.SetMeanSetPlaneEntityGroupVisibility(True)
        print("  ✓ SetMeanSetPlaneEntityGroupVisibility: True")
    except Exception as e:
        print(f"  ✗ SetMeanSetPlaneEntityGroupVisibility: {e}")
    
    try:
        view.SetUserPlaneEntityGroupVisibility(True)
        print("  ✓ SetUserPlaneEntityGroupVisibility: True")
    except Exception as e:
        print(f"  ✗ SetUserPlaneEntityGroupVisibility: {e}")
    
    try:
        view.SetTraverseEntityGroupVisibility(True)
        print("  ✓ SetTraverseEntityGroupVisibility: True")
    except Exception as e:
        print(f"  ✗ SetTraverseEntityGroupVisibility: {e}")
    
    try:
        view.SetFoldWindowEntityGroupVisibility(True)
        print("  ✓ SetFoldWindowEntityGroupVisibility: True")
    except Exception as e:
        print(f"  ✗ SetFoldWindowEntityGroupVisibility: {e}")
    
    try:
        view.SetBestFitFoldPlaneEntityGroupVisibility(True)
        print("  ✓ SetBestFitFoldPlaneEntityGroupVisibility: True")
    except Exception as e:
        print(f"  ✗ SetBestFitFoldPlaneEntityGroupVisibility: {e}")


# =============================================================================
# LEGEND AND DISPLAY SETTINGS
# =============================================================================

def demonstrate_legend_and_settings(view):
    """Demonstrate legend and display settings."""
    print("\n" + "=" * 60)
    print("LEGEND AND DISPLAY SETTINGS")
    print("=" * 60)
    
    try:
        view.SetLegendVisibility(True)
        print("  ✓ SetLegendVisibility: True")
    except Exception as e:
        print(f"  ✗ SetLegendVisibility: {e}")
    
    try:
        view.SetIsWeighted(False)
        print("  ✓ SetIsWeighted: False")
    except Exception as e:
        print(f"  ✗ SetIsWeighted: {e}")
    
    try:
        view.SetVectorMode(DipsAPI_pb2.eVectorMode.Pole)
        print("  ✓ SetVectorMode: Pole")
    except Exception as e:
        print(f"  ✗ SetVectorMode: {e}")


# =============================================================================
# ENTITY REFERENCE DEMONSTRATIONS
# =============================================================================

def demonstrate_entity_references(view):
    """Demonstrate getting and setting entity references."""
    print("\n" + "=" * 60)
    print("ENTITY REFERENCES")
    print("=" * 60)
    
    try:
        entities = view.GetSetWindowEntityVisibilityList()
        print(f"  ✓ GetSetWindowEntityVisibilityList: {len(entities)} found")
    except Exception as e:
        print(f"  ✗ GetSetWindowEntityVisibilityList: {e}")
    
    try:
        entities = view.GetMeanSetPlaneEntityVisibilityList()
        print(f"  ✓ GetMeanSetPlaneEntityVisibilityList: {len(entities)} found")
    except Exception as e:
        print(f"  ✗ GetMeanSetPlaneEntityVisibilityList: {e}")
    
    try:
        entities = view.GetUserPlaneEntityVisibilityList()
        print(f"  ✓ GetUserPlaneEntityVisibilityList: {len(entities)} found")
    except Exception as e:
        print(f"  ✗ GetUserPlaneEntityVisibilityList: {e}")
    
    try:
        entities = view.GetTraverseEntityVisibilityList()
        print(f"  ✓ GetTraverseEntityVisibilityList: {len(entities)} found")
    except Exception as e:
        print(f"  ✗ GetTraverseEntityVisibilityList: {e}")
    
    try:
        entities = view.GetFoldWindowEntityVisibilityList()
        print(f"  ✓ GetFoldWindowEntityVisibilityList: {len(entities)} found")
    except Exception as e:
        print(f"  ✗ GetFoldWindowEntityVisibilityList: {e}")
    
    try:
        entities = view.GetBestFitFoldPlaneEntityVisibilityList()
        print(f"  ✓ GetBestFitFoldPlaneEntityVisibilityList: {len(entities)} found")
    except Exception as e:
        print(f"  ✗ GetBestFitFoldPlaneEntityVisibilityList: {e}")


def demonstrate_individual_entity_visibility(view):
    """Demonstrate setting visibility and options for individual entities."""
    print("\n" + "=" * 60)
    print("INDIVIDUAL ENTITY VISIBILITY/OPTIONS")
    print("=" * 60)
    
    try:
        entities = view.GetSetWindowEntityVisibilityList()
        if entities:
            entities[0].SetSetWindowEntityVisibility(True)
            print("  ✓ SetSetWindowEntityVisibility: True")
        else:
            print("  - SetSetWindowEntityVisibility: No set windows available")
    except Exception as e:
        print(f"  ✗ SetSetWindowEntityVisibility: {e}")
    
    try:
        entities = view.GetMeanSetPlaneEntityVisibilityList()
        if entities:
            entities[0].SetMeanSetPlaneEntityVisibility(True)
            print("  ✓ SetMeanSetPlaneEntityVisibility: True")
            try:
                import dips.SetEntityOptionsVal
                opts = dips.SetEntityOptionsVal.SetEntityOptionsVal()
                opts.show_label = True
                entities[0].SetMeanSetPlaneEntityOptions(opts)
                print("  ✓ SetMeanSetPlaneEntityOptions")
            except Exception as e:
                print(f"  ✗ SetMeanSetPlaneEntityOptions: {e}")
        else:
            print("  - SetMeanSetPlaneEntityVisibility: No mean set planes available")
    except Exception as e:
        print(f"  ✗ SetMeanSetPlaneEntityVisibility: {e}")
    
    try:
        entities = view.GetUserPlaneEntityVisibilityList()
        if entities:
            entities[0].SetUserPlaneEntityVisibility(True)
            print("  ✓ SetUserPlaneEntityVisibility: True")
            try:
                import dips.UserPlaneEntityOptionsVal
                opts = dips.UserPlaneEntityOptionsVal.UserPlaneEntityOptionsVal()
                opts.show_label = True
                entities[0].SetUserPlaneEntityOptions(opts)
                print("  ✓ SetUserPlaneEntityOptions")
            except Exception as e:
                print(f"  ✗ SetUserPlaneEntityOptions: {e}")
        else:
            print("  - SetUserPlaneEntityVisibility: No user planes available")
    except Exception as e:
        print(f"  ✗ SetUserPlaneEntityVisibility: {e}")
    
    try:
        entities = view.GetTraverseEntityVisibilityList()
        if entities:
            entities[0].SetTraverseEntityVisibility(True)
            print("  ✓ SetTraverseEntityVisibility: True")
            try:
                import dips.TraverseEntityOptionsVal
                opts = dips.TraverseEntityOptionsVal.TraverseEntityOptionsVal()
                opts.show_label = True
                entities[0].SetTraverseEntityOptions(opts)
                print("  ✓ SetTraverseEntityOptions")
            except Exception as e:
                print(f"  ✗ SetTraverseEntityOptions: {e}")
        else:
            print("  - SetTraverseEntityVisibility: No traverses available")
    except Exception as e:
        print(f"  ✗ SetTraverseEntityVisibility: {e}")
    
    try:
        entities = view.GetFoldWindowEntityVisibilityList()
        if entities:
            entities[0].SetFoldWindowEntityVisibility(True)
            print("  ✓ SetFoldWindowEntityVisibility: True")
        else:
            print("  - SetFoldWindowEntityVisibility: No fold windows available")
    except Exception as e:
        print(f"  ✗ SetFoldWindowEntityVisibility: {e}")
    
    try:
        entities = view.GetBestFitFoldPlaneEntityVisibilityList()
        if entities:
            entities[0].SetFoldEntityVisibility(True)
            print("  ✓ SetFoldEntityVisibility: True")
            try:
                import dips.FoldEntityOptionsVal
                opts = dips.FoldEntityOptionsVal.FoldEntityOptionsVal()
                opts.show_label = True
                entities[0].SetFoldEntityOptions(opts)
                print("  ✓ SetFoldEntityOptions")
            except Exception as e:
                print(f"  ✗ SetFoldEntityOptions: {e}")
        else:
            print("  - SetFoldEntityVisibility: No fold entities available")
    except Exception as e:
        print(f"  ✗ SetFoldEntityVisibility: {e}")


# =============================================================================
# DATA FILTER DEMONSTRATIONS
# =============================================================================

def demonstrate_active_data_filter(view, model):
    """Demonstrate active data filter management."""
    print("\n" + "=" * 60)
    print("ACTIVE DATA FILTER")
    print("=" * 60)
    
    try:
        active_filter = view.GetActiveDataFilter()
        if active_filter:
            filter_value = active_filter.GetValue()
            print(f"  ✓ GetActiveDataFilter: '{filter_value.name}'")
        else:
            print("  ✓ GetActiveDataFilter: None (no active filter)")
    except Exception as e:
        print(f"  ✗ GetActiveDataFilter: {e}")
    
    try:
        filters = model.GetDataFilterList()
        if filters:
            view.SetActiveDataFilter(filters[0])
            filter_value = filters[0].GetValue()
            print(f"  ✓ SetActiveDataFilter: '{filter_value.name}'")
        else:
            print("  - SetActiveDataFilter: No filters available")
    except Exception as e:
        print(f"  ✗ SetActiveDataFilter: {e}")


# =============================================================================
# VIEW CLOSE DEMONSTRATION
# =============================================================================

def demonstrate_close_view(view):
    """Demonstrate closing a view."""
    print("\n" + "=" * 60)
    print("CLOSE VIEW")
    print("=" * 60)
    
    try:
        view_value = view.GetValue()
        view_name = view_value.view_name
        view.CloseStereonet3DView()
        print(f"  ✓ CloseStereonet3DView: '{view_name}'")
    except Exception as e:
        print(f"  ✗ CloseStereonet3DView: {e}")


# =============================================================================
# MAIN
# =============================================================================

def main():
    """Main demonstration function."""
    print("=" * 60)
    print("Dips API - Stereonet3D Comprehensive Demo")
    print("=" * 60)
    
    # Connect to Dips
    print("\nConnecting to Dips application...")
    try:
        app = DipsApp.LaunchApp(62535)
        print("✓ Connected to Dips")
    except Exception as e:
        print(f"✗ Failed to connect: {e}")
        print("Make sure Dips is running with scripting enabled on port 62535")
        return
    
    model = app.GetModel()
    
    # Create sample data if needed
    print("\n" + "-" * 60)
    print("SAMPLE DATA SETUP")
    print("-" * 60)
    try:
        traverses = model.GetTraverseList()
        if len(traverses) == 0:
            print("Creating sample traverse with poles...")
            ods = create_sample_traverse_with_poles(model)
            model.AddTraverse(ods)
            print(f"  ✓ Created traverse with {len(ods.discontinuity_list)} poles")
        else:
            print(f"  ✓ Found {len(traverses)} existing traverse(s)")
    except Exception as e:
        print(f"  Note: {e}")
    
    # Get or create a view
    views = model.GetStereonet3DViewList()
    if views:
        view = views[0]
        print(f"  Using existing view: '{view.GetValue().view_name}'")
    else:
        view = demonstrate_view_management(model)
    
    # Run all demonstrations
    demonstrate_entity_visibility(view)
    demonstrate_pole_options(view, model)
    demonstrate_intersection_options(view, model)
    demonstrate_contour_options(view, model)
    demonstrate_global_plane_options(view)
    demonstrate_stereonet_overlay(view)
    demonstrate_group_visibility(view)
    demonstrate_legend_and_settings(view)
    demonstrate_entity_references(view)
    demonstrate_individual_entity_visibility(view)
    demonstrate_active_data_filter(view, model)
    
    # Create and close a new view to demonstrate view lifecycle
    print("\n" + "-" * 60)
    print("VIEW LIFECYCLE DEMO")
    print("-" * 60)
    new_view = model.CreateStereonet3DView()
    print(f"  ✓ Created new view: '{new_view.GetValue().view_name}'")
    demonstrate_close_view(new_view)
    
    # Show the application
    print("\n" + "-" * 60)
    app.Show()
    
    # Summary
    print("\n" + "=" * 60)
    print("DEMONSTRATION COMPLETE")
    print("=" * 60)
    print("""
Stereonet3D services demonstrated (47 methods):

VIEW MANAGEMENT (3 methods):
  - GetStereonet3DViewList
  - CreateStereonet3DView
  - CloseStereonet3DView

ENTITY VISIBILITY (6 methods):
  - SetPoleEntityVisibility
  - SetIntersectionEntityVisibility
  - SetContourEntityVisibility
  - SetGlobalMeanPlaneEntityVisibility
  - SetGlobalBestFitPlaneEntityVisibility
  - SetStereonetOverlayEntityVisibility

ENTITY OPTIONS (12 methods):
  - SetPoleEntityOptions
  - SetIntersectionEntityOptions
  - SetIntersectionType
  - SetSetVersusSet
  - SetContourEntityOptions
  - SetContourType
  - SetPoleVectorDensityContourSettings
  - SetIntersectionVectorDensityContourSettings
  - SetQuantitativeContourSettings
  - SetPoleVectorContourOptions
  - SetIntersectionVectorContourOptions
  - SetQuantitativeContourOptions
  - SetGlobalMeanPlaneEntityOptions
  - SetGlobalBestFitPlaneEntityOptions
  - SetStereonetOverlayEntityOptions

GROUP VISIBILITY (6 methods):
  - SetSetWindowEntityGroupVisibility
  - SetMeanSetPlaneEntityGroupVisibility
  - SetUserPlaneEntityGroupVisibility
  - SetTraverseEntityGroupVisibility
  - SetFoldWindowEntityGroupVisibility
  - SetBestFitFoldPlaneEntityGroupVisibility

LEGEND AND SETTINGS (3 methods):
  - SetLegendVisibility
  - SetIsWeighted
  - SetVectorMode

ENTITY REFERENCE LISTS (6 methods):
  - GetSetWindowEntityVisibilityList
  - GetMeanSetPlaneEntityVisibilityList
  - GetUserPlaneEntityVisibilityList
  - GetTraverseEntityVisibilityList
  - GetFoldWindowEntityVisibilityList
  - GetBestFitFoldPlaneEntityVisibilityList

INDIVIDUAL ENTITY VISIBILITY/OPTIONS (10 methods):
  - SetSetWindowEntityVisibility
  - SetMeanSetPlaneEntityVisibility
  - SetMeanSetPlaneEntityOptions
  - SetUserPlaneEntityVisibility
  - SetUserPlaneEntityOptions
  - SetTraverseEntityVisibility
  - SetTraverseEntityOptions
  - SetFoldWindowEntityVisibility
  - SetFoldEntityVisibility
  - SetFoldEntityOptions

DATA FILTER (2 methods):
  - GetActiveDataFilter
  - SetActiveDataFilter
""")


if __name__ == "__main__":
    main()