2009-04-07 13 views
21

के बावजूद पथ की परिवर्तनीय स्ट्रोक मोटाई हम पाथ ऑब्जेक्ट का उपयोग कर कैनवास पर चित्रों को लागू करने वाले अनुप्रयोग जैसे कैड को विकसित करने के लिए wpf का उपयोग कर रहे हैं। मैं बस एक मामूली समस्या में भाग गया कि जब भी मैं अपने कैनवास को स्केल/ज़ूम करता हूं, तो कैनवास के सभी तत्व स्केल हो जाते हैं और यह वह व्यवहार है जो मैं चाहता था लेकिन यह पथ की स्ट्रोक मोटाई भी बढ़ाता है।स्केल

क्या कोई तरीका है जिसके द्वारा मैं वस्तुओं को बढ़ा/स्केल/ज़ूम करता हूं लेकिन फिर भी मैं पथ की एक ही स्ट्रोक मोटाई को बनाए रखता हूं।

इस संबंध में कोई भी सहायता मेरे लिए बहुत उपयोगी होगी।

उत्तर

6

अंत में मुझे उपरोक्त समाधान के लिए कामकाज मिला। मैंने के स्केलिंग के सापेक्ष के StrokeThickness को सेट करके किया था।

इस तरह

:

// scale = scaling factor applied to the canvas 
path.StrokeThickness = 1.0/scale; 

यह केवल काम करता है अगर ScaleX और ScaleY वर्दी कर रहे हैं।

+13

यह ठीक है अगर आपके एक्स और वाई स्केल वर्दी हैं, लेकिन स्केल एक जैसे नहीं हैं तो काम नहीं करते हैं। – Klay

13

एक बेहतर समाधान अपने रास्तों स्टोर करने के लिए एक या अधिक System.Windows.Media.Geometry वस्तु का उपयोग किया जाएगा, आदि

यह ज्यामिति एक पेन के साथ तैयार किया जा सकता अंक ताकि आप वास्तव में स्ट्रोक को बदल सकता है जब आप ज़ूम करते हैं तो मोटाई, लेकिन ट्रांसफॉर्म प्रॉपर्टी का उपयोग करना अधिक लचीला है।

ट्रांसफॉर्म का उपयोग करके, आप ज्यामितीय प्रतिनिधित्व के वास्तविक निर्देशांक को "ज़ूम" कर सकते हैं, न कि विज़ुअलाइज़ेशन - इसलिए जब आप इसे आकर्षित करते हैं, तो आपको रेंडर ट्रांसफॉर्म के साथ बेवकूफ़ बनाने की आवश्यकता नहीं होती है।

गणना करने के लिए बदलना, मैं जैसे निम्नलिखित कोड का उपयोग करें:

public static Matrix TransformShape(Rect fromPosition, Rect toPosition, bool flipVertical) { 
    Matrix translateThenScale = Matrix.Identity; 
    //we first translate to origin since that's just easier 
    translateThenScale.Translate(-fromPosition.X, -fromPosition.Y); 
    //now we scale the graph to the appropriate dimensions 
    translateThenScale.Scale(toPosition.Width/fromPosition.Width, toPosition.Height/fromPosition.Height); 
    //then we flip the graph vertically around the viewport middle since in our graph positive is up, not down. 
    if (flipVertical) 
     translateThenScale.ScaleAt(1.0, -1.0, 0.0, toPosition.Height/2.0); 
    //now we push the graph to the right spot, which will usually simply be 0,0. 
    translateThenScale.Translate(toPosition.X, toPosition.Y); 

    return translateThenScale; 
} 

जहां fromPosition रेक्ट untransformed सीमा को शामिल करना चाहिए, और toPosition रेक्ट तब्दील सीमा में होना चाहिए। यह एक्स और वाई को अलग-अलग स्केल करने की भी अनुमति देता है, जो अक्सर साजिश के लिए आवश्यक होता है।

यह अपने ज्यामिति की सीमा की गणना करना आसान है:

Geometry graphGeom; 
//[...] 
//the bounds are modified by the transform, so we want no transform!  
graphGeom.Transform = Transform.Identity; 
Rect graphBounds = graphGeom.Bounds; 
//then set the transform again 

//or, if the transform is axis-aligned, the following _should_ work: 
Rect graphBoundsAlt = graphGeom.Transform.Inverse.TransformBounds(graphGeom.Bounds); 

और निश्चित रूप से WPF जो सीमा आप में प्रस्तुत करने के लिए की जरूरत है, कि आवश्यक होना चाहिए आप बता सकते हैं। यह एक साथ रखें, आप की तरह

