একটি 2D বক্রাকে ডেটা সঞ্চয় করার জন্য পয়েন্টগুলিতে রূপান্তর করা


12

আমি একটি অ্যালগরিদম তৈরি করেছি যা যে কোনও বাঁক অর্থাৎ পাথকে ন্যূনতম সংখ্যায় রূপান্তর করে যাতে আমি এটি একটি ফাইল বা ডাটাবেসে সংরক্ষণ করতে পারি।

পদ্ধতিটি সহজ: এটি তিনটি পয়েন্টকে সমান ধাপে সরায় এবং এই পয়েন্টগুলির আকারের রেখার মধ্যবর্তী কোণটি পরিমাপ করে। যদি কোণটি সহনশীলতার চেয়ে বড় হয় তবে এটি সেই বিন্দুতে একটি নতুন ঘনকীয় বক্ররেখা তৈরি করে। তারপরে এটি লাইনগুলি এগিয়ে নিয়ে যায় এবং আবার কোণটি পরিমাপ করে ...

যারা অ্যান্ড্রয়েড পাথ ক্লাস জানেন তাদের জন্য - নোট করুন যে ডিএসটিপথটি একটি কাস্টম শ্রেণি, যা পয়েন্টগুলি একটি অ্যারেতে রেকর্ড করে তাই আমি পয়েন্টগুলি পরে সংরক্ষণ করতে পারি, যখন এসসিআরপথ একটি অঞ্চল ইউনিয়নের ফলাফল এবং তাই আমার জন্য কোনও মূল পয়েন্ট নেই has বাঁচাতে.

সমস্যাটি হ'ল নীচের কোড দ্বারা উত্পাদিত এই চিত্রটিতে যেমন দেখতে পাবেন তেমন বৃত্তটি মসৃণ দেখাচ্ছে না, যেখানে উত্স পথটি একটি নিখুঁত বৃত্ত এবং আয়তক্ষেত্র নিয়ে গঠিত। আমি সহনশীলতার কোণ এবং পদক্ষেপগুলির দৈর্ঘ্য পরিবর্তন করার চেষ্টা করেছি, তবে কিছুই সাহায্য করে না। আমি ভাবছি যদি আপনি এই অ্যালগরিদম বা অন্য কোনও পদ্ধতির কোনও উন্নতি প্রস্তাব করতে পারেন।

সম্পাদনা: যারা এখন অ্যান্ড্রয়েড জাভা ব্যবহার করেন তাদের জন্য আমি পুরো কোডটি পোস্ট করেছি, যাতে তারা সহজেই চেষ্টা ও পরীক্ষা করতে পারে।

এখানে চিত্র বর্ণনা লিখুন

public class CurveSavePointsActivity extends Activity{

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(new CurveView(this));
    }

    class CurveView extends View{

        Path srcPath, dstPath;
        Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        public CurveView(Context context) {
            super(context);

            srcPaint.setColor(Color.BLACK);
            srcPaint.setStyle(Style.STROKE);
            srcPaint.setStrokeWidth(2);
            srcPaint.setTextSize(20);

            dstPaint.setColor(Color.BLUE);
            dstPaint.setStyle(Style.STROKE);
            dstPaint.setStrokeWidth(2);
            dstPaint.setTextSize(20);

            srcPath = new Path();
            dstPath = new Path();

        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);

            //make a circle path
            srcPath.addCircle(w/4, h/2, w/6 - 30, Direction.CW);

            //make a rectangle path
            Path rectPath = new Path();
            rectPath.addRect(new RectF(w/4, h/2 - w/16, w*0.5f, h/2 + w/16), Direction.CW);


            //create a path union of circle and rectangle paths
            RectF bounds = new RectF();
            srcPath.computeBounds(bounds, true);
            Region destReg = new Region();
            Region clip = new Region();
            clip.set(new Rect(0,0, w, h));
            destReg.setPath(srcPath, clip);
            Region srcReg = new Region();
            srcReg.setPath(rectPath, clip); 
            Region resultReg = new Region();
            resultReg.op(destReg, srcReg, Region.Op.UNION);
            if(!resultReg.isEmpty()){
                srcPath.reset();
                srcPath.addPath(resultReg.getBoundaryPath());
            }

            //extract a new path from the region boundary path
            extractOutlinePath();

            //shift the resulting path bottom left, so they can be compared
            Matrix matrix = new Matrix();
            matrix.postTranslate(10, 30);
            dstPath.transform(matrix);

        }

         @Override 
            public void onDraw(Canvas canvas) { 
                super.onDraw(canvas);    
                canvas.drawColor(Color.WHITE);
                canvas.drawPath(srcPath, srcPaint);
                canvas.drawPath(dstPath, dstPaint);

                canvas.drawText("Source path", 40, 50, srcPaint);
                canvas.drawText("Destination path", 40, 100, dstPaint);
         }


         public void extractOutlinePath() {

             PathMeasure pm = new PathMeasure(srcPath, false); //get access to curve points

             float p0[] = {0f, 0f}; //current position of the new polygon
             float p1[] = {0f, 0f}; //beginning of the first line
             float p2[] = {0f, 0f}; //end of the first & the beginning of the second line
             float p3[] = {0f, 0f}; //end of the second line

             float pxStep = 5; //sampling step for extracting points
             float pxPlace  = 0; //current place on the curve for taking x,y coordinates
             float angleT = 5; //angle of tolerance

             double a1 = 0; //angle of the first line
             double a2 = 0; //angle of the second line

             pm.getPosTan(0, p0, null); //get the beginning x,y of the original curve into p0
             dstPath.moveTo(p0[0], p0[1]); //start new path from the beginning of the curve
             p1 = p0.clone(); //set start of the first line

             pm.getPosTan(pxStep, p2, null); //set end of the first line & the beginning of the second

             pxPlace = pxStep * 2;
             pm.getPosTan(pxPlace, p3, null); //set end of the second line


             while(pxPlace < pm.getLength()){
             a1 = 180 - Math.toDegrees(Math.atan2(p1[1] - p2[1], p1[0] - p2[0])); //angle of the first line
             a2 = 180 - Math.toDegrees(Math.atan2(p2[1] - p3[1], p2[0] - p3[0])); //angle of the second line

             //check the angle between the lines
             if (Math.abs(a1-a2) > angleT){

               //draw a straight line to the first point if the current p0 is not already there
               if(p0[0] != p1[0] && p0[1] != p1[1]) dstPath.quadTo((p0[0] + p1[0])/2, (p0[1] + p1[1])/2, p1[0], p1[1]);

               dstPath.quadTo(p2[0] , p2[1], p3[0], p3[1]); //create a curve to the third point through the second

               //shift the three points by two steps forward
               p0 = p3.clone();
               p1 = p3.clone();
               pxPlace += pxStep;
               pm.getPosTan(pxPlace, p2, null); 
               pxPlace += pxStep;
               pm.getPosTan(pxPlace, p3, null);
               if (pxPlace > pm.getLength()) break;
             }else{
               //shift three points by one step towards the end of the curve
               p1 = p2.clone(); 
               p2 = p3.clone();
               pxPlace += pxStep;
               pm.getPosTan(pxPlace, p3, null); 
             }
             }
             dstPath.close();
         }
    }

}

