classdef SBSRVECIMAGE
    % vector image
    properties(Dependent=true)
        % number of stroke
        nstroke
        
        % points after transformation
        pts
        
        % gradient directions after transformation
        dirs
        
        % symplane normal and p0 after transformation
        symplane_normal
        symplane_p0
    end
    
    properties
        % all points
        m_pts %the points are sequenced by timestamp
        m_curvature %curvature value of each point
        m_dirs %tangent direction of each point
        
        % parameter on the bspline
        m_tt
        
        % splines, spline(i) is the source of stroke(i)
        m_splinelist
        
        % segmentation by stroke, larger value is later stroke
        m_segby_stroke
        
        % segmentation by line
        m_segby_line
        
        % segmentation by intersection
        m_segby_intersect
        
        % parallel grouping
        m_segby_parallel_group
        
        % segmentation by object
        m_idxpts_per_obj
        m_label_per_obj     %label(i) is the label for idxpts_per_obj(i)
        
        % segmentation by object label
%         m_idxpts_per_label
        m_dblbs
        
        % segmentation by arclength
        m_segby_arclen
        
        % segmentation by junction, junction is different from intersection
        % in that they are detected with torelence, so even if two stroke
        % does not touch, they can form a junction if looks so
        m_segby_junction
        
        % transformat that transforms the points to image coordinate
        m_transmat_to_imgc = eye(3)
        m_imgsize %for imgc, the image size
        
        % the file from which this vecimg is created
        m_datafile
        
        % the 3d view
        m_view
        
        % symmetry plane
        % coordinate = x down, y right, z up
        % z=0 is the image plane
        m_symplane_normal
        m_symplane_p0
    end
    
    methods
        function val = get.symplane_normal(obj)
            % this is not affected by transmat, and will be invalid if the
            % sketch is rotated or non-uniformly scaled
            val = obj.m_symplane_normal;
        end
        
        function val = get.symplane_p0(obj)
            val = [];
            if ~isempty(obj.m_symplane_p0)
                p0 = obj.m_symplane_p0;
                p0(1:2) = util_transform_pts(p0(1:2),obj.m_transmat_to_imgc);
                val = p0(:);
            end
        end
        
        function val = get.nstroke(obj)
            val = max(obj.m_segby_stroke);
        end
        
        function val = get.pts(obj)
            if isempty(obj.m_transmat_to_imgc)
                val = obj.m_pts;
            else
                val = util_transform_pts(obj.m_pts,obj.m_transmat_to_imgc);
            end
        end
        
        function val = get.dirs(obj)
            if isempty(obj.m_transmat_to_imgc)
                val = obj.m_dirs;
            else
                val = util_transform_tangents(obj.m_dirs,obj.m_transmat_to_imgc);
            end
        end
    end
    
    methods
        % low-level segmentation
        function [ptslist,dirlist,idxlist] = pts_by_stroke(obj,varargin)
            [ptslist,dirlist,idxlist] = obj.pts_by_type(obj.m_segby_stroke);
        end
        
        function [ptslist,dirlist,idxlist] = pts_by_line(obj,varargin)
            [ptslist,dirlist,idxlist] = obj.pts_by_type(obj.m_segby_line);
        end
        
        function [ptslist,dirlist,idxlist] = pts_by_intersect(obj,varargin)
            [ptslist,dirlist,idxlist] = obj.pts_by_type(obj.m_segby_intersect);
        end
        
        function [ptslist,dirlist,idxlist] = pts_by_arclen(obj,varargin)
            [ptslist,dirlist,idxlist] = obj.pts_by_type(obj.m_segby_arclen);
        end
        
        function [ptslist,dirlist,idxlist] = pts_by_junction(obj,varargin)
            [ptslist,dirlist,idxlist] = obj.pts_by_type(obj.m_segby_junction);
        end
        
        function [ptslist,dirlist,idxlist] = pts_by_parallel_group(obj,varargin)
            [ptslist,dirlist,idxlist] = obj.pts_by_type(obj.m_segby_parallel_group,'ignorezero',true);
        end
        
        % semantic segmentation
        function [ptslist,dirlist,idxlist] = pts_by_label(obj,varargin)
            %ptslist{i} = points that have label obj.m_dblbs(i)
            idxlist = obj.m_idxpts_per_label;
            pts = obj.pts;
            dirs = obj.dirs;
            ptslist = cellfun(@(x)pts(:,x),idxlist,'uniformoutput',false);
            dirlist = cellfun(@(x)dirs(:,x),idxlist,'uniformoutput',false);
        end
        
        function [ptslist,dirlist,idxlist] = pts_by_object(obj,varargin)
            % ptslist{i} = points that belongs to object i
            idxlist = obj.m_idxpts_per_obj;
            pts = obj.pts;
            dirs = obj.dirs;
            ptslist = cellfun(@(x)pts(:,x),idxlist,'uniformoutput',false);
            dirlist = cellfun(@(x)dirs(:,x),idxlist,'uniformoutput',false);
        end
        
        % utility
        [ptslist,dirlist,idxlist] = pts_by_type(obj,typevec,varargin)
        
        % transformation
        obj = set_transmat_by_imgc(obj,imgsize,npixlong,varargin)
    end
    
    methods(Static=true)
        % make from svg file
        obj = init_with_svg(svgfile,varargin)
        
        % given a list of bsplines, make vecimg
        obj = init_with_curvelist(bsplist,varargin)
        
        % given some ptslist, make vecimg
        obj = init_with_ptslist(ptslist,varargin)
        
        % make from raw sketch data (util_dataset_from_sketchdata)
        obj = init_with_dataset(skdata,varargin)
        
        % given that seglbs(i) is the label of point i, and strokeidx(i) is
        % the stroke index of point i, clean up short segments, that is,
        % nnz(seglbs==k) is short
        seglbs = cleanup_short_seglbs(seglbs,strokeidx)
    end
    
end