public void RecomputeTransform(Rect targetRect, bool flipVertical) { 
    graphGeom.Transform = Transform.Identity; 
    Rect graphBounds = graphGeom.Bounds; 
    Matrix transMat = TransformShape(graphBounds,targetRect,flipVertical); 
    graphGeom.Transform = new MatrixTransform(transMat); 
} 

कुछ कर सकते हैं इस समाधान का उपयोग करने का लाभ यह है कि आप RenderTransforms साथ गड़बड़ की जरूरत नहीं है, आप का उपयोग करने के लिए स्वतंत्र हैं है बदल देती है कि कतरनी और/या पैमाने एक्स और वाई स्वतंत्र रूप से आपकी लाइनों में अजीब विकृतियों के बिना, और आप पेन को एक अपारदर्शी वस्तु के रूप में देख सकते हैं (यानी यूआई से कस्टमाइज़ करना आसान है - यदि आप पेन चौड़ाई या व्हाट्नॉट का चयन करते हैं, तो कोई और सुधार आवश्यक नहीं है)।

+0

मुझे लगता है कि इस समाधान का उपयोग करने के लिए ड्राइंग के कुछ हिस्सों की आवश्यकता होगी जिसे आप मुख्य कैनवास से अलग होने के लिए स्केल करना नहीं चाहते हैं। उदाहरण एक वेक्टर ड्राइंग एप्लिकेशन होगा जहां ड्राइंग स्वयं स्केल करता है लेकिन एंकर पॉइंट विज़ुअल और ऐसे पैमाने पर स्थितित्मक रूप से लेकिन उनकी मोटाई और इतनी दूर तक नहीं। क्या मैं इस धारणा में सही हूं? – jpierson

+0

मुझे खेद है, मैं आपके प्रश्न को समझ नहीं पा रहा हूं ... वास्तव में यह एक ऐसा है जो आप एक वेक्टर ड्राइंग परिदृश्य में करेंगे जहां आप आदर्शीकृत रेखाओं या बिंदुओं की देखभाल करते हैं और उनकी मोटाई के बारे में नहीं। यह दृष्टिकोण रेखा चौड़ाई को बदलने के बिना एक लाइन ड्राइंग को स्केल करेगा (या अन्यथा रैखिक रूप से परिवर्तित)। यानी, आप आदर्शीकृत ज्यामिति को बदल रहे हैं और केवल * फिर * इसे "वास्तविक" आकार में परिवर्तित कर रहे हैं जिसमें निश्चित रूप से गैर-शून्य चौड़ाई की रेखाएं हैं। यदि आप 'ड्राइंग' को बदलना चाहते थे, तो आप लाइन के साथ लाइन और लाइन जॉइन इत्यादि जैसे विवरण बदल रहे होंगे। क्या यह स्पष्ट करता है? –

+0

मुझे ऐसा लगता है, मेरी धारणा यह थी कि ड्राइंग एप्लिकेशन में कुछ हिस्सों होंगे जो चित्रों और कुछ हिस्सों जैसे स्केलर की तरह हैं जो मोटाई के मामले में स्केल नहीं करते हैं, लेकिन अभी भी स्केल किए गए चित्र के सापेक्ष स्थित हैं। वेक्टर ड्राइंग अनुप्रयोग जैसे कि इंकस्केप जहां मोटाई के मामले में ड्राइंग लाइनों को स्केल किया जाता है लेकिन चयनित ऑब्जेक्ट के लिए दिखाए गए एंकर पॉइंट उसी तरीके से स्केल नहीं किए जाते हैं। तो मेरी धारणा है कि इसे .NET में पूरा करना है। आपको अभी भी इन हिस्सों को दो अलग-अलग पैनलों में रखना होगा जिन्हें स्वतंत्र रूप से स्केल किया गया है। – jpierson

0

मैं यहां कई बार वापस आ गया हूं, लेकिन यह विचार सिर्फ मेरे लिए हुआ, इसे केवल एक व्यूबॉक्स में लपेटने के बारे में कैसे?

आप इसे आजमा सकते हैं: ऊंचाई/चौड़ाई के साथ गड़बड़ करने से मोटाई के आकार में अनुपात नहीं बदला जाना चाहिए। शायद यह अन्य बुरी चीजें करता है जिन्हें मैंने अभी तक नहीं खोजा है ...

<Viewbox Height="50" Width="50"> 
    <Path Stroke="Black" Fill="Black" StrokeThickness="0.8" Stretch="Uniform" 
       Data="M0,0 20,20" /> 
</Viewbox>