এখানে মূল এবং আমার অ্যালগরিদম যা উত্পাদন করে তার মধ্যে একটি তুলনা করা হয়েছে:

পাথের মধ্যে তুলনা;  লক্ষণীয়ভাবে ডেরিভেটিভের উপর মসৃণ কোণগুলি


বি স্প্লিংস ব্যবহার করবেন না কেন?
গ্রিফিনহার্ট

4
যদি আপনি জানেন যে জিনিসটি একটি বৃত্ত এবং একটি আয়তক্ষেত্র, কেন একটি বৃত্ত এবং একটি আয়তক্ষেত্র সংরক্ষণ করবেন না? এবং জেনারালাইজড ফর্মে - আপনার জিনিসটি যা কিছু উত্পন্ন করেছিল তা সম্ভবত এটি সংরক্ষণ করার জন্য একটি যুক্তিসঙ্গত ফর্ম্যাট you to be সহায়ক)।
জেফ গেটস

এটি যে কোনও অপ্রত্যাশিত আকার হতে পারে যেমন আমি প্রথম বাক্যে বলেছিলাম - এখানে বৃত্ত এবং আয়তক্ষেত্র কেবল একটি পরীক্ষার উদাহরণ।
লুমিস

@ লুমিস, আপনার সত্যিকার অর্থে বি-স্প্লাইনের দিকে নজর দেওয়া উচিত, এটি তাদের জন্য কী। নিজের সমাধান বাস্তবায়নের চেষ্টা করার কোনও কারণ?
গ্রিফিনহার্ট

1
ওয়েল পাথ ক্লাসটি সেই কার্ভগুলি স্প্লিংসের সাথে তৈরি করবে যাতে আপনি ইতিমধ্যে এটি ব্যবহার করছেন। আমার কাছে আরও একটি পরামর্শ আছে, কম গণিতমুখী: পয়েন্টগুলি সংরক্ষণ করার পরিবর্তে ব্যবহারকারীর ইনপুট (কমান্ড প্যাটার্ন) সংরক্ষণ করুন এবং একই "চিত্র" তৈরি করতে এটি পুনরায় খেলুন।
গ্রিফিনহার্ট

উত্তর:


6

আমার মনে হয় আপনার দুটি সমস্যা আছে:

অ-প্রতিসম নিয়ন্ত্রণ ব্যবস্থা

প্রাথমিকভাবে আপনি p0 থেকে p1 এবং p1 থেকে p2 এর সমান দূরত্ব দিয়ে শুরু করুন। যদি লাইন বিভাগগুলির মধ্যে সহনশীলতা কোণটি পূরণ না করা হয়, আপনি p1 এবং p2 এগিয়ে যান, তবে p0 যেখানে ছিল তা রাখুন। এটি পি 1 থেকে পি 2 এর মধ্যে দূরত্ব একই রাখে এবং পি 1 থেকে পি 2 এর দূরত্ব একই রাখে। আপনি যখন নিয়ন্ত্রণ পয়েন্ট হিসাবে p1 ব্যবহার করে একটি বক্ররেখা তৈরি করেন, শেষ বক্রটি থেকে কতগুলি পুনরাবৃত্তি পেরিয়ে গেছে তার উপর নির্ভর করে এটি পি 2 এর দিকে ভারী পক্ষপাতমূলক হতে পারে। আপনি যদি পি 1 এর চেয়ে দ্বিগুণ পরিমাণে পি 2 স্থানান্তরিত করেন তবে আপনি পয়েন্টগুলির মধ্যে এমনকি দূরত্বও পাবেন।

চতুর্ভুজ বক্ররেখা

