رسم نمودارهای ۳ بعدی در iOS با Plot3d — از صفر تا صد

۲۰۳ بازدید
آخرین به‌روزرسانی: ۲۳ اردیبهشت ۱۴۰۲
زمان مطالعه: ۴ دقیقه
رسم نمودارهای ۳ بعدی در iOS با Plot3d — از صفر تا صد

رسم داده‌ها در سه بُعد، روشی عالی برای بصری‌سازی آن‌ها محسوب می‌شود. یک نمودار سه بعدی از داده‌ها موجب برانگیختن خلاقیت می‌شود. در iOS رسم نمودار در سه بعد کمی چالش‌برانگیز است، زیرا فریمورک های زیادی برای استفاده به این منظور وجود ندارند و تنها گزینه موجود نیز رایگان نیست. Plot3d یک پروژه اوپن سورس است که می‌توان از آن برای رسم نمودارهای 3 بعدی در iOS بهره جست.

طرز کار Plot3d

Plot3d از SceneKit (+) برای بازنمایی داده‌ها در سه بُعد بهره می‌گیرد. در دو بخش بَعدی توضیح مختصری در مرود این فریمورک‌ها ارائه می‌کنیم.

توضیح SceneKit

در SceneKit یک SCNScene به جایی گفته می‌شود که همه اشیای 3 بعدی در آن حضور دارند. هر شیء بصری در یک صحنه در واقع یک SCNScene است. یک هندسه (Geometry) به هر SCNScene الصاق یافته است که یک عنصر ساختاری از یک صحنه محسوب می‌شود و موقعیت و تبدیل آن را در یک فضای با مختصات سه بعدی نشان می‌دهد.

توضیح Plot3d

Plot3d برای مدیریت یک صحنه که شامل همه گره‌ها و هندسه مورد نیاز برای رسم داده‌ها در فضای سه بعدی است از یک PlotView استفاده می‌کند. PlotView یک زیرکلاس از UIView است و هر چیزی که در صحنه باشد به یک PlotSpaceNode اضافه می‌شود.

PlotSpaceNode در واقع گره ریشه یک صحنه در یک PlotView است. اغلب عملیات سه بعدی در یک فضای نموداری (plot-space) مدیریت می‌شود که از دید توسعه‌دهنده پنهان است. داده‌هایی که باید در یک plot-space رسم شوند، با استفاده از یک منبع داده شناسایی شده و با الگویی مشابه شیوه استفاده از UITableView رسم می‌شوند.

کاربرد عملی Plot3d

برای شروع صرفاً یک نما با پیکربندی مفروض ایجاد می‌کنیم و سپس داده‌ها را ارائه می‌کنیم. در همه کدهای زیر فرض شده است که از یک UIViewController استفاده می‌کنیم.

ایجاد یک PlotView

ابتدا یک PlotView را با پیکربندی سفارشی مقداردهی می‌کنیم و سپس عناوین محورها را تعیین می‌کنیم:

1// Configure the plot.
2var config = PlotConfiguration()
3config.xAxisHeight = 3
4config.yAxisHeight = 4
5config.zAxisHeight = 3
6config.xTickInterval = 1
7config.zTickInterval = 1
8config.xMax = 6
9config.zMax = 6
10
11// Initialize the PlotView
12let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
13let plotView = PlotView(frame: frame, configuration: config)
14view.addSubview(plotView)
15
16// When using a custom configuration, the camera's position and orientation might need to be updated
17plotView.setCamera(position: PlotPoint(10, 6, 10))
18plotView.setCamera(lookAt: PlotPoint(0, 0, 0))
19
20plotView.setAxisTitle(.x, text: "x axis", textColor: .white)
21plotView.setAxisTitle(.y, text: "y axis", textColor: .white)
22plotView.setAxisTitle(.z, text: "z axis", textColor: .white)

رسم 3 بعدی

Plot3d

یک فضای plot داده‌ها را با استفاده از یک PlotDataSource و یک PlotDelegate رسم می‌کند. از آنجا که PlotDataSource افشا نشده است، منبع داده و delegate از طریق PlotView انتساب می‌یابند.

برای رسم داده‌ها کنترلر نما را طوری بسط می‌دهیم که پروتکل‌های data source و delegate را پیاده‌سازی کند و سپس آن‌ها را به نمای plot انتساب می‌دهیم.

plotView.dataSource = self
plotView.delegate = self
plotView.reloadData()

