आप देख रहे हैं क्या प्रभावी रूप से एक गैर रेखीय बदलना है। दृश्य पर ट्रांसफॉर्म संपत्ति केवल रैखिक परिवर्तन कर सकती है। सौभाग्य से डब्ल्यूपीएफ की 3 डी विशेषताएं आपके बचाव में आती हैं। आप आसानी से पूरा कर सकते हैं क्या आपको लगता है कि इस तरह से इस्तेमाल किया जाएगा एक सरल कस्टम नियंत्रण बनाने के द्वारा तलाश कर रहे हैं:
<local:DisplayOnPath Path="{Binding ...}" Content="Text to display" />
तरीके से ऐसा करने के लिए है:
पहले "DisplayOnPath" कस्टम नियंत्रण बनाने।
- दृश्य स्टूडियो के कस्टम नियंत्रण टेम्पलेट का उपयोग कर यह बनाएँ (सुनिश्चित करें कि आपके विधानसभा बनाने: ThemeInfo विशेषता ठीक से सेट है और जो कुछ)
- प्रकार
Geometry
की निर्भरता संपत्ति "पथ" (उपयोग wpfdp झलकी)
- जोड़े एक केवल पढ़ने के लिए निर्भरता संपत्ति "DisplayMesh" प्रकार
Geometry3D
की (प्रयोग wpfdpro झलकी) जोड़ें
- पथ के लिए एक
PropertyChangedCallback
जोड़ें Geometry3D के लिए पथ परिवर्तित करने के लिए एक "ComputeDisplayMesh" विधि कॉल करने के लिए, तो सेट DisplayMesh इसे से
वह कुछ इस तरह दिखेगा:
public class DisplayOnPath : ContentControl
{
static DisplayOnPath()
{
DefaultStyleKeyProperty.OverrideMetadata ...
}
public Geometry Path { get { return (Geometry)GetValue(PathProperty) ...
public static DependencyProperty PathProperty = ... new UIElementMetadata
{
PropertyChangedCallback = (obj, e) =>
{
var displayOnPath = obj as DisplayOnPath;
displayOnPath.DisplayMesh = ComputeDisplayMesh(displayOnPath.Path);
}));
public Geometry3D DisplayMesh { get { ... } private set { ... } }
private static DependencyPropertyKey DisplayMeshPropertyKey = ...
public static DependencyProperty DisplayMeshProperty = ...
}
अगला शैली और नियंत्रण Themes/Generic.xaml
में (या एक ResourceDictionary
यह द्वारा शामिल है) किसी भी कस्टम नियंत्रण के लिए के रूप में टेम्पलेट बनाने के। क्या करता है स्थान के लिए एक DisplayMesh उपयोग करता है और एक ब्रश सामग्री के रूप में अपने नियंत्रण के सामग्री का उपयोग करता है एक 3D मॉडल प्रदर्शित है
<Style TargetType="{x:Type local:DisplayOnPath}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DisplayOnPath}">
<Viewport3DVisual ...>
<ModelVisual3D>
<ModelVisual3D.Content>
<GeometryModel3D Geometry="{Binding DisplayMesh, RelativeSource={RelativeSource TemplatedParent}}">
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<VisualBrush ...>
<VisualBrush.Visual>
<ContentPresenter />
...
: टेम्पलेट इस तरह की सामग्री को होगा।
ध्यान दें कि आपको इच्छित तरीके से काम करने के लिए लेआउट प्राप्त करने के लिए व्यूपोर्ट 3 डीविज़ुअल और विजुअलब्रश पर अन्य गुणों को सेट करने की आवश्यकता हो सकती है और सामग्री दृश्य को उचित रूप से फैलाया जा सकता है।
जो कुछ भी बचा है वह "ComputeDisplayMesh" फ़ंक्शन है। यदि आप सामग्री के शीर्ष (पथ जिन्हें आप प्रदर्शित कर रहे हैं) चाहते हैं तो यह एक छोटा मैपिंग है जो पथ से एक निश्चित दूरी से लंबवत होना चाहिए। बेशक, ऐसे अन्य एल्गोरिदम भी हैं जिन्हें आप चुन सकते हैं, जैसे समानांतर पथ बनाना और प्रत्येक के साथ प्रतिशत दूरी का उपयोग करना।
किसी भी मामले में, बुनियादी एल्गोरिथ्म एक ही है:
- अपनी पसंद का एक अनुमानी का उपयोग कर अपने जाल में आयतों की एक उचित संख्या का चयन करें
PathGeometry.CreateFromGeometry
- का उपयोग कर
PathGeometry
में बदलें, 'एन',। शायद हार्ड कोडिंग एन = 50 के साथ शुरू करें।
- आयताकारों के सभी कोनों के लिए अपने
Positions
मानों की गणना करें। शीर्ष पर एन + 1 कोनों और नीचे + एन कोनों पर हैं। प्रत्येक निचला कोने PathGeometry.GetPointAtFractionOfLength
पर कॉल करके पाया जा सकता है। यह एक स्पर्शरेखा भी देता है, इसलिए शीर्ष कोने को भी ढूंढना आसान है।
- अपने
TriangleIndices
पर गणना करें। यह तुच्छ है। प्रत्येक आयत दो त्रिभुज होंगे, इसलिए प्रति आयताकार छह सूचकांक होंगे।
- अपने
TextureCoordinates
पर गणना करें। यह और भी मामूली है, क्योंकि वे सभी 0, 1, या i/n (जहां मैं आयताकार सूचकांक है)।
ध्यान दें कि अगर आप n के एक निश्चित मूल्य का उपयोग कर रहे हैं, केवल एक चीज आप कभी भी है जब पथ में परिवर्तन recompute करने Posisions
सरणी है। बाकी सब कुछ तय है।
यहाँ है क्या इस विधि के मुख्य भाग की तरह दिखता है:
var pathGeometry = PathGeometry.CreateFromGeometry(path);
int n=50;
// Compute points in 2D
var positions = new List<Point>();
for(int i=0; i<=n; i++)
{
Point point, tangent;
pathGeometry.GetPointAtFractionOfLength((double)i/n, out point, out tangent);
var perpendicular = new Vector(tangent.Y, -tangent.X);
perpendicular.Normalize();
positions.Add(point + perpendicular * height); // Top corner
positions.Add(point); // Bottom corner
}
// Convert to 3D by adding 0 'Z' value
mesh.Positions = new Point3DCollection(from p in positions select new Point3D(p.X, p.Y, 0));
// Now compute the triangle indices, same way
for(int i=0; i<n; i++)
{
// First triangle
mesh.TriangleIndices.Add(i*2+0); // Upper left
mesh.TriangleIndices.Add(i*2+2); // Upper right
mesh.TriangleIndices.Add(i*2+1); // Lower left
// Second triangle
mesh.TriangleIndices.Add(i*2+1); // Lower left
mesh.TriangleIndices.Add(i*2+2); // Upper right
mesh.TriangleIndices.Add(i*2+3); // Lower right
}
// Add code here to create the TextureCoordinates
इसके बारे में है। अधिकांश कोड ऊपर लिखा गया है। मैं बाकी को भरने के लिए इसे छोड़ देता हूं।
वैसे, ध्यान दें कि 'जेड' मूल्य के साथ रचनात्मक होने के कारण, आप कुछ वाकई शानदार प्रभाव प्राप्त कर सकते हैं।
अद्यतन
मार्क इस के लिए कोड लागू किया है और तीन समस्याओं का सामना करना पड़ा। यहाँ उनके लिए समस्याएं और समाधान कर रहे हैं:
मैं # 1 त्रिकोण के लिए मेरे TriangleIndices क्रम में एक गलती की है। यह ऊपर सही है। मैं मूल रूप से उन सूचकांक ऊपरी बाएं - निचले बाएं - ऊपरी दाएं जा रहा था। त्रिभुज के चारों तरफ घुसपैठ करके हम वास्तव में त्रिकोण के पीछे देखा, इसलिए कुछ भी चित्रित नहीं किया गया था। सूचकांक के क्रम को बदलकर हम घड़ी की दिशा में घूमते हैं ताकि त्रिभुज दिखाई दे।
ज्यामिति मॉडेल 3 डी पर बाध्यकारी मूल रूप से TemplateBinding
था। यह काम नहीं करता है क्योंकि टेम्पलेट बाइंडिंग अपडेट को उसी तरह से संभाल नहीं पाती है। इसे नियमित बाध्यकारी में बदलना समस्या को हल करता है।
3 डी के लिए समन्वय प्रणाली + वाई है, जबकि 2 डी + वाई नीचे है, इसलिए पथ उल्टा दिखाई दिया। इसे कोड में वाई को अस्वीकार कर या ViewPort3DVisual
पर, जैसा कि आप चाहें, को हल करके हल किया जा सकता है। मैं व्यक्तिगत रूप से रेंडरट्रांसफॉर्म पसंद करता हूं क्योंकि यह ComputeDisplayMesh कोड को और अधिक पठनीय बनाता है।
यहाँ एक भावना एनिमेट मार्क कोड का एक स्नैपशॉट है मैं हम सभी शेयर लगता है:
Snapshot of animating text "StackOverflowIsFun" http://rayburnsresume.com/StackOverflowImages/WavyLetters.png
लिंक के लिए धन्यवाद, मुझे विश्वास नहीं है कि यह लेख मेरे गुगल में नहीं आया है ... – Mark
कोई चिंता नहीं - खुश मैं मदद कर सकता है :-) –