অন্যান্য উত্তরে যেমন উল্লেখ করা হয়েছে, চতুর্ভুজ বক্ররেখা এই ক্ষেত্রে খুব ভাল হয় না। আপনার তৈরি সংলগ্ন কার্ভগুলির একটি নিয়ন্ত্রণ পয়েন্ট এবং একটি স্পর্শক ভাগ করা উচিত । যখন আপনার ইনপুট ডেটা কেবলমাত্র পয়েন্ট থাকে, তখন ক্যাটমুল-রোম স্প্লাইন সেই উদ্দেশ্যে একটি ভাল পছন্দ। এটি একটি কিউবিক হার্মাইট কার্ভ, যেখানে নিয়ন্ত্রণ পয়েন্টগুলির স্পর্শকাতরগুলি পূর্ববর্তী এবং পরবর্তী পয়েন্টগুলি থেকে গণনা করা হয়।

অ্যান্ড্রয়েডের পাথ এপিআই বাজিয়ার কার্ভগুলি সমর্থন করে যা প্যারামিটারগুলি সম্পর্কিত হার্মাইট কার্ভের থেকে কিছুটা আলাদা। ভাগ্যক্রমে হার্মাইট কার্ভগুলি বেজিয়ার কার্ভে রূপান্তর করা যেতে পারে। গুগলিংয়ের সময় আমি এখানে প্রথম উদাহরণ কোডটি পেয়েছি। এই স্ট্যাকওভারফ্লো উত্তরটি সূত্রটি দেবে বলে মনে হয়।

আপনি ধারালো প্রান্তের সমস্যাটিও উল্লেখ করেছেন। আপনার কাছে থাকা ইনপুট ডেটার সাথে, সত্যিকারের ধারালো কোণ বা কেবল খুব খাড়া বাঁক আছে কিনা তা সনাক্ত করা অসম্ভব। যদি এটি কোনও সমস্যা হয়ে যায়, আপনি প্রয়োজন অনুসারে ধাপটি বাড়িয়ে / কমিয়ে পুনরুক্তিটিকে আরও অভিযোজিত করতে পারেন।

সম্পাদনা: আরও চিন্তা করার পরে চতুর্ভুজ বক্ররেখাগুলি সর্বোপরি ব্যবহার করা যেতে পারে। কন্ট্রোল পয়েন্ট হিসাবে p1 ব্যবহার করে p0 থেকে p2 পর্যন্ত একটি চতুর্ভুজ বক্ররেখা অঙ্কনের পরিবর্তে, নিয়ন্ত্রণ পয়েন্ট হিসাবে নতুন পয়েন্ট p0_1 ব্যবহার করে p0 থেকে p1 এ আঁকুন। নীচের ছবিটি দেখুন। নতুন নিয়ন্ত্রণ পয়েন্ট

P0_1 যদি p0 এবং p1 এর স্পর্শকের ছেদে থাকে তবে ফলাফলটি মসৃণ হওয়া উচিত। আরও ভাল, যেহেতু PathMeasure.getPosTan()তৃতীয় প্যারামিটার হিসাবে রিটার্নগুলিও স্পর্শকাতর, তাই আপনি সংলগ্ন পয়েন্টগুলি থেকে আনুমানিক পরিবর্তে প্রকৃত নির্ভুল স্পর্শকাতর ব্যবহার করতে পারেন। এই পদ্ধতির সাথে আপনার বিদ্যমান সমাধানে আপনার কম পরিবর্তন দরকার।

এই উত্তরের ভিত্তিতে , ছেদ বিন্দুটি নিম্নলিখিত সূত্র দিয়ে গণনা করা যেতে পারে:

getPosTan(pxPlace0, p0, t0); // Also get the tangent
getPosTan(pxPlace1, p1, t1);
t1 = -t1; // Reverse direction of second tangent
vec2 d = p1 - p0;
float det = t1.x * t0.y - t1.y * t0.x;
float u = (d.y * t1.x - d.x * t1.y) / det;
float v = (d.y * t0.x - d.x * t0.y) / det; // Not needed ... yet
p0_1 = p0 + u * t0;

এই সমাধানটি কেবল তখনই কাজ করে যদি আপনি এবং v উভয়ই নেতিবাচক হন। দ্বিতীয় ছবিটি দেখুন: রশ্মি ছেদ করে না

এখানে রেগুলি ছেদ করে না যদিও লাইনগুলি হবে, যেহেতু আপনি negativeণাত্মক। এক্ষেত্রে চতুর্ভুজ বক্ররেখা আঁকানো সম্ভব নয় যা পূর্বেরটির সাথে সহজেই সংযোগ স্থাপন করবে। এখানে আপনার বেজিয়ার বক্ররেখা প্রয়োজন। আপনি এই উত্তরের পূর্বে প্রদত্ত পদ্ধতিতে এটির জন্য নিয়ন্ত্রণ পয়েন্টগুলি গণনা করতে পারেন বা স্পর্শকাতর থেকে সরাসরি প্রাপ্ত করতে পারেন। স্পর্শকাতর রশ্মিকে p0 + u * t0 এবং অন্য রশ্মির জন্য বৈপরীত্যের বিপরীতে p0 প্রজেক্ট করা নিয়ন্ত্রণ পয়েন্ট c0 এবং c1 উভয়ই দেয়। আপনি স্পর্শকাতর রশ্মির উপরে যতক্ষণ না থাকে তবে c0 এর পরিবর্তে p0 এবং c0 এর মধ্যে যে কোনও পয়েন্ট ব্যবহার করে আপনি বক্ররেখা সামঞ্জস্য করতে পারেন।