PlotDataSource

منابع داده برای تعیین تعداد نقاطی که باید رسم شده و اتصال‌هایی برقرار شوند مورد استفاده قرار می‌گیرد. فضای plot زیرین روی مقادیر مفروض حلقه‌ای تعریف می‌کند و هر نقطه و اتصال را بر همین اساس رسم می‌کند.

1extension ViewController: PlotDataSource {
2    func numberOfPoints() -> Int {
3        return 33 // The example in this artcile will only need a fixed number of points.
4    }
5}

PlotDelegate

در ادامه برخی از متدهای delegate که می‌توانند برای ارائه داده‌ها به فضای نمودار پیاده‌سازی شوند، ارائه شده‌اند:

  1. یک PlotPoint (مختصات 3 بعدی) برای رسم هر نقطه ارائه شود (پیاده‌سازی ضروری است).
  2. هندسه برای استفاده در هر نقطه رسم شده ارائه می‌شود (پیاده‌سازی ضروری است).
  3. PlotText برای استفاده در هر علامت تیک ارائه می‌شود (پیاده‌سازی اختیاری است).
1extension ViewController: PlotDelegate {
2
3    // 1
4    func plot(_ plotView: PlotView, pointForItemAt index: Int) -> PlotPoint {
5        let v = CGFloat(index % 16)
6        if index < 16 {
7            return PlotPoint(cos(v) + 5, v, sin(v) + 5)
8        }
9        return PlotPoint(cos(v + 1.57) + 5, v, sin(v + 1.57) + 5)
10    }
11
12    // 2
13    func plot(_ plotView: PlotView, geometryForItemAt index: Int) -> SCNGeometry? {
14        let geo = SCNSphere(radius: 0.15)
15        if index < 16  {
16            geo.materials.first!.diffuse.contents = UIColor.red
17        } else {
18            geo.materials.first!.diffuse.contents = UIColor.blue
19        }
20        return geo
21    }
22
23    // 3
24    func plot(_ plotView: PlotView, textAtTickMark index: Int, forAxis axis: PlotAxis) -> PlotText? {
25        let config = PlotConfiguration()
26        switch axis {
27        case .x:
28            return PlotText(text: "\(index + 1)", fontSize: 0.3, offset: 0.25)
29        case .y:
30            return PlotText(text: "\(Int(CGFloat(index + 1) * config.yTickInterval))", fontSize: 0.3, offset: 0.1)
31        case .z:
32            return PlotText(text: "\(index + 1)", fontSize: 0.3, offset: 0.25)
33        }
34    }
35}

افزودن اتصال‌ها

Plot3d

می‌توانیم نمودار را یک گام به پیش بریم و اتصال‌هایی بین نقاط رسم شده نیز برقرار سازیم تا بصری‌سازی داده‌ها آسانتر شود. با افزودن کد زیر به PlotDataSource تعداد اتصال‌هایی که باید برقرار شوند را ذکر می‌کنیم:

1func numberOfConnections() -> Int {
2    return 47
3}

با افزودن کد زیر به PlotDelegate نقاطی که باید اتصال یابند و شیوه نمایش اتصال را تعیین می‌کنیم:

1// Connect the points in a way that creates a double helix.
2func plot(_ plotView: PlotView, pointsToConnectAt index: Int) -> (p0: Int, p1: Int)? {
3    guard index != 31 else {
4	return nil
5    }
6        
7    if index < 16 {
8        return (p0: index, p1: index + 16)
9    }
10    
11    let i = index - 16
12    return (p0: i, p1: i + 1)
13}
14
15// Define the geometry of each connection.
16func plot(_ plotView: PlotView, connectionAt index: Int) -> PlotConnection? {
17    if index < 16 {
18        return PlotConnection(radius: 0.025, color: .green)
19    }
20    
21    if index - 16 < 16 {
22        return PlotConnection(radius: 0.04, color: .red)
23    } else {
24        return PlotConnection(radius: 0.04, color: .blue)
25    }
26}

سخن پایانی

هدف از Plot3d آسان‌تر ساختن ایجاد بصری‌سازی‌های 3 بعدی از داده‌ها در iOS است. اگرچه ممکن است تقاضای گراف‌های 3 بعدی روی آیفون چندان بالا نباشد، اما به هر حال آشنایی با یک کتابخانه اوپن سورس برای انجام این کار موجب آسودگی خیال ما می‌شود.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
better-programming
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *