मैं अपने आवेदन में उपयोगकर्ता किसी छवि के क्षेत्रों का चयन कर सकता हूं। उपयोगकर्ता एक आयताकार क्षेत्र को Canvas में खींचता है। यह निम्न जैसा दिखता है:

Rectangle selection area

चयन क्षेत्र के शीर्ष पर वृत्त (Ellipse), क्षेत्र को घुमाने के लिए एक हैंडल है। नीचे चित्र देखें:

enter image description here

जब चयन क्षेत्र को घुमाया नहीं जाता नहीं, और उपयोगकर्ता क्षेत्र का आकार बदलने के लिए चौकोर आकार के हैंडल का उपयोग करता है, तो यह काम करता है। लेकिन जब उपयोगकर्ता अंडाकार का उपयोग करके चयन क्षेत्र को घुमाता है, और फिर क्षेत्र का आकार बदलने के लिए स्क्वायर हैंडल का उपयोग करता है, तो यह दोनों विपरीत दिशाओं (घुमाए गए समन्वय प्रणाली के संदर्भ में) का आकार बदलता है।

मेरी तत्व संरचना इस प्रकार है:

Canvas
+--- Image (covers whole canvas)
+--- Canvas (Background white with opacity as shown in images above, and contains the elements to draw the 
           selection area. I'll call this the 'area canvas')
    +--- Rectangle (left handle)
    +--- Rectangle (top handle)
    +--- Rectangle (right handle)
    +--- Rectangle (bottom handle)
    +--- Ellipse (rotation handle)

मैं एक RotateTransform का उपयोग करके रोटेशन करता हूं। रूपांतरण को चयन क्षेत्र के कैनवास पर लागू किया जाता है। कैनवास का RenderTransformOrigin है (0.5, 0.5)। तो कैनवास हमेशा इसके केंद्र के चारों ओर घुमाया जाएगा।

कल्पना कीजिए कि क्षेत्र को 10 डिग्री दक्षिणावर्त घुमाया जाता है। फिर आप दाईं ओर हैंडल का उपयोग करके इसका आकार बदलते हैं। अब क्षेत्र का विस्तार केवल दाईं ओर होना चाहिए। दूसरे शब्दों में: कैनवास के केवल 2 कोनों को हिलना चाहिए, क्या होता है, यह है कि क्षेत्र का बायां हिस्सा भी चलता है। तो बाईं ओर के कोने भी (बाईं ओर) चलते हैं। मुझे लगता है कि यह इस तथ्य के कारण होता है कि क्षेत्र कैनवास की चौड़ाई/ऊंचाई में परिवर्तन भी केंद्र बिंदु बदलता है। लेकिन इसे कैसे ठीक करें? चयन क्षेत्र का व्यवहार ठीक एमएस वर्ड जैसे कार्यक्रमों में चयनित तत्व के समान होना चाहिए।

संबंधित कोड वाले Github रिपॉजिटरी से लिंक करें: https://github.com/websitetest/ चयन

1
user2190492 13 सितंबर 2019, 23:07

1 उत्तर

सबसे बढ़िया उत्तर

समाधान एक अनुवाद जोड़ना है जो घूर्णन के बाद कैनवास के केंद्र की चाल को रद्द कर देता है: इसलिए मैंने आपके लिए कुछ संशोधन किया है विधि UpdateResizeArea (गणितीय समाधान)

    private void UpdateResizeArea(Point currentMousePoint)
    {
           :
           :
        switch (_activeResizeAreaSide)
        {
            case SelectionArea.ResizeSide.LEFT:
                {
                    _activeResizeArea.OffsetX = _activeResizeAreaXbeforeStart + deltaX;
                    _activeResizeArea.AreaWidth = _activeResizeAreaWidthbeforeStart - deltaX;
                    var tg = new TransformGroup();
                    var rad = _activeResizeArea.Rotation * Math.PI / 180;
                    var cx = _activeResizeArea.CalculateCenterPoint().X - _activeRotateAreaCenterPointBeforeStart.X;
                    var cy = _activeResizeArea.CalculateCenterPoint().Y - _activeRotateAreaCenterPointBeforeStart.Y;

                    var tx = cx * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d + cy * Math.Sin(rad);
                    var ty = cx * Math.Sin(rad) - cy * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d;

                    var t = new TranslateTransform(-tx, ty);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);

                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
            case SelectionArea.ResizeSide.TOP:
                {
                    _activeResizeArea.OffsetY = _activeResizeAreaYbeforeStart + deltaY;
                    _activeResizeArea.AreaHeight = _activeResizeAreaHeightbeforeStart - deltaY;

                    var tg = new TransformGroup();
                    var rad = _activeResizeArea.Rotation * Math.PI / 180;

                    var cx = _activeResizeArea.CalculateCenterPoint().X - _activeRotateAreaCenterPointBeforeStart.X;
                    var cy = _activeResizeArea.CalculateCenterPoint().Y - _activeRotateAreaCenterPointBeforeStart.Y;

                    var tx = cy * Math.Sin(rad) + cx * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d;
                    var ty = cy * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d - cx * Math.Sin(rad);

                    var t = new TranslateTransform(-tx, -ty);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);
                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
            case SelectionArea.ResizeSide.RIGHT:
                {
                    _activeResizeArea.AreaWidth = _activeResizeAreaWidthbeforeStart + deltaX;

                    var tg = new TransformGroup();
                    var rad = _activeResizeArea.Rotation * Math.PI / 180;
                    var cx = _activeResizeArea.CalculateCenterPoint().X - _activeRotateAreaCenterPointBeforeStart.X;
                    var cy = _activeResizeArea.CalculateCenterPoint().Y - _activeRotateAreaCenterPointBeforeStart.Y;

                    var tx = cx * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d + cy * Math.Sin(rad);
                    var ty = cx * Math.Sin(rad) - cy * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d;

                    var t = new TranslateTransform(-tx, ty);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);
                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
            case SelectionArea.ResizeSide.BOTTOM:
                {
                    _activeResizeArea.AreaHeight = _activeResizeAreaHeightbeforeStart + deltaY;

                    var tg = new TransformGroup();
                    var rad = _activeResizeArea.Rotation * Math.PI / 180;

                    var cx = _activeResizeArea.CalculateCenterPoint().X - _activeRotateAreaCenterPointBeforeStart.X;
                    var cy = _activeResizeArea.CalculateCenterPoint().Y - _activeRotateAreaCenterPointBeforeStart.Y;

                    var tx = cy * Math.Sin(rad) + cx * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d;
                    var ty = cy * Math.Sin(rad / 2d) * Math.Sin(rad / 2d) * 2d - cx * Math.Sin(rad);

                    var t = new TranslateTransform(-tx, -ty);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);
                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
        }

आप अपनी परियोजना के समाधान को अनुकूलित कर सकते हैं .. क्योंकि मैंने आपके प्रोग्राम के तर्क को बदले बिना कोडिंग की कुछ पंक्तियाँ जोड़ी हैं

______________________________________________________________________________________________

एक अन्य समाधान (गणित गणना के बिना) प्रारंभिक केंद्र रोटेशन के साथ कैनवास के एक बिंदु की स्थिति और नए केंद्र के साथ एक ही बिंदु की नई स्थिति के बीच अंतर को पूर्व-गणना करना है:

        switch (_activeResizeAreaSide)
        {
            case SelectionArea.ResizeSide.LEFT:
                {
                    _activeResizeArea.OffsetX = _activeResizeAreaXbeforeStart + deltaX;
                    _activeResizeArea.AreaWidth = _activeResizeAreaWidthbeforeStart - deltaX;

                    var ir = new RotateTransform(_activeResizeArea.Rotation, _activeRotateAreaCenterPointBeforeStart.X, _activeRotateAreaCenterPointBeforeStart.Y);
                    var fr = new RotateTransform(_activeResizeArea.Rotation, _activeResizeArea.CalculateCenterPoint().X, _activeResizeArea.CalculateCenterPoint().Y);
                    var ip = ir.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));
                    var fp = fr.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));

                    var tg = new TransformGroup();

                    var txx = ip.X - fp.X;
                    var tyy = ip.Y - fp.Y;

                    var t = new TranslateTransform(txx, tyy);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);

                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
            case SelectionArea.ResizeSide.TOP:
                {
                    _activeResizeArea.OffsetY = _activeResizeAreaYbeforeStart + deltaY;
                    _activeResizeArea.AreaHeight = _activeResizeAreaHeightbeforeStart - deltaY;

                    var ir = new RotateTransform(_activeResizeArea.Rotation, _activeRotateAreaCenterPointBeforeStart.X, _activeRotateAreaCenterPointBeforeStart.Y);
                    var fr = new RotateTransform(_activeResizeArea.Rotation, _activeResizeArea.CalculateCenterPoint().X, _activeResizeArea.CalculateCenterPoint().Y);
                    var ip = ir.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));
                    var fp = fr.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));

                    var tg = new TransformGroup();

                    var txx = ip.X - fp.X;
                    var tyy = ip.Y - fp.Y;

                    var t = new TranslateTransform(txx, tyy);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);
                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
            case SelectionArea.ResizeSide.RIGHT:
                {
                    _activeResizeArea.AreaWidth = _activeResizeAreaWidthbeforeStart + deltaX;

                    var ir = new RotateTransform(_activeResizeArea.Rotation, _activeRotateAreaCenterPointBeforeStart.X, _activeRotateAreaCenterPointBeforeStart.Y);
                    var fr = new RotateTransform(_activeResizeArea.Rotation, _activeResizeArea.CalculateCenterPoint().X, _activeResizeArea.CalculateCenterPoint().Y);
                    var ip = ir.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));
                    var fp = fr.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));

                    var tg = new TransformGroup();

                    var txx = ip.X - fp.X;
                    var tyy = ip.Y - fp.Y;

                    var t = new TranslateTransform(txx, tyy);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);
                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
            case SelectionArea.ResizeSide.BOTTOM:
                {
                    _activeResizeArea.AreaHeight = _activeResizeAreaHeightbeforeStart + deltaY;

                    var ir = new RotateTransform(_activeResizeArea.Rotation, _activeRotateAreaCenterPointBeforeStart.X, _activeRotateAreaCenterPointBeforeStart.Y);
                    var fr = new RotateTransform(_activeResizeArea.Rotation, _activeResizeArea.CalculateCenterPoint().X, _activeResizeArea.CalculateCenterPoint().Y);
                    var ip = ir.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));
                    var fp = fr.Transform(new Point(_activeResizeArea.OffsetX, _activeResizeArea.OffsetY));

                    var tg = new TransformGroup();

                    var txx = ip.X - fp.X;
                    var tyy = ip.Y - fp.Y;

                    var t = new TranslateTransform(txx, tyy);

                    tg.Children.Add(_activeResizeArea.RotateTransform);
                    tg.Children.Add(t);
                    _activeResizeArea.AreaCanvas.RenderTransform = tg;
                }
                break;
        }

नतीजा:

Result

1
Frenchy 19 सितंबर 2019, 21:40