সম্পাদনা 2: আপনার অঙ্কনের অবস্থানটি পি 1 এ থাকলে আপনি নীচের সিউডো কোড দিয়ে বেজিয়ার নিয়ন্ত্রণ পয়েন্টগুলি পি 2 তে গণনা করতে পারেন:

vec2 p0, p1, p2, p3; // These are calculated with PathMeasure
vec2 cp1 = p1 + (p2 - p0) / 6;
vec2 cp2 = p2 - (p3 - p1) / 6;

এগুলির সাহায্যে আপনি পি 1 থেকে পি 2 পর্যন্ত একটি পথ সংযোজন করতে পারেন:

path.cubicTo(cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);

আপনার কোডটি মেলে ফ্লোট [ 2 ] অ্যারেতে প্রতি উপাদান ক্রিয়াকলাপ সহ ভেক্টর অপারেশনগুলি প্রতিস্থাপন করুন । আপনি আরম্ভের মাধ্যমে শুরু করুন p1 = start;এবং পি 2 এবং পি 3 পরবর্তী পয়েন্টগুলি। p0 প্রাথমিকভাবে সংজ্ঞায়িত। প্রথম বিভাগে যেখানে আপনার কাছে এখনও পি 0 নেই, আপনি কন্ট্রোল পয়েন্ট হিসাবে সিপি 2 দিয়ে পি 1 থেকে পি 2 পর্যন্ত চতুর্ভুজ বক্র ব্যবহার করতে পারেন। যেখানে আপনার পি 3 নেই সেই পথের শেষের জন্য একই, আপনি কন্ট্রোল পয়েন্ট হিসাবে সিপি 1 দিয়ে পি 1 থেকে পি 2 তে চতুর্ভুজ বক্ররেখা আঁকতে পারেন। বিকল্পভাবে আপনি প্রথম বিভাগের জন্য p0 = p1 এবং শেষ বিভাগের জন্য p3 = p2 শুরু করতে পারেন। প্রতিটি বিভাগের পরে p0 = p1; p1 = p2; and p2 = p3;যখন আপনি এগিয়ে চলেছেন তখন মানগুলি স্থানান্তর করুন ।

আপনি যখন পথটি সংরক্ষণ করছেন, আপনি কেবল সমস্ত পয়েন্ট p0 ... pN সংরক্ষণ করুন। নিয়ন্ত্রণ পয়েন্টগুলি সিপি 1 এবং সিপি 2 সংরক্ষণ করার দরকার নেই, কারণ এটি প্রয়োজনীয় হিসাবে গণনা করা যায়।

সম্পাদনা 3: কার্ভ জেনারেশনের জন্য ভাল ইনপুট মান পাওয়া শক্ত বলে মনে হচ্ছে, আমি অন্য পদ্ধতির প্রস্তাব করছি: সিরিয়ালাইজেশন ব্যবহার করুন। অ্যান্ড্রয়েড পাথ এটি সমর্থন করে বলে মনে হয় না, তবে ভাগ্যক্রমে অঞ্চল শ্রেণি তা ​​করে। কোডের জন্য এই উত্তরটি দেখুন । এটি আপনাকে সঠিক ফলাফল দেবে। এটি অনুকূলিত না হলে সিরিয়ালাইজড ফর্মটিতে কিছুটা জায়গা লাগতে পারে তবে সেক্ষেত্রে এটি খুব ভালভাবে সংকোচিত হওয়া উচিত। অ্যান্ড্রয়েড জাভাতে জিজেআইপিআউটপুট স্ট্রিম ব্যবহার করে সংক্ষেপণ সহজ ।


আশাব্যঞ্জক মনে হচ্ছে। তবে এটি পি 0 নয় বরং ব্যবহৃত হয় পি 1, পি 2, পি 3 যা কেবল নতুন নির্দিষ্ট পয়েন্টগুলি গণনা করা হয় এবং সরল রেখার জন্য সংরক্ষণ করার জন্য, যাতে প্রতিটি পদক্ষেপে নমুনা না হয়। নতুন নিয়ন্ত্রণ পয়েন্টগুলির জন্য কীভাবে x, y গণনা করতে পারেন আপনি আমাকে সহায়তা করতে পারেন?
লুমিস

আমি এটি পরে করতে পারি তবে এর মধ্যেই স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি / 2931573/… দেখুন । ইউ এবং ভি দিয়ে আপনি ছেদ পয়েন্টটি পেতে পারেন।
মিসেল

সহায়তার জন্য আপনাকে ধন্যবাদ, আমি এটি চেষ্টা করতে চাই, তবে এটি অ্যান্ড্রয়েডের জন্য জাভাতে লেখা উচিত। ভেক্টর 2 এবং টি 1 এবং পি 1 ইত্যাদি ভাসমান অ্যারে নেই তাই আমি তাদের উপর টি 1 = -t1, বা u * t0 এর মতো সরাসরি কোনও ক্রিয়াকলাপ করতে পারি না। আমি ধরে নিয়েছি যে t1 = -t1 এর অর্থ t1.x = -t1x; t1.y = -t1.y ইত্যাদি, তাই না?
লুমিস

হ্যাঁ, এটি আরও কমপ্যাক্ট এবং পঠনযোগ্য করার জন্য এটি কেবল ছদ্ম কোড ছিল।
মিসেল

ঠিক আছে, প্লটটি আরও ঘন হচ্ছে। কারণ অ্যান্ড্রয়েডে দুটি পাথের অঞ্চল ছেদটি এমন একটি পথ ফেরায় যা অ্যান্টি-এলয়েসড নয়, স্পর্শকাতরটি জায়গাটির উপরে। সুতরাং সঠিক সমাধানটি হ'ল প্রথমে প্রদত্ত পয়েন্টগুলির মধ্যে কিছু মসৃণ বক্ররেখা চালনা এবং তারপরে এটি নমুনা করুন। আপনার কোডটি অ্যান্টি-এলিয়াসযুক্ত পথে পুরোপুরি সূক্ষ্মভাবে কাজ করে, এটি সঠিক নিয়ন্ত্রণ পয়েন্ট তৈরি করে।
লুমিস

13

ডাব্লু 3 সি কী করবে?

ইন্টারনেটে এই সমস্যা হয়েছে। ওয়ার্ল্ড ওয়াইড ওয়েব কনসোর্টিয়াম লক্ষ্য। এটির 1999 সালের পর থেকে একটি প্রস্তাবিত মান সমাধান রয়েছে: স্কেলেবল ভেক্টর গ্রাফিক্স (এসভিজি) । এটি একটি এক্সএমএল ভিত্তিক ফাইল ফর্ম্যাট যা 2D আকার সংরক্ষণের জন্য বিশেষভাবে ডিজাইন করা হয়েছে।

" স্কেলেবল-কি? "

স্কেলেবল ভেক্টর গ্রাফিক্স !

  • স্কেলেবল : এটি যে কোনও আকারে সহজেই স্কেল করা বোঝায়।
  • ভেক্টর : এটা গাণিতিক ধারণা উপর ভিত্তি করে ভেক্টর
  • গ্রাফিক্স । এটি ছবি তৈরির উদ্দেশ্যে।

এসভিজি সংস্করণ ১.১ এর প্রযুক্তিগত বিবরণ এখানে
(নাম শুনে ভয় পাবেন না; এটি পড়তে আসলেই আনন্দদায়ক))

চেনাশোনা বা আয়তক্ষেত্রের মতো মৌলিক আকারগুলি কীভাবে সংরক্ষণ করতে হয় তা তারা ঠিক লিখে রেখেছিল। উদাহরণস্বরূপ, আয়তক্ষেত্র এই বৈশিষ্ট্য আছে: , ,xywidth , height, rx, ry। ( rxএবং ryগোলাকার কোণগুলির জন্য ব্যবহার করা যেতে পারে))

এসভিজিতে তাদের উদাহরণের আয়তক্ষেত্র এখানে: (ভাল, দুটি সত্যিই - ক্যানভাসের রূপরেখার জন্য একটি))

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example rect01 - rectangle with sharp corners</desc>

  <!-- Show outline of canvas using 'rect' element -->
  <rect x="1" y="1" width="1198" height="398"
        fill="none" stroke="blue" stroke-width="2"/>

  <rect x="400" y="100" width="400" height="200"
        fill="yellow" stroke="navy" stroke-width="10"  />
</svg>

এটি এখানে যা উপস্থাপন করে তা এখানে:

একটি নীল রূপরেখার সাথে একটি হলুদ আয়তক্ষেত্র

স্পেসিফিকেশন হিসাবে বলা হয়েছে, আপনার যদি কিছু সম্পত্তি প্রয়োজন না হয় তবে আপনি কিছু ছেড়ে দিতে পারেন। (উদাহরণ স্বরূপ,rx এবং ryবৈশিষ্ট্যগুলি এখানে ব্যবহৃত হয়নি)) হ্যাঁ, শীর্ষে একটি টন ক্রাফ্ট রয়েছে DOCTYPEযার সম্পর্কে আপনার কেবল আপনার খেলার প্রয়োজন হবে না। তারাও areচ্ছিক।

পথ

এসভিজি পাথগুলি "পাথ" এই অর্থে যে আপনি যদি কোনও কাগজে একটি পেন্সিল রাখেন তবে এটিকে চারপাশে সরান এবং শেষ পর্যন্ত এটি আবার উত্থাপন করেন , আপনার একটি পথ রয়েছে। তারা না আছে হতে বন্ধ , কিন্তু তারা হতে পারে।

