【问题标题】:Undoing last drawn Polyline撤消最后绘制的折线
【发布时间】:2014-12-17 03:17:36
【问题描述】:

我一直在做折线叠加,当我遇到困难时得到了很好的帮助,我希望再次获得更多帮助。

在我的项目中,我在地图上绘制折线,从触摸开始到触摸移动。我的手指被拖动的坐标被添加到我的数组中并显示出来。

当我想清除我的行时,我只需清空数组,这很好

但是,如果我想删除/撤消最后绘制的线。我的印象是我可以从数组中减去最后一个值,但在更深入地思考时,我意识到我可能有问题。数组中的每个元素都是我的手指最后一次触摸的坐标。 我还没有尝试过,但我想如果我只减去数组的最后一个值,我会花很长时间“擦除”我画的一条线。 我正在寻找一种方法,当我按下“撤消”时,它会擦除​​我画的整条线。即使这条线从北美延伸到英国。

【问题讨论】:

  • 什么决定了一条线是什么?它是数组中的简单元素,还是数组中的多个元素?如果是多个元素,如何定义行首元素和行尾元素?
  • @Pavan 我不相信我能 100% 理解这个问题。然而,在触摸开始时,我将坐标添加到一个数组中,这个数组在触摸移动时更新,我手指沿着的那些坐标被添加到数组中,然后在地图上绘制
  • 所以问题1)单行可能有多个坐标吗?如果问题一的答案是肯定的,那么 2) 采取以下操作:用户按下手指开始画线,在屏幕上滑动,然后抬起手指。此操作是否将它们归类为单线?
  • 1) 可以。确实是的
  • 而您遇到的问题是,当您尝试删除坐标数组的最后一个元素时,您会在视觉上想象它只会删除部分行?啊哈 :D 很高兴您提前考虑过;是的,这就是会发生的事情;这是一个有趣的问题;幸运的是,它很容易解决。 :)

标签: ios objective-c mkmapview mkoverlay mkpolyline


【解决方案1】:

OP 希望能够撤消绘制的最后一条线。他想象的问题是,从数组中删除单个元素在视觉上只会删除用户绘制的线的一部分。 他希望做的是删除数组中构成该行的所有元素。

我在绘图方面做得不多,但我对您的问题的解决方案应该有效。

执行以下操作,创建一个枚举数据类型,该类型将为绘制到屏幕/添加到数组的每个坐标创建三种可能的状态。

这种数据类型看起来像这样:

typedef NS_ENUM(NSInteger, PKLinePointState) {
    PKLinePointStart,
    PKLinePointMiddle,
    PKLinePointEnd
};

这里的想法是,您将使用此数据类型来确定数组中的哪些元素是起点,以及数组中的哪些元素是终点。通过这种方式,您可以确定数组中的行,因此能够确定要删除多少元素,直到您点击状态为 PKLinePointStart 的坐标。

您不想只在数组中存储坐标,而是希望存储一个数据模型,该模型将包含更多信息,以便您可以做您想做的性感事情。

第一个数据模型将用于存储数组中的开始和结束坐标和元素。这将使您的坐标更容易工作。这就是它的样子:

LinePointModel.h

typedef NS_ENUM(NSInteger, PKLinePointState) {
        PKLinePointStart,
        PKLinePointMiddle,
        PKLinePointEnd
    };

@interface LinePointModel : NSObject

@property (assign) CGPoint linePointCoordinate; 
@property (assign) PKLinePointState linePointState; 
@end

//you may want to create a custom initialiser so that the coordinate and state are initialised straight away.
//It would look something like this -(instanceType)initWithLinePointCoordinate:(CGPoint)coordinate andLinePointState:(PKLinePointState)linePointstate;

LinePointModel.m

//I'll let you complete the initialiser method in the implementation file.

现在您已经创建了可以将坐标正确存储在 coordinates array 中的数据模型,下面是我将它们添加到数组中的方法。

逻辑第一阶段:

当用户点击屏幕时 - 调用 touchesBegan 方法,您可能希望创建 LinePointModel 的实例并将其坐标值设置为用户在屏幕上点击的第一个坐标并设置statePKLinePointStart 这将标记行的开头。将此元素添加到数组中。

然后,当用户在屏幕上拖动时,您将收到来自touchesMoved 的多个坐标。在这里,您将再次设置坐标创建相同数据模型的实例,但这次状态将存储为PKLinePointMiddle,我们并不真正关心这些点,因为我们不会检查此状态,但它仍然很好给它一个值,以便我们知道数组中具有此状态的任何元素仅服务于形成一个点,这些点最终形成一条完整的线。在这里,这些实例将根据需要不断地添加到数组中,直到用户最终停止在屏幕上拖动(绘制当前行)。

一旦touchesEnded 方法被调用 - 表示行的结束 - 用户抬起手指,这是您创建数据模型的最后一个实例的地方,相应地设置坐标,最后状态将是PKLinePointEnd 状态。同样,您也可以在数组中添加这个实例。

现在您有了一个有意义的自定义数组,它跟踪所有坐标,但让您知道哪个元素具有起始状态、中间状态和结束状态。

每个开始状态都与结束状态相结合,中间元素需要组成线条。

如果您想在这里停下来,您只需运行 for 循环,并确定在您的数组中添加的最新 startend 元素。 :)

逻辑阶段 2 - 改进算法:

现在您不想循环遍历数组中的数千个元素,只是为了确定您必须返回到数组中的多远才能删除一行,那将是低效的。这就是您的第二个数据模型会派上用场的地方。第二个数据模型将跟踪您的行并通过存储startend index 或更好地存储数组中的哪些元素构成其行,或者更好地存储坐标数组,这就是我们将要做的.

LineArrayModel.h

@interface LineArrayModel : NSObject

@property (nonatomic, retain) NSMutableArray *arrayOfLinePoints;  //What matters.
//@property (assign) int lineNumber; 
//@property (assign) CGFloat lineThickness;
//@property (strong, nonatomic) UIColor *lineColor;
@end

使用此数据模型,您将在用户在屏幕上绘制一条线时创建一个临时数组,一旦他们完成绘制一条线,您将获取该数组并将其存储在 @987654340 的实例中@;您将使用此实例将其存储在名为 myLinesArray 的新数组中。这是您将用来在屏幕上绘制线条的数组。

然后要简单地撤消一行,您只需删除存储所有行的数组中LineArrayModel 的最后一个实例,然后在必要时简单地重新绘制您的行。

让我知道你过得怎么样。

【讨论】:

  • 检查一下睡眠瘫痪 :)
  • 谢谢,我自己也是这么想的 :)
  • 真的吗?从你擦掉额头的汗水看,情况似乎并非如此;)。无论如何,没问题。祝你好运。
  • 哈哈,因为,看起来(而且看起来仍然)有很多东西可以吸收。:D
  • 没问题。如果您需要任何帮助,请告诉我。不过,我很想大致了解你在做什么。
猜你喜欢
  • 2016-11-12
  • 2021-03-28
  • 2018-02-20
  • 2016-04-12
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多