Search code examples
dm-script

Keep a oval annotation as a circle by using dm-script


If I manually change the size of the circle by using dm-script, is that possible to lock the center of the circle to center of FFT image, and also keep it as a circle, instead of ellipse


Solution

  • When you place a circle annotation (component) you of course determine its size and position yourself in the according commands:

    Image img := RealImage( "Test", 4, 512, 512 )
    img.ShowImage()
    ImageDisplay disp = img.ImageGetImageDisplay(0)
    Component testComp = NewOvalAnnotation(20,20,90,120)    // Specify coordinates
    disp.ComponentAddChildAtEnd(testComp)
    

    and

    number kOvalType = 6
    ImageDisplay disp = GetFrontImage().ImageGetImageDisplay(0)
    Component anno = disp.ComponentGetNthChildOfType(kOvalType,0)
    if (!anno.ComponentIsValid()) Throw("No oval annoation found")
    
    number t,l,b,r,w,h, px, py
    anno.ComponentGetRect(t,l,b,r)
    w = abs(r-l)
    h = abs(b-t)
    px = (r+l)/2
    py = (t+b)/2
    
    // Place where you want it, f.e.:
    px = 100
    py = 100
    w = 20
    h = 20
    
    anno.ComponentSetRect(py-h/2,px-w/2,py+h/2,px+w/2)
    

    I assume, what you are asking here is, how one can have a script control how the annotation can and can not be altered by the user with the mouse. This can be done by adding event-listeners which jump into action, when the user changes the annotation by mouse. Here is an example script:

    // EventListener example showing how to "restrict" annotation-interactions.
    // Whenever the annotation changes, the event-listener restricts properties
    // to allowed values and repositions the annoation accordingly.
    // The listener-object stays in scope as long as it is registered to a valid
    // imageDisplay. Therefore, it should not itself hold images or imageDisplays
    // as member variables
    
    Class CAnnoRestrictor
    {
        number imgID
        number annoID
        number listenID     
        number cx,cy,rad,ar
        
        imageDisplay GetDisp(object self)
        {
            image img := FindImageByID(imgID)
            if ( !img.ImageIsValid() ) return NULL
            if ( 0 == img.ImageCountImageDisplays() ) return NULL       
            return img.ImageGetImageDisplay(0)      
        }
        
        component GetAnno(object self)
        {
            imageDisplay disp = self.GetDisp()
            if ( !disp.ImageDisplayIsValid() ) return NULL
            return disp.ComponentGetChildByID(annoID)
        }
    
        void DoRestrict(object self){
            // This now defines the restriction action.
            // here, we ensure that the centre of the annoation is always lying 
            // in a rect of +/- rad around the image centre 
            // and that the aspect ratio of the annotation matches that of the image
            component anno = self.GetAnno()
            number t,l,b,r, w, h, px, py
            anno.ComponentGetRect(t,l,b,r)
            w = abs(r-l)
            h = w/ar
            px = max( min( (r+l)/2, cx+rad ), cx-rad )
            py = max( min( (t+b)/2, cy+rad ), cy-rad )
            
            // Set the restrictet Annoation
            anno.ComponentSetRect(py-h/2,px-w/2,py+h/2,px+w/2)      
        }
        
        object AttachToAnno(object self, component anno){
            if ( !anno.ComponentIsValid() ) Throw( "Invalid annotation." )
            if ( 0 != imgID ) Throw( "Restrictor already initialized." )
            imageDisplay disp = anno.ComponentGetParentComponent()
            if ( !disp.ImageDisplayIsValid() ) Throw( "Annotation is not a child of an image display" )
            image img := disp.ImageDisplayGetImage()
            
            img.ImageGetDimensionSizes(cx,cy)
            ar = cx/cy
            cx/=2
            cy/=2
            rad = min(cx,cy)/2
            
            annoID = anno.ComponentGetID()      
            imgID = img.ImageGetID()
            
            self.DoRestrict()
            
            string messagemap = "component_property_changed:OnCompPropChanged" 
            listenID = ImageDisplayAddEventListener( self.GetDisp(), self, messagemap )                     
        }
        
        void OnCompPropChanged( object self, Number disp_flags, ImageDisplay disp, Number comp_flags1, Number comp_flags2, Component comp ){
            if ( comp.ComponentGetID() == annoID )
                self.DoRestrict()
        }
    }
    
    // Test Script
    Image img := RealImage( "Test", 4, 512, 800 )
    img.ShowImage()
    ImageDisplay disp = img.ImageGetImageDisplay(0)
    Component testComp = NewOvalAnnotation(20,20,90,120)
    testComp.ComponentSetForeGroundColor(0.5,0.8,0.8)
    testComp.ComponentSetBackGroundColor(1,0,0)
    testComp.ComponentSetDrawingMode(1)
    testComp.ComponentSetFillMode(1)
    testComp.ComponentSetTransferrable(0)
    disp.ComponentAddChildAtEnd(testComp)
    If (TwoButtonDialog("Restrict Annotation?","Yes","No"))
        Alloc(CAnnoRestrictor).AttachToAnno( testComp )