প্রতিটি পাথের একটি dবৈশিষ্ট্য রয়েছে (আমি মনে করি এটি "আঁকুন" হিসাবে দাঁড়িয়েছে, যার মধ্যে পথের ডেটা রয়েছে , মূলত কেবল একটি কাগজে কলম লাগানো এবং এটিকে ঘুরিয়ে দেওয়ার জন্য কমান্ডের অনুক্রম ।

তারা একটি ত্রিভুজের উদাহরণ দেয়:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4cm" height="4cm" viewBox="0 0 400 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <title>Example triangle01- simple example of a 'path'</title>
  <desc>A path that draws a triangle</desc>
  <rect x="1" y="1" width="398" height="398"
        fill="none" stroke="blue" />
  <path d="M 100 100 L 300 100 L 200 300 z"
        fill="red" stroke="blue" stroke-width="3" />
</svg>

একটি লাল ত্রিভুজ

dবৈশিষ্ট্যটি দেখুন path?

d="M 100 100 L 300 100 L 200 300 z"

Mএকটি হল কমান্ড জন্য এতে সরান (স্থানাঙ্ক থাকে), Ls এর জন্য হয় রেখার (স্থানাঙ্ক সঙ্গে) এবং zকমান্ড পথ বন্ধ করতে (অর্থাত প্রথম অবস্থানে একটি লাইন ফিরে আঁকা; যে স্থানাঙ্ক দরকার নেই)।

সোজা লাইন বিরক্তিকর হয়? কিউবিক বা চতুর্ভুজ Bézier কমান্ড ব্যবহার করুন !

কিছু কিউবিক Béziers

বাজিয়ার রেখাঙ্কনগুলির পিছনে তত্ত্বটি অন্য কোথাও (যেমন উইকিপিডিয়ায় ) ভালভাবে আচ্ছাদিত , তবে এখানে কার্যনির্বাহী সংক্ষিপ্তসার রয়েছে: বেজিয়ার্সের একটি সূচনা এবং শেষের পয়েন্ট রয়েছে, সম্ভবত অনেকগুলি নিয়ন্ত্রণ পয়েন্ট রয়েছে যেখানে প্রভাবিত হয় যেখানে মধ্যবর্তী বক্ররেখাটি চলছে।

চতুর্ভুজীয় বেজিয়ার ট্রেসিং

স্পেসিফিকেশনটি আপনি চান সর্বাধিক প্রাথমিক আকারগুলিকে পাথে রূপান্তর করার জন্য নির্দেশাবলীও দেয়।

কেন এবং কখন এসভিজি ব্যবহার করবেন

আপনি যদি এই পথে (পাং উদ্দেশ্যে) যেতে চান তবে সাবধানতার সাথে সিদ্ধান্ত নিন, কারণ পাঠ্যের কোনও যথেচ্ছ 2D আকারের প্রতিনিধিত্ব করা সত্যিই বেশ জটিল! আপনি উদাহরণস্বরূপ নিজেকে (কেবলমাত্র অনেকগুলি) সরল রেখার তৈরি পথগুলিতে সীমাবদ্ধ রাখলে আপনি আপনার জীবনকে আরও সহজ করে তুলতে পারেন।

তবে আপনি যদি নির্ধারণ করেন যে আপনি নির্বিচারে আকারগুলি চান, এসভিজি যাওয়ার উপায়: এটির দুর্দান্ত সরঞ্জাম সমর্থন রয়েছে: আপনি নিম্ন স্তরে এক্সএমএল পার্সিংয়ের জন্য অনেকগুলি গ্রন্থাগার এবং উচ্চ স্তরে এসভিজি সম্পাদক সরঞ্জামগুলি পেতে পারেন

নির্বিশেষে, এসভিজি স্ট্যান্ডার্ড একটি ভাল উদাহরণ স্থাপন করে।


প্রশ্নটি কোনও বাঁককে পয়েন্টে রূপান্তরিত করার বিষয়ে, এটি সংরক্ষণ না করে। তবে এই রেফারেন্সের জন্য আপনাকে ধন্যবাদ, এসভিজি স্ট্যান্ডার্ড সম্পর্কে জানা ভাল is
লুমিস

@ লুমিস শিরোনাম এবং সামগ্রী অন্যথায় প্রস্তাব করবে suggest প্রশ্নটি পুনরায় বিবেচনা করুন। (বা, এখন এটি বেশ প্রতিষ্ঠিত,
অন্যটিকে

4

আপনার কোডটিতে একটি বিভ্রান্তিকর মন্তব্য রয়েছে:

dstPath.quadTo(p2[0] , p2[1], p3[0], p3[1]); //create a curve to the third point through the second

একটি দ্বিঘাত বেজিয়ে কার্ভ করে না যেতে দিয়ে দ্বিতীয় বিন্দু। আপনি যদি দ্বিতীয় পয়েন্টটি দিয়ে যেতে চান তবে আপনার বিভিন্ন ধরণের বাঁক দরকার যেমন হরমাইট বক্ররেখা । আপনি হারমাইট কার্ভগুলি বেজিয়ারে রূপান্তর করতে সক্ষম হতে পারেন যাতে আপনি পথের ক্লাসটি ব্যবহার করতে পারেন।

আরেকটি পরামর্শ হ'ল পয়েন্টগুলি স্যাম্পল করার পরিবর্তে আপনি যে পয়েন্টগুলি বাদ দিচ্ছেন তার মধ্যমাটি ব্যবহার করুন।

আরেকটি পরামর্শ হ'ল একটি চৌম্বক হিসাবে কোণ ব্যবহার করার পরিবর্তে প্রকৃত বক্ররেখা এবং আনুমানিক বক্ররেখার মধ্যে পার্থক্যটি ব্যবহার করুন। কোণগুলি আসল সমস্যা নয়; আসল সমস্যাটি যখন পয়েন্টগুলির সেটটি বেজিয়ার বক্ররেখায় না খায়।

আরেকটি পরামর্শ হ'ল কিউবিক বেজিয়ারগুলি ব্যবহার করা, যার সাথে একটির সাথে পরেরটির স্পর্শকটির স্পর্শক মেলে। অন্যথায় (চতুর্ভুজ সহ) আমি মনে করি আপনার বক্ররেখা সহজেই মেলে না।


আপনি ঠিক বলেছেন, দ্বিতীয় পয়েন্টটি কেবল তার দিকে বক্ররেখা "টান"। কিউবিকটোতে কোয়াডটো হিসাবে একটির পরিবর্তে দুটি নিয়ন্ত্রণ পয়েন্টের প্রয়োজন। সমস্যাটি কীভাবে সঠিক নিয়ন্ত্রণ পয়েন্টগুলি পাবেন তা অবশ্যই। দ্রষ্টব্য যে আমি তীর কোণটি হারাতে চাই না কারণ উত্স পাথ সোজা বা বৃত্তাকার কোনও আকারের সংমিশ্রণ হতে পারে - মূলত আমি একটি চিত্র নির্বাচন সরঞ্জাম তৈরি করছি যেখানে আমি নির্বাচিত পথটি সংরক্ষণ করতে পারি।
লুমিস

4

দুটি পথের একটি মসৃণ ছেদ পেতে, আপনি ছেদ করার আগে এগুলি স্কেল করতে পারেন এবং পরে এগুলি স্কেল করতে পারেন।

আমি জানি না এটির কোনও ভাল সমাধান কিনা, তবে এটি আমার পক্ষে ভালভাবে কাজ করেছে। এটিও দ্রুত। আমার উদাহরণে, আমি তৈরি করা একটি প্যাটার্ন দিয়ে একটি বৃত্তাকার পথটি ছেদ করি inters স্কেল করা হলেও এটি দেখতে দুর্দান্ত দেখাচ্ছে।

এখানে আমার কোড:

    Path mypath=new Path(<desiredpath to fill with a pattern>);
    String sPatternType=cpath.getsPattern();

    Path pathtempforbounds=new Path(cpath.getPath());
    RectF rectF = new RectF();
     if (sPatternType.equals("1")){
         turnPath(pathtempforbounds, -45);
     }
     pathtempforbounds.computeBounds(rectF, true);

     float ftop=rectF.top;
     float fbottom=rectF.bottom;
     float fleft=rectF.left;
     float fright=rectF.right;
     float xlength=fright-fleft;

     Path pathpattern=new Path();

     float ypos=ftop;
     float xpos=fleft;

     float fStreifenbreite=4f;

     while(ypos<fbottom){
         pathpattern.moveTo(xpos,ypos);
         xpos=xpos+xlength;
         pathpattern.lineTo(xpos, ypos);
         ypos=ypos+fStreifenbreite;
         pathpattern.lineTo(xpos, ypos);
         xpos=xpos-xlength;
         pathpattern.lineTo(xpos, ypos);
         ypos=ypos-fStreifenbreite;
         pathpattern.lineTo(xpos, ypos);
         pathpattern.close();
         ypos=ypos+2*fStreifenbreite;

     }

     // Original vergrössern

     scalepath(pathpattern,10);
     scalepath(mypath,10);

     if (sPatternType.equals("1")){
         Matrix mdrehen=new Matrix();
         RectF bounds=new RectF();
         pathpattern.computeBounds(bounds, true);
         mdrehen.postRotate(45, (bounds.right + bounds.left)/2,(bounds.bottom + bounds.top)/2);
         pathpattern.transform(mdrehen);
     }

     RectF rectF2 = new RectF();
     mypath.computeBounds(rectF2, true);

     Region clip = new Region();
     clip.set((int)(rectF2.left-100f),(int)(rectF2.top -100f), (int)(rectF2.right+100f),(int)( rectF2.bottom+100f));
     Region region1 = new Region();
     region1.setPath(pathpattern, clip);

     Region region2 = new Region();
     region2.setPath(mypath, clip);

     region1.op(region2, Region.Op.INTERSECT);


     Path pnew=region1.getBoundaryPath();


     scalepath(pnew, 0.1f);
     cpath.setPathpattern(pnew);




public void turnPath(Path p,int idegree){
     Matrix mdrehen=new Matrix();
     RectF bounds=new RectF();
     p.computeBounds(bounds, true);
     mdrehen.postRotate(idegree, (bounds.right + bounds.left)/2,(bounds.bottom + bounds.top)/2);
     p.transform(mdrehen);
}

public void scalepath(Path p,float fscale){
     Matrix mverkleinern=new Matrix();
     mverkleinern.preScale(fscale,fscale);
     p.transform(mverkleinern);
}

এখানে চিত্র বর্ণনা লিখুন

ক্যানভাস.স্কেল () এর সাথে জুম করার সময় এখনও মসৃণ দেখাচ্ছে: এখানে চিত্র বর্ণনা লিখুন


ছবিগুলি যোগ করতে আমার জন্য যিনি কখনও 10 খ্যাতি ব্যয় করেছেন বলে ধন্যবাদ :-)
ব্যবহারকারী 1344545

1
আশ্চর্যজনকভাবে, এই সহজ কৌশলটি দুটি সমস্যার সমাধান করে: প্রথমত এটি ছেদ বা ইউনিয়নের ফলে প্রাপ্ত পথটিকে মসৃণ করে তোলে এবং দ্বিতীয়ত এই একই স্কেলড আপ পথটির নমুনা দেওয়ার সময় পুরোপুরি মসৃণ ফলাফল দেয়। কি অপ্রত্যাশিত এবং সহজ সমাধান, আপনাকে ধন্যবাদ!
লুমিস

@ ব্যবহারকারীর সম্পাদনা বিনামূল্যে। <2k-rep ব্যবহারকারীদের জন্য এটি আসলে একটি +2।
আনকো

@ লুমিস আমি কিছুটা বিভ্রান্ত - আমি ভেবেছিলাম আপনি কীভাবে পথ সঞ্চয় করবেন ?
আনকো

1
দুর্ভাগ্যক্রমে, আরও পরীক্ষার পরে আমি দেখতে পেয়েছি যে অঞ্চলটি পিক্সেলগুলি ব্যবহার করে যা আঁকানোর সময় পাথটি দখল করবে, অ্যাপ্লিকেশনটি স্মৃতি থেকে সহজেই চলে যায় যদি পাথের স্কেলিং বড় হয় এবং বারবার করা হয়। সুতরাং এই সমাধানটি সীমিত এবং ঝুঁকিপূর্ণ তবে মনে রাখা ভাল।
লুমিস

3

বহুভুজের প্রক্ষিপ্ত বিবরণটি দেখুন ( http://en.wikedia.org/wiki/Polynomial_interpolation )

মূলত, আপনি এন ইক্যুস্পিপসড নোডগুলি গ্রহণ করেন (সর্বোপরি আন্তবিভাজনটি সমৃদ্ধ হয় না, তবে আপনার ক্ষেত্রে এটি যথেষ্ট ভাল এবং কার্যকর করা সহজ হওয়া উচিত)

আপনি অর্ডার এন এর বহুভুজ দিয়ে শেষ করেছেন যা আপনার বক্ররেখার মধ্যে ত্রুটি হ্রাস করে যদি (<- বড় যদি) আপনার লাইনটি যথেষ্ট মসৃণ হয়।

আপনার ক্ষেত্রে, আপনি লিনিয়ার (অর্ডার 1) ইন্টারপোলেশন করছেন।

অন্য কেস ( গ্রিফিনহার্ট প্রস্তাবিত হিসাবে ) ছিল স্প্লাইনস ( http://en.wikedia.org/wiki/Spline_interpolation ) ব্যবহার করা

উভয় ক্ষেত্রেই আপনার বক্ররেখার জন্য আপনাকে একাধিক রূপ দেবে fit


2

যদি রূপান্তরটির বিন্দুটি কেবলমাত্র সঞ্চয় করার জন্য হয় এবং আপনি যখন এটি পর্দায় ফেরত পাঠান তখন আপনার মসৃণ হওয়া দরকার, তবে প্রদত্ত বক্ররেখাকে ধরে রাখতে মোট স্টোরেজকে কমিয়ে আনতে পারলে আপনি যে সর্বোচ্চ বিশ্বস্ত সঞ্চয় করতে পারেন তা হতে পারে be প্রকৃতপক্ষে বৃত্তের বৈশিষ্ট্যগুলি (বা একটি তোরণ পরিবর্তে) সঞ্চয় করতে এবং এটি চাহিদা অনুযায়ী পুনরায় আঁকতে।

মূল। ব্যাসার্ধ। চাপটি আঁকার জন্য কোণগুলি শুরু / বন্ধ করুন।

যদি আপনাকে রেন্ডারিংয়ের জন্য বৃত্ত / আর্কটিকে যেভাবেই পয়েন্টগুলিতে রূপান্তর করতে হয় তবে সর্বদা কেবলমাত্র বৈশিষ্ট্যগুলি সংরক্ষণ করে আপনি সম্ভবত এটি স্টোরেজ থেকে লোড করার পরে করতে পারেন।


উত্সের পথ / বক্ররেখা কোনও মুক্ত লাইনের অঙ্কন সহ কোনও আকার হতে পারে। আমি সেই সমাধানটি বিবেচনা করছি যা প্রতিটি উপাদান পৃথকভাবে সংরক্ষণ করতে হবে এবং তারপরে লোড করার সময় তাদের একত্রিত করতে হবে তবে এটির জন্য প্রচুর পরিমাণে কাজ প্রয়োজন এবং এটি এমন জটিল বস্তুর হেরফের কমিয়ে দেয় কারণ প্রতিটি রূপান্তর প্রতিটিটির জন্য প্রয়োগ করতে হবে এর উপাদানগুলি যাতে এটি আবার সংরক্ষণ করতে সক্ষম হয়।
লুমিস

2

সোজা লাইনের বিপরীতে কার্ভগুলিতে যাওয়ার কোনও কারণ আছে কি? সোজা লাইনগুলি কাজ করা সহজ, এবং হার্ডওয়্যারে দক্ষতার সাথে রেন্ডার করা যায়।

বিবেচনা করার মতো অন্যান্য উপায় হ'ল পিক্সেলটিতে কয়েক বিট সংরক্ষণ করা, এটি উল্লেখ করে যদি এটি ভিতরে, বাহিরের বা আকারের বাহ্যরেখায় থাকে তবে। এটি ভালভাবে সংকোচিত হওয়া উচিত এবং জটিল নির্বাচনের জন্য লাইনগুলির চেয়ে আরও দক্ষ হতে পারে।

আপনি এই নিবন্ধগুলি আকর্ষণীয় / দরকারী খুঁজে পেতে পারেন:


1

কার্ভ বিরতি একবার দেখুন - আপনি প্রয়োগ করতে পারেন কয়েকটি ভিন্ন ধরণের যা আপনার বক্রকে মসৃণ করতে সহায়তা করবে। আপনি যে বৃত্তে আরও বেশি পয়েন্ট পেতে পারেন তত ভাল। স্টোরেজটি বেশ সস্তা - তাই যদি 360 ঘনিষ্ঠ নোডগুলি উত্তোলন করা যথেষ্ট সস্তা হয় (এমনকি অবস্থানের জন্য 8 বাইটেও; 360 নোডগুলি সঞ্চয় করা খুব কম ব্যয়বহুল)।

আপনি এখানে কেবলমাত্র চারটি পয়েন্টের সাথে কিছু সংক্ষেপণের নমুনা রেখে দিতে পারেন ; এবং ফলাফলগুলি বেশ ভাল (আমার ক্ষেত্রে এই ক্ষেত্রে বেজিয়ার হ'ল, যদিও অন্যরা কার্যকর সমাধানগুলি সম্পর্কে আরও কিছু বলতে পারেন)।

আপনি এখানে প্রায় কাছাকাছি খেলতে পারেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.