Rosette Demo#

Comprehensive demonstration of Rosette functionality in Dips Python API.

This script demonstrates Rosette services including: - View Management: Create, Get, Close views - Legend and Settings: Visibility, Weighting, Rosette settings, Projection mode - Group Visibility: User planes - Entity References: Get and set user plane entity visibility - Data Filters: Get and set active filter

Note: Tool demonstrations are in RosetteToolsDemo.py

Code Snippet: RosetteDemo.py#
"""
Comprehensive demonstration of Rosette functionality in Dips Python API.

This script demonstrates Rosette services including:
- View Management: Create, Get, Close views
- Legend and Settings: Visibility, Weighting, Rosette settings, Projection mode
- Group Visibility: User planes
- Entity References: Get and set user plane entity visibility
- Data Filters: Get and set active filter

Note: Tool demonstrations are in RosetteToolsDemo.py
"""

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
import dips.StereonetProjectionModeVal
import dips.RosetteSettingsVal

# 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 Rosette 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
    try:
        views = model.GetRosetteViewList()
        print(f"  ✓ GetRosetteViewList: {len(views)} found")
    except Exception as e:
        print(f"  ✗ GetRosetteViewList: {e}")
        views = []
    
    # Create a new view
    try:
        print("  Creating new Rosette view...")
        new_view = model.CreateRosetteView()
        view_value = new_view.GetValue()
        print(f"  ✓ CreateRosetteView: '{view_value.view_name}'")
        return new_view
    except Exception as e:
        print(f"  ✗ CreateRosetteView: {e}")
        return views[0] if views else None


# =============================================================================
# LEGEND AND SETTINGS DEMONSTRATIONS
# =============================================================================

def demonstrate_legend_and_settings(view, model):
    """Demonstrate legend visibility and settings."""
    print("\n" + "=" * 60)
    print("LEGEND AND SETTINGS")
    print("=" * 60)
    
    # Legend visibility
    try:
        view.SetLegendVisibility(True)
        print("  ✓ SetLegendVisibility: True")
    except Exception as e:
        print(f"  ✗ SetLegendVisibility: {e}")
    
    # IsWeighted
    try:
        view.SetIsWeighted(False)
        print("  ✓ SetIsWeighted: False")
    except Exception as e:
        print(f"  ✗ SetIsWeighted: {e}")
    
    # Rosette settings - use GetDefault
    # RosetteSettings properties:
    #   - sight_line_orientation: TrendPlunge
    #   - min_angle: AngleData
    #   - max_angle: AngleData
    #   - start_bin_strike: AngleData
    #   - num_bins: int (number of bins/sectors)
    #   - custom_scaling: bool
    #   - num_planes_per_circle_increment: int
    #   - is_weighted: bool
    try:
        rosette_settings = model.GetDefaultRosetteSettings()
        rosette_settings.num_bins = 36
        rosette_settings.is_weighted = False
        view.SetRosetteSettings(rosette_settings)
        print("  ✓ SetRosetteSettings (36 bins)")
    except Exception as e:
        print(f"  ✗ SetRosetteSettings: {e}")
    
    # Projection mode - use GetDefault
    try:
        projection = model.GetDefaultStereonetProjectionMode()
        projection.hemisphere_draw_option = DipsAPI_pb2.eHemisphereDrawOption.Lower
        projection.projection_method_draw_option = DipsAPI_pb2.eProjectionMethodDrawOption.EqualArea
        view.SetProjectionMode(projection)
        print("  ✓ SetProjectionMode: Lower Hemisphere, EqualArea")
    except Exception as e:
        print(f"  ✗ SetProjectionMode: {e}")


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

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


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

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


def demonstrate_individual_entity_visibility(view):
    """Demonstrate setting visibility for individual user planes."""
    print("\n" + "=" * 60)
    print("INDIVIDUAL ENTITY VISIBILITY")
    print("=" * 60)
    
    try:
        entities = view.GetUserPlaneEntityVisibilityList()
        if entities:
            entities[0].SetUserPlaneEntityVisibility(True)
            print("  ✓ SetUserPlaneEntityVisibility: True")
        else:
            print("  - SetUserPlaneEntityVisibility: No user planes available")
    except Exception as e:
        print(f"  ✗ SetUserPlaneEntityVisibility: {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)
    
    # Get current active filter
    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}")
    
    # Set active filter (if filters exist)
    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.CloseRosetteView()
        print(f"  ✓ CloseRosetteView: '{view_name}'")
    except Exception as e:
        print(f"  ✗ CloseRosetteView: {e}")


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

def main():
    """Main demonstration function."""
    print("=" * 60)
    print("Dips API - Rosette 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.GetRosetteViewList()
    if views:
        view = views[0]
        print(f"  Using existing view: '{view.GetValue().view_name}'")
    else:
        view = demonstrate_view_management(model)
    
    if view is None:
        print("  ✗ Could not create or find a Rosette view")
        return
    
    # Run all demonstrations
    demonstrate_legend_and_settings(view, model)
    demonstrate_group_visibility(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.CreateRosetteView()
    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("""
Rosette services demonstrated (12 methods):

VIEW MANAGEMENT (3 methods):
  - GetRosetteViewList
  - CreateRosetteView
  - CloseRosetteView

LEGEND AND SETTINGS (4 methods):
  - SetLegendVisibility
  - SetIsWeighted
  - SetRosetteSettings
  - SetProjectionMode

GROUP VISIBILITY (1 method):
  - SetUserPlaneEntityGroupVisibility

ENTITY REFERENCE LISTS (1 method):
  - GetUserPlaneEntityVisibilityList

INDIVIDUAL ENTITY VISIBILITY (1 method):
  - SetUserPlaneEntityVisibility

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


if __name__ == "__main__":